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