]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/rpp/eth.c
eth.h documentation completed; eth.c - removed casts to (const char *) from prints
[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 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 program is free software; you can redistribute it and/or modify
48  * it under the terms of the GNU General Public License as published by
49  * the Free Software Foundation; either version 2 of the License, or
50  * (at your option) any later version.
51  *
52  * This program is distributed in the hope that it will be useful,
53  * but WITHOUT ANY WARRANTY; without even the implied warranty of
54  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
55  * GNU General Public License for more details.
56  *
57  * You should have received a copy of the GNU General Public License
58  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
59  *
60  * File : eth.c
61  * Abstract:
62  *     Ethernet Communication RPP API implementation file. Using one PHY.
63  *
64  * References:
65  *     eth.h
66  *     RPP API documentation.
67  */
68
69 /* lwIP headers */
70 #include "lwip/init.h"
71 #include "lwip/timers.h" /* for DHCP binding in NO_SYS mode */
72 #include "lwip/sys.h" /* includes - lwip/opt.h, lwip/err.h, arch/sys_arch.h */
73 #include "lwip/tcpip.h" /* includes - lwip/opt.h, lwip/api_msg.h, lwip/netifapi.h, lwip/pbuf.h, lwip/api.h, lwip/sys.h, lwip/timers.h, lwip/netif.h */
74 #include "lwip/stats.h" /* includes - lwip/mem.h, lwip/memp.h, lwip/opt.h */
75 #include "netif/etharp.h" /* includes - lwip/ip.h, lwip/netif.h, lwip/ip_addr.h, lwip/pbuf.h */
76 #include "lwip/def.h"
77 #include "lwip/snmp.h"
78 #include "lwip/dhcp.h"
79 #include "lwip/autoip.h"
80 #include "netif/ppp_oe.h"
81 /* end - lwIP headers */
82
83 #include "hal/hal.h"
84 #include "rpp/rpp.h"
85 #include "sys/sys.h" /* includes - sys/phy_dp83848h.h */
86 #include "drv/emac.h"
87 #include "os/os.h"
88 #include "types.h"
89
90
91 #if rppCONFIG_INCLUDE_ETH == 1
92
93 /* options */
94
95 /* Number of EMAC Instances */
96 #define MAX_EMAC_INSTANCE         1
97
98 #define DEFAULT_PHY_ADDR          0x1
99 #define FIND_FIRST_PHY_ALIVE      1 /* or use default (phy_address: 1) */
100 #define NUM_OF_PHYs               32
101 #define SIZE_OF_DESC              16 /* in bytes */
102 #define CHANNEL                   0 /* channel number for everything - for rx, tx, unicast, broadcast or damaged frames ; there are different channels for rx and tx operations */
103
104 #define MAX_TRANSFER_UNIT         1500 /* take in account oversized frames */
105 #define PBUF_LEN_MAX              MAX_TRANSFER_UNIT
106 #define MAX_RX_PBUF_ALLOC         10
107 #define MIN_PKT_LEN               60
108
109 /* Define those to better describe the network interface. */
110 #define IFNAME0                   'e'
111 #define IFNAME1                   'n'
112 /* end options */
113
114 /* Defining interface for all the emac instances */
115 static struct hdkif hdkif_data[MAX_EMAC_INSTANCE];
116
117 /*
118 ** The lwIP network interface structure for the HDK Ethernet MAC.
119 */
120 static struct netif hdkNetIF[MAX_EMAC_INSTANCE];
121
122 /* rpp startup init indicator */
123 static boolean_t initialized = FALSE, postInitialized = FALSE;
124
125 boolean_t sendDone = TRUE;
126
127 /* free pbuf notification */
128 #if !NO_SYS
129 xSemaphoreHandle pbufFreed;
130 #endif
131
132 /**********************************************testing functions**********************************************/
133
134 uint32_t rpp_eth_phylinkstat(uint32_t instNum)
135 {
136         struct hdkif *hdkif = &hdkif_data[instNum];
137         return PHY_link_status_get(hdkif->mdio_base, hdkif->phy_addr, 1);
138 }
139
140 #define BYTE_BUFF_SIZE 2
141 #define OFFSET_MAC_LETTERS (MAC_BIG_LETTERS ? 'A' : 'a')
142 /* puts string of MAC address assigned to EMAC instance reffered by instNum into *mac */
143 void rpp_eth_get_macAddrStr(uint32_t instNum, uint8_t *macStr)
144 {
145     uint8_t index, outindex = 0;
146     char buff[BYTE_BUFF_SIZE];
147     struct hdkif *hdkif = &hdkif_data[instNum];
148         for(index = 0; index < MAC_ADDR_LEN; index++) {
149                 if(index)macStr[outindex++] = ':';
150         buff[0] = (hdkif->mac_addr[(MAC_ADDR_LEN - 1) - index] >> 4);
151         buff[1] = (hdkif->mac_addr[(MAC_ADDR_LEN - 1) - index] & 0xf);
152                 macStr[outindex++] = (buff[0]<10) ? (buff[0] + '0') : (buff[0] - '\012' + OFFSET_MAC_LETTERS);
153                 macStr[outindex++] = (buff[1]<10) ? (buff[1] + '0') : (buff[1] - '\012' + OFFSET_MAC_LETTERS);
154         }
155         macStr[outindex] = '\0';
156 }
157
158 /* @param ip will be filled accroding to content of ipstr */
159 err_t rpp_eth_stringToIP(ip_addr_t * ip, uint8_t * ipstr)
160 {
161         uint8_t charProccessed, index = 0, dotindex = 0xff, tmp = 0, dots = 0, fldEdit = 0;
162         uint32_t ipaddr = 0;
163         for(charProccessed = ipstr[index]; (charProccessed >= '0' && charProccessed <= '9') || charProccessed == '.' ; charProccessed = ipstr[++index])
164         {
165                 if(charProccessed == '.')
166                 {
167                         if(++dotindex == index)
168                         {
169                                 dots = 0;
170                                 break;
171                         }
172                         dotindex = index;
173
174                         ipaddr = (ipaddr << 8) + tmp;
175
176                         dots++;
177                         if(dots > 3)break;
178
179                         tmp = 0;
180                         fldEdit = FALSE;
181                 }
182                 else
183                 {
184                         fldEdit = TRUE;
185                         tmp = tmp*10 + charProccessed - '0';
186                 }
187         }
188         if(dots != 3 || !fldEdit)
189         {
190                 /* if unsuccesful, don't modify previous content */
191                 return FAILURE;
192         }
193         ipaddr = (ipaddr << 8) + tmp;
194         ip->addr = ipaddr;
195         return SUCCESS;
196 }
197
198 /* returns number in range 0-65535 where 0 is error */
199 uint16_t rpp_eth_portStrToInt(uint8_t *string)
200 {
201         uint8_t index;
202         uint16_t portNO = 0;
203         for(index = 0;string[index] != '\0';index++)
204         {
205                 if(string[index] < '0' || string[index] > '9')
206                 {
207                         portNO = 0;
208                         break;
209                 }
210                 portNO = portNO * 10 + string[index] - '0';
211         }
212         return portNO;
213 }
214
215 struct netif *rpp_eth_get_netif(uint32_t instNum)
216 {
217         return &hdkNetIF[instNum];
218 }
219
220 /********************************************** forward declares **********************************************/
221
222 /*
223  * interface initializes
224  */
225 err_t rpp_eth_lwip_init(struct netif *netif);
226
227 /*
228  * Initializes hw such as PHY, MDIO, EMAC, EMAC control module
229  *
230  * @return SUCCESS if initialization successful.\n
231  *         FAILURE if initialization not successful.
232  */
233 err_t rpp_eth_hw_init(struct hdkif *hdkif);
234
235 /*
236  * Initializes hw, after lwIP was initialized and
237  * OS was initialized in case OS is used.
238  */
239 err_t rpp_eth_hw_init_postInit(struct netif *netif);
240
241 /********************************************** utility functions **********************************************/
242
243 /*
244 * Function to set the MAC address to the interface
245 * @param   inst_num the instance number
246 *
247 * @note    mac_addr[0] is considered MSB
248 */
249 void
250 hdkif_macaddrset(u32_t inst_num, u8_t *mac_addr) {
251   struct hdkif *hdkif;
252   u32_t temp;
253
254   hdkif = &hdkif_data[inst_num];
255
256   /* set MAC hardware address */
257   for(temp = 0; temp < MAC_ADDR_LEN; temp++) {
258     hdkif->mac_addr[temp] = mac_addr[(MAC_ADDR_LEN - 1) - temp];
259   }
260 #ifdef DEBUG
261   uint8_t macStr[18];
262   rpp_eth_get_macAddrStr(inst_num, macStr);
263   rpp_debug_printf("Setting MAC... %s\r\n", macStr);
264 #endif
265 }
266
267 /**
268 * Function to setup the instance parameters inside the interface
269 * @param   hdkif
270 * @return  none.
271 */
272 static void
273 hdkif_inst_config(struct hdkif *hdkif) {
274   if(hdkif->inst_num == 0)
275   {
276     hdkif->emac_base = EMAC_BASE_m(0);
277     hdkif->emac_ctrl_base = EMAC_CTRL_BASE_m(0);
278     hdkif->emac_ctrl_ram = EMAC_CTRL_RAM_BASE_m(0);
279     hdkif->mdio_base = MDIO_BASE_m(0);
280     hdkif->phy_addr = DEFAULT_PHY_ADDR; /* Default address of PHY on "MDIO bus" (depends on PHY hw configuration) */
281     hdkif->phy_autoneg = PHY_auto_negotiate;
282     hdkif->phy_autoneg_start = PHY_start_auto_negotiate;
283     hdkif->phy_autoneg_is_done = PHY_is_done_auto_negotiate;
284     hdkif->phy_partnerability = PHY_partner_ability_get;
285   }
286 }
287
288 /********************************************** initializing functions **********************************************/
289
290 int8_t rpp_eth_init()
291 {
292     uint8_t instNum;
293         int8_t retVal = SUCCESS;
294     if(initialized) {
295         return FAILURE;
296     }
297
298     /* config of EMAC instances and other stuff */
299     for(instNum = 0; instNum < MAX_EMAC_INSTANCE; instNum++)
300     {
301         hdkif_data[instNum].inst_num = instNum;
302         hdkif_inst_config(&hdkif_data[instNum]); /* hdkif_inst_config must contain instNum specific settings */
303         if(retVal = rpp_eth_hw_init(&hdkif_data[instNum]))
304         {
305 #ifdef DEBUG
306                 rpp_sci_printk("rpp_eth_hw_init: %d", retVal);
307 #endif
308                 retVal = FAILURE;
309         }
310     }
311
312     /* when one of instances was not initialized correctly return FAILURE without setting initialized variable to TRUE */
313     if(retVal)return FAILURE;
314
315 #if NO_SYS
316
317 #else /* NO_SYS */
318
319 #endif /* NO_SYS */
320
321     initialized = TRUE;
322
323     return retVal;
324 }
325
326 int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray)
327 {
328     if(postInitialized) {
329         return FAILURE;
330     }
331     int8_t retVal = SUCCESS;
332     struct netif *netif = &hdkNetIF[instNum];
333     u8_t mac_addr[MAC_ADDR_LEN] = RPP_MAC_ADDR;
334
335     /* ----- lwIP stuff ----- */
336     struct ip_addr ip_addr;
337     struct ip_addr net_mask;
338     struct ip_addr gw_addr;
339     volatile unsigned int dhcpBindWait = 0x3FFFFFFF;
340
341     if(macArray == NULL)
342     {
343         macArray = mac_addr; /* use default MAC */
344     }
345     hdkif_macaddrset(instNum, macArray);
346
347     struct hdkif *hdkif;
348 #if NO_SYS
349     lwip_init();
350 #else /* NO_SYS */
351     /* this can be called only within post OS init */
352     tcpip_init(NULL,NULL); /* calls lwip_init() implicitly, starts lwIP task (thread), when started function given to tcpip_init is executed first */
353 #endif /* NO_SYS */
354
355 #if STATIC_IP_ADDRESS
356     ip_addr.addr = htonl(RPP_IP_ADDR);
357     net_mask.addr = htonl(RPP_NETMASK);
358     gw_addr.addr = htonl(RPP_GW);
359 #else /* STATIC_IP_ADDRESS */
360     ip_addr.addr = 0;
361     net_mask.addr = 0;
362     gw_addr.addr = 0;
363 #endif /* STATIC_IP_ADDRESS */
364
365     /* init and add new netif */
366     /* add new network interface to lwIP list of ifaces and initialize netif with specific function */
367 #if NO_SYS
368     if( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void *) instNum, rpp_eth_lwip_init, ethernet_input) == NULL )
369 #else /* NO_SYS */
370     if( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void *) instNum, rpp_eth_lwip_init, tcpip_input) == NULL )
371 #endif /* NO_SYS */
372     {
373         return NETIF_ADD_ERR;
374     }
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     {
395         rpp_debug_printf((const char *)"cable connected ... setting IP params\r\n");
396 #if STATIC_IP_ADDRESS
397         netif_set_up(netif);
398 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
399         if(dhcp_start(netif) != ERR_OK)
400         {
401                 rpp_debug_printf("dhcp mem err\r\n");
402                 return DHCP_MEM_ERR;
403         }
404         rpp_debug_printf("binding DHCP\r");
405         while((netif->dhcp->state != DHCP_BOUND) && (dhcpBindWait--))/*sys_check_timeouts()*/;
406         if(!dhcpBindWait)
407                 rpp_debug_printf("dhcp binding timeout...\r\n");
408 #else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
409         autoip_start(netif);
410 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
411 #ifdef DEBUG
412         uint8_t ipString[16];
413         rpp_eth_getIPDecimalStr(netif->ip_addr, ipString);
414         rpp_debug_printf("Address: %s\r\n", ipString);
415         rpp_eth_getIPDecimalStr(netif->netmask, ipString);
416         rpp_debug_printf("Netmask: %s\r\n", ipString);
417         rpp_eth_getIPDecimalStr(netif->gw, ipString);
418         rpp_debug_printf("Gateway: %s\r\n", ipString);
419 #endif
420     }
421     else
422     {
423         rpp_debug_printf((const char *)"cable not connected\r\n");
424         retVal = PHY_LINK_DOWN;
425     }
426
427 #else /* !PHY_LINK_MONITOR_INT */
428     /* now when we established environment needed for phy link status change we can allow it */
429     /* set PHY number which is monitored for link changes in MDIO and enable interrupt */
430     HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) = ((hdkif->phy_addr && 0x1f) | MDIO_USERPHYSEL0_LINKINTENB);
431
432     /* enable MISC interrupt - link monitoring in EMAC controle module */
433     HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_LINKINT0ENB;
434
435 #endif /* !PHY_LINK_MONITOR_INT */
436     /* ----- end - lwIP stuff ----- */
437
438     postInitialized = TRUE;
439         return retVal;
440 }
441
442 err_t rpp_eth_lwip_init(struct netif *netif)
443 {
444 #if LWIP_NETIF_HOSTNAME
445     /* Initialize interface hostname */
446     netif->hostname = "rpp";
447 #endif /* LWIP_NETIF_HOSTNAME */
448
449     uint32_t instNum = (uint32_t)netif->state;
450     /*netif->num = instNum; - auto-initiated when netif_add is called */
451
452     /* netif->state contained instNum, we replace it with corresponding hdkif */
453     struct hdkif *hdkif = &hdkif_data[instNum];
454     netif->state = hdkif;
455
456     netif->name[0] = IFNAME0;
457     netif->name[1] = IFNAME1;
458
459 #if !NO_SYS
460     hdkif->waitTicksForPHYAneg = TICKS_PHY_AUTONEG;
461 #endif
462
463     /*
464      * Initialize the snmp variables and counters inside the struct netif.
465      * The last argument should be replaced with your link speed, in units
466      * of bits per second.
467     */
468     NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
469
470     /* We directly use etharp_output() here to save a function call.
471      * You can instead declare yo_SKIP_TO_HWur own function an call etharp_output()
472      * from it if you have to do some checks before sending (e.g. if link
473      * is available...)
474      */
475     netif->output = etharp_output;
476     netif->linkoutput = rpp_eth_send;
477     return rpp_eth_hw_init_postInit(netif);
478 }
479
480 #define INIT_ONLY_AFTER_RESET 1
481 err_t rpp_eth_hw_init(struct hdkif *hdkif)
482 {
483         uint8_t index;
484     uint16_t regContent;
485     uint32_t physAlive;
486
487     /* Deactivate reset pin of PHY */
488     /* for hw reset of PHY, it is necessary that PIN_NAME_ETHRST is 1us logical low state, before putting it to logical high */
489 #if !INIT_ONLY_AFTER_RESET
490 #if NO_SYS
491         uint8_t index = 80; /* Initially used to hw reset of PHY connected to GIO pin. This means 1us - for 80MHz clock. */
492 #else /* NO_SYS */
493     uint8_t index = configCPU_CLOCK_HZ/1000000; /* Initially used to hw reset of PHY connected to GIO pin 'rpp project only'; 1us - according to PHY specification. */
494 #endif /* NO_SYS */
495     hal_gpio_pin_set_value(*hal_gpio_pin_get_dsc(PIN_NAME_ETHRST,-1),0);
496     while(index--);
497 #endif /* !INIT_ONLY_AFTER_RESET */
498     /* we have pull-down resistor, so after reset, we only need to put ETHRST pin to log. high */
499     hal_gpio_pin_set_value(*hal_gpio_pin_get_dsc(PIN_NAME_ETHRST,-1),1);
500
501     /* initializes EMAC control module and EMAC module */
502     EMACInit(hdkif->emac_ctrl_base, hdkif->emac_base);
503     /* initializes MDIO module (reset) */
504     MDIOInit(hdkif->mdio_base, 0x0, 0x0);
505
506     /* enable used receive channel if necessary */
507
508
509     /* try to read random register from defaultPhy to make MDIO fill alive bit for this one if it returned
510        ACK bit in msg response - this must be done, because MDIO has not set alive bit of PHY after that
511        short time after MDIOInit() */
512         MDIOPhyRegRead(hdkif->mdio_base, hdkif->phy_addr, PHY_BMSR, &regContent);
513
514     /* find first alive PHY - or use default if alive */
515     physAlive = MDIOPhyAliveStatusGet(hdkif->mdio_base);
516     if(!(physAlive & (1 << hdkif->phy_addr)))
517     {
518 #if FIND_FIRST_PHY_ALIVE
519         for(index = 0;index < NUM_OF_PHYs;index++) /* i..PHY tested */
520         {
521             if(physAlive && (1 << index))
522             {
523                 hdkif->phy_addr = index;
524                 break;
525             }
526             else
527             {
528                 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 */
529                 physAlive = MDIOPhyAliveStatusGet(hdkif->mdio_base); /* get updated register */
530                 if(physAlive && (1 << index))
531                 {
532                     hdkif->phy_addr = index;
533                     break;
534                 }
535             }
536         }
537         if(!physAlive)
538         {
539             rpp_debug_printf("no phy found, phys: %d\r\n", physAlive);
540                 return NO_PHY_ALIVE;
541         }
542 #else
543         rpp_debug_printf("default phy not alive\r\n");
544         return DFLT_PHY_NOT_ALIVE;
545 #endif
546     }
547
548     /* start autonegotiation and check on completion later or when complete link register will be updated */
549     hdkif->phy_autoneg_start(hdkif->mdio_base, hdkif->phy_addr, PHY_100BASETXDUPL_m | PHY_100BASETX_m | PHY_10BASETDUPL_m | PHY_10BASET_m);
550
551     /* TODO: you can implement init of receive flow control somewhere here if desired - set RXBUFFERFLOWEN in MACCONTROL */
552
553
554     /* acknowledge EMAC control module RX, TX and MISC interrupts */
555         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
556         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
557         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
558
559     /* sets which channel will receive broadcasts */
560         EMACRxBroadCastEnable(hdkif->emac_base, CHANNEL);
561         /* sets channel where all frames will be copied to - either with MAC address different from local device address, either packets with error will be copied; appropriate error will be set in the frame EOP buffer descriptor */
562         EMACRxPromiscEnable(hdkif->emac_base, CHANNEL);
563         /* enables unicast */
564         EMACRxUnicastSet(hdkif->emac_base, CHANNEL);
565
566     /* enable TX and RX interrupts in both EMAC module and EMAC control module */
567         EMACTxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, CHANNEL);
568         EMACRxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, CHANNEL);
569
570         /* switch of send bd handling and when sending, just wait till send was done and then return (making the driver simple) */
571         //vim_mask_clr(TXinterruptVectorNumber);
572
573         return SUCCESS;
574 }
575
576 err_t rpp_eth_hw_init_postInit(struct netif *netif)
577 {
578         volatile unsigned int autonegFinishWait = 0x3FFFFFFF; /* 0x3FFFFFFF is for 80MHz aproximately 13s */
579     uint16_t regContent;
580     uint32_t num_bd, pbuf_cnt = 0;
581     volatile struct emac_tx_bd *curr_txbd, *last_txbd;
582     volatile struct emac_rx_bd *curr_rxbd, *last_rxbd;
583     struct pbuf *p, *q;
584     struct rxch *rxch;
585     struct txch *txch;
586
587     struct hdkif *hdkif = (struct hdkif *) netif->state;
588
589     rxch = &(hdkif->rxch);
590     txch = &(hdkif->txch);
591
592     rpp_debug_printf("autoneg started - check on cable if it's connected!\r\n");
593
594
595         /*
596         * Initialize the Descriptor Memory For TX and RX
597         * Only Channel 0 is supported for both TX and RX
598         */
599         txch->free_head = ((volatile struct emac_tx_bd *) hdkif->emac_ctrl_ram);
600         txch->next_bd_to_process = txch->free_head;
601         txch->active_tail = NULL;
602
603         /* Set the number of descriptors for the channel */
604         num_bd = (SIZE_EMAC_CTRL_RAM >> 1) / sizeof(struct emac_tx_bd); /* take half of CPPI ram for TX BDs */
605
606         curr_txbd = txch->free_head;
607
608         /* Initialize all the TX buffer Descriptors */
609         while(num_bd--) {
610             curr_txbd->next = curr_txbd + 1;
611             curr_txbd->flags_pktlen = 0;
612             last_txbd = curr_txbd;
613             curr_txbd = curr_txbd->next;
614         }
615         last_txbd->next = txch->free_head;
616
617         /* Initialize the descriptors for the RX channel */
618         rxch->active_head = (volatile struct emac_rx_bd*)(curr_txbd);
619         rxch->free_head = NULL;
620         rxch->freed_pbuf_len = 0;
621         num_bd = ((SIZE_EMAC_CTRL_RAM >> 1) / sizeof(struct emac_rx_bd)); /* when using 20B emac_bd structs, u can allocate one more ;) ( 8192/20 = 409 together rx and tx and there is still 12 bytes remaining) */
622         curr_rxbd = rxch->active_head;
623         last_rxbd = curr_rxbd;
624
625         /*
626         ** Allocate the pbufs for the maximum count permitted or till the
627         ** number of buffer desceriptors expire, which ever is earlier.
628         */
629         while(pbuf_cnt < MAX_RX_PBUF_ALLOC) {
630             p = pbuf_alloc(PBUF_RAW, PBUF_LEN_MAX, PBUF_POOL);
631
632             if(p != NULL) {
633                 /* write the descriptors if there are enough numbers to hold the pbuf*/
634                 if(((uint32_t)pbuf_clen(p)) <= num_bd) {
635                     for(q = p; q != NULL; q = q->next) {
636                         curr_rxbd->bufptr = (uint8_t *)(q->payload);
637                         curr_rxbd->bufoff_len = q->len;
638                         curr_rxbd->next = curr_rxbd + 1;
639                         curr_rxbd->flags_pktlen = EMAC_DSC_FLAG_OWNER;
640
641                         /* Save the pbuf */
642                         curr_rxbd->pbuf = q;
643                         last_rxbd = curr_rxbd;
644                         curr_rxbd = curr_rxbd->next;
645                         num_bd--;
646                     }
647                 }
648
649                 /* free the allocated pbuf if no free descriptors are left */
650                 else {
651                     pbuf_free(p);
652                     break;
653                 }
654             }
655             else {
656                 break;
657             }
658             pbuf_cnt++;
659         }
660
661         if(!pbuf_cnt)rpp_debug_printf("no pbufs attached to rx buffer descriptors during init\n");
662
663         last_rxbd->next = NULL;
664         rxch->active_tail = last_rxbd;
665
666         num_bd = ( ((uint32_t)rxch->active_tail - (uint32_t)rxch->active_head) / sizeof(struct emac_rx_bd) + 1 );
667         rpp_debug_printf("%d pbuf chains allocated for %d rx buffer descriptors\n", pbuf_cnt, num_bd);
668         /* for flow control or QoS - there could be set an interrupt when we reach preset amount of receive descriptors remaining - see RXBUFFERFLOWEN */
669         /* EMACNumFreeBufSet(hdkif->emac_base, CHANNEL, num_bd); */ /* not used */
670
671         /* set header descriptor pointers - this shows EMAC which descriptor is beginning one for writing received frames/packets  */
672         EMACRxHdrDescPtrWrite(hdkif->emac_base, (uint32_t)rxch->active_head, CHANNEL);
673
674         /* lwIP stuff */
675
676         /* set length of MAC address */
677         netif->hwaddr_len = MAC_ADDR_LEN;
678
679         /* set MAC address */
680         for(regContent = 0; regContent < MAC_ADDR_LEN; regContent++) {
681             netif->hwaddr[regContent] = hdkif->mac_addr[(MAC_ADDR_LEN - 1) - regContent];
682         }
683
684         /* maximum transfer unit */
685         netif->mtu = MAX_TRANSFER_UNIT;
686
687         /* device capabilities */
688         /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
689         netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
690
691         /* lwIP stuff - end */
692
693     /* for flow control frames */
694     EMACMACSrcAddrSet(hdkif->emac_base, hdkif->mac_addr);
695
696     /*  Be sure to program all eight MAC address registers -
697      *  whether the receive channel is to be enabled or not.
698      */
699     for (regContent = 0; regContent < 8; regContent++) /* i..channel_number */
700         EMACMACAddrSet(hdkif->emac_base, regContent, hdkif->mac_addr, EMAC_MACADDR_NO_MATCH_NO_FILTER);
701
702 #if !PHY_LINK_MONITOR_INT /* in case we don't use interrupt when phy link status changes, we need to try to finish autoneg in here */
703     /* wait for autonegotiation to be done or continue, when delay was reached */
704 #if !NO_SYS
705     uint32_t timeToWake = hdkif->waitTicksForPHYAneg + sys_jiffies();
706     while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE && timeToWake > sys_jiffies())vTaskDelay(20); /* XXX: if init is not done at the startup, but couple days later, this might cause troubles */
707 #else
708     while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE && autonegFinishWait--); /* wait till aneg done */
709 #endif
710
711     if(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) != FALSE)
712         rpp_debug_printf("aneg finished \r\n");
713     else
714         rpp_debug_printf("aneg timeout \r\n");
715
716     /* provide informations retrieved from autoneg to EMAC module */
717     hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, &regContent);
718     if (regContent & (PHY_100BASETXDUPL_m | PHY_10BASETDUPL_m)) {
719         EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_FULL);
720         /* this is right place to implement transmit flow control if desired - set TXFLOWEN in MACCONTROL */
721     } else if (regContent & (PHY_100BASETX_m | PHY_10BASET_m)) {
722         EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_HALF);
723     } else {
724         rpp_debug_printf("Unknown duplex mode\r\n");
725         return UNKN_DUPLEX_MODE;
726     }
727 #endif /* !PHY_LINK_MONITOR_INT */
728
729     /* enable hostpend interrupts in emac module */
730     HWREG(hdkif->emac_base + EMAC_MACINTMASKSET) |= EMAC_MACINTMASKSET_HOSTMASK;
731
732     /* enable hostpend interrupts in emac control module */
733     HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_HOSTPENDENB;
734
735         /* enable EMAC's Media Independent Interface TX and RX */
736         EMACMIIEnable(hdkif->emac_base);
737         /* enable EMAC transmit */
738         EMACTxEnable(hdkif->emac_base);
739         /* enable EMAC receive */
740         EMACRxEnable(hdkif->emac_base);
741
742         return SUCCESS;
743 }
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758 /********************************************** send and receive functions / ISRs **********************************************/
759
760 err_t rpp_eth_send(struct netif * netif, struct pbuf *p)
761 {
762         err_t retVal = SUCCESS;
763         SYS_ARCH_DECL_PROTECT(lev);
764
765         /**
766          * This entire function must run within a "critical section" to preserve
767          * the integrity of the transmit pbuf queue.
768          *
769          */
770         SYS_ARCH_PROTECT(lev);
771
772         /* protect from access receive acces from interrupt */
773 #if !SYS_LIGHTWEIGHT_PROT
774         uint32_t prevProt = (uint32_t) _get_CPSR() & 0x80;
775         _disable_IRQ();
776 #endif
777
778
779         /* adjust the packet length if less than minimum required */
780         if(p->tot_len < MIN_PKT_LEN) {
781            p->tot_len = MIN_PKT_LEN;
782            p->len = MIN_PKT_LEN;
783         }
784
785         /* call the actual transmit function */
786         retVal = rpp_eth_send_raw(netif, p);
787
788         /* Return to prior interrupt state and return. */
789         SYS_ARCH_UNPROTECT(lev);
790
791 #if !SYS_LIGHTWEIGHT_PROT
792     if(!prevProt)_enable_IRQ();
793 #endif
794
795         return retVal;
796 }
797
798 /**
799  * send packet, blocks till it is sent
800  * every send uses bds on the beginning of CPPI RAM
801  */
802 err_t rpp_eth_send_raw(struct netif *netif, struct pbuf *p)
803 {
804         struct pbuf *q;
805         volatile struct emac_tx_bd *curr_bd, *bd_end;
806         struct hdkif *hdkif;
807
808     hdkif = (struct hdkif *) netif->state;
809         curr_bd = (struct emac_tx_bd *) hdkif->emac_ctrl_ram;
810
811         /* destroy all flags previously set and update the total packet length */
812         curr_bd->flags_pktlen = p->tot_len;
813
814         /* Indicate the start of the packet */
815         curr_bd->flags_pktlen |= (EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_OWNER);
816
817         /* Copy pbuf information into TX buffer descriptors */
818         for(q = p; q != NULL; q = q->next) {
819
820             /* Intialize the buffer pointer and length */
821             curr_bd->bufptr = (uint8_t *)(q->payload);
822             curr_bd->bufoff_len = (q->len) & 0xFFFF;
823             bd_end = curr_bd;
824             curr_bd->pbuf = p;
825             curr_bd = curr_bd->next;
826             curr_bd->flags_pktlen = 0x0; /* destroy all previously set flags */
827         }
828
829         /* Indicate the end of the packet */
830         bd_end->next = NULL;
831         bd_end->flags_pktlen |= EMAC_DSC_FLAG_EOP;
832
833     /* don't write to hdp till it turns zero */
834     while (0 != *((volatile uint32_t *) (hdkif->emac_base + EMAC_TXHDP(CHANNEL)) ));
835     /* notify hw where to start transmission from */
836     HWREG(hdkif->emac_base + EMAC_TXHDP(CHANNEL)) = hdkif->emac_ctrl_ram;
837         //EMACTxHdrDescPtrWrite(hdkif->emac_base, hdkif->emac_ctrl_ram, CHANNEL);
838
839         /* wait till queued pkt is sent */
840     vim_mask_set(TXinterruptVectorNumber);
841         xSemaphoreTake(hdkif->goTX, portMAX_DELAY);
842         while (!(bd_end->flags_pktlen & EMAC_DSC_FLAG_EOQ) || (((struct emac_tx_bd *)(hdkif->emac_ctrl_ram))->flags_pktlen & EMAC_DSC_FLAG_OWNER))rpp_sci_printk("!");
843
844         EMACTxCPWrite(hdkif->emac_base, CHANNEL, (uint32_t) bd_end);
845
846     EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
847
848         /* restore bds chain */
849         bd_end->next = curr_bd;
850
851     LINK_STATS_INC(link.xmit);
852         return SUCCESS;
853 }
854
855 void rpp_eth_recv_raw(void *arg)
856 {
857     volatile struct emac_rx_bd *curr_bd, *processed_bd, *curr_tail, *last_bd;
858     volatile struct pbuf *pbuf, *q, *new_pbuf;
859     uint32_t ex_len, len_to_alloc;
860     uint16_t tot_len;
861         struct netif *netif = (struct netif *) arg;
862         struct hdkif *hdkif = (struct hdkif *) netif->state;
863         struct rxch *rxch;
864
865         rxch = &(hdkif->rxch);
866
867
868 #if !NO_SYS && !ONE_DRIVER_TASK
869         SYS_ARCH_DECL_PROTECT(lev);
870     for(;;)
871     {
872         vim_mask_set(RXinterruptVectorNumber);
873         sys_arch_sem_wait(&(hdkif->goRX), 0);
874         SYS_ARCH_PROTECT(lev);
875 #endif
876
877
878             /* Get the bd which contains the earliest filled data */
879             curr_bd = rxch->active_head;
880             last_bd = rxch->active_tail;
881
882             if(curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP != EMAC_DSC_FLAG_SOP)rpp_debug_printf("ERR: Active head is not SOP!\n");
883
884             /**
885              * Process the descriptors as long as data is available
886              * when the DMA is receiving data, SOP flag will be set
887              */
888             while(curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP)
889         {
890                 ex_len = 0;
891                 len_to_alloc = 0;
892                 /* Start processing once the packet is loaded */
893                 if((curr_bd->flags_pktlen & EMAC_DSC_FLAG_OWNER) != EMAC_DSC_FLAG_OWNER)
894             {
895                         if(rxch->free_head == NULL)
896                         {
897                                 /* this bd chain will be freed after processing */
898                             rxch->free_head = curr_bd;
899                         }
900
901                         /* Get the total length of the packet. curr_bd points to the start
902                      * of the packet.
903                      */
904                     tot_len = (curr_bd->flags_pktlen) & 0xFFFF;
905
906                     /* Get the start of the pbuf queue */
907                     q = curr_bd->pbuf;
908
909                     do {
910                         /* Get the pbuf pointer which is associated with the current bd */
911                         pbuf = curr_bd->pbuf;
912
913                         /* If the earlier pbuf ended, update the chain */
914                         if(pbuf->next == NULL)
915                         {
916                             pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;
917                         }
918
919                         len_to_alloc += pbuf->len;
920                         /* Update the len and tot_len fields for the pbuf in the chain*/
921                         pbuf->len = (curr_bd->bufoff_len) & 0xFFFF;
922                         pbuf->tot_len = tot_len - ex_len ;
923                         processed_bd = curr_bd;
924                         ex_len += pbuf->len;
925                         curr_bd = curr_bd->next;
926 #ifdef DEBUG
927                         if(curr_bd == NULL)rpp_debug_printf("rx curr_bd set to zero!\n");
928 #endif
929                         /* FIXME: curr_bd here could be NULL - (currently solved by having always allocated enough pbufs -> waiting for pbuf_free() function) a solution could be: we need to keep at least TCP_MSS bytes, so allocate at least that if not possible block */
930                     } while((processed_bd->flags_pktlen & EMAC_DSC_FLAG_EOP) != EMAC_DSC_FLAG_EOP);
931
932                     /**
933                      * Close the chain for this pbuf. A full packet is received in
934                      * this pbuf chain. Now this pbuf can be given to upper layers for
935                      * processing. The start of the pbuf chain is now 'q'.
936                     */
937                     pbuf->next = NULL;
938
939                     /* Adjust the link statistics */
940                     LINK_STATS_INC(link.recv);
941
942                     /* Process the packet - this function is specified while adding netif using netif_add() function */
943                     if(netif->input((struct pbuf *)q, netif) != ERR_OK)
944                     {
945                         /* Adjust the link statistics */
946                         LINK_STATS_INC(link.memerr);
947                         LINK_STATS_INC(link.drop);
948                     }
949
950                     /* Acknowledge that this packet is processed */
951                     EMACRxCPWrite(hdkif->emac_base, CHANNEL, (unsigned int)processed_bd);
952
953                     if(curr_bd != NULL)
954                     {
955                         rxch->active_head = curr_bd;
956                     }
957                     else
958                     {
959                         rxch->active_head = processed_bd + 1; //todo:reconsider
960                     }
961
962                     /**
963                      * The earlier pbuf chain is freed from the upper layer. So, we need to
964                      * allocate a new pbuf chain and update the descriptors with the pbuf info.
965                      * To support chaining, the total length freed by the upper layer is tracked.
966                      * Care should be taken even if the allocation fails.
967                      */
968                     /**
969                      * now len_to_alloc will contain the length of the pbuf which was freed
970                      * from the upper layer
971                      */
972                     rxch->freed_pbuf_len += len_to_alloc;
973 #if !NO_SYS
974                     /* if there is not enough pbufs predefined, we need application to process them and return them back to pool -> YIELD */
975                     /* XXX: this is not fixed in NO_SYS version - problem is when curr_bd is set to NULL (see above), and we don't obtain new_pbuf
976                      * from pool, then in *bd pointing to NULL might be such values (EMAC_DSC_FLAG_SOP == 1 &| EMAC_DSC_FLAG_OWNER == 0), that we
977                      * stay cycling around */
978                     do
979                     {
980 #endif
981                             new_pbuf = pbuf_alloc(PBUF_RAW, (rxch->freed_pbuf_len), PBUF_POOL);
982 #if !NO_SYS
983                             if(new_pbuf != NULL)
984                                 break;
985                             else
986                                 xSemaphoreTake(pbufFreed, 0);
987                                 xSemaphoreTake(pbufFreed, portMAX_DELAY);
988                     }while(1);
989 #endif
990
991                     /* Write the descriptors with the pbuf info till either of them expires */
992                     if(new_pbuf != NULL)
993                     {
994                         curr_bd = rxch->free_head;
995
996                         for(q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next)
997                         {
998                             curr_bd->bufptr = (uint8_t *)(q->payload);
999
1000                             /* no support for buf_offset. RXBUFFEROFFSET register is 0 */
1001                             curr_bd->bufoff_len = (q->len) & 0xFFFF;
1002                             curr_bd->flags_pktlen = EMAC_DSC_FLAG_OWNER;
1003
1004                             rxch->freed_pbuf_len -= q->len;
1005
1006                             /* Save the pbuf */
1007                             curr_bd->pbuf = q;
1008                             last_bd = curr_bd;
1009                             curr_bd = curr_bd->next;
1010                         }
1011
1012                         /**
1013                          * At this point either pbuf expired or no rxbd to allocate. If
1014                          * there are no, enough rx bds to allocate all pbufs in the chain,
1015                          * free the rest of the pbuf
1016                          */
1017                         if(q != NULL)
1018                         {
1019                             pbuf_free((struct pbuf *)q);
1020                         }
1021
1022                         curr_tail = rxch->active_tail;
1023                         last_bd->next = NULL;
1024
1025                         curr_tail->next = rxch->free_head;
1026
1027                         /**
1028                          * Check if the reception has ended. If the EOQ flag is set, the NULL
1029                          * Pointer is taken by the DMA engine. So we need to write the RX HDP
1030                          * with the next descriptor.
1031                          */
1032                         if(curr_tail->flags_pktlen & EMAC_DSC_FLAG_EOQ)
1033                         {
1034                             EMACRxHdrDescPtrWrite(hdkif->emac_base, (u32_t)(rxch->free_head), CHANNEL);
1035                         }
1036
1037                         rxch->free_head  = curr_bd;
1038                         rxch->active_tail = last_bd;
1039                     }
1040             }
1041                 curr_bd = rxch->active_head;
1042             }
1043                 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
1044
1045 #if !NO_SYS && !ONE_DRIVER_TASK
1046                 SYS_ARCH_UNPROTECT(lev);
1047     }
1048 #endif
1049 }
1050
1051 void RxIntHandler(u32_t instNum)
1052 {
1053 #if !NO_SYS
1054         vim_mask_clr(RXinterruptVectorNumber);
1055         /*
1056         static portBASE_TYPE xHigherPriorityTaskWoken;
1057         xHigherPriorityTaskWoken = pdFALSE;
1058         */
1059         /* 'Give' the semaphore to unblock the task. */
1060         xSemaphoreGiveFromISR(hdkif_data[instNum].goRX, NULL); // whenever there is time to process received packets, wake up task processing them
1061         /*
1062     if( xHigherPriorityTaskWoken == pdTRUE )
1063     {
1064     */
1065     /* Giving the semaphore unblocked a task, and the priority of the
1066     unblocked task is higher than or equal to the currently running task
1067     - force a context switch to ensure that the interrupt returns directly
1068     to the unblocked (higher priority) task.
1069     NOTE: The actual macro to use to force a context switch from an
1070     ISR is dependent on the port. This is the correct macro for the
1071     Open Watcom DOS port. Other ports may require different syntax.
1072         Refer to the examples provided for the port being used to determine
1073     the syntax required. */
1074         /*
1075     portSWITCH_CONTEXT();
1076     }
1077         */
1078 #else
1079         rpp_eth_recv_raw((void *) &hdkNetIF[instNum]);
1080 #endif
1081 }
1082
1083 void TxIntHandler(u32_t instNum)
1084 {
1085         //struct hdkif *hdkif = &hdkif_data[instNum];
1086 #if !NO_SYS
1087         vim_mask_clr(TXinterruptVectorNumber); /* see sys_startup.c */
1088         xSemaphoreGiveFromISR(hdkif_data[instNum].goTX, NULL);
1089 #else
1090         //sendDone = TRUE;
1091         //rpp_eth_send_bd_handler((void *) &hdkif_data[instNum]);
1092 #endif
1093 }
1094
1095 /**
1096  * TX err codes:
1097  *
1098  * 0 No error
1099  * 1h SOP error; the buffer is the first buffer in a packet, but the SOP bit is not set in software.
1100  * 2h Ownership bit not set in SOP buffer
1101  * 3h Zero next buffer descriptor pointer without EOP
1102  * 4h Zero buffer pointer
1103  * 5h Zero buffer length
1104  * 6h Packet length error (sum of buffers is less than packet length)
1105  *
1106  *
1107  * RX err codes:
1108  *
1109  * 0 No error
1110  * 1h Reserved
1111  * 2h Ownership bit not set in SOP buffer
1112  * 3h Reserved
1113  * 4h Zero buffer pointer
1114  */
1115 boolean_t HostPendErrHandler(void)
1116 {
1117         uint8_t index = MAX_EMAC_INSTANCE, errFound = FALSE;
1118         uint32_t reg;
1119         struct hdkif *hdkif;
1120
1121         while(index){
1122                 hdkif = &hdkif_data[--index];
1123             if(EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_HOSTPEND)errFound = TRUE;
1124         }
1125         if(!errFound)return FALSE; /* this is not the cause of the interrupt */
1126         rpp_sci_printk("HOSTPEND err\n");
1127         reg = HWREG(hdkif->emac_base + EMAC_MACSTATUS);
1128         rpp_sci_printk("TXCHERR: %d at CH: %d\n", ((reg >> EMAC_MACSTATUS_TXERRCODE_SHIFT) & 0x7), ((reg >> EMAC_MACSTATUS_TXERRCH_SHIFT) & 0x7));
1129         rpp_sci_printk("RXCHERR: %d at CH: %d\n", ((reg >> EMAC_MACSTATUS_RXERRCODE_SHIFT) & 0x7), ((reg >> EMAC_MACSTATUS_RXERRCH_SHIFT) & 0x7));
1130         /* no acknowledge - emac module has to be restarted */
1131         return TRUE; /* this was the reason of interrupt */
1132 }
1133
1134 #if PHY_LINK_MONITOR_INT
1135 boolean_t LinkIntHandler(void)
1136 {
1137         uint8_t index = MAX_EMAC_INSTANCE, phyFound = FALSE;
1138         struct hdkif *hdkif;
1139         uint16_t regContent;
1140         volatile unsigned int autonegFinishWait = 0xFFFFFFF;
1141     volatile unsigned int dhcpBindWait = 0x3FFFFFFF;
1142
1143         /* check each instance, whether this interrupt was meant for this function, if not return FALSE so other function may be tried */
1144         while(index){
1145         hdkif = &hdkif_data[--index];
1146             if( hdkif->phy_addr == (HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) & 0x1f) && EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_LINKINT0 )phyFound = TRUE;
1147         }
1148     if(!phyFound)return FALSE;
1149     struct netif *netif = &hdkNetIF[hdkif->inst_num];
1150
1151     /* we handles here connection of cable after startup, not changes of linkstatus */
1152
1153     /* wait for autonegotiation to be done */
1154 #if ONCE_LINK_SETUP
1155     while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE);
1156 #else /* ONCE_LINK_SETUP */
1157     while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE & autonegFinishWait--);
1158 #endif /* ONCE_LINK_SETUP */
1159
1160     /* provide informations retrieved from autoneg to EMAC module */
1161     hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, &regContent);
1162     if (regContent & (PHY_100BASETXDUPL_m | PHY_10BASETDUPL_m)) {
1163         EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_FULL);
1164         /* this is right place to implement transmit flow control if desired - set TXFLOWEN in MACCONTROL */
1165     } else if (regContent & (PHY_100BASETX_m | PHY_10BASET_m)) {
1166         EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_HALF);
1167     } else {
1168         /* acknowledge MDIO module */
1169         HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1170         HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1171
1172         /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1173         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1174         return FALSE;
1175     }
1176     /* if link is up configure lwip struct netif */
1177     if(rpp_eth_phylinkstat(hdkif->inst_num))
1178     {
1179 #if STATIC_IP_ADDRESS
1180         netif_set_up(netif);
1181 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
1182         if(dhcp_start(netif) != ERR_OK) /* XXX: can't be used from ISR (mem_malloc()) */
1183         {
1184                 return DHCP_MEM_ERR;
1185         }
1186 #if ONCE_LINK_SETUP
1187         while(netif->dhcp->state != DHCP_BOUND);
1188 #else
1189         while(netif->dhcp->state != DHCP_BOUND & dhcpBindWait--);
1190         if(!dhcpBindWait)
1191         {
1192                 /* acknowledge MDIO module */
1193                 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1194                 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1195
1196                 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1197                 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1198                 return FALSE;
1199         }
1200 #endif
1201 #else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
1202         autoip_start(netif);
1203 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
1204 #if ONCE_LINK_SETUP
1205         /* turn this interrupt off */
1206         HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) &= (~EMAC_CTRL_MISC_LINKINT0ENB & 0xf);
1207 #endif /* ONCE_LINK_SETUP */
1208     }
1209     else
1210     {
1211 #if ONCE_LINK_SETUP
1212         /* acknowledge MDIO module */
1213         HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1214         HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1215
1216         /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1217         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1218         return FALSE;
1219 #else
1220 #if STATIC_IP_ADDRESS
1221         netif_set_down(netif);
1222 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
1223         dhcp_stop(netif);
1224 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
1225 #endif
1226     }
1227
1228         /* acknowledge MDIO module */
1229         HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1230         HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1231
1232         /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1233         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1234
1235         return TRUE;
1236 }
1237 #endif /* PHY_LINK_MONITOR_INT */
1238
1239 #endif /* rppCONFIG_INCLUDE_ETH */