]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/rpp/eth.c
Merge branch 'init_rework'
[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         return PHY_link_status_get(hdkif->mdio_base, hdkif->phy_addr, 1);
148 }
149
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)
154 {
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);
164         }
165         macStr[outindex] = '\0';
166 }
167
168 /* @param ip will be filled accroding to content of ipstr */
169 err_t rpp_eth_stringToIP(ip_addr_t * ip, uint8_t * ipstr)
170 {
171         uint8_t charProccessed, index = 0, dotindex = 0xff, tmp = 0, dots = 0, fldEdit = 0;
172         uint32_t ipaddr = 0;
173         for(charProccessed = ipstr[index]; (charProccessed >= '0' && charProccessed <= '9') || charProccessed == '.' ; charProccessed = ipstr[++index])
174         {
175                 if(charProccessed == '.')
176                 {
177                         if(++dotindex == index)
178                         {
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         {
200                 /* if unsuccesful, don't modify previous content */
201                 return FAILURE;
202         }
203         ipaddr = (ipaddr << 8) + tmp;
204         ip->addr = ipaddr;
205         return SUCCESS;
206 }
207
208 /* returns number in range 0-65535 where 0 is error */
209 uint16_t rpp_eth_portStrToInt(uint8_t *string)
210 {
211         uint8_t index;
212         uint16_t portNO = 0;
213         for(index = 0;string[index] != '\0';index++)
214         {
215                 if(string[index] < '0' || string[index] > '9')
216                 {
217                         portNO = 0;
218                         break;
219                 }
220                 portNO = portNO * 10 + string[index] - '0';
221         }
222         return portNO;
223 }
224
225 struct netif *rpp_eth_get_netif(uint32_t instNum)
226 {
227         return &hdkNetIF[instNum];
228 }
229
230 /********************************************** forward declares **********************************************/
231
232 /*
233  * interface initializes
234  */
235 err_t rpp_eth_lwip_init(struct netif *netif);
236
237 /*
238  * Initializes hw such as PHY, MDIO, EMAC, EMAC control module
239  *
240  * @return SUCCESS if initialization successful.\n
241  *         FAILURE if initialization not successful.
242  */
243 err_t rpp_eth_hw_init(struct hdkif *hdkif);
244
245 /*
246  * Initializes hw, after lwIP was initialized and
247  * OS was initialized in case OS is used.
248  */
249 err_t rpp_eth_hw_init_postInit(struct netif *netif);
250
251 /********************************************** utility functions **********************************************/
252
253 /*
254 * Function to set the MAC address to the interface
255 * @param   inst_num the instance number
256 *
257 * @note    mac_addr[0] is considered MSB
258 */
259 void
260 hdkif_macaddrset(u32_t inst_num, u8_t *mac_addr) {
261   struct hdkif *hdkif;
262   u32_t temp;
263
264   hdkif = &hdkif_data[inst_num];
265
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];
269   }
270 #ifdef DEBUG
271   uint8_t macStr[18];
272   rpp_eth_get_macAddrStr(inst_num, macStr);
273   rpp_debug_printf("Setting MAC... %s\r\n", macStr);
274 #endif
275 }
276
277 /**
278 * Function to setup the instance parameters inside the interface
279 * @param   hdkif
280 * @return  none.
281 */
282 static void
283 hdkif_inst_config(struct hdkif *hdkif) {
284   if(hdkif->inst_num == 0)
285   {
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;
295   }
296 }
297
298 /********************************************** initializing functions **********************************************/
299
300 int8_t rpp_eth_init()
301 {
302     uint8_t instNum;
303         int8_t retVal = SUCCESS;
304     if(initialized) {
305         return FAILURE;
306     }
307
308     /* config of EMAC instances and other stuff */
309     for(instNum = 0; instNum < MAX_EMAC_INSTANCE; instNum++)
310     {
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]))
314         {
315 #ifdef DEBUG
316                 rpp_sci_printk("rpp_eth_hw_init: %d", retVal);
317 #endif
318                 retVal = FAILURE;
319         }
320     }
321
322     /* when one of instances was not initialized correctly return FAILURE without setting initialized variable to TRUE */
323     if(retVal)return FAILURE;
324
325 #if NO_SYS
326
327 #else /* NO_SYS */
328
329 #endif /* NO_SYS */
330
331     initialized = TRUE;
332
333     return retVal;
334 }
335
336 int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray)
337 {
338     if(postInitialized) {
339         return FAILURE;
340     }
341     int8_t retVal = SUCCESS;
342     struct netif *netif = &hdkNetIF[instNum];
343     u8_t mac_addr[MAC_ADDR_LEN] = RPP_MAC_ADDR;
344
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;
350
351     if(macArray == NULL)
352     {
353         macArray = mac_addr; /* use default MAC */
354     }
355     hdkif_macaddrset(instNum, macArray);
356
357     struct hdkif *hdkif;
358 #if NO_SYS
359     lwip_init();
360 #else /* NO_SYS */
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 */
363 #endif /* NO_SYS */
364
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 */
370     ip_addr.addr = 0;
371     net_mask.addr = 0;
372     gw_addr.addr = 0;
373 #endif /* STATIC_IP_ADDRESS */
374
375     /* init and add new netif */
376     /* add new network interface to lwIP list of ifaces and initialize netif with specific function */
377 #if NO_SYS
378     if( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void *) instNum, rpp_eth_lwip_init, ethernet_input) == NULL )
379 #else /* NO_SYS */
380     if( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void *) instNum, rpp_eth_lwip_init, tcpip_input) == NULL )
381 #endif /* NO_SYS */
382     {
383         return NETIF_ADD_ERR;
384     }
385
386     netif_set_default(netif);
387
388     hdkif = (struct hdkif *) netif->state;
389 #if !NO_SYS
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 ----- */
399 #endif /* !NO_SYS */
400
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))
404     {
405         rpp_debug_printf((const char *)"cable connected ... setting IP params\r\n");
406 #if STATIC_IP_ADDRESS
407         netif_set_up(netif);
408 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
409         if(dhcp_start(netif) != ERR_OK)
410         {
411                 rpp_debug_printf("dhcp mem err\r\n");
412                 return DHCP_MEM_ERR;
413         }
414         rpp_debug_printf("binding DHCP\r");
415         while((netif->dhcp->state != DHCP_BOUND) && (dhcpBindWait--))/*sys_check_timeouts()*/;
416         if(!dhcpBindWait)
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 */
419         autoip_start(netif);
420 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
421 #ifdef DEBUG
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);
429 #endif
430     }
431     else
432     {
433         rpp_debug_printf((const char *)"cable not connected\r\n");
434         retVal = PHY_LINK_DOWN;
435     }
436
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);
441
442     /* enable MISC interrupt - link monitoring in EMAC controle module */
443     HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_LINKINT0ENB;
444
445 #endif /* !PHY_LINK_MONITOR_INT */
446     /* ----- end - lwIP stuff ----- */
447
448     postInitialized = TRUE;
449         return retVal;
450 }
451
452 err_t rpp_eth_lwip_init(struct netif *netif)
453 {
454 #if LWIP_NETIF_HOSTNAME
455     /* Initialize interface hostname */
456     netif->hostname = "rpp";
457 #endif /* LWIP_NETIF_HOSTNAME */
458
459     uint32_t instNum = (uint32_t)netif->state;
460     /*netif->num = instNum; - auto-initiated when netif_add is called */
461
462     /* netif->state contained instNum, we replace it with corresponding hdkif */
463     struct hdkif *hdkif = &hdkif_data[instNum];
464     netif->state = hdkif;
465
466     netif->name[0] = IFNAME0;
467     netif->name[1] = IFNAME1;
468
469 #if !NO_SYS
470     hdkif->waitTicksForPHYAneg = TICKS_PHY_AUTONEG;
471 #endif
472
473     /*
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.
477     */
478     NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
479
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
483      * is available...)
484      */
485     netif->output = etharp_output;
486     netif->linkoutput = rpp_eth_send;
487     return rpp_eth_hw_init_postInit(netif);
488 }
489
490 #define INIT_ONLY_AFTER_RESET 1
491 err_t rpp_eth_hw_init(struct hdkif *hdkif)
492 {
493         uint8_t index;
494     uint16_t regContent;
495     uint32_t physAlive;
496
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
500 #if NO_SYS
501         uint8_t index = 80; /* Initially used to hw reset of PHY connected to GIO pin. This means 1us - for 80MHz clock. */
502 #else /* NO_SYS */
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. */
504 #endif /* NO_SYS */
505     hal_gpio_pin_set_value(*hal_gpio_pin_get_dsc(PIN_NAME_ETHRST,-1),0);
506     while(index--);
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);
510
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);
515
516     /* enable used receive channel if necessary */
517
518
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, &regContent);
523
524     /* find first alive PHY - or use default if alive */
525     physAlive = MDIOPhyAliveStatusGet(hdkif->mdio_base);
526     if(!(physAlive & (1 << hdkif->phy_addr)))
527     {
528 #if FIND_FIRST_PHY_ALIVE
529         for(index = 0;index < NUM_OF_PHYs;index++) /* i..PHY tested */
530         {
531             if(physAlive && (1 << index))
532             {
533                 hdkif->phy_addr = index;
534                 break;
535             }
536             else
537             {
538                 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 */
539                 physAlive = MDIOPhyAliveStatusGet(hdkif->mdio_base); /* get updated register */
540                 if(physAlive && (1 << index))
541                 {
542                     hdkif->phy_addr = index;
543                     break;
544                 }
545             }
546         }
547         if(!physAlive)
548         {
549             rpp_debug_printf("no phy found, phys: %d\r\n", physAlive);
550                 return NO_PHY_ALIVE;
551         }
552 #else
553         rpp_debug_printf("default phy not alive\r\n");
554         return DFLT_PHY_NOT_ALIVE;
555 #endif
556     }
557
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);
560
561     /* TODO: you can implement init of receive flow control somewhere here if desired - set RXBUFFERFLOWEN in MACCONTROL */
562
563
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);
568
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);
575
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);
579
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);
582
583         return SUCCESS;
584 }
585
586 err_t rpp_eth_hw_init_postInit(struct netif *netif)
587 {
588         volatile unsigned int autonegFinishWait = 0x3FFFFFFF; /* 0x3FFFFFFF is for 80MHz aproximately 13s */
589     uint16_t regContent;
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;
593     struct pbuf *p, *q;
594     struct rxch *rxch;
595     struct txch *txch;
596
597     struct hdkif *hdkif = (struct hdkif *) netif->state;
598
599     rxch = &(hdkif->rxch);
600     txch = &(hdkif->txch);
601
602     rpp_debug_printf("autoneg started - check on cable if it's connected!\r\n");
603
604
605         /*
606         * Initialize the Descriptor Memory For TX and RX
607         * Only Channel 0 is supported for both TX and RX
608         */
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;
612
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 */
615
616         curr_txbd = txch->free_head;
617
618         /* Initialize all the TX buffer Descriptors */
619         while(num_bd--) {
620             curr_txbd->next = curr_txbd + 1;
621             curr_txbd->flags_pktlen = 0;
622             last_txbd = curr_txbd;
623             curr_txbd = curr_txbd->next;
624         }
625         last_txbd->next = txch->free_head;
626
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;
634
635         /*
636         ** Allocate the pbufs for the maximum count permitted or till the
637         ** number of buffer desceriptors expire, which ever is earlier.
638         */
639         while(pbuf_cnt < MAX_RX_PBUF_ALLOC) {
640             p = pbuf_alloc(PBUF_RAW, PBUF_LEN_MAX, PBUF_POOL);
641
642             if(p != NULL) {
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;
650
651                         /* Save the pbuf */
652                         curr_rxbd->pbuf = q;
653                         last_rxbd = curr_rxbd;
654                         curr_rxbd = curr_rxbd->next;
655                         num_bd--;
656                     }
657                 }
658
659                 /* free the allocated pbuf if no free descriptors are left */
660                 else {
661                     pbuf_free(p);
662                     break;
663                 }
664             }
665             else {
666                 break;
667             }
668             pbuf_cnt++;
669         }
670
671         if(!pbuf_cnt)rpp_debug_printf("no pbufs attached to rx buffer descriptors during init\n");
672
673         last_rxbd->next = NULL;
674         rxch->active_tail = last_rxbd;
675
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 */
680
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);
683
684         /* lwIP stuff */
685
686         /* set length of MAC address */
687         netif->hwaddr_len = MAC_ADDR_LEN;
688
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];
692         }
693
694         /* maximum transfer unit */
695         netif->mtu = MAX_TRANSFER_UNIT;
696
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;
700
701         /* lwIP stuff - end */
702
703     /* for flow control frames */
704     EMACMACSrcAddrSet(hdkif->emac_base, hdkif->mac_addr);
705
706     /*  Be sure to program all eight MAC address registers -
707      *  whether the receive channel is to be enabled or not.
708      */
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);
711
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 */
714 #if !NO_SYS
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 */
717 #else
718     while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE && autonegFinishWait--); /* wait till aneg done */
719 #endif
720
721     if(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) != FALSE)
722         rpp_debug_printf("aneg finished \r\n");
723     else
724         rpp_debug_printf("aneg timeout \r\n");
725
726     /* provide informations retrieved from autoneg to EMAC module */
727     hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, &regContent);
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);
733     } else {
734         rpp_debug_printf("Unknown duplex mode\r\n");
735         return UNKN_DUPLEX_MODE;
736     }
737 #endif /* !PHY_LINK_MONITOR_INT */
738
739     /* enable hostpend interrupts in emac module */
740     HWREG(hdkif->emac_base + EMAC_MACINTMASKSET) |= EMAC_MACINTMASKSET_HOSTMASK;
741
742     /* enable hostpend interrupts in emac control module */
743     HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_HOSTPENDENB;
744
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);
751
752         return SUCCESS;
753 }
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768 /********************************************** send and receive functions / ISRs **********************************************/
769
770 err_t rpp_eth_send(struct netif * netif, struct pbuf *p)
771 {
772         err_t retVal = SUCCESS;
773         SYS_ARCH_DECL_PROTECT(lev);
774
775         /**
776          * This entire function must run within a "critical section" to preserve
777          * the integrity of the transmit pbuf queue.
778          *
779          */
780         SYS_ARCH_PROTECT(lev);
781
782         /* protect from access receive acces from interrupt */
783 #if !SYS_LIGHTWEIGHT_PROT
784         uint32_t prevProt = (uint32_t) _get_CPSR() & 0x80;
785         _disable_IRQ();
786 #endif
787
788
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;
793         }
794
795         /* call the actual transmit function */
796         retVal = rpp_eth_send_raw(netif, p);
797
798         /* Return to prior interrupt state and return. */
799         SYS_ARCH_UNPROTECT(lev);
800
801 #if !SYS_LIGHTWEIGHT_PROT
802     if(!prevProt)_enable_IRQ();
803 #endif
804
805         return retVal;
806 }
807
808 /**
809  * send packet, blocks till it is sent
810  * every send uses bds on the beginning of CPPI RAM
811  */
812 err_t rpp_eth_send_raw(struct netif *netif, struct pbuf *p)
813 {
814         struct pbuf *q;
815         volatile struct emac_tx_bd *curr_bd, *bd_end;
816         struct hdkif *hdkif;
817
818     hdkif = (struct hdkif *) netif->state;
819         curr_bd = (struct emac_tx_bd *) hdkif->emac_ctrl_ram;
820
821         /* destroy all flags previously set and update the total packet length */
822         curr_bd->flags_pktlen = p->tot_len;
823
824         /* Indicate the start of the packet */
825         curr_bd->flags_pktlen |= (EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_OWNER);
826
827         /* Copy pbuf information into TX buffer descriptors */
828         for(q = p; q != NULL; q = q->next) {
829
830             /* Intialize the buffer pointer and length */
831             curr_bd->bufptr = (uint8_t *)(q->payload);
832             curr_bd->bufoff_len = (q->len) & 0xFFFF;
833             bd_end = curr_bd;
834             curr_bd->pbuf = p;
835             curr_bd = curr_bd->next;
836             curr_bd->flags_pktlen = 0x0; /* destroy all previously set flags */
837         }
838
839         /* Indicate the end of the packet */
840         bd_end->next = NULL;
841         bd_end->flags_pktlen |= EMAC_DSC_FLAG_EOP;
842
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);
848
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("!");
853
854         EMACTxCPWrite(hdkif->emac_base, CHANNEL, (uint32_t) bd_end);
855
856     EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
857
858         /* restore bds chain */
859         bd_end->next = curr_bd;
860
861     LINK_STATS_INC(link.xmit);
862         return SUCCESS;
863 }
864
865 void rpp_eth_recv_raw(void *arg)
866 {
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;
870     uint16_t tot_len;
871         struct netif *netif = (struct netif *) arg;
872         struct hdkif *hdkif = (struct hdkif *) netif->state;
873         struct rxch *rxch;
874
875         rxch = &(hdkif->rxch);
876
877
878 #if !NO_SYS && !ONE_DRIVER_TASK
879         SYS_ARCH_DECL_PROTECT(lev);
880     for(;;)
881     {
882         vim_mask_set(RXinterruptVectorNumber);
883         sys_arch_sem_wait(&(hdkif->goRX), 0);
884         SYS_ARCH_PROTECT(lev);
885 #endif
886
887
888             /* Get the bd which contains the earliest filled data */
889             curr_bd = rxch->active_head;
890             last_bd = rxch->active_tail;
891
892             if(curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP != EMAC_DSC_FLAG_SOP)rpp_debug_printf("ERR: Active head is not SOP!\n");
893
894             /**
895              * Process the descriptors as long as data is available
896              * when the DMA is receiving data, SOP flag will be set
897              */
898             while(curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP)
899         {
900                 ex_len = 0;
901                 len_to_alloc = 0;
902                 /* Start processing once the packet is loaded */
903                 if((curr_bd->flags_pktlen & EMAC_DSC_FLAG_OWNER) != EMAC_DSC_FLAG_OWNER)
904             {
905                         if(rxch->free_head == NULL)
906                         {
907                                 /* this bd chain will be freed after processing */
908                             rxch->free_head = curr_bd;
909                         }
910
911                         /* Get the total length of the packet. curr_bd points to the start
912                      * of the packet.
913                      */
914                     tot_len = (curr_bd->flags_pktlen) & 0xFFFF;
915
916                     /* Get the start of the pbuf queue */
917                     q = curr_bd->pbuf;
918
919                     do {
920                         /* Get the pbuf pointer which is associated with the current bd */
921                         pbuf = curr_bd->pbuf;
922
923                         /* If the earlier pbuf ended, update the chain */
924                         if(pbuf->next == NULL)
925                         {
926                             pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;
927                         }
928
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;
934                         ex_len += pbuf->len;
935                         curr_bd = curr_bd->next;
936 #ifdef DEBUG
937                         if(curr_bd == NULL)rpp_debug_printf("rx curr_bd set to zero!\n");
938 #endif
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);
941
942                     /**
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'.
946                     */
947                     pbuf->next = NULL;
948
949                     /* Adjust the link statistics */
950                     LINK_STATS_INC(link.recv);
951
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)
954                     {
955                         /* Adjust the link statistics */
956                         LINK_STATS_INC(link.memerr);
957                         LINK_STATS_INC(link.drop);
958                     }
959
960                     /* Acknowledge that this packet is processed */
961                     EMACRxCPWrite(hdkif->emac_base, CHANNEL, (unsigned int)processed_bd);
962
963                     if(curr_bd != NULL)
964                     {
965                         rxch->active_head = curr_bd;
966                     }
967                     else
968                     {
969                         rxch->active_head = processed_bd + 1; //todo:reconsider
970                     }
971
972                     /**
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.
977                      */
978                     /**
979                      * now len_to_alloc will contain the length of the pbuf which was freed
980                      * from the upper layer
981                      */
982                     rxch->freed_pbuf_len += len_to_alloc;
983 #if !NO_SYS
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 */
988                     do
989                     {
990 #endif
991                             new_pbuf = pbuf_alloc(PBUF_RAW, (rxch->freed_pbuf_len), PBUF_POOL);
992 #if !NO_SYS
993                             if(new_pbuf != NULL)
994                                 break;
995                             else
996                                 xSemaphoreTake(pbufFreed, 0);
997                                 xSemaphoreTake(pbufFreed, portMAX_DELAY);
998                     }while(1);
999 #endif
1000
1001                     /* Write the descriptors with the pbuf info till either of them expires */
1002                     if(new_pbuf != NULL)
1003                     {
1004                         curr_bd = rxch->free_head;
1005
1006                         for(q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next)
1007                         {
1008                             curr_bd->bufptr = (uint8_t *)(q->payload);
1009
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;
1013
1014                             rxch->freed_pbuf_len -= q->len;
1015
1016                             /* Save the pbuf */
1017                             curr_bd->pbuf = q;
1018                             last_bd = curr_bd;
1019                             curr_bd = curr_bd->next;
1020                         }
1021
1022                         /**
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
1026                          */
1027                         if(q != NULL)
1028                         {
1029                             pbuf_free((struct pbuf *)q);
1030                         }
1031
1032                         curr_tail = rxch->active_tail;
1033                         last_bd->next = NULL;
1034
1035                         curr_tail->next = rxch->free_head;
1036
1037                         /**
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.
1041                          */
1042                         if(curr_tail->flags_pktlen & EMAC_DSC_FLAG_EOQ)
1043                         {
1044                             EMACRxHdrDescPtrWrite(hdkif->emac_base, (u32_t)(rxch->free_head), CHANNEL);
1045                         }
1046
1047                         rxch->free_head  = curr_bd;
1048                         rxch->active_tail = last_bd;
1049                     }
1050             }
1051                 curr_bd = rxch->active_head;
1052             }
1053                 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
1054
1055 #if !NO_SYS && !ONE_DRIVER_TASK
1056                 SYS_ARCH_UNPROTECT(lev);
1057     }
1058 #endif
1059 }
1060
1061 void RxIntHandler(u32_t instNum)
1062 {
1063 #if !NO_SYS
1064         vim_mask_clr(RXinterruptVectorNumber);
1065         /*
1066         static portBASE_TYPE xHigherPriorityTaskWoken;
1067         xHigherPriorityTaskWoken = pdFALSE;
1068         */
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
1071         /*
1072     if( xHigherPriorityTaskWoken == pdTRUE )
1073     {
1074     */
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. */
1084         /*
1085     portSWITCH_CONTEXT();
1086     }
1087         */
1088 #else
1089         rpp_eth_recv_raw((void *) &hdkNetIF[instNum]);
1090 #endif
1091 }
1092
1093 void TxIntHandler(u32_t instNum)
1094 {
1095         //struct hdkif *hdkif = &hdkif_data[instNum];
1096 #if !NO_SYS
1097         vim_mask_clr(TXinterruptVectorNumber); /* see sys_startup.c */
1098         xSemaphoreGiveFromISR(hdkif_data[instNum].goTX, NULL);
1099 #else
1100         //sendDone = TRUE;
1101         //rpp_eth_send_bd_handler((void *) &hdkif_data[instNum]);
1102 #endif
1103 }
1104
1105 /**
1106  * TX err codes:
1107  *
1108  * 0 No error
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)
1115  *
1116  *
1117  * RX err codes:
1118  *
1119  * 0 No error
1120  * 1h Reserved
1121  * 2h Ownership bit not set in SOP buffer
1122  * 3h Reserved
1123  * 4h Zero buffer pointer
1124  */
1125 boolean_t HostPendErrHandler(void)
1126 {
1127         uint8_t index = MAX_EMAC_INSTANCE, errFound = FALSE;
1128         uint32_t reg;
1129         struct hdkif *hdkif;
1130
1131         while(index){
1132                 hdkif = &hdkif_data[--index];
1133             if(EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_HOSTPEND)errFound = TRUE;
1134         }
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 */
1142 }
1143
1144 #if PHY_LINK_MONITOR_INT
1145 boolean_t LinkIntHandler(void)
1146 {
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;
1152
1153         /* check each instance, whether this interrupt was meant for this function, if not return FALSE so other function may be tried */
1154         while(index){
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;
1157         }
1158     if(!phyFound)return FALSE;
1159     struct netif *netif = &hdkNetIF[hdkif->inst_num];
1160
1161     /* we handles here connection of cable after startup, not changes of linkstatus */
1162
1163     /* wait for autonegotiation to be done */
1164 #if ONCE_LINK_SETUP
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 */
1169
1170     /* provide informations retrieved from autoneg to EMAC module */
1171     hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, &regContent);
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);
1177     } else {
1178         /* acknowledge MDIO module */
1179         HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1180         HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1181
1182         /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1183         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1184         return FALSE;
1185     }
1186     /* if link is up configure lwip struct netif */
1187     if(rpp_eth_phylinkstat(hdkif->inst_num))
1188     {
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()) */
1193         {
1194                 return DHCP_MEM_ERR;
1195         }
1196 #if ONCE_LINK_SETUP
1197         while(netif->dhcp->state != DHCP_BOUND);
1198 #else
1199         while(netif->dhcp->state != DHCP_BOUND & dhcpBindWait--);
1200         if(!dhcpBindWait)
1201         {
1202                 /* acknowledge MDIO module */
1203                 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1204                 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1205
1206                 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1207                 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1208                 return FALSE;
1209         }
1210 #endif
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 */
1214 #if ONCE_LINK_SETUP
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 */
1218     }
1219     else
1220     {
1221 #if 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;
1225
1226         /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1227         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1228         return FALSE;
1229 #else
1230 #if STATIC_IP_ADDRESS
1231         netif_set_down(netif);
1232 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
1233         dhcp_stop(netif);
1234 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
1235 #endif
1236     }
1237
1238         /* acknowledge MDIO module */
1239         HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1240         HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1241
1242         /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1243         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1244
1245         return TRUE;
1246 }
1247 #endif /* PHY_LINK_MONITOR_INT */
1248 #endif /* FREERTOS_POSIX */