CVE-2021-26788 (C, published 2021-03-08T13:15Z)
Description: value: Oryx Embedded CycloneTCP 1.7.6 to 2.0.0, fixed in 2.0.2, is affected by incorrect input validation, which may cause a denial of service (DoS). To exploit the vulnerability, an attacker needs to have TCP connectivity to the target system. Receiving a maliciously crafted TCP packet from an unauthenticated endpoint is sufficient to trigger the bug.
Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: CWE-20 \u2014 Improper Input Validation
The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
Repository: https://github.com/Oryx-Embedded/CycloneTCP
Files changed:
coap/coap_client.c
coap/coap_client.h
coap/coap_client_block.c
coap/coap_client_block.h
coap/coap_client_misc.c
coap/coap_client_misc.h
coap/coap_client_observe.c
coap/coap_client_observe.h
coap/coap_client_request.c
coap/coap_client_request.h
coap/coap_client_transport.c
coap/coap_client_transport.h
coap/coap_common.h
coap/coap_debug.c
coap/coap_debug.h
coap/coap_message.c
coap/coap_message.h
coap/coap_option.c
coap/coap_option.h
coap/coap_server.c
coap/coap_server.h
coap/coap_server_misc.c
coap/coap_server_misc.h
coap/coap_server_request.c
coap/coap_server_request.h
coap/coap_server_transport.c
coap/coap_server_transport.h
core/bsd_socket.c
core/bsd_socket.h
core/ethernet.c
core/ethernet.h
core/ethernet_misc.c
core/ethernet_misc.h
core/ip.c
core/ip.h
core/net.c
core/net.h
core/net_legacy.h
core/net_mem.c
core/net_mem.h
core/net_misc.c
core/net_misc.h
core/nic.c
core/nic.h
core/ping.c
core/ping.h
core/raw_socket.c
core/raw_socket.h
core/socket.c
core/socket.h
core/tcp.c
core/tcp.h
core/tcp_fsm.c
core/tcp_fsm.h
core/tcp_misc.c
core/tcp_misc.h
core/tcp_timer.c
core/tcp_timer.h
core/udp.c
core/udp.h
dhcp/dhcp_client.c
dhcp/dhcp_client.h
dhcp/dhcp_common.c
dhcp/dhcp_common.h
dhcp/dhcp_debug.c
dhcp/dhcp_debug.h
dhcp/dhcp_server.c
dhcp/dhcp_server.h
dhcpv6/dhcpv6_client.c
dhcpv6/dhcpv6_client.h
dhcpv6/dhcpv6_common.c
dhcpv6/dhcpv6_common.h
dhcpv6/dhcpv6_debug.c
dhcpv6/dhcpv6_debug.h
dhcpv6/dhcpv6_relay.c
dhcpv6/dhcpv6_relay.h
dns/dns_cache.c
dns/dns_cache.h
dns/dns_client.c
dns/dns_client.h
dns/dns_common.c
dns/dns_common.h
dns/dns_debug.c
dns/dns_debug.h
dns_sd/dns_sd.c
dns_sd/dns_sd.h
drivers/eth/dm9000_driver.c
drivers/eth/dm9000_driver.h
drivers/eth/enc28j60_driver.c
drivers/eth/enc28j60_driver.h
drivers/eth/enc624j600_driver.c
drivers/eth/enc624j600_driver.h
drivers/eth/ksz8851_driver.c
drivers/eth/ksz8851_driver.h
drivers/loopback/loopback_driver.c
drivers/loopback/loopback_driver.h
drivers/mac/a2fxxxm3_eth_driver.c
drivers/mac/a2fxxxm3_eth_driver.h
drivers/mac/am335x_eth_driver.c
drivers/mac/am335x_eth_driver.h
drivers/mac/aps3_eth_driver.c
drivers/mac/aps3_eth_driver.h
drivers/mac/avr32_eth_driver.c
drivers/mac/avr32_eth_driver.h
drivers/mac/efm32gg11_eth_driver.c
drivers/mac/efm32gg11_eth_driver.h
drivers/mac/esp32_eth_driver.c
drivers/mac/esp32_eth_driver.h
drivers/mac/f28m35x_eth_driver.c
drivers/mac/f28m35x_eth_driver.h
drivers/mac/fm4_eth_driver.c
drivers/mac/fm4_eth_driver.h
drivers/mac/gd32f307_eth_driver.c
drivers/mac/gd32f307_eth_driver.h
drivers/mac/lm3s_eth_driver.c
drivers/mac/lm3s_eth_driver.h
drivers/mac/lpc175x_eth_driver.c
drivers/mac/lpc175x_eth_driver.h
drivers/mac/lpc176x_eth_driver.c
drivers/mac/lpc176x_eth_driver.h
drivers/mac/lpc178x_eth_driver.c
drivers/mac/lpc178x_eth_driver.h
drivers/mac/lpc18xx_eth_driver.c
drivers/mac/lpc18xx_eth_driver.h
drivers/mac/lpc23xx_eth_driver.c
drivers/mac/lpc23xx_eth_driver.h
drivers/mac/lpc43xx_eth_driver.c
drivers/mac/lpc43xx_eth_driver.h
drivers/mac/lpc54xxx_eth_driver.c
drivers/mac/lpc54xxx_eth_driver.h
drivers/mac/m2sxxx_eth_driver.c
drivers/mac/m2sxxx_eth_driver.h
drivers/mac/m487_eth_driver.c
drivers/mac/m487_eth_driver.h
drivers/mac/mcf5225x_eth_driver.c
drivers/mac/mcf5225x_eth_driver.h
drivers/mac/mcimx6ul_eth1_driver.c
drivers/mac/mcimx6ul_eth1_driver.h
drivers/mac/mcimx6ul_eth2_driver.c
drivers/mac/mcimx6ul_eth2_driver.h
drivers/mac/mimxrt1020_eth_driver.c
drivers/mac/mimxrt1020_eth_driver.h
drivers/mac/mimxrt1050_eth_driver.c
drivers/mac/mimxrt1050_eth_driver.h
drivers/mac/mimxrt1060_eth_driver.c
drivers/mac/mimxrt1060_eth_driver.h
drivers/mac/mk6x_eth_driver.c
drivers/mac/mk6x_eth_driver.h
drivers/mac/mk7x_eth_driver.c
drivers/mac/mk7x_eth_driver.h
drivers/mac/mkv5x_eth_driver.c
drivers/mac/mkv5x_eth_driver.h
drivers/mac/mpc57xx_eth_driver.c
drivers/mac/mpc57xx_eth_driver.h
drivers/mac/mpfsxxx_eth1_driver.c
drivers/mac/mpfsxxx_eth1_driver.h
drivers/mac/mpfsxxx_eth2_driver.c
drivers/mac/mpfsxxx_eth2_driver.h
drivers/mac/msp432e4_eth_driver.c
drivers/mac/msp432e4_eth_driver.h
drivers/mac/nuc472_eth_driver.c
drivers/mac/nuc472_eth_driver.h
drivers/mac/omapl138_eth_driver.c
drivers/mac/omapl138_eth_driver.h
drivers/mac/pic32mx_eth_driver.c
drivers/mac/pic32mx_eth_driver.h
drivers/mac/pic32mz_eth_driver.c
drivers/mac/pic32mz_eth_driver.h
drivers/mac/ra6m3_eth_driver.c
drivers/mac/ra6m3_eth_driver.h
drivers/mac/rx62n_eth_driver.c
drivers/mac/rx62n_eth_driver.h
drivers/mac/rx63n_eth_driver.c
drivers/mac/rx63n_eth_driver.h
drivers/mac/rza1_eth_driver.c
drivers/mac/rza1_eth_driver.h
drivers/mac/s32k148_eth_driver.c
drivers/mac/s32k148_eth_driver.h
drivers/mac/s5d9_eth_driver.c
drivers/mac/s5d9_eth_driver.h
drivers/mac/s7g2_eth_driver.c
drivers/mac/s7g2_eth_driver.h
drivers/mac/sam3x_eth_driver.c
drivers/mac/sam3x_eth_driver.h
drivers/mac/sam4e_eth_driver.c
drivers/mac/sam4e_eth_driver.h
drivers/mac/sam7x_eth_driver.c
drivers/mac/sam7x_eth_driver.h
drivers/mac/sam9263_eth_driver.c
drivers/mac/sam9263_eth_driver.h
drivers/mac/sama5d2_eth_driver.c
drivers/mac/sama5d2_eth_driver.h
drivers/mac/sama5d3_eth_driver.c
drivers/mac/sama5d3_eth_driver.h
drivers/mac/sama5d3_geth_driver.c
drivers/mac/sama5d3_geth_driver.h
drivers/mac/same54_eth_driver.c
drivers/mac/same54_eth_driver.h
drivers/mac/same70_eth_driver.c
drivers/mac/same70_eth_driver.h
drivers/mac/samv71_eth_driver.c
drivers/mac/samv71_eth_driver.h
drivers/mac/stm32f1xx_eth_driver.c
drivers/mac/stm32f1xx_eth_driver.h
drivers/mac/stm32f2xx_eth_driver.c
drivers/mac/stm32f2xx_eth_driver.h
drivers/mac/stm32f4xx_eth_driver.c
drivers/mac/stm32f4xx_eth_driver.h
drivers/mac/stm32f7xx_eth_driver.c
drivers/mac/stm32f7xx_eth_driver.h
drivers/mac/stm32h7xx_eth_driver.c
drivers/mac/stm32h7xx_eth_driver.h
drivers/mac/stm32mp1xx_eth_driver.c
drivers/mac/stm32mp1xx_eth_driver.h
drivers/mac/str912_eth_driver.c
drivers/mac/str912_eth_driver.h
drivers/mac/tm4c129_eth_driver.c
drivers/mac/tm4c129_eth_driver.h
drivers/mac/tms570_eth_driver.c
drivers/mac/tms570_eth_driver.h
drivers/mac/xmc4400_eth_driver.c
drivers/mac/xmc4400_eth_driver.h
drivers/mac/xmc4500_eth_driver.c
drivers/mac/xmc4500_eth_driver.h
drivers/mac/xmc4700_eth_driver.c
drivers/mac/xmc4700_eth_driver.h
drivers/mac/xmc4800_eth_driver.c
drivers/mac/xmc4800_eth_driver.h
drivers/mac/zynq7000_eth_driver.c
drivers/mac/zynq7000_eth_driver.h
drivers/pcap/pcap_driver.c
drivers/pcap/pcap_driver.h
drivers/phy/ar8031_driver.c
drivers/phy/ar8031_driver.h
drivers/phy/ar8035_driver.c
drivers/phy/ar8035_driver.h
drivers/phy/dm9161_driver.c
drivers/phy/dm9161_driver.h
drivers/phy/dp83620_driver.c
drivers/phy/dp83620_driver.h
drivers/phy/dp83630_driver.c
drivers/phy/dp83630_driver.h
drivers/phy/dp83640_driver.c
drivers/phy/dp83640_driver.h
drivers/phy/dp83822_driver.c
drivers/phy/dp83822_driver.h
drivers/phy/dp83848_driver.c
drivers/phy/dp83848_driver.h
drivers/phy/dp83tc811_driver.c
drivers/phy/dp83tc811_driver.h
drivers/phy/ip101_driver.c
drivers/phy/ip101_driver.h
drivers/phy/ksz8031_driver.c
drivers/phy/ksz8031_driver.h
drivers/phy/ksz8041_driver.c
drivers/phy/ksz8041_driver.h
drivers/phy/ksz8051_driver.c
drivers/phy/ksz8051_driver.h
drivers/phy/ksz8061_driver.c
drivers/phy/ksz8061_driver.h
drivers/phy/ksz8081_driver.c
drivers/phy/ksz8081_driver.h
drivers/phy/ksz8091_driver.c
drivers/phy/ksz8091_driver.h
drivers/phy/ksz8721_driver.c
drivers/phy/ksz8721_driver.h
drivers/phy/ksz9031_driver.c
drivers/phy/ksz9031_driver.h
drivers/phy/ksz9131_driver.c
drivers/phy/ksz9131_driver.h
drivers/phy/lan8700_driver.c
drivers/phy/lan8700_driver.h
drivers/phy/lan8710_driver.c
drivers/phy/lan8710_driver.h
drivers/phy/lan8720_driver.c
drivers/phy/lan8720_driver.h
drivers/phy/lan8740_driver.c
drivers/phy/lan8740_driver.h
drivers/phy/lan8742_driver.c
drivers/phy/lan8742_driver.h
drivers/phy/lan8770_driver.c
drivers/phy/lan8770_driver.h
drivers/phy/mv88e1512_driver.c
drivers/phy/mv88e1512_driver.h
drivers/phy/pef7071_driver.c
drivers/phy/pef7071_driver.h
drivers/phy/rtl8211e_driver.c
drivers/phy/rtl8211e_driver.h
drivers/phy/rtl8211f_driver.c
drivers/phy/rtl8211f_driver.h
drivers/phy/st802rt1a_driver.c
drivers/phy/st802rt1a_driver.h
drivers/phy/tja1100_driver.c
drivers/phy/tja1100_driver.h
drivers/phy/tja1101_driver.c
drivers/phy/tja1101_driver.h
drivers/phy/upd60611_driver.c
drivers/phy/upd60611_driver.h
drivers/switch/ksz8463_driver.c
drivers/switch/ksz8463_driver.h
drivers/switch/ksz8563_driver.c
drivers/switch/ksz8563_driver.h
drivers/switch/ksz8775_driver.c
drivers/switch/ksz8775_driver.h
drivers/switch/ksz8794_driver.c
drivers/switch/ksz8794_driver.h
drivers/switch/ksz8795_driver.c
drivers/switch/ksz8795_driver.h
drivers/switch/ksz8863_driver.c
drivers/switch/ksz8863_driver.h
drivers/switch/ksz8864_driver.c
drivers/switch/ksz8864_driver.h
drivers/switch/ksz8873_driver.c
drivers/switch/ksz8873_driver.h
drivers/switch/ksz8895_driver.c
drivers/switch/ksz8895_driver.h
drivers/switch/ksz9477_driver.c
drivers/switch/ksz9477_driver.h
drivers/switch/ksz9563_driver.c
drivers/switch/ksz9563_driver.h
drivers/switch/ksz9893_driver.c
drivers/switch/ksz9893_driver.h
drivers/switch/ksz9897_driver.c
drivers/switch/ksz9897_driver.h
drivers/switch/lan9303_driver.c
drivers/switch/lan9303_driver.h
drivers/switch/mv88e6060_driver.c
drivers/switch/mv88e6060_driver.h
drivers/usb_rndis/rndis.c
drivers/usb_rndis/rndis.h
drivers/usb_rndis/rndis_debug.c
drivers/usb_rndis/rndis_debug.h
drivers/usb_rndis/rndis_driver.c
drivers/usb_rndis/rndis_driver.h
drivers/usb_rndis/usbd_desc.c
drivers/usb_rndis/usbd_desc.h
drivers/usb_rndis/usbd_rndis.c
drivers/usb_rndis/usbd_rndis.h
drivers/wifi/bcm43362_driver.c
drivers/wifi/bcm43362_driver.h
drivers/wifi/esp32_wifi_driver.c
drivers/wifi/esp32_wifi_driver.h
drivers/wifi/esp8266_driver.c
drivers/wifi/esp8266_driver.h
drivers/wifi/mrf24wg_driver.c
drivers/wifi/mrf24wg_driver.h
drivers/wifi/wf200_driver.c
drivers/wifi/wf200_driver.h
drivers/wifi/wilc1000_driver.c
drivers/wifi/wilc1000_driver.h
drivers/wifi/winc1500_driver.c
drivers/wifi/winc1500_driver.h
ftp/ftp_client.c
ftp/ftp_client.h
ftp/ftp_client_misc.c
ftp/ftp_client_misc.h
ftp/ftp_client_transport.c
ftp/ftp_client_transport.h
ftp/ftp_server.c
ftp/ftp_server.h
ftp/ftp_server_commands.c
ftp/ftp_server_commands.h
ftp/ftp_server_control.c
ftp/ftp_server_control.h
ftp/ftp_server_data.c
ftp/ftp_server_data.h
ftp/ftp_server_misc.c
ftp/ftp_server_misc.h
ftp/ftp_server_transport.c
ftp/ftp_server_transport.h
http/http_client.c
http/http_client.h
http/http_client_auth.c
http/http_client_auth.h
http/http_client_misc.c
http/http_client_misc.h
http/http_client_transport.c
http/http_client_transport.h
http/http_common.c
http/http_common.h
http/http_server.c
http/http_server.h
http/http_server_auth.c
http/http_server_auth.h
http/http_server_misc.c
http/http_server_misc.h
http/mime.c
http/mime.h
http/ssi.c
http/ssi.h
icecast/icecast_client.c
icecast/icecast_client.h
ipv4/arp.c
ipv4/arp.h
ipv4/auto_ip.c
ipv4/auto_ip.h
ipv4/icmp.c
ipv4/icmp.h
ipv4/igmp.c
ipv4/igmp.h
ipv4/ipv4.c
ipv4/ipv4.h
ipv4/ipv4_frag.c
ipv4/ipv4_frag.h
ipv4/ipv4_misc.c
ipv4/ipv4_misc.h
ipv4/ipv4_routing.h
ipv6/icmpv6.c
ipv6/icmpv6.h
ipv6/ipv6.c
ipv6/ipv6.h
ipv6/ipv6_frag.c
ipv6/ipv6_frag.h
ipv6/ipv6_misc.c
ipv6/ipv6_misc.h
ipv6/ipv6_pmtu.c
ipv6/ipv6_pmtu.h
ipv6/ipv6_routing.c
ipv6/ipv6_routing.h
ipv6/mld.c
ipv6/mld.h
ipv6/ndp.c
ipv6/ndp.h
ipv6/ndp_cache.c
ipv6/ndp_cache.h
ipv6/ndp_misc.c
ipv6/ndp_misc.h
ipv6/ndp_router_adv.c
ipv6/ndp_router_adv.h
ipv6/slaac.c
ipv6/slaac.h
llmnr/llmnr_client.c
llmnr/llmnr_client.h
llmnr/llmnr_common.c
llmnr/llmnr_common.h
llmnr/llmnr_responder.c
llmnr/llmnr_responder.h
mdns/mdns_client.c
mdns/mdns_client.h
mdns/mdns_common.c
mdns/mdns_common.h
mdns/mdns_responder.c
mdns/mdns_responder.h
mibs/if_mib_impl.c
mibs/if_mib_impl.h
mibs/if_mib_module.c
mibs/if_mib_module.h
mibs/ip_mib_impl.c
mibs/ip_mib_impl.h
mibs/ip_mib_module.c
mibs/ip_mib_module.h
mibs/mib2_impl.c
mibs/mib2_impl.h
mibs/mib2_module.c
mibs/mib2_module.h
mibs/mib_common.c
mibs/mib_common.h
mibs/snmp_community_mib_impl.c
mibs/snmp_community_mib_impl.h
mibs/snmp_community_mib_module.c
mibs/snmp_community_mib_module.h
mibs/snmp_framework_mib_impl.c
mibs/snmp_framework_mib_impl.h
mibs/snmp_framework_mib_module.c
mibs/snmp_framework_mib_module.h
mibs/snmp_mib_impl.c
mibs/snmp_mib_impl.h
mibs/snmp_mib_module.c
mibs/snmp_mib_module.h
mibs/snmp_mpd_mib_impl.c
mibs/snmp_mpd_mib_impl.h
mibs/snmp_mpd_mib_module.c
mibs/snmp_mpd_mib_module.h
mibs/snmp_usm_mib_impl.c
mibs/snmp_usm_mib_impl.h
mibs/snmp_usm_mib_module.c
mibs/snmp_usm_mib_module.h
mibs/snmp_vacm_mib_impl.c
mibs/snmp_vacm_mib_impl.h
mibs/snmp_vacm_mib_module.c
mibs/snmp_vacm_mib_module.h
mibs/tcp_mib_impl.c
mibs/tcp_mib_impl.h
mibs/tcp_mib_module.c
mibs/tcp_mib_module.h
mibs/udp_mib_impl.c
mibs/udp_mib_impl.h
mibs/udp_mib_module.c
mibs/udp_mib_module.h
modbus/modbus_client.c
modbus/modbus_client.h
modbus/modbus_client_misc.c
modbus/modbus_client_misc.h
modbus/modbus_client_pdu.c
modbus/modbus_client_pdu.h
modbus/modbus_client_transport.c
modbus/modbus_client_transport.h
modbus/modbus_common.h
modbus/modbus_debug.c
modbus/modbus_debug.h
modbus/modbus_server.c
modbus/modbus_server.h
modbus/modbus_server_misc.c
modbus/modbus_server_misc.h
modbus/modbus_server_pdu.c
modbus/modbus_server_pdu.h
modbus/modbus_server_security.c
modbus/modbus_server_security.h
modbus/modbus_server_transport.c
modbus/modbus_server_transport.h
mqtt/mqtt_client.c
mqtt/mqtt_client.h
mqtt/mqtt_client_misc.c
mqtt/mqtt_client_misc.h
mqtt/mqtt_client_packet.c
mqtt/mqtt_client_packet.h
mqtt/mqtt_client_transport.c
mqtt/mqtt_client_transport.h
mqtt/mqtt_common.h
mqtt_sn/mqtt_sn_client.c
mqtt_sn/mqtt_sn_client.h
mqtt_sn/mqtt_sn_client_message.c
mqtt_sn/mqtt_sn_client_message.h
mqtt_sn/mqtt_sn_client_misc.c
mqtt_sn/mqtt_sn_client_misc.h
mqtt_sn/mqtt_sn_client_transport.c
mqtt_sn/mqtt_sn_client_transport.h
mqtt_sn/mqtt_sn_common.h
mqtt_sn/mqtt_sn_debug.c
mqtt_sn/mqtt_sn_debug.h
mqtt_sn/mqtt_sn_message.c
mqtt_sn/mqtt_sn_message.h
netbios/nbns_client.c
netbios/nbns_client.h
netbios/nbns_common.c
netbios/nbns_common.h
netbios/nbns_responder.c
netbios/nbns_responder.h
ppp/chap.c
ppp/chap.h
ppp/ipcp.c
ppp/ipcp.h
ppp/ipv6cp.c
ppp/ipv6cp.h
ppp/lcp.c
ppp/lcp.h
ppp/pap.c
ppp/pap.h
ppp/ppp.c
ppp/ppp.h
ppp/ppp_debug.c
ppp/ppp_debug.h
ppp/ppp_fsm.c
ppp/ppp_fsm.h
ppp/ppp_hdlc.c
ppp/ppp_hdlc.h
ppp/ppp_misc.c
ppp/ppp_misc.h
smtp/smtp_client.c
smtp/smtp_client.h
smtp/smtp_client_auth.c
smtp/smtp_client_auth.h
smtp/smtp_client_misc.c
smtp/smtp_client_misc.h
smtp/smtp_client_transport.c
smtp/smtp_client_transport.h
snmp/snmp_agent.c
snmp/snmp_agent.h
snmp/snmp_agent_dispatch.c
snmp/snmp_agent_dispatch.h
snmp/snmp_agent_inform.c
snmp/snmp_agent_inform.h
snmp/snmp_agent_message.c
snmp/snmp_agent_message.h
snmp/snmp_agent_misc.c
snmp/snmp_agent_misc.h
snmp/snmp_agent_object.c
snmp/snmp_agent_object.h
snmp/snmp_agent_pdu.c
snmp/snmp_agent_pdu.h
snmp/snmp_agent_trap.c
snmp/snmp_agent_trap.h
snmp/snmp_agent_usm.c
snmp/snmp_agent_usm.h
snmp/snmp_agent_vacm.c
snmp/snmp_agent_vacm.h
snmp/snmp_common.h
sntp/ntp_common.h
sntp/sntp_client.c
sntp/sntp_client.h
sntp/sntp_client_misc.c
sntp/sntp_client_misc.h
tftp/tftp_client.c
tftp/tftp_client.h
tftp/tftp_client_misc.c
tftp/tftp_client_misc.h
tftp/tftp_common.h
tftp/tftp_server.c
tftp/tftp_server.h
tftp/tftp_server_misc.c
tftp/tftp_server_misc.h
web_socket/web_socket.c
web_socket/web_socket.h
web_socket/web_socket_auth.c
web_socket/web_socket_auth.h
web_socket/web_socket_frame.c
web_socket/web_socket_frame.h
web_socket/web_socket_misc.c
web_socket/web_socket_misc.h
web_socket/web_socket_transport.c
web_socket/web_socket_transport.h
Commit message: Version 2.0.2


Vulnerable code:
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Pointer to the CoAP request
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @param[in] request Pointer to the request message
   //Sucessful processing
   //Sucessful processing
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * @param[in] message Pointer to the CoAP message
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @param[in] context Pointer to the TLS context
 * @param[in] clientParams Client parameters
 * @param[in] param An opaque pointer provided by the user
 * @param[in] handle An opaque pointer specified by the user
 * @param[in] params Client parameters
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @param[out] info Address of the specified host
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   ETH_TYPE_VMAN  = 0x88A8
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   if(strchr(str, ':'))
   if(strchr(str, '.'))
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
#define CYCLONE_TCP_VERSION_STRING "2.0.0"
#define CYCLONE_TCP_REV_NUMBER 0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   //Gather entropy
   netContext.entropy += netGetSystemTickCount();

 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   //The socket may be bound to a particular network interface
   interface = socket->interface;
   if(socket->interface != NULL)
 * @param[out] srcIpAddr Source IP address (optional)
 * @param[out] destIpAddr Destination IP address (optional)
 * @param[out] data Buffer where to store the incoming data
 * @param[in] size Maximum number of bytes that can be received
 * @param[out] received Number of bytes that have been received
 * @param[out] data Buffer where to store the incoming data
 * @param[in] size Maximum number of bytes that can be received
 * @param[out] received Number of bytes that have been received
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
         else if(n <= 15 && !strchr(name, '.') && type == HOST_TYPE_IPV4)
         else if(!strchr(name, '.'))
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   void *data;             ///<Pointer to the payload
   size_t size;            ///<Size of the payload, in bytes
   size_t length;          ///<Actual length of the payload, in bytes
   uint8_t ttl;            ///<Time-to-live value
   IpAddr srcIpAddr;       ///<Source IP address
   uint16_t srcPort;       ///<Source port
   IpAddr destIpAddr;      ///<Destination IP address
   uint16_t destPort;      ///<Destination port
   MacAddr srcMacAddr;     ///<Source MAC address
   MacAddr destMacAddr;    ///<Destination MAC address
   uint8_t switchPort;     ///<Switch port identifier
   int32_t timestampId;    ///<Unique identifier for hardware time stamping
   NetTimestamp timestamp; ///<Captured time stamp
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   uint_t i;
   //Length of the complete option field
   //Make sure there is enough space to add the specified option
   if((segment->dataOffset * 4 + length) > TCP_MAX_HEADER_LENGTH)
      return ERROR_FAILURE;
   //Index of the first available byte
   i = segment->dataOffset * 4 - sizeof(TcpHeader);
   //Calculate the number of padding bytes
   paddingSize = (length % 4) ? 4 - (length % 4) : 0;
   //Write padding bytes
   while(paddingSize--)
      segment->options[i++] = TCP_OPTION_NOP;
   //Point to the current location
   option = (TcpOption *) (segment->options + i);
   //Write specified option
   option->kind = kind;
   option->length = length;
   osMemcpy(option->value, value, length - sizeof(TcpOption));
   //Adjust index value
   i += length;
   //Update TCP header length
   segment->dataOffset = (sizeof(TcpHeader) + i) / 4;
   //Option successfully added
   return NO_ERROR;
   uint_t i;
   if(segment->dataOffset < 5)
      return NULL;
   //Compute the length of the options field
   length = segment->dataOffset * 4 - sizeof(TcpHeader);
   //Point to the very first option
   i = 0;
   //Parse TCP options
   while(i < length)
   {
      //Point to the current option
      option = (TcpOption *) (segment->options + i);
      //NOP option detected?
      if(option->kind == TCP_OPTION_NOP)
      {
         i++;
         continue;
      }
      //END option detected?
      if(option->kind == TCP_OPTION_END)
         break;
      //Check option length
      if((i + 1) >= length || (i + option->length) > length)
         break;
      //Current option kind match the specified one?
      if(option->kind == kind)
         return option;
      //Jump to next the next option
      i += option->length;
   //Specified option code not found
      //If an incoming segment is not acceptable, an acknowledgment
      //should be sent in reply (unless the RST bit is set)
         tcpSendSegment(socket, TCP_FLAG_ACK, socket->sndNxt, socket->rcvNxt, 0, FALSE);
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      error = udpSendBuffer(socket->interface, &message->srcIpAddr,
         socket->localPort, &message->destIpAddr, message->destPort, buffer,
         offset, &ancillary);
 * @param[out] srcIpAddr Source IP address (optional)
 * @param[out] srcPort Source port number (optional)
 * @param[out] destIpAddr Destination IP address (optional)
 * @param[out] data Buffer where to store the incoming data
 * @param[in] size Maximum number of bytes that can be received
 * @param[out] received Number of bytes that have been received
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   if(length < sizeof(DhcpMessage))
      return;
   if(length > DHCP_MAX_MSG_SIZE)
 * @return Error code
 * @return Error code
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      //Jump to next the next option
      //Jump to next the next option
   uint_t i;
   if(length < sizeof(DhcpMessage))
      return NULL;
   //Get the length of the options field
   length -= sizeof(DhcpMessage);

   //Parse DHCP options
   for(i = 0; i < length; i++)
      //Point to the current option
      option = (DhcpOption *) (message->options + i);

      //Pad option detected?
      if(option->code == DHCP_OPT_PAD)
         continue;
      //End option detected?
      if(option->code == DHCP_OPT_END)
         break;
      //Check option length
      if((i + 1) >= length || (i + 1 + option->length) >= length)
         break;

      //Current option code matches the specified one?
      if(option->code == optionCode)
         return option;

      //Jump to the next option
      i += option->length + 1;
   //Specified option code not found
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      //Sucessful processing
               //Sucessful processing
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   uint8_t chipRevision;
   vendorId = (dm9000ReadReg(DM9000_REG_VIDH) << 8) | dm9000ReadReg(DM9000_REG_VIDL);
   productId = (dm9000ReadReg(DM9000_REG_PIDH) << 8) | dm9000ReadReg(DM9000_REG_PIDL);
   chipRevision = dm9000ReadReg(DM9000_REG_CHIPR);
   if(chipRevision != DM9000A_CHIP_REV && chipRevision != DM9000B_CHIP_REV)
   dm9000WriteReg(DM9000_REG_GPR, 0x00);
   dm9000WriteReg(DM9000_REG_NCR, NCR_RST);
   while((dm9000ReadReg(DM9000_REG_NCR) & NCR_RST) != 0)
   dm9000WritePhyReg(DM9000_PHY_REG_BMCR, BMCR_RST);
   while((dm9000ReadPhyReg(DM9000_PHY_REG_BMCR) & BMCR_RST) != 0)
   TRACE_INFO("  CHIPR = 0x%02" PRIX8 "\r\n", chipRevision);
   TRACE_INFO("  PHYIDR1 = 0x%04" PRIX16 "\r\n", dm9000ReadPhyReg(DM9000_PHY_REG_PHYIDR1));
   TRACE_INFO("  PHYIDR2 = 0x%04" PRIX16 "\r\n", dm9000ReadPhyReg(DM9000_PHY_REG_PHYIDR2));
   dm9000WriteReg(DM9000_REG_NCR, DM9000_LBK_PHY);
   dm9000WritePhyReg(DM9000_PHY_REG_BMCR, BMCR_LOOPBACK | BMCR_SPEED_SEL | BMCR_AN_EN | BMCR_DUPLEX_MODE);
      dm9000WriteReg(DM9000_REG_PAR0 + i, interface->macAddr.b[i]);
      dm9000WriteReg(DM9000_REG_MAR0 + i, 0x00);
   dm9000WriteReg(DM9000_REG_MAR7, 0x80);
   dm9000WriteReg(DM9000_REG_IMR, IMR_PAR);
   dm9000WriteReg(DM9000_REG_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
   dm9000WriteReg(DM9000_REG_ISR, ISR_LNKCHG | ISR_UDRUN | ISR_ROO | ISR_ROS | ISR_PT | ISR_PR);
   dm9000WriteReg(DM9000_REG_IMR, IMR_PAR | IMR_LNKCHGI | IMR_PTI | IMR_PRI);
   dm9000WriteReg(DM9000_REG_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
   status = dm9000ReadReg(DM9000_REG_ISR);
   if((status & ISR_LNKCHG) != 0)
      mask = dm9000ReadReg(DM9000_REG_IMR);
      dm9000WriteReg(DM9000_REG_IMR, mask & ~IMR_LNKCHGI);
   if((status & ISR_PT) != 0)
      if(dm9000ReadReg(DM9000_REG_NSR) & (NSR_TX2END | NSR_TX1END))
      dm9000WriteReg(DM9000_REG_ISR, ISR_PT);
   if((status & ISR_PR) != 0)
      mask = dm9000ReadReg(DM9000_REG_IMR);
      dm9000WriteReg(DM9000_REG_IMR, mask & ~IMR_PRI);
   status = dm9000ReadReg(DM9000_REG_ISR);
   if((status & ISR_LNKCHG) != 0)
      dm9000WriteReg(DM9000_REG_ISR, ISR_LNKCHG);
      status = dm9000ReadReg(DM9000_REG_NSR);
      if((status & NSR_LINKST) != 0)
         if((status & NSR_SPEED) != 0)
         status = dm9000ReadReg(DM9000_REG_NCR);
         if((status & NCR_FDX) != 0)
   if((status & ISR_PR) != 0)
      dm9000WriteReg(DM9000_REG_ISR, ISR_PR);
   dm9000WriteReg(DM9000_REG_IMR, IMR_PAR | IMR_LNKCHGI | IMR_PTI | IMR_PRI);
   dm9000WriteReg(DM9000_REG_MWCMDX, 0);
   DM9000_INDEX_REG = DM9000_REG_MWCMD;
   dm9000WriteReg(DM9000_REG_TXPLL, LSB(length));
   dm9000WriteReg(DM9000_REG_TXPLH, MSB(length));
   dm9000WriteReg(DM9000_REG_ISR, ISR_PT);
   dm9000WriteReg(DM9000_REG_TCR, TCR_TXREQ);
   data = dm9000ReadReg(DM9000_REG_MRCMDX);
   DM9000_INDEX_REG = DM9000_REG_MRCMDX1;
      DM9000_INDEX_REG = DM9000_REG_MRCMD;
      if((status & (RSR_LCS | RSR_RWTO | RSR_PLE | RSR_AE | RSR_CE | RSR_FOE)) == 0)
      dm9000WriteReg(DM9000_REG_MAR0 + i, hashTable[i]);
      dm9000ReadReg(DM9000_REG_MAR0), dm9000ReadReg(DM9000_REG_MAR1),
      dm9000ReadReg(DM9000_REG_MAR2), dm9000ReadReg(DM9000_REG_MAR3),
      dm9000ReadReg(DM9000_REG_MAR4), dm9000ReadReg(DM9000_REG_MAR5),
      dm9000ReadReg(DM9000_REG_MAR6), dm9000ReadReg(DM9000_REG_MAR7));
   dm9000WriteReg(DM9000_REG_EPAR, 0x40 | address);
   dm9000WriteReg(DM9000_REG_EPDRL, LSB(data));
   dm9000WriteReg(DM9000_REG_EPDRH, MSB(data));
   dm9000WriteReg(DM9000_REG_EPCR, EPCR_EPOS | EPCR_ERPRW);
   while((dm9000ReadReg(DM9000_REG_EPCR) & EPCR_ERRE) != 0)
   dm9000WriteReg(DM9000_REG_EPCR, EPCR_EPOS);
   dm9000WriteReg(DM9000_REG_EPAR, 0x40 | address);
   dm9000WriteReg(DM9000_REG_EPCR, EPCR_EPOS | EPCR_ERPRR);
   while((dm9000ReadReg(DM9000_REG_EPCR) & EPCR_ERRE) != 0)
   dm9000WriteReg(DM9000_REG_EPCR, EPCR_EPOS);
   return (dm9000ReadReg(DM9000_REG_EPDRH) << 8) | dm9000ReadReg(DM9000_REG_EPDRL);
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
//DM9000 bus timing
#define AT91C_SMC2_NWS_2        (2 << 0)
#define AT91C_SMC2_TDF_2        (2 << 8)
#define AT91C_SMC2_BAT_16       (1 << 12)
#define AT91C_SMC2_DRP_STANDARD (0 << 15)
#define AT91C_SMC2_RWSETUP_1    (1 << 24)
#define AT91C_SMC2_RWHOLD_1     (1 << 28)

#define DM9000_VID             0x0A46
#define DM9000_PID             0x9000
#define DM9000A_CHIP_REV       0x19
#define DM9000B_CHIP_REV       0x1A
#define DM9000_REG_NCR         0x00
#define DM9000_REG_NSR         0x01
#define DM9000_REG_TCR         0x02
#define DM9000_REG_TSR1        0x03
#define DM9000_REG_TSR2        0x04
#define DM9000_REG_RCR         0x05
#define DM9000_REG_RSR         0x06
#define DM9000_REG_ROCR        0x07
#define DM9000_REG_BPTR        0x08
#define DM9000_REG_FCTR        0x09
#define DM9000_REG_FCR         0x0A
#define DM9000_REG_EPCR        0x0B
#define DM9000_REG_EPAR        0x0C
#define DM9000_REG_EPDRL       0x0D
#define DM9000_REG_EPDRH       0x0E
#define DM9000_REG_WCR         0x0F
#define DM9000_REG_PAR0        0x10
#define DM9000_REG_PAR1        0x11
#define DM9000_REG_PAR2        0x12
#define DM9000_REG_PAR3        0x13
#define DM9000_REG_PAR4        0x14
#define DM9000_REG_PAR5        0x15
#define DM9000_REG_MAR0        0x16
#define DM9000_REG_MAR1        0x17
#define DM9000_REG_MAR2        0x18
#define DM9000_REG_MAR3        0x19
#define DM9000_REG_MAR4        0x1A
#define DM9000_REG_MAR5        0x1B
#define DM9000_REG_MAR6        0x1C
#define DM9000_REG_MAR7        0x1D
#define DM9000_REG_GPCR        0x1E
#define DM9000_REG_GPR         0x1F
#define DM9000_REG_TRPAL       0x22
#define DM9000_REG_TRPAH       0x23
#define DM9000_REG_RWPAL       0x24
#define DM9000_REG_RWPAH       0x25
#define DM9000_REG_VIDL        0x28
#define DM9000_REG_VIDH        0x29
#define DM9000_REG_PIDL        0x2A
#define DM9000_REG_PIDH        0x2B
#define DM9000_REG_CHIPR       0x2C
#define DM9000_REG_TCR2        0x2D
#define DM9000_REG_OCR         0x2E
#define DM9000_REG_SMCR        0x2F
#define DM9000_REG_ETXCSR      0x30
#define DM9000_REG_TCSCR       0x31
#define DM9000_REG_RCSCSR      0x32
#define DM9000_REG_MPAR        0x33
#define DM9000_REG_LEDCR       0x34
#define DM9000_REG_BUSCR       0x38
#define DM9000_REG_INTCR       0x39
#define DM9000_REG_SCCR        0x50
#define DM9000_REG_RSCCR       0x51
#define DM9000_REG_MRCMDX      0xF0
#define DM9000_REG_MRCMDX1     0xF1
#define DM9000_REG_MRCMD       0xF2
#define DM9000_REG_MRRL        0xF4
#define DM9000_REG_MRRH        0xF5
#define DM9000_REG_MWCMDX      0xF6
#define DM9000_REG_MWCMD       0xF8
#define DM9000_REG_MWRL        0xFA
#define DM9000_REG_MWRH        0xFB
#define DM9000_REG_TXPLL       0xFC
#define DM9000_REG_TXPLH       0xFD
#define DM9000_REG_ISR         0xFE
#define DM9000_REG_IMR         0xFF
#define DM9000_PHY_REG_BMCR    0x00
#define DM9000_PHY_REG_BMSR    0x01
#define DM9000_PHY_REG_PHYIDR1 0x02
#define DM9000_PHY_REG_PHYIDR2 0x03
#define DM9000_PHY_REG_ANAR    0x04
#define DM9000_PHY_REG_ANLPAR  0x05
#define DM9000_PHY_REG_ANER    0x06
#define DM9000_PHY_REG_DSCR    0x10
#define DM9000_PHY_REG_DSCSR   0x11
#define DM9000_PHY_REG_10BTCSR 0x12
#define DM9000_PHY_REG_PWDOR   0x13
#define DM9000_PHY_REG_SCR     0x14
#define DM9000_PHY_REG_DSP     0x1B
#define DM9000_PHY_REG_PSCR    0x1D

//NCR register
#define NCR_WAKEEN         (1 << 6)
#define NCR_FCOL           (1 << 4)
#define NCR_FDX            (1 << 3)
#define NCR_LBK            (3 << 1)
#define NCR_RST            (1 << 0)

//NSR register
#define NSR_SPEED          (1 << 7)
#define NSR_LINKST         (1 << 6)
#define NSR_WAKEST         (1 << 5)
#define NSR_TX2END         (1 << 3)
#define NSR_TX1END         (1 << 2)
#define NSR_RXOV           (1 << 1)

//TCR register
#define TCR_TJDIS          (1 << 6)
#define TCR_EXCECM         (1 << 5)
#define TCR_PAD_DIS2       (1 << 4)
#define TCR_CRC_DIS2       (1 << 3)
#define TCR_PAD_DIS1       (1 << 2)
#define TCR_CRC_DIS1       (1 << 1)
#define TCR_TXREQ          (1 << 0)

//TSR1 and TSR2 registers
#define TSR_TJTO           (1 << 7)
#define TSR_LC             (1 << 6)
#define TSR_NC             (1 << 5)
#define TSR_LCOL           (1 << 4)
#define TSR_COL            (1 << 3)
#define TSR_EC             (1 << 2)

//RCR register
#define RCR_WTDIS          (1 << 6)
#define RCR_DIS_LONG       (1 << 5)
#define RCR_DIS_CRC        (1 << 4)
#define RCR_ALL            (1 << 3)
#define RCR_RUNT           (1 << 2)
#define RCR_PRMSC          (1 << 1)
#define RCR_RXEN           (1 << 0)

//RSR register
#define RSR_RF             (1 << 7)
#define RSR_MF             (1 << 6)
#define RSR_LCS            (1 << 5)
#define RSR_RWTO           (1 << 4)
#define RSR_PLE            (1 << 3)
#define RSR_AE             (1 << 2)
#define RSR_CE             (1 << 1)
#define RSR_FOE            (1 << 0)

//ROCR register
#define ROCR_ROC           (127 << 0)
#define ROCR_RXFU          (1 << 7)

//BPTR register
#define BPTR_BPHW          (15 << 4)
#define BPTR_JPT           (15 << 0)

//FCTR register
#define FCTR_HWOT          (15 << 4)
#define FCTR_LWOT          (15 << 0)

//FCR register
#define FCR_TXP0           (1 << 7)
#define FCR_TXPF           (1 << 6)
#define FCR_TXPEN          (1 << 5)
#define FCR_BKPA           (1 << 4)
#define FCR_BKPM           (1 << 3)
#define FCR_RXPS           (1 << 2)
#define FCR_RXPCS          (1 << 1)
#define FCR_FLCE           (1 << 0)

//EPCR register
#define EPCR_REEP          (1 << 5)
#define EPCR_WEP           (1 << 4)
#define EPCR_EPOS          (1 << 3)
#define EPCR_ERPRR         (1 << 2)
#define EPCR_ERPRW         (1 << 1)
#define EPCR_ERRE          (1 << 0)

//EPAR register
#define EPAR_PHY_ADR       (3 << 6)
#define EPAR_EROA          (31 << 0)

//WCR register
#define WCR_LINKEN         (1 << 5)
#define WCR_SAMPLEEN       (1 << 4)
#define WCR_MAGICEN        (1 << 3)
#define WCR_LINKST         (1 << 2)
#define WCR_SAMPLEST       (1 << 1)
#define WCR_MAGICST        (1 << 0)

//GPCR register
#define GPCR_GPC6          (1 << 6)
#define GPCR_GPC5          (1 << 5)
#define GPCR_GPC4          (1 << 4)
#define GPCR_GPC3          (1 << 3)
#define GPCR_GPC2          (1 << 2)
#define GPCR_GPC1          (1 << 1)

//GPR register
#define GPR_GPO6           (1 << 6)
#define GPR_GPO5           (1 << 5)
#define GPR_GPO4           (1 << 4)
#define GPR_GPIO3          (1 << 3)
#define GPR_GPIO2          (1 << 2)
#define GPR_GPIO1          (1 << 1)
#define GPR_PHYPD          (1 << 0)

//TCR2 register
#define TCR2_LED           (1 << 7)
#define TCR2_RLCP          (1 << 6)
#define TCR2_DTU           (1 << 5)
#define TCR2_ONEPM         (1 << 4)
#define TCR2_IFGS          (15 << 0)

//OCR register
#define OCR_SCC            (3 << 6)
#define OCR_SOE            (1 << 4)
#define OCR_SCS            (1 << 3)
#define OCR_PHYOP          (7 << 0)

//SMCR register
#define SMCR_SM_EN         (1 << 7)
#define SMCR_FLC           (1 << 2)
#define SMCR_FB1           (1 << 1)
#define SMCR_FB0           (1 << 0)

//ETXCSR register
#define ETXCSR_ETE         (1 << 7)
#define ETXCSR_ETS2        (1 << 6)
#define ETXCSR_ETS1        (1 << 5)
#define ETXCSR_ETT         (3 << 0)

//TCSCR register
#define TCSCR_UDPCSE       (1 << 2)
#define TCSCR_TCPCSE       (1 << 1)
#define TCSCR_IPCSE        (1 << 0)

//RCSCSR register
#define RCSCSR_UDPS        (1 << 7)
#define RCSCSR_TCPS        (1 << 6)
#define RCSCSR_IPS         (1 << 5)
#define RCSCSR_UDPP        (1 << 4)
#define RCSCSR_TCPP        (1 << 3)
#define RCSCSR_IPP         (1 << 2)
#define RCSCSR_RCSEN       (1 << 1)
#define RCSCSR_DCSE        (1 << 0)

//MPAR register
#define MPAR_ADR_EN        (1 << 7)
#define MPAR_EPHYADR       (31 << 0)

//LEDC register
#define LEDCR_GPIO         (1 << 1)
#define LEDCR_MII          (1 << 0)

//BUSCR register
#define BUSCR_CURR         (3 << 5)
#define BUSCR_EST          (1 << 3)
#define BUSCR_IOW_SPIKE    (1 << 1)
#define BUSCR_IOR_SPIKE    (1 << 0)

//INTCR register
#define INTCR_INT_TYPE     (1 << 1)
#define INTCR_INT_POL      (1 << 0)

//SCCR register
#define SCCR_DIS_CLK       (1 << 0)

//ISR register
#define ISR_IOMODE         (1 << 7)
#define ISR_LNKCHG         (1 << 5)
#define ISR_UDRUN          (1 << 4)
#define ISR_ROO            (1 << 3)
#define ISR_ROS            (1 << 2)
#define ISR_PT             (1 << 1)
#define ISR_PR             (1 << 0)

//IMR register
#define IMR_PAR            (1 << 7)
#define IMR_LNKCHGI        (1 << 5)
#define IMR_UDRUNI         (1 << 4)
#define IMR_ROOI           (1 << 3)
#define IMR_ROI            (1 << 2)
#define IMR_PTI            (1 << 1)
#define IMR_PRI            (1 << 0)

//PHY BMCR register
#define BMCR_RST           (1 << 15)
#define BMCR_LOOPBACK      (1 << 14)
#define BMCR_SPEED_SEL     (1 << 13)
#define BMCR_AN_EN         (1 << 12)
#define BMCR_PD            (1 << 11)
#define BMCR_ISOLATE       (1 << 10)
#define BMCR_RESTART_AN    (1 << 9)
#define BMCR_DUPLEX_MODE   (1 << 8)
#define BMCR_COL_TEST      (1 << 7)

//Loopback mode
#define DM9000_LBK_NORMAL  (0 << 1)
#define DM9000_LBK_MAC     (1 << 1)
#define DM9000_LBK_PHY     (2 << 1)
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
#include <limits.h>
   revisionId = enc28j60ReadReg(interface, ENC28J60_REG_EREVID);
   enc28j60WriteReg(interface, ENC28J60_REG_ECOCON, 0x00);
   enc28j60WriteReg(interface, ENC28J60_REG_MAADR1, interface->macAddr.b[0]);
   enc28j60WriteReg(interface, ENC28J60_REG_MAADR2, interface->macAddr.b[1]);
   enc28j60WriteReg(interface, ENC28J60_REG_MAADR3, interface->macAddr.b[2]);
   enc28j60WriteReg(interface, ENC28J60_REG_MAADR4, interface->macAddr.b[3]);
   enc28j60WriteReg(interface, ENC28J60_REG_MAADR5, interface->macAddr.b[4]);
   enc28j60WriteReg(interface, ENC28J60_REG_MAADR6, interface->macAddr.b[5]);
   enc28j60WriteReg(interface, ENC28J60_REG_ERXSTL, LSB(ENC28J60_RX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_REG_ERXSTH, MSB(ENC28J60_RX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_REG_ERXNDL, LSB(ENC28J60_RX_BUFFER_STOP));
   enc28j60WriteReg(interface, ENC28J60_REG_ERXNDH, MSB(ENC28J60_RX_BUFFER_STOP));
   //The ERXRDPT register defines a location within the FIFO
   //where the receive hardware is forbidden to write to
   enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTL, LSB(ENC28J60_RX_BUFFER_STOP));
   enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTH, MSB(ENC28J60_RX_BUFFER_STOP));
   enc28j60WriteReg(interface, ENC28J60_REG_ERXFCON, ERXFCON_UCEN |
      ERXFCON_CRCEN | ERXFCON_HTEN | ERXFCON_BCEN);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT0, 0x00);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT1, 0x00);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT2, 0x00);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT3, 0x00);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT4, 0x00);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT5, 0x00);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT6, 0x00);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT7, 0x00);
   enc28j60WriteReg(interface, ENC28J60_REG_MACON2, 0x00);
   enc28j60WriteReg(interface, ENC28J60_REG_MACON1,
      MACON1_TXPAUS | MACON1_RXPAUS | MACON1_MARXEN);
   //Enable automatic padding to at least 60 bytes, always append a valid CRC
   //and check frame length. MAC can operate in half-duplex or full-duplex mode
   enc28j60WriteReg(interface, ENC28J60_REG_MACON3, MACON3_PADCFG(1) |
      MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX);
   enc28j60WriteReg(interface, ENC28J60_REG_MACON3, MACON3_PADCFG(1) |
      MACON3_TXCRCEN | MACON3_FRMLNEN);
   enc28j60WriteReg(interface, ENC28J60_REG_MACON4, MACON4_DEFER);
   enc28j60WriteReg(interface, ENC28J60_REG_MAMXFLL, LSB(ETH_MAX_FRAME_SIZE));
   enc28j60WriteReg(interface, ENC28J60_REG_MAMXFLH, MSB(ETH_MAX_FRAME_SIZE));
   enc28j60WriteReg(interface, ENC28J60_REG_MABBIPG, 0x15);
   enc28j60WriteReg(interface, ENC28J60_REG_MABBIPG, 0x12);
   enc28j60WriteReg(interface, ENC28J60_REG_MAIPGL, 0x12);
   enc28j60WriteReg(interface, ENC28J60_REG_MAIPGH, 0x0C);
   enc28j60WriteReg(interface, ENC28J60_REG_MACLCON2, 63);
   enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHCON1, PHCON1_PDPXMD);
   enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHCON1, 0x0000);
   enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHCON2, PHCON2_HDLDIS);
   enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHLCON,
      PHLCON_LACFG(4) | PHLCON_LBCFG(7) | PHLCON_LFRQ(0) | PHLCON_STRCH);
   enc28j60WriteReg(interface, ENC28J60_REG_EIR, 0x00);
   enc28j60WriteReg(interface, ENC28J60_REG_EIE, EIE_INTIE |
      EIE_PKTIE | EIE_LINKIE | EIE_TXIE | EIE_TXERIE);
   enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHIE,
      PHIE_PLNKIE | PHIE_PGEIE);
   enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_RXEN);
   enc28j60ClearBit(interface, ENC28J60_REG_EIE, EIE_INTIE);
   status = enc28j60ReadReg(interface, ENC28J60_REG_EIR);
   if((status & EIR_LINKIF) != 0)
      enc28j60ClearBit(interface, ENC28J60_REG_EIE, EIE_LINKIE);
   if((status & EIR_PKTIF) != 0)
      enc28j60ClearBit(interface, ENC28J60_REG_EIE, EIE_PKTIE);
   if((status & (EIR_TXIF | EIE_TXERIE)) != 0)
      enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_TXIF | EIE_TXERIE);
   enc28j60SetBit(interface, ENC28J60_REG_EIE, EIE_INTIE);
   status = enc28j60ReadReg(interface, ENC28J60_REG_EIR);
   if((status & EIR_LINKIF) != 0)
      enc28j60ReadPhyReg(interface, ENC28J60_PHY_REG_PHIR);
      enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_LINKIF);
      value = enc28j60ReadPhyReg(interface, ENC28J60_PHY_REG_PHSTAT2);
      if((value & PHSTAT2_LSTAT) != 0)
   if((status & EIR_PKTIF) != 0)
      enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_PKTIF);
   enc28j60SetBit(interface, ENC28J60_REG_EIE, EIE_LINKIE | EIE_PKTIE);
   enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_TXRST);
   enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_TXRST);
   enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_TXIF | EIR_TXERIF);
   enc28j60WriteReg(interface, ENC28J60_REG_ETXSTL, LSB(ENC28J60_TX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_REG_ETXSTH, MSB(ENC28J60_TX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_REG_EWRPTL, LSB(ENC28J60_TX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_REG_EWRPTH, MSB(ENC28J60_TX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_REG_ETXNDL, LSB(ENC28J60_TX_BUFFER_START + length));
   enc28j60WriteReg(interface, ENC28J60_REG_ETXNDH, MSB(ENC28J60_TX_BUFFER_START + length));
   enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_TXRTS);
   uint16_t n;
   if(enc28j60ReadReg(interface, ENC28J60_REG_EPKTCNT))
      enc28j60WriteReg(interface, ENC28J60_REG_ERDPTL, LSB(context->nextPacket));
      enc28j60WriteReg(interface, ENC28J60_REG_ERDPTH, MSB(context->nextPacket));
      //Read the first two bytes, which are the address of the next packet
      enc28j60ReadBuffer(interface, (uint8_t *) &context->nextPacket, sizeof(uint16_t));
      //Get the length of the received frame in bytes
      enc28j60ReadBuffer(interface, (uint8_t *) &n, sizeof(uint16_t));
      //Read the receive status vector (RSV)
      enc28j60ReadBuffer(interface, (uint8_t *) &status, sizeof(uint16_t));
      if((status & RSV_RECEIVED_OK) != 0)
         n = MIN(n, ETH_MAX_FRAME_SIZE);
         enc28j60ReadBuffer(interface, context->rxBuffer, n);
         enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTL, LSB(ENC28J60_RX_BUFFER_STOP));
         enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTH, MSB(ENC28J60_RX_BUFFER_STOP));
         enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTL, LSB(context->nextPacket - 1));
         enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTH, MSB(context->nextPacket - 1));
      enc28j60SetBit(interface, ENC28J60_REG_ECON2, ECON2_PKTDEC);
      nicProcessPacket(interface, context->rxBuffer, n, &ancillary);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT0, hashTable[0]);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT1, hashTable[1]);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT2, hashTable[2]);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT3, hashTable[3]);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT4, hashTable[4]);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT5, hashTable[5]);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT6, hashTable[6]);
   enc28j60WriteReg(interface, ENC28J60_REG_EHT7, hashTable[7]);
   TRACE_DEBUG("  EHT0 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT0));
   TRACE_DEBUG("  EHT1 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT1));
   TRACE_DEBUG("  EHT2 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT2));
   TRACE_DEBUG("  EHT3 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT3));
   TRACE_DEBUG("  EHT0 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT4));
   TRACE_DEBUG("  EHT1 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT5));
   TRACE_DEBUG("  EHT2 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT6));
   TRACE_DEBUG("  EHT3 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT7));
      //Select specified bank
      switch(bank)
      case BANK_0:
         enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1 | ECON1_BSEL0);
         break;
      case BANK_1:
         enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL0);
         enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1);
         break;
      case BANK_2:
         enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL0);
         enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1);
         break;
      case BANK_3:
         enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1 | ECON1_BSEL0);
         break;
      default:
         //Invalid bank
         break;
   enc28j60WriteReg(interface, ENC28J60_REG_MIREGADR, address & REG_ADDR_MASK);
   enc28j60WriteReg(interface, ENC28J60_REG_MIWRL, LSB(data));
   enc28j60WriteReg(interface, ENC28J60_REG_MIWRH, MSB(data));
   while((enc28j60ReadReg(interface, ENC28J60_REG_MISTAT) & MISTAT_BUSY) != 0)
   enc28j60WriteReg(interface, ENC28J60_REG_MIREGADR, address & REG_ADDR_MASK);
   enc28j60WriteReg(interface, ENC28J60_REG_MICMD, MICMD_MIIRD);
   while((enc28j60ReadReg(interface, ENC28J60_REG_MISTAT) & MISTAT_BUSY) != 0)
   enc28j60WriteReg(interface, ENC28J60_REG_MICMD, 0);
   data = enc28j60ReadReg(interface, ENC28J60_REG_MIRDL);
   data |= enc28j60ReadReg(interface, ENC28J60_REG_MIRDH) << 8;
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
//Silicon revision identifiers
#define ENC28J60_REV_B1 0x02
#define ENC28J60_REV_B4 0x04
#define ENC28J60_REV_B5 0x05
#define ENC28J60_REV_B7 0x06

//Bank 0 registers
#define ENC28J60_REG_ERDPTL      (ETH_REG_TYPE | BANK_0 | 0x00)
#define ENC28J60_REG_ERDPTH      (ETH_REG_TYPE | BANK_0 | 0x01)
#define ENC28J60_REG_EWRPTL      (ETH_REG_TYPE | BANK_0 | 0x02)
#define ENC28J60_REG_EWRPTH      (ETH_REG_TYPE | BANK_0 | 0x03)
#define ENC28J60_REG_ETXSTL      (ETH_REG_TYPE | BANK_0 | 0x04)
#define ENC28J60_REG_ETXSTH      (ETH_REG_TYPE | BANK_0 | 0x05)
#define ENC28J60_REG_ETXNDL      (ETH_REG_TYPE | BANK_0 | 0x06)
#define ENC28J60_REG_ETXNDH      (ETH_REG_TYPE | BANK_0 | 0x07)
#define ENC28J60_REG_ERXSTL      (ETH_REG_TYPE | BANK_0 | 0x08)
#define ENC28J60_REG_ERXSTH      (ETH_REG_TYPE | BANK_0 | 0x09)
#define ENC28J60_REG_ERXNDL      (ETH_REG_TYPE | BANK_0 | 0x0A)
#define ENC28J60_REG_ERXNDH      (ETH_REG_TYPE | BANK_0 | 0x0B)
#define ENC28J60_REG_ERXRDPTL    (ETH_REG_TYPE | BANK_0 | 0x0C)
#define ENC28J60_REG_ERXRDPTH    (ETH_REG_TYPE | BANK_0 | 0x0D)
#define ENC28J60_REG_ERXWRPTL    (ETH_REG_TYPE | BANK_0 | 0x0E)
#define ENC28J60_REG_ERXWRPTH    (ETH_REG_TYPE | BANK_0 | 0x0F)
#define ENC28J60_REG_EDMASTL     (ETH_REG_TYPE | BANK_0 | 0x10)
#define ENC28J60_REG_EDMASTH     (ETH_REG_TYPE | BANK_0 | 0x11)
#define ENC28J60_REG_EDMANDL     (ETH_REG_TYPE | BANK_0 | 0x12)
#define ENC28J60_REG_EDMANDH     (ETH_REG_TYPE | BANK_0 | 0x13)
#define ENC28J60_REG_EDMADSTL    (ETH_REG_TYPE | BANK_0 | 0x14)
#define ENC28J60_REG_EDMADSTH    (ETH_REG_TYPE | BANK_0 | 0x15)
#define ENC28J60_REG_EDMACSL     (ETH_REG_TYPE | BANK_0 | 0x16)
#define ENC28J60_REG_EDMACSH     (ETH_REG_TYPE | BANK_0 | 0x17)
#define ENC28J60_REG_EIE         (ETH_REG_TYPE | BANK_0 | 0x1B)
#define ENC28J60_REG_EIR         (ETH_REG_TYPE | BANK_0 | 0x1C)
#define ENC28J60_REG_ESTAT       (ETH_REG_TYPE | BANK_0 | 0x1D)
#define ENC28J60_REG_ECON2       (ETH_REG_TYPE | BANK_0 | 0x1E)
#define ENC28J60_REG_ECON1       (ETH_REG_TYPE | BANK_0 | 0x1F)

//Bank 1 registers
#define ENC28J60_REG_EHT0        (ETH_REG_TYPE | BANK_1 | 0x00)
#define ENC28J60_REG_EHT1        (ETH_REG_TYPE | BANK_1 | 0x01)
#define ENC28J60_REG_EHT2        (ETH_REG_TYPE | BANK_1 | 0x02)
#define ENC28J60_REG_EHT3        (ETH_REG_TYPE | BANK_1 | 0x03)
#define ENC28J60_REG_EHT4        (ETH_REG_TYPE | BANK_1 | 0x04)
#define ENC28J60_REG_EHT5        (ETH_REG_TYPE | BANK_1 | 0x05)
#define ENC28J60_REG_EHT6        (ETH_REG_TYPE | BANK_1 | 0x06)
#define ENC28J60_REG_EHT7        (ETH_REG_TYPE | BANK_1 | 0x07)
#define ENC28J60_REG_EPMM0       (ETH_REG_TYPE | BANK_1 | 0x08)
#define ENC28J60_REG_EPMM1       (ETH_REG_TYPE | BANK_1 | 0x09)
#define ENC28J60_REG_EPMM2       (ETH_REG_TYPE | BANK_1 | 0x0A)
#define ENC28J60_REG_EPMM3       (ETH_REG_TYPE | BANK_1 | 0x0B)
#define ENC28J60_REG_EPMM4       (ETH_REG_TYPE | BANK_1 | 0x0C)
#define ENC28J60_REG_EPMM5       (ETH_REG_TYPE | BANK_1 | 0x0D)
#define ENC28J60_REG_EPMM6       (ETH_REG_TYPE | BANK_1 | 0x0E)
#define ENC28J60_REG_EPMM7       (ETH_REG_TYPE | BANK_1 | 0x0F)
#define ENC28J60_REG_EPMCSL      (ETH_REG_TYPE | BANK_1 | 0x10)
#define ENC28J60_REG_EPMCSH      (ETH_REG_TYPE | BANK_1 | 0x11)
#define ENC28J60_REG_EPMOL       (ETH_REG_TYPE | BANK_1 | 0x14)
#define ENC28J60_REG_EPMOH       (ETH_REG_TYPE | BANK_1 | 0x15)
#define ENC28J60_REG_EWOLIE      (ETH_REG_TYPE | BANK_1 | 0x16)
#define ENC28J60_REG_EWOLIR      (ETH_REG_TYPE | BANK_1 | 0x17)
#define ENC28J60_REG_ERXFCON     (ETH_REG_TYPE | BANK_1 | 0x18)
#define ENC28J60_REG_EPKTCNT     (ETH_REG_TYPE | BANK_1 | 0x19)

//Bank 2 registers
#define ENC28J60_REG_MACON1      (MAC_REG_TYPE | BANK_2 | 0x00)
#define ENC28J60_REG_MACON2      (MAC_REG_TYPE | BANK_2 | 0x01)
#define ENC28J60_REG_MACON3      (MAC_REG_TYPE | BANK_2 | 0x02)
#define ENC28J60_REG_MACON4      (MAC_REG_TYPE | BANK_2 | 0x03)
#define ENC28J60_REG_MABBIPG     (MAC_REG_TYPE | BANK_2 | 0x04)
#define ENC28J60_REG_MAIPGL      (MAC_REG_TYPE | BANK_2 | 0x06)
#define ENC28J60_REG_MAIPGH      (MAC_REG_TYPE | BANK_2 | 0x07)
#define ENC28J60_REG_MACLCON1    (MAC_REG_TYPE | BANK_2 | 0x08)
#define ENC28J60_REG_MACLCON2    (MAC_REG_TYPE | BANK_2 | 0x09)
#define ENC28J60_REG_MAMXFLL     (MAC_REG_TYPE | BANK_2 | 0x0A)
#define ENC28J60_REG_MAMXFLH     (MAC_REG_TYPE | BANK_2 | 0x0B)
#define ENC28J60_REG_MAPHSUP     (MAC_REG_TYPE | BANK_2 | 0x0D)
#define ENC28J60_REG_MICON       (MII_REG_TYPE | BANK_2 | 0x11)
#define ENC28J60_REG_MICMD       (MII_REG_TYPE | BANK_2 | 0x12)
#define ENC28J60_REG_MIREGADR    (MII_REG_TYPE | BANK_2 | 0x14)
#define ENC28J60_REG_MIWRL       (MII_REG_TYPE | BANK_2 | 0x16)
#define ENC28J60_REG_MIWRH       (MII_REG_TYPE | BANK_2 | 0x17)
#define ENC28J60_REG_MIRDL       (MII_REG_TYPE | BANK_2 | 0x18)
#define ENC28J60_REG_MIRDH       (MII_REG_TYPE | BANK_2 | 0x19)

//Bank 3 registers
#define ENC28J60_REG_MAADR5      (MAC_REG_TYPE | BANK_3 | 0x00)
#define ENC28J60_REG_MAADR6      (MAC_REG_TYPE | BANK_3 | 0x01)
#define ENC28J60_REG_MAADR3      (MAC_REG_TYPE | BANK_3 | 0x02)
#define ENC28J60_REG_MAADR4      (MAC_REG_TYPE | BANK_3 | 0x03)
#define ENC28J60_REG_MAADR1      (MAC_REG_TYPE | BANK_3 | 0x04)
#define ENC28J60_REG_MAADR2      (MAC_REG_TYPE | BANK_3 | 0x05)
#define ENC28J60_REG_EBSTSD      (ETH_REG_TYPE | BANK_3 | 0x06)
#define ENC28J60_REG_EBSTCON     (ETH_REG_TYPE | BANK_3 | 0x07)
#define ENC28J60_REG_EBSTCSL     (ETH_REG_TYPE | BANK_3 | 0x08)
#define ENC28J60_REG_EBSTCSH     (ETH_REG_TYPE | BANK_3 | 0x09)
#define ENC28J60_REG_MISTAT      (MII_REG_TYPE | BANK_3 | 0x0A)
#define ENC28J60_REG_EREVID      (ETH_REG_TYPE | BANK_3 | 0x12)
#define ENC28J60_REG_ECOCON      (ETH_REG_TYPE | BANK_3 | 0x15)
#define ENC28J60_REG_EFLOCON     (ETH_REG_TYPE | BANK_3 | 0x17)
#define ENC28J60_REG_EPAUSL      (ETH_REG_TYPE | BANK_3 | 0x18)
#define ENC28J60_REG_EPAUSH      (ETH_REG_TYPE | BANK_3 | 0x19)

//PHY registers
#define ENC28J60_PHY_REG_PHCON1  (PHY_REG_TYPE | 0x00)
#define ENC28J60_PHY_REG_PHSTAT1 (PHY_REG_TYPE | 0x01)
#define ENC28J60_PHY_REG_PHID1   (PHY_REG_TYPE | 0x02)
#define ENC28J60_PHY_REG_PHID2   (PHY_REG_TYPE | 0x03)
#define ENC28J60_PHY_REG_PHCON2  (PHY_REG_TYPE | 0x10)
#define ENC28J60_PHY_REG_PHSTAT2 (PHY_REG_TYPE | 0x11)
#define ENC28J60_PHY_REG_PHIE    (PHY_REG_TYPE | 0x12)
#define ENC28J60_PHY_REG_PHIR    (PHY_REG_TYPE | 0x13)
#define ENC28J60_PHY_REG_PHLCON  (PHY_REG_TYPE | 0x14)

//EIE register
#define EIE_INTIE         (1 << 7)
#define EIE_PKTIE         (1 << 6)
#define EIE_DMAIE         (1 << 5)
#define EIE_LINKIE        (1 << 4)
#define EIE_TXIE          (1 << 3)
#define EIE_WOLIE         (1 << 2)
#define EIE_TXERIE        (1 << 1)
#define EIE_RXERIE        (1 << 0)

//EIR register
#define EIR_PKTIF         (1 << 6)
#define EIR_DMAIF         (1 << 5)
#define EIR_LINKIF        (1 << 4)
#define EIR_TXIF          (1 << 3)
#define EIR_WOLIF         (1 << 2)
#define EIR_TXERIF        (1 << 1)
#define EIR_RXERIF        (1 << 0)

//ESTAT register
#define ESTAT_INT         (1 << 7)
#define ESTAT_LATECOL     (1 << 4)
#define ESTAT_RXBUSY      (1 << 2)
#define ESTAT_TXABRT      (1 << 1)
#define ESTAT_CLKRDY      (1 << 0)

//ECON2 register
#define ECON2_AUTOINC     (1 << 7)
#define ECON2_PKTDEC      (1 << 6)
#define ECON2_PWRSV       (1 << 5)
#define ECON2_VRPS        (1 << 3)

//ECON1 register
#define ECON1_TXRST       (1 << 7)
#define ECON1_RXRST       (1 << 6)
#define ECON1_DMAST       (1 << 5)
#define ECON1_CSUMEN      (1 << 4)
#define ECON1_TXRTS       (1 << 3)
#define ECON1_RXEN        (1 << 2)
#define ECON1_BSEL1       (1 << 1)
#define ECON1_BSEL0       (1 << 0)

//ERXFCON register
#define ERXFCON_UCEN      (1 << 7)
#define ERXFCON_ANDOR     (1 << 6)
#define ERXFCON_CRCEN     (1 << 5)
#define ERXFCON_PMEN      (1 << 4)
#define ERXFCON_MPEN      (1 << 3)
#define ERXFCON_HTEN      (1 << 2)
#define ERXFCON_MCEN      (1 << 1)
#define ERXFCON_BCEN      (1 << 0)

//MACON1 register
#define MACON1_LOOPBK     (1 << 4)
#define MACON1_TXPAUS     (1 << 3)
#define MACON1_RXPAUS     (1 << 2)
#define MACON1_PASSALL    (1 << 1)
#define MACON1_MARXEN     (1 << 0)

//MACON2 register
#define MACON2_MARST      (1 << 7)
#define MACON2_RNDRST     (1 << 6)
#define MACON2_MARXRST    (1 << 3)
#define MACON2_RFUNRST    (1 << 2)
#define MACON2_MATXRST    (1 << 1)
#define MACON2_TFUNRST    (1 << 0)

//MACON3 register
#define MACON3_PADCFG2    (1 << 7)
#define MACON3_PADCFG1    (1 << 6)
#define MACON3_PADCFG0    (1 << 5)
#define MACON3_TXCRCEN    (1 << 4)
#define MACON3_PHDRLEN    (1 << 3)
#define MACON3_HFRMLEN    (1 << 2)
#define MACON3_FRMLNEN    (1 << 1)
#define MACON3_FULDPX     (1 << 0)

#define MACON3_PADCFG(x) ((x) << 5)

//MACON4 register
#define MACON4_DEFER      (1 << 6)
#define MACON4_BPEN       (1 << 5)
#define MACON4_NOBKOFF    (1 << 4)
#define MACON4_LONGPRE    (1 << 1)
#define MACON4_PUREPRE    (1 << 0)

//MAPHSUP register
#define MAPHSUP_RSTINTFC  (1 << 7)
#define MAPHSUP_RSTRMII   (1 << 3)

//MICON register
#define MICON_RSTMII      (1 << 7)

//MICMD register
#define MICMD_MIISCAN     (1 << 1)
#define MICMD_MIIRD       (1 << 0)

//EBSTCON register
#define EBSTCON_PSV2      (1 << 7)
#define EBSTCON_PSV1      (1 << 6)
#define EBSTCON_PSV0      (1 << 5)
#define EBSTCON_PSEL      (1 << 4)
#define EBSTCON_TMSEL1    (1 << 3)
#define EBSTCON_TMSEL0    (1 << 2)
#define EBSTCON_TME       (1 << 1)
#define EBSTCON_BISTST    (1 << 0)

//MISTAT register
#define MISTAT_NVALID     (1 << 2)
#define MISTAT_SCAN       (1 << 1)
#define MISTAT_BUSY       (1 << 0)

//ECOCON register
#define ECOCON_COCON2     (1 << 2)
#define ECOCON_COCON1     (1 << 1)
#define ECOCON_COCON0     (1 << 0)

//EFLOCON register
#define EFLOCON_FULDPXS   (1 << 2)
#define EFLOCON_FCEN1     (1 << 1)
#define EFLOCON_FCEN0     (1 << 0)

//PHCON1 register
#define PHCON1_PRST       (1 << 15)
#define PHCON1_PLOOPBK    (1 << 14)
#define PHCON1_PPWRSV     (1 << 11)
#define PHCON1_PDPXMD     (1 << 8)

//PHSTAT1 register
#define PHSTAT1_PFDPX     (1 << 12)
#define PHSTAT1_PHDPX     (1 << 11)
#define PHSTAT1_LLSTAT    (1 << 2)
#define PHSTAT1_JBSTAT    (1 << 1)

//PHCON2 register
#define PHCON2_FRCLINK    (1 << 14)
#define PHCON2_TXDIS      (1 << 13)
#define PHCON2_JABBER     (1 << 10)
#define PHCON2_HDLDIS     (1 << 8)

//PHSTAT2 register
#define PHSTAT2_TXSTAT    (1 << 13)
#define PHSTAT2_RXSTAT    (1 << 12)
#define PHSTAT2_COLSTAT   (1 << 11)
#define PHSTAT2_LSTAT     (1 << 10)
#define PHSTAT2_DPXSTAT   (1 << 9)
#define PHSTAT2_PLRITY    (1 << 4)

//PHIE register
#define PHIE_PLNKIE       (1 << 4)
#define PHIE_PGEIE        (1 << 1)

//PHIR register
#define PHIR_PLNKIF       (1 << 4)
#define PHIR_PGIF         (1 << 2)

//PHLCON register
#define PHLCON_LACFG3     (1 << 11)
#define PHLCON_LACFG2     (1 << 10)
#define PHLCON_LACFG1     (1 << 9)
#define PHLCON_LACFG0     (1 << 8)
#define PHLCON_LBCFG3     (1 << 7)
#define PHLCON_LBCFG2     (1 << 6)
#define PHLCON_LBCFG1     (1 << 5)
#define PHLCON_LBCFG0     (1 << 4)
#define PHLCON_LFRQ1      (1 << 3)
#define PHLCON_LFRQ0      (1 << 2)
#define PHLCON_STRCH      (1 << 1)

#define PHLCON_LACFG(x)  ((x) << 8)
#define PHLCON_LBCFG(x)  ((x) << 4)
#define PHLCON_LFRQ(x)   ((x) << 2)
#define TX_CTRL_PHUGEEN   (1 << 3)
#define TX_CTRL_PPADEN    (1 << 2)
#define TX_CTRL_PCRCEN    (1 << 1)
#define TX_CTRL_POVERRIDE (1 << 0)
#define RSV_VLAN_TYPE           0x4000
#define RSV_UNKNOWN_OPCODE      0x2000
#define RSV_PAUSE_CONTROL_FRAME 0x1000
#define RSV_CONTROL_FRAME       0x0800
#define RSV_DRIBBLE_NIBBLE      0x0400
#define RSV_BROADCAST_PACKET    0x0200
#define RSV_MULTICAST_PACKET    0x0100
#define RSV_RECEIVED_OK         0x0080
#define RSV_LENGTH_OUT_OF_RANGE 0x0040
#define RSV_LENGTH_CHECK_ERROR  0x0020
#define RSV_CRC_ERROR           0x0010
#define RSV_CARRIER_EVENT       0x0004
#define RSV_DROP_EVENT          0x0001
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   enc624j600WriteReg(interface, ENC624J600_REG_ECON2, ECON2_ETHEN | ECON2_STRCH);
      temp = enc624j600ReadReg(interface, ENC624J600_REG_MAADR1);
      temp = enc624j600ReadReg(interface, ENC624J600_REG_MAADR2);
      temp = enc624j600ReadReg(interface, ENC624J600_REG_MAADR3);
      enc624j600WriteReg(interface, ENC624J600_REG_MAADR1, temp);
      enc624j600WriteReg(interface, ENC624J600_REG_MAADR2, temp);
      enc624j600WriteReg(interface, ENC624J600_REG_MAADR3, temp);
   enc624j600WriteReg(interface, ENC624J600_REG_ERXST, ENC624J600_RX_BUFFER_START);
   enc624j600WriteReg(interface, ENC624J600_REG_ERXTAIL, ENC624J600_RX_BUFFER_STOP);
   enc624j600WriteReg(interface, ENC624J600_REG_ERXFCON, ERXFCON_HTEN |
      ERXFCON_CRCEN | ERXFCON_RUNTEN | ERXFCON_UCEN | ERXFCON_BCEN);
   enc624j600WriteReg(interface, ENC624J600_REG_EHT1, 0x0000);
   enc624j600WriteReg(interface, ENC624J600_REG_EHT2, 0x0000);
   enc624j600WriteReg(interface, ENC624J600_REG_EHT3, 0x0000);
   enc624j600WriteReg(interface, ENC624J600_REG_EHT4, 0x0000);
   //All short frames will be zero-padded to 60 bytes and a valid CRC is then appended
   enc624j600WriteReg(interface, ENC624J600_REG_MACON2,
      MACON2_DEFER | MACON2_PADCFG0 | MACON2_TXCRCEN | MACON2_R1);
   enc624j600WriteReg(interface, ENC624J600_REG_MAMXFL, ETH_MAX_FRAME_SIZE);
   enc624j600WritePhyReg(interface, ENC624J600_PHY_REG_PHANA, PHANA_ADPAUS0 |
      PHANA_AD100FD | PHANA_AD100 | PHANA_AD10FD | PHANA_AD10 | PHANA_ADIEEE0);
   enc624j600WriteReg(interface, ENC624J600_REG_EIR, 0x0000);
   enc624j600WriteReg(interface, ENC624J600_REG_EIE, EIE_INTIE |
      EIE_LINKIE | EIE_PKTIE | EIE_TXIE | EIE_TXABTIE);
   enc624j600SetBit(interface, ENC624J600_REG_ECON1, ECON1_RXEN);
   enc624j600ClearBit(interface, ENC624J600_REG_EIE, EIE_INTIE);
   status = enc624j600ReadReg(interface, ENC624J600_REG_EIR);
   if((status & EIR_LINKIF) != 0)
      enc624j600ClearBit(interface, ENC624J600_REG_EIE, EIE_LINKIE);
   if((status & EIR_PKTIF) != 0)
      enc624j600ClearBit(interface, ENC624J600_REG_EIE, EIE_PKTIE);
   if((status & (EIR_TXIF | EIR_TXABTIF)) != 0)
      enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_TXIF | EIR_TXABTIF);
   enc624j600SetBit(interface, ENC624J600_REG_EIE, EIE_INTIE);
   status = enc624j600ReadReg(interface, ENC624J600_REG_EIR);
   if((status & EIR_LINKIF) != 0)
      enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_LINKIF);
      value = enc624j600ReadReg(interface, ENC624J600_REG_ESTAT);
      if((value & ESTAT_PHYLNK) != 0)
         value = enc624j600ReadPhyReg(interface, ENC624J600_PHY_REG_PHSTAT3);
         if((value & PHSTAT3_SPDDPX1) != 0)
         if((value & PHSTAT3_SPDDPX2) != 0)
   if((status & EIR_PKTIF) != 0)
      enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_PKTIF);
   enc624j600SetBit(interface, ENC624J600_REG_EIE, EIE_LINKIE | EIE_PKTIE);
   if(enc624j600ReadReg(interface, ENC624J600_REG_ECON1) & ECON1_TXRTS)
   enc624j600WriteReg(interface, ENC624J600_REG_EGPWRPT, ENC624J600_TX_BUFFER_START);
   enc624j600WriteReg(interface, ENC624J600_REG_ETXST, ENC624J600_TX_BUFFER_START);
   enc624j600WriteReg(interface, ENC624J600_REG_ETXLEN, length);
   enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_TXIF | EIR_TXABTIF);
   enc624j600SetBit(interface, ENC624J600_REG_ECON1, ECON1_TXRTS);
   uint16_t n;
   if(enc624j600ReadReg(interface, ENC624J600_REG_ESTAT) & ESTAT_PKTCNT)
      enc624j600WriteReg(interface, ENC624J600_REG_ERXRDPT, context->nextPacket);

      //Read the first two bytes, which are the address of the next packet
      enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA,
         (uint8_t *) &context->nextPacket, sizeof(uint16_t));

      //Convert the value to host byte order
      context->nextPacket = letoh16(context->nextPacket);

      //Get the length of the received frame in bytes
      enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA,
         (uint8_t *) &n, sizeof(uint16_t));

      //Convert the value to host byte order
      n = letoh16(n);
      //Read the receive status vector (RSV)
      enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA,
         (uint8_t *) &status, sizeof(uint32_t));
      //Convert the value to host byte order
      status = letoh32(status);
      if((status & RSV_RECEIVED_OK) != 0)
         n = MIN(n, ETH_MAX_FRAME_SIZE);
         enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA, context->rxBuffer, n);
         enc624j600WriteReg(interface, ENC624J600_REG_ERXTAIL, ENC624J600_RX_BUFFER_STOP);
         enc624j600WriteReg(interface, ENC624J600_REG_ERXTAIL, context->nextPacket - 2);
      enc624j600SetBit(interface, ENC624J600_REG_ECON1, ECON1_PKTDEC);
      nicProcessPacket(interface, context->rxBuffer, n, &ancillary);
   enc624j600WriteReg(interface, ENC624J600_REG_EHT1, hashTable[0]);
   enc624j600WriteReg(interface, ENC624J600_REG_EHT2, hashTable[1]);
   enc624j600WriteReg(interface, ENC624J600_REG_EHT3, hashTable[2]);
   enc624j600WriteReg(interface, ENC624J600_REG_EHT4, hashTable[3]);
   TRACE_DEBUG("  EHT1 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT1));
   TRACE_DEBUG("  EHT2 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT2));
   TRACE_DEBUG("  EHT3 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT3));
   TRACE_DEBUG("  EHT4 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT4));
   duplexMode = enc624j600ReadReg(interface, ENC624J600_REG_ESTAT) & ESTAT_PHYDPX;
      enc624j600WriteReg(interface, ENC624J600_REG_MACON2, MACON2_DEFER |
         MACON2_PADCFG2 | MACON2_PADCFG0 | MACON2_TXCRCEN | MACON2_R1 | MACON2_FULDPX);
      enc624j600WriteReg(interface, ENC624J600_REG_MABBIPG, 0x15);
      enc624j600WriteReg(interface, ENC624J600_REG_MACON2, MACON2_DEFER |
         MACON2_PADCFG2 | MACON2_PADCFG0 | MACON2_TXCRCEN | MACON2_R1);
      enc624j600WriteReg(interface, ENC624J600_REG_MABBIPG, 0x12);
      enc624j600WriteReg(interface, ENC624J600_REG_EUDAST, 0x1234);
   } while(enc624j600ReadReg(interface, ENC624J600_REG_EUDAST) != 0x1234);
   while((enc624j600ReadReg(interface, ENC624J600_REG_ESTAT) & ESTAT_CLKRDY) == 0)
   enc624j600SetBit(interface, ENC624J600_REG_ECON2, ECON2_ETHRST);
   if(enc624j600ReadReg(interface, ENC624J600_REG_EUDAST) != 0x0000)
   enc624j600WriteReg(interface, ENC624J600_REG_MIREGADR, MIREGADR_R8 | address);
   enc624j600WriteReg(interface, ENC624J600_REG_MIWR, data);
   while((enc624j600ReadReg(interface, ENC624J600_REG_MISTAT) & MISTAT_BUSY) != 0)
   }
   enc624j600WriteReg(interface, ENC624J600_REG_MIREGADR, MIREGADR_R8 | address);
   enc624j600WriteReg(interface, ENC624J600_REG_MICMD, MICMD_MIIRD);
   while((enc624j600ReadReg(interface, ENC624J600_REG_MISTAT) & MISTAT_BUSY) != 0)
   }
   enc624j600WriteReg(interface, ENC624J600_REG_MICMD, 0x00);
   return enc624j600ReadReg(interface, ENC624J600_REG_MIRD);
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
#define ENC624J600_REG_ETXST       0x00
#define ENC624J600_REG_ETXLEN      0x02
#define ENC624J600_REG_ERXST       0x04
#define ENC624J600_REG_ERXTAIL     0x06
#define ENC624J600_REG_ERXHEAD     0x08
#define ENC624J600_REG_EDMAST      0x0A
#define ENC624J600_REG_EDMALEN     0x0C
#define ENC624J600_REG_EDMADST     0x0E
#define ENC624J600_REG_EDMACS      0x10
#define ENC624J600_REG_ETXSTAT     0x12
#define ENC624J600_REG_ETXWIRE     0x14
#define ENC624J600_REG_EUDAST      0x16
#define ENC624J600_REG_EUDAND      0x18
#define ENC624J600_REG_ESTAT       0x1A
#define ENC624J600_REG_EIR         0x1C
#define ENC624J600_REG_ECON1       0x1E
#define ENC624J600_REG_EHT1        0x20
#define ENC624J600_REG_EHT2        0x22
#define ENC624J600_REG_EHT3        0x24
#define ENC624J600_REG_EHT4        0x26
#define ENC624J600_REG_EPMM1       0x28
#define ENC624J600_REG_EPMM2       0x2A
#define ENC624J600_REG_EPMM3       0x2C
#define ENC624J600_REG_EPMM4       0x2E
#define ENC624J600_REG_EPMCS       0x30
#define ENC624J600_REG_EPMO        0x32
#define ENC624J600_REG_ERXFCON     0x34
#define ENC624J600_REG_MACON1      0x40
#define ENC624J600_REG_MACON2      0x42
#define ENC624J600_REG_MABBIPG     0x44
#define ENC624J600_REG_MAIPG       0x46
#define ENC624J600_REG_MACLCON     0x48
#define ENC624J600_REG_MAMXFL      0x4A
#define ENC624J600_REG_MICMD       0x52
#define ENC624J600_REG_MIREGADR    0x54
#define ENC624J600_REG_MAADR3      0x60
#define ENC624J600_REG_MAADR2      0x62
#define ENC624J600_REG_MAADR1      0x64
#define ENC624J600_REG_MIWR        0x66
#define ENC624J600_REG_MIRD        0x68
#define ENC624J600_REG_MISTAT      0x6A
#define ENC624J600_REG_EPAUS       0x6C
#define ENC624J600_REG_ECON2       0x6E
#define ENC624J600_REG_ERXWM       0x70
#define ENC624J600_REG_EIE         0x72
#define ENC624J600_REG_EIDLED      0x74
#define ENC624J600_REG_EGPDATA     0x80
#define ENC624J600_REG_ERXDATA     0x82
#define ENC624J600_REG_EUDADATA    0x84
#define ENC624J600_REG_EGPRDPT     0x86
#define ENC624J600_REG_EGPWRPT     0x88
#define ENC624J600_REG_ERXRDPT     0x8A
#define ENC624J600_REG_ERXWRPT     0x8C
#define ENC624J600_REG_EUDARDPT    0x8E
#define ENC624J600_REG_EUDAWRPT    0x90
#define ENC624J600_PHY_REG_PHCON1  0x00
#define ENC624J600_PHY_REG_PHSTAT1 0x01
#define ENC624J600_PHY_REG_PHANA   0x04
#define ENC624J600_PHY_REG_PHANLPA 0x05
#define ENC624J600_PHY_REG_PHANE   0x06
#define ENC624J600_PHY_REG_PHCON2  0x11
#define ENC624J600_PHY_REG_PHSTAT2 0x1B
#define ENC624J600_PHY_REG_PHSTAT3 0x1F

//ESTAT register
#define ESTAT_INT                  0x8000
#define ESTAT_FCIDLE               0x4000
#define ESTAT_RXBUSY               0x2000
#define ESTAT_CLKRDY               0x1000
#define ESTAT_R11                  0x0800
#define ESTAT_PHYDPX               0x0400
#define ESTAT_R9                   0x0200
#define ESTAT_PHYLNK               0x0100
#define ESTAT_PKTCNT               0x00FF

//EIR register
#define EIR_CRYPTEN                0x8000
#define EIR_MODEXIF                0x4000
#define EIR_HASHIF                 0x2000
#define EIR_AESIF                  0x1000
#define EIR_LINKIF                 0x0800
#define EIR_R10                    0x0400
#define EIR_R9                     0x0200
#define EIR_R8                     0x0100
#define EIR_R7                     0x0080
#define EIR_PKTIF                  0x0040
#define EIR_DMAIF                  0x0020
#define EIR_R4                     0x0010
#define EIR_TXIF                   0x0008
#define EIR_TXABTIF                0x0004
#define EIR_RXABTIF                0x0002
#define EIR_PCFULIF                0x0001

//ECON1 register
#define ECON1_MODEXST              0x8000
#define ECON1_HASHEN               0x4000
#define ECON1_HASHOP               0x2000
#define ECON1_HASHLST              0x1000
#define ECON1_AESST                0x0800
#define ECON1_AESOP1               0x0400
#define ECON1_AESOP0               0x0200
#define ECON1_PKTDEC               0x0100
#define ECON1_FCOP1                0x0080
#define ECON1_FCOP0                0x0040
#define ECON1_DMAST                0x0020
#define ECON1_DMACPY               0x0010
#define ECON1_DMACSSD              0x0008
#define ECON1_DMANOCS              0x0004
#define ECON1_TXRTS                0x0002
#define ECON1_RXEN                 0x0001

//ETXSTAT register
#define ETXSTAT_R12                0x1000
#define ETXSTAT_R11                0x0800
#define ETXSTAT_LATECOL            0x0400
#define ETXSTAT_MAXCOL             0x0200
#define ETXSTAT_EXDEFER            0x0100
#define ETXSTAT_DEFER              0x0080
#define ETXSTAT_R6                 0x0040
#define ETXSTAT_R5                 0x0020
#define ETXSTAT_CRCBAD             0x0010
#define ETXSTAT_COLCNT             0x000F

//ERXFCON register
#define ERXFCON_HTEN               0x8000
#define ERXFCON_MPEN               0x4000
#define ERXFCON_NOTPM              0x1000
#define ERXFCON_PMEN3              0x0800
#define ERXFCON_PMEN2              0x0400
#define ERXFCON_PMEN1              0x0200
#define ERXFCON_PMEN0              0x0100
#define ERXFCON_CRCEEN             0x0080
#define ERXFCON_CRCEN              0x0040
#define ERXFCON_RUNTEEN            0x0020
#define ERXFCON_RUNTEN             0x0010
#define ERXFCON_UCEN               0x0008
#define ERXFCON_NOTMEEN            0x0004
#define ERXFCON_MCEN               0x0002
#define ERXFCON_BCEN               0x0001

//MACON1 register
#define MACON1_R15                 0x8000
#define MACON1_R14                 0x4000
#define MACON1_R11                 0x0800
#define MACON1_R10                 0x0400
#define MACON1_R9                  0x0200
#define MACON1_R8                  0x0100
#define MACON1_LOOPBK              0x0010
#define MACON1_R3                  0x0008
#define MACON1_RXPAUS              0x0004
#define MACON1_PASSALL             0x0002
#define MACON1_R0                  0x0001

//MACON2 register
#define MACON2_DEFER               0x4000
#define MACON2_BPEN                0x2000
#define MACON2_NOBKOFF             0x1000
#define MACON2_R9                  0x0200
#define MACON2_R8                  0x0100
#define MACON2_PADCFG2             0x0080
#define MACON2_PADCFG1             0x0040
#define MACON2_PADCFG0             0x0020
#define MACON2_TXCRCEN             0x0010
#define MACON2_PHDREN              0x0008
#define MACON2_HFRMEN              0x0004
#define MACON2_R1                  0x0002
#define MACON2_FULDPX              0x0001

//MABBIPG register
#define MABBIPG_BBIPG              0x007F

//MAIPG register
#define MAIPG_R14                  0x4000
#define MAIPG_R13                  0x2000
#define MAIPG_R12                  0x1000
#define MAIPG_R11                  0x0800
#define MAIPG_R10                  0x0400
#define MAIPG_R9                   0x0200
#define MAIPG_R8                   0x0100
#define MAIPG_IPG                  0x007F

//MACLCON register
#define MACLCON_R13                0x2000
#define MACLCON_R12                0x1000
#define MACLCON_R11                0x0800
#define MACLCON_R10                0x0400
#define MACLCON_R9                 0x0200
#define MACLCON_R8                 0x0100
#define MACLCON_MAXRET             0x000F

//MICMD register
#define MICMD_MIISCAN              0x0002
#define MICMD_MIIRD                0x0001

//MIREGADR register
#define MIREGADR_R12               0x1000
#define MIREGADR_R11               0x0800
#define MIREGADR_R10               0x0400
#define MIREGADR_R9                0x0200
#define MIREGADR_R8                0x0100
#define MIREGADR_PHREG             0x001F

//MISTAT register
#define MISTAT_R3                  0x0008
#define MISTAT_NVALID              0x0004
#define MISTAT_SCAN                0x0002
#define MISTAT_BUSY                0x0001

//ECON2 register
#define ECON2_ETHEN                0x8000
#define ECON2_STRCH                0x4000
#define ECON2_TXMAC                0x2000
#define ECON2_SHA1MD5              0x1000
#define ECON2_COCON3               0x0800
#define ECON2_COCON2               0x0400
#define ECON2_COCON1               0x0200
#define ECON2_COCON0               0x0100
#define ECON2_AUTOFC               0x0080
#define ECON2_TXRST                0x0040
#define ECON2_RXRST                0x0020
#define ECON2_ETHRST               0x0010
#define ECON2_MODLEN1              0x0008
#define ECON2_MODLEN0              0x0004
#define ECON2_AESLEN1              0x0002
#define ECON2_AESLEN0              0x0001

//ERXWM register
#define ERXWM_RXFWM                0xFF00
#define ERXWM_RXEWM                0x00FF

//EIE register
#define EIE_INTIE                  0x8000
#define EIE_MODEXIE                0x4000
#define EIE_HASHIE                 0x2000
#define EIE_AESIE                  0x1000
#define EIE_LINKIE                 0x0800
#define EIE_R10                    0x0400
#define EIE_R9                     0x0200
#define EIE_R8                     0x0100
#define EIE_R7                     0x0080
#define EIE_PKTIE                  0x0040
#define EIE_DMAIE                  0x0020
#define EIE_R4                     0x0010
#define EIE_TXIE                   0x0008
#define EIE_TXABTIE                0x0004
#define EIE_RXABTIE                0x0002
#define EIE_PCFULIE                0x0001

//EIDLED register
#define EIDLED_LACFG3              0x8000
#define EIDLED_LACFG2              0x4000
#define EIDLED_LACFG1              0x2000
#define EIDLED_LACFG0              0x1000
#define EIDLED_LBCFG3              0x0800
#define EIDLED_LBCFG2              0x0400
#define EIDLED_LBCFG1              0x0200
#define EIDLED_LBCFG0              0x0100
#define EIDLED_DEVID               0x00FF

//PHCON1 register
#define PHCON1_PRST                0x8000
#define PHCON1_PLOOPBK             0x4000
#define PHCON1_SPD100              0x2000
#define PHCON1_ANEN                0x1000
#define PHCON1_PSLEEP              0x0800
#define PHCON1_RENEG               0x0200
#define PHCON1_PFULDPX             0x0100

//PHSTAT1 register
#define PHSTAT1_FULL100            0x4000
#define PHSTAT1_HALF100            0x2000
#define PHSTAT1_FULL10             0x1000
#define PHSTAT1_HALF10             0x0800
#define PHSTAT1_ANDONE             0x0020
#define PHSTAT1_LRFAULT            0x0010
#define PHSTAT1_ANABLE             0x0008
#define PHSTAT1_LLSTAT             0x0004
#define PHSTAT1_EXTREGS            0x0001

//PHANA register
#define PHANA_ADNP                 0x8000
#define PHANA_ADFAULT              0x2000
#define PHANA_ADPAUS1              0x0800
#define PHANA_ADPAUS0              0x0400
#define PHANA_AD100FD              0x0100
#define PHANA_AD100                0x0080
#define PHANA_AD10FD               0x0040
#define PHANA_AD10                 0x0020
#define PHANA_ADIEEE4              0x0010
#define PHANA_ADIEEE3              0x0008
#define PHANA_ADIEEE2              0x0004
#define PHANA_ADIEEE1              0x0002
#define PHANA_ADIEEE0              0x0001

//PHANLPA register
#define PHANLPA_LPNP               0x8000
#define PHANLPA_LPACK              0x4000
#define PHANLPA_LPFAULT            0x2000
#define PHANLPA_LPPAUS1            0x0800
#define PHANLPA_LPPAUS0            0x0400
#define PHANLPA_LP100T4            0x0200
#define PHANLPA_LP100FD            0x0100
#define PHANLPA_LP100              0x0080
#define PHANLPA_LP10FD             0x0040
#define PHANLPA_LP10               0x0020
#define PHANLPA_LPIEEE             0x001F
#define PHANLPA_LPIEEE4            0x0010
#define PHANLPA_LPIEEE3            0x0008
#define PHANLPA_LPIEEE2            0x0004
#define PHANLPA_LPIEEE1            0x0002
#define PHANLPA_LPIEEE0            0x0001

//PHANE register
#define PHANE_PDFLT                0x0010
#define PHANE_LPARCD               0x0002
#define PHANE_LPANABL              0x0001

//PHCON2 register
#define PHCON2_EDPWRDN             0x2000
#define PHCON2_EDTHRES             0x0800
#define PHCON2_FRCLNK              0x0004
#define PHCON2_EDSTAT              0x0002

//PHSTAT2 register
#define PHSTAT2_PLRITY             0x0010

//PHSTAT3 register
#define PHSTAT3_SPDDPX2            0x0010
#define PHSTAT3_SPDDPX1            0x0008
#define PHSTAT3_SPDDPX0            0x0004
#define RSV_UNICAST_FILTER         0x00100000
#define RSV_PATTERN_MATCH_FILTER   0x00080000
#define RSV_MAGIC_PACKET_FILTER    0x00040000
#define RSV_HASH_FILTER            0x00020000
#define RSV_NOT_ME_FILTER          0x00010000
#define RSV_RUNT_FILTER            0x00008000
#define RSV_VLAN_TYPE              0x00004000
#define RSV_UNKNOWN_OPCODE         0x00002000
#define RSV_PAUSE_CONTROL_FRAME    0x00001000
#define RSV_CONTROL_FRAME          0x00000800
#define RSV_DRIBBLE_NIBBLE         0x00000400
#define RSV_BROADCAST_PACKET       0x00000200
#define RSV_MULTICAST_PACKET       0x00000100
#define RSV_RECEIVED_OK            0x00000080
#define RSV_LENGTH_OUT_OF_RANGE    0x00000040
#define RSV_LENGTH_CHECK_ERROR     0x00000020
#define RSV_CRC_ERROR              0x00000010
#define RSV_CARRIER_EVENT          0x00000004
#define RSV_PACKET_IGNORED         0x00000001
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   TRACE_DEBUG("CIDER=0x%04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_CIDER));
   TRACE_DEBUG("PHY1ILR=0x%04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_PHY1ILR));
   TRACE_DEBUG("PHY1IHR=0x%04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_PHY1IHR));
   if(ksz8851ReadReg(interface, KSZ8851_REG_CIDER) != KSZ8851_REV_A3_ID)
   ksz8851WriteReg(interface, KSZ8851_REG_MARH, htons(interface->macAddr.w[0]));
   ksz8851WriteReg(interface, KSZ8851_REG_MARM, htons(interface->macAddr.w[1]));
   ksz8851WriteReg(interface, KSZ8851_REG_MARL, htons(interface->macAddr.w[2]));
   //Packets shorter than 64 bytes are padded and the CRC is automatically generated
   ksz8851WriteReg(interface, KSZ8851_REG_TXCR, TXCR_TXFCE | TXCR_TXPE | TXCR_TXCE);
   ksz8851WriteReg(interface, KSZ8851_REG_TXFDPR, TXFDPR_TXFPAI);
   ksz8851WriteReg(interface, KSZ8851_REG_RXCR1,
      RXCR1_RXPAFMA | RXCR1_RXFCE | RXCR1_RXBE | RXCR1_RXME | RXCR1_RXUE);
   ksz8851WriteReg(interface, KSZ8851_REG_RXCR2,
      RXCR2_SRDBL2 | RXCR2_IUFFP | RXCR2_RXIUFCEZ);
   ksz8851WriteReg(interface, KSZ8851_REG_RXQCR, RXQCR_RXFCTE | RXQCR_ADRFE);
   ksz8851WriteReg(interface, KSZ8851_REG_RXFDPR, RXFDPR_RXFPAI);
   ksz8851WriteReg(interface, KSZ8851_REG_RXFCTR, 1);
   ksz8851ClearBit(interface, KSZ8851_REG_P1CR, P1CR_FORCE_DUPLEX);
   ksz8851SetBit(interface, KSZ8851_REG_P1CR, P1CR_RESTART_AN);
   ksz8851SetBit(interface, KSZ8851_REG_ISR, ISR_LCIS | ISR_TXIS |
      ISR_RXIS | ISR_RXOIS | ISR_TXPSIS | ISR_RXPSIS | ISR_TXSAIS |
      ISR_RXWFDIS | ISR_RXMPDIS | ISR_LDIS | ISR_EDIS | ISR_SPIBEIS);
   ksz8851SetBit(interface, KSZ8851_REG_IER, IER_LCIE | IER_TXIE | IER_RXIE);
   ksz8851SetBit(interface, KSZ8851_REG_TXCR, TXCR_TXE);
   ksz8851SetBit(interface, KSZ8851_REG_RXCR1, RXCR1_RXE);
   ier = ksz8851ReadReg(interface, KSZ8851_REG_IER);
   ksz8851WriteReg(interface, KSZ8851_REG_IER, 0);
   isr = ksz8851ReadReg(interface, KSZ8851_REG_ISR);
   if((isr & ISR_LCIS) != 0)
      ier &= ~IER_LCIE;
   if((isr & ISR_TXIS) != 0)
      ksz8851WriteReg(interface, KSZ8851_REG_ISR, ISR_TXIS);
      n = ksz8851ReadReg(interface, KSZ8851_REG_TXMIR) & TXMIR_TXMA_MASK;
   if((isr & ISR_RXIS) != 0)
      ier &= ~IER_RXIE;
   ksz8851WriteReg(interface, KSZ8851_REG_IER, ier);
   status = ksz8851ReadReg(interface, KSZ8851_REG_ISR);
   if((status & ISR_LCIS) != 0)
      ksz8851WriteReg(interface, KSZ8851_REG_ISR, ISR_LCIS);
      status = ksz8851ReadReg(interface, KSZ8851_REG_P1SR);
      if((status & P1SR_LINK_GOOD) != 0)
         if((status & P1SR_OPERATION_SPEED) != 0)
         if((status & P1SR_OPERATION_DUPLEX) != 0)
   if((status & ISR_RXIS) != 0)
      ksz8851WriteReg(interface, KSZ8851_REG_ISR, ISR_RXIS);
      frameCount = MSB(ksz8851ReadReg(interface, KSZ8851_REG_RXFCTR));
   ksz8851SetBit(interface, KSZ8851_REG_IER, IER_LCIE | IER_RXIE);
   n = ksz8851ReadReg(interface, KSZ8851_REG_TXMIR) & TXMIR_TXMA_MASK;
   header.controlWord = htole16(TX_CTRL_TXIC | (context->frameId++ & TX_CTRL_TXFID));
   ksz8851SetBit(interface, KSZ8851_REG_RXQCR, RXQCR_SDA);
   ksz8851ClearBit(interface, KSZ8851_REG_RXQCR, RXQCR_SDA);
   ksz8851SetBit(interface, KSZ8851_REG_TXQCR, TXQCR_METFE);
   n = ksz8851ReadReg(interface, KSZ8851_REG_TXMIR) & TXMIR_TXMA_MASK;
   status = ksz8851ReadReg(interface, KSZ8851_REG_RXFHSR);
   if((status & RXFHSR_RXFV) != 0)
      if((status & (RXFHSR_RXMR | RXFHSR_RXFTL | RXFHSR_RXRF | RXFHSR_RXCE)) == 0)
         n = ksz8851ReadReg(interface, KSZ8851_REG_RXFHBCR) & RXFHBCR_RXBC_MASK;
            ksz8851WriteReg(interface, KSZ8851_REG_RXFDPR, RXFDPR_RXFPAI);
            ksz8851SetBit(interface, KSZ8851_REG_RXQCR, RXQCR_SDA);
            ksz8851ClearBit(interface, KSZ8851_REG_RXQCR, RXQCR_SDA);
   ksz8851SetBit(interface, KSZ8851_REG_RXQCR, RXQCR_RRXEF);
   ksz8851WriteReg(interface, KSZ8851_REG_MAHTR0, hashTable[0]);
   ksz8851WriteReg(interface, KSZ8851_REG_MAHTR1, hashTable[1]);
   ksz8851WriteReg(interface, KSZ8851_REG_MAHTR2, hashTable[2]);
   ksz8851WriteReg(interface, KSZ8851_REG_MAHTR3, hashTable[3]);
   TRACE_DEBUG("  MAHTR0 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_MAHTR0));
   TRACE_DEBUG("  MAHTR1 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_MAHTR1));
   TRACE_DEBUG("  MAHTR2 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_MAHTR2));
   TRACE_DEBUG("  MAHTR3 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_MAHTR3));
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
//Device ID
#define KSZ8851_REV_A2_ID        0x8870
#define KSZ8851_REV_A3_ID        0x8872

#define KSZ8851_CMD_RD_REG       0x00
#define KSZ8851_CMD_WR_REG       0x40
#define KSZ8851_CMD_RD_FIFO      0x80
#define KSZ8851_CMD_WR_FIFO      0xC0
   #define KSZ8851_CMD_B0        0x04
   #define KSZ8851_CMD_B1        0x08
   #define KSZ8851_CMD_B2        0x10
   #define KSZ8851_CMD_B3        0x20
   #define KSZ8851_CMD_B0        0x1000
   #define KSZ8851_CMD_B1        0x2000
   #define KSZ8851_CMD_B2        0x4000
   #define KSZ8851_CMD_B3        0x8000
#define KSZ8851_REG_CCR          0x08
#define KSZ8851_REG_MARL         0x10
#define KSZ8851_REG_MARM         0x12
#define KSZ8851_REG_MARH         0x14
#define KSZ8851_REG_OBCR         0x20
#define KSZ8851_REG_EEPCR        0x22
#define KSZ8851_REG_MBIR         0x24
#define KSZ8851_REG_GRR          0x26
#define KSZ8851_REG_WFCR         0x2A
#define KSZ8851_REG_WF0CRC0      0x30
#define KSZ8851_REG_WF0CRC1      0x32
#define KSZ8851_REG_WF0BM0       0x34
#define KSZ8851_REG_WF0BM1       0x36
#define KSZ8851_REG_WF0BM2       0x38
#define KSZ8851_REG_WF0BM3       0x3A
#define KSZ8851_REG_WF1CRC0      0x40
#define KSZ8851_REG_WF1CRC1      0x42
#define KSZ8851_REG_WF1BM0       0x44
#define KSZ8851_REG_WF1BM1       0x46
#define KSZ8851_REG_WF1BM2       0x48
#define KSZ8851_REG_WF1BM3       0x4A
#define KSZ8851_REG_WF2CRC0      0x50
#define KSZ8851_REG_WF2CRC1      0x52
#define KSZ8851_REG_WF2BM0       0x54
#define KSZ8851_REG_WF2BM1       0x56
#define KSZ8851_REG_WF2BM2       0x58
#define KSZ8851_REG_WF2BM3       0x5A
#define KSZ8851_REG_WF3CRC0      0x60
#define KSZ8851_REG_WF3CRC1      0x62
#define KSZ8851_REG_WF3BM0       0x64
#define KSZ8851_REG_WF3BM1       0x66
#define KSZ8851_REG_WF3BM2       0x68
#define KSZ8851_REG_WF3BM3       0x6A
#define KSZ8851_REG_TXCR         0x70
#define KSZ8851_REG_TXSR         0x72
#define KSZ8851_REG_RXCR1        0x74
#define KSZ8851_REG_RXCR2        0x76
#define KSZ8851_REG_TXMIR        0x78
#define KSZ8851_REG_RXFHSR       0x7C
#define KSZ8851_REG_RXFHBCR      0x7E
#define KSZ8851_REG_TXQCR        0x80
#define KSZ8851_REG_RXQCR        0x82
#define KSZ8851_REG_TXFDPR       0x84
#define KSZ8851_REG_RXFDPR       0x86
#define KSZ8851_REG_RXDTTR       0x8C
#define KSZ8851_REG_RXDBCTR      0x8E
#define KSZ8851_REG_IER          0x90
#define KSZ8851_REG_ISR          0x92
#define KSZ8851_REG_RXFCTR       0x9C
#define KSZ8851_REG_TXNTFSR      0x9E
#define KSZ8851_REG_MAHTR0       0xA0
#define KSZ8851_REG_MAHTR1       0xA2
#define KSZ8851_REG_MAHTR2       0xA4
#define KSZ8851_REG_MAHTR3       0xA6
#define KSZ8851_REG_FCLWR        0xB0
#define KSZ8851_REG_FCHWR        0xB2
#define KSZ8851_REG_FCOWR        0xB4
#define KSZ8851_REG_CIDER        0xC0
#define KSZ8851_REG_CGCR         0xC6
#define KSZ8851_REG_IACR         0xC8
#define KSZ8851_REG_IADLR        0xD0
#define KSZ8851_REG_IADHR        0xD2
#define KSZ8851_REG_PMECR        0xD4
#define KSZ8851_REG_GSWUTR       0xD6
#define KSZ8851_REG_PHYRR        0xD8
#define KSZ8851_REG_P1MBCR       0xE4
#define KSZ8851_REG_P1MBSR       0xE6
#define KSZ8851_REG_PHY1ILR      0xE8
#define KSZ8851_REG_PHY1IHR      0xEA
#define KSZ8851_REG_P1ANAR       0xEC
#define KSZ8851_REG_P1ANLPR      0xEE
#define KSZ8851_REG_P1SCLMD      0xF4
#define KSZ8851_REG_P1CR         0xF6
#define KSZ8851_REG_P1SR         0xF8

//CCR register
#define CCR_BUS_ENDIAN_MODE      0x0400
#define CCR_EEPROM_PRESENCE      0x0200
#define CCR_SPI_MODE             0x0100
#define CCR_8_BIT_DATA_BUS       0x0080
#define CCR_16_BIT_DATA_BUS      0x0040
#define CCR_32_BIT_DATA_BUS      0x0020
#define CCR_BUS_SHARED_MODE      0x0010
#define CCR_128_PIN_PACKAGE      0x0008
#define CCR_48_PIN_PACKAGE       0x0002
#define CCR_32_PIN_PACKAGE       0x0001

//OBCR register
#define OBCR_OUT_DRIVE_STRENGTH  0x0040
#define OBCR_SPI_SO_DELAY2       0x0020
#define OBCR_SPI_SO_DELAY1       0x0010
#define OBCR_SPI_SO_DELAY0       0x0008
#define OBCR_BUS_CLOCK_SEL       0x0004
#define OBCR_BUS_CLOCK_DIV1      0x0002
#define OBCR_BUS_CLOCK_DIV0      0x0001

//EEPCR register
#define EEPCR_EESA               0x0010
#define EEPCR_EESB               0x0008
#define EEPCR_EECB2              0x0004
#define EEPCR_EECB1              0x0002
#define EEPCR_EECB0              0x0001

//MBIR register
#define MBIR_TXMBF               0x1000
#define MBIR_TXMBFA              0x0800
#define MBIR_TXMBFC2             0x0400
#define MBIR_TXMBFC1             0x0200
#define MBIR_TXMBFC0             0x0100
#define MBIR_RXMBF               0x0010
#define MBIR_RXMBFA              0x0008
#define MBIR_RXMBFC2             0x0004
#define MBIR_RXMBFC1             0x0002
#define MBIR_RXMBFC0             0x0001

//GRR register
#define GRR_QMU_MODULE_SOFT_RST  0x0002
#define GRR_GLOBAL_SOFT_RST      0x0001

//WFCR register
#define WFCR_MPRXE               0x0080
#define WFCR_WF3E                0x0008
#define WFCR_WF2E                0x0004
#define WFCR_WF1E                0x0002
#define WFCR_WF0E                0x0001

//TXCR register
#define TXCR_TCGICMP             0x0100
#define TXCR_TCGUDP              0x0080
#define TXCR_TCGTCP              0x0040
#define TXCR_TCGIP               0x0020
#define TXCR_FTXQ                0x0010
#define TXCR_TXFCE               0x0008
#define TXCR_TXPE                0x0004
#define TXCR_TXCE                0x0002
#define TXCR_TXE                 0x0001

//TXSR register
#define TXSR_TXLC                0x2000
#define TXSR_TXMC                0x1000
#define TXSR_TXFID5              0x0020
#define TXSR_TXFID4              0x0010
#define TXSR_TXFID3              0x0008
#define TXSR_TXFID2              0x0004
#define TXSR_TXFID1              0x0002
#define TXSR_TXFID0              0x0001

//RXCR1 register
#define RXCR1_FRXQ               0x8000
#define RXCR1_RXUDPFCC           0x4000
#define RXCR1_RXTCPFCC           0x2000
#define RXCR1_RXIPFCC            0x1000
#define RXCR1_RXPAFMA            0x0800
#define RXCR1_RXFCE              0x0400
#define RXCR1_RXEFE              0x0200
#define RXCR1_RXMAFMA            0x0100
#define RXCR1_RXBE               0x0080
#define RXCR1_RXME               0x0040
#define RXCR1_RXUE               0x0020
#define RXCR1_RXAE               0x0010
#define RXCR1_RXINVF             0x0002
#define RXCR1_RXE                0x0001

//RXCR2 register
#define RXCR2_SRDBL2             0x0080
#define RXCR2_SRDBL1             0x0040
#define RXCR2_SRDBL0             0x0020
#define RXCR2_IUFFP              0x0010
#define RXCR2_RXIUFCEZ           0x0008
#define RXCR2_UDPLFE             0x0004
#define RXCR2_RXICMPFCC          0x0002
#define RXCR2_RXSAF              0x0001

//TXMIR register
#define TXMIR_TXMA_MASK          0x1FFF

//RXFHSR register
#define RXFHSR_RXFV              0x8000
#define RXFHSR_RXICMPFCS         0x2000
#define RXFHSR_RXIPFCS           0x1000
#define RXFHSR_RXTCPFCS          0x0800
#define RXFHSR_RXUDPFCS          0x0400
#define RXFHSR_RXBF              0x0080
#define RXFHSR_RXMF              0x0040
#define RXFHSR_RXUF              0x0020
#define RXFHSR_RXMR              0x0010
#define RXFHSR_RXFT              0x0008
#define RXFHSR_RXFTL             0x0004
#define RXFHSR_RXRF              0x0002
#define RXFHSR_RXCE              0x0001

//RXFHBCR register
#define RXFHBCR_RXBC_MASK        0x0FFF

//TXQCR register
#define TXQCR_AETFE              0x0004
#define TXQCR_TXQMAM             0x0002
#define TXQCR_METFE              0x0001

//RXQCR register
#define RXQCR_RXDTTS             0x1000
#define RXQCR_RXDBCTS            0x0800
#define RXQCR_RXFCTS             0x0400
#define RXQCR_RXIPHTOE           0x0200
#define RXQCR_RXDTTE             0x0080
#define RXQCR_RXDBCTE            0x0040
#define RXQCR_RXFCTE             0x0020
#define RXQCR_ADRFE              0x0010
#define RXQCR_SDA                0x0008
#define RXQCR_RRXEF              0x0001

//TXFDPR register
#define TXFDPR_TXFPAI            0x4000

//RXFDPR register
#define RXFDPR_RXFPAI            0x4000

//IER register
#define IER_LCIE                 0x8000
#define IER_TXIE                 0x4000
#define IER_RXIE                 0x2000
#define IER_RXOIE                0x0800
#define IER_TXPSIE               0x0200
#define IER_RXPSIE               0x0100
#define IER_TXSAIE               0x0040
#define IER_RXWFDIE              0x0020
#define IER_RXMPDIE              0x0010
#define IER_LDIE                 0x0008
#define IER_EDIE                 0x0004
#define IER_SPIBEIE              0x0002
#define IER_DEDIE                0x0001

//ISR register
#define ISR_LCIS                 0x8000
#define ISR_TXIS                 0x4000
#define ISR_RXIS                 0x2000
#define ISR_RXOIS                0x0800
#define ISR_TXPSIS               0x0200
#define ISR_RXPSIS               0x0100
#define ISR_TXSAIS               0x0040
#define ISR_RXWFDIS              0x0020
#define ISR_RXMPDIS              0x0010
#define ISR_LDIS                 0x0008
#define ISR_EDIS                 0x0004
#define ISR_SPIBEIS              0x0002

//CGCR register
#define CGCR_LEDSEL0             0x0200

//IACR register
#define IACR_READ_ENABLE         0x1000
#define IACR_TABLE_SELECT1       0x0800
#define IACR_TABLE_SELECT0       0x0400

//PMECR register
#define PMECR_PME_DELAY_EN       0x4000
#define PMECR_PME_POLARITY       0x1000
#define PMECR_PME_WUP_FRAME_EN   0x0800
#define PMECR_PME_MAGIC_EN       0x0400
#define PMECR_PME_LINK_UP_EN     0x0200
#define PMECR_PME_ENERGY_EN      0x0100
#define PMECR_AUTO_WUP_EN        0x0080
#define PMECR_WUP_NORMAL_OP_MODE 0x0040
#define PMECR_WUP_FROM_WUP_FRAME 0x0020
#define PMECR_WUP_FROM_MAGIC     0x0010
#define PMECR_WUP_FROM_LINK_UP   0x0008
#define PMECR_WUP_FROM_ENERGY    0x0004
#define PMECR_PWR_MODE1          0x0002
#define PMECR_PWR_MODE0          0x0001

//PHYRR register
#define PHYRR_PHY_RESET          0x0001

//P1MBCR register
#define P1MBCR_LOCAL_LOOPBACK    0x4000
#define P1MBCR_FORCE_100         0x2000
#define P1MBCR_AN_ENABLE         0x1000
#define P1MBCR_RESTART_AN        0x0200
#define P1MBCR_FORCE_FULL_DUPLEX 0x0100
#define P1MBCR_HP_MDIX           0x0020
#define P1MBCR_FORCE_MDIX        0x0010
#define P1MBCR_DISABLE_MDIX      0x0008
#define P1MBCR_DISABLE_TRANSMIT  0x0002
#define P1MBCR_DISABLE_LED       0x0001

//P1MBSR register
#define P1MBSR_T4_CAPABLE        0x8000
#define P1MBSR_100_FD_CAPABLE    0x4000
#define P1MBSR_100_CAPABLE       0x2000
#define P1MBSR_10_FD_CAPABLE     0x1000
#define P1MBSR_10_CAPABLE        0x0800
#define P1MBSR_PREAMBLE_SUPPR    0x0040
#define P1MBSR_AN_COMPLETE       0x0020
#define P1MBSR_AN_CAPABLE        0x0008
#define P1MBSR_LINK_STATUS       0x0004
#define P1MBSR_JABBER_TEST       0x0002
#define P1MBSR_EXTENDED_CAPABLE  0x0001

//P1ANAR register
#define P1ANAR_NEXT_PAGE         0x8000
#define P1ANAR_REMOTE_FAULT      0x2000
#define P1ANAR_ADV_PAUSE         0x0400
#define P1ANAR_ADV_100_FD        0x0100
#define P1ANAR_ADV_100           0x0080
#define P1ANAR_ADV_10_FD         0x0040
#define P1ANAR_ADV_10            0x0020
#define P1ANAR_SELECTOR_FIELD4   0x0010
#define P1ANAR_SELECTOR_FIELD3   0x0008
#define P1ANAR_SELECTOR_FIELD2   0x0004
#define P1ANAR_SELECTOR_FIELD1   0x0002
#define P1ANAR_SELECTOR_FIELD0   0x0001

//P1ANLPR register
#define P1ANLPR_NEXT_PAGE        0x8000
#define P1ANLPR_LP_ACK           0x4000
#define P1ANLPR_REMOTE_FAULT     0x2000
#define P1ANLPR_ADV_PAUSE        0x0400
#define P1ANLPR_ADV_100_FD       0x0100
#define P1ANLPR_ADV_100          0x0080
#define P1ANLPR_ADV_10_FD        0x0040
#define P1ANLPR_ADV_10           0x0020

//P1SCLMD register
#define P1SCLMD_VCT_RESULT1      0x4000
#define P1SCLMD_VCT_RESULT0      0x2000
#define P1SCLMD_VCT_EN           0x1000
#define P1SCLMD_FORCE_LNK        0x0800
#define P1SCLMD_REMOTE_LOOPBACK  0x0200

//P1CR register
#define P1CR_LED_OFF             0x8000
#define P1CR_TX_DISABLE          0x4000
#define P1CR_RESTART_AN          0x2000
#define P1CR_DISABLE_AUTO_MDIX   0x0400
#define P1CR_FORCE_MDIX          0x0200
#define P1CR_AN_ENABLE           0x0080
#define P1CR_FORCE_SPEED         0x0040
#define P1CR_FORCE_DUPLEX        0x0020
#define P1CR_ADV_PAUSE           0x0010
#define P1CR_ADV_100_FD          0x0008
#define P1CR_ADV_100             0x0004
#define P1CR_ADV_10_FD           0x0002
#define P1CR_ADV_10              0x0001

//P1SR register
#define P1SR_HP_MDIX             0x8000
#define P1SR_REVERSED_POLARITY   0x2000
#define P1SR_OPERATION_SPEED     0x0400
#define P1SR_OPERATION_DUPLEX    0x0200
#define P1SR_MDIX_STATUS         0x0080
#define P1SR_AN_DONE             0x0040
#define P1SR_LINK_GOOD           0x0020
#define P1SR_PARTNER_ADV_PAUSE   0x0010
#define P1SR_PARTNER_ADV_100_FD  0x0008
#define P1SR_PARTNER_ADV_100     0x0004
#define P1SR_PARTNER_ADV_10_FD   0x0002
#define P1SR_PARTNER_ADV_10      0x0001
#define TX_CTRL_TXIC             0x8000
#define TX_CTRL_TXFID            0x003F
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
//Keil MDK-ARM or GCC compiler?
      //Sucessful processing
      //Sucessful processing
      //Sucessful processing
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0


 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
//Keil MDK-ARM or GCC compiler?
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @file lpc546xx_eth_driver.c
 * @brief LPC54608/LPC54618/LPC54628 Ethernet MAC driver
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
#include "drivers/mac/lpc546xx_eth_driver.h"
static uint8_t txBuffer[LPC546XX_ETH_TX_BUFFER_COUNT][LPC546XX_ETH_TX_BUFFER_SIZE];
static uint8_t rxBuffer[LPC546XX_ETH_RX_BUFFER_COUNT][LPC546XX_ETH_RX_BUFFER_SIZE];
static Lpc546xxTxDmaDesc txDmaDesc[LPC546XX_ETH_TX_BUFFER_COUNT];
static Lpc546xxRxDmaDesc rxDmaDesc[LPC546XX_ETH_RX_BUFFER_COUNT];
static uint8_t txBuffer[LPC546XX_ETH_TX_BUFFER_COUNT][LPC546XX_ETH_TX_BUFFER_SIZE]
static uint8_t rxBuffer[LPC546XX_ETH_RX_BUFFER_COUNT][LPC546XX_ETH_RX_BUFFER_SIZE]
static Lpc546xxTxDmaDesc txDmaDesc[LPC546XX_ETH_TX_BUFFER_COUNT]
static Lpc546xxRxDmaDesc rxDmaDesc[LPC546XX_ETH_RX_BUFFER_COUNT]
 * @brief LPC546xx Ethernet MAC driver
const NicDriver lpc546xxEthDriver =
   lpc546xxEthInit,
   lpc546xxEthTick,
   lpc546xxEthEnableIrq,
   lpc546xxEthDisableIrq,
   lpc546xxEthEventHandler,
   lpc546xxEthSendPacket,
   lpc546xxEthUpdateMacAddrFilter,
   lpc546xxEthUpdateMacConfig,
   lpc546xxEthWritePhyReg,
   lpc546xxEthReadPhyReg,
 * @brief LPC546xx Ethernet MAC initialization
error_t lpc546xxEthInit(NetInterface *interface)
   TRACE_INFO("Initializing LPC546xx Ethernet MAC...\r\n");
   lpc546xxEthInitGpio(interface);
      ENET_DMA_CH_DMA_CHX_RX_CTRL_RBSZ(LPC546XX_ETH_RX_BUFFER_SIZE / 4);
   lpc546xxEthInitDmaDesc(interface);
   NVIC_SetPriorityGrouping(LPC546XX_ETH_IRQ_PRIORITY_GROUPING);
   NVIC_SetPriority(ETHERNET_IRQn, NVIC_EncodePriority(LPC546XX_ETH_IRQ_PRIORITY_GROUPING,
      LPC546XX_ETH_IRQ_GROUP_PRIORITY, LPC546XX_ETH_IRQ_SUB_PRIORITY));
//LPCXpresso54608 evaluation board?
#if defined(USE_LPCXPRESSO_54608)
void lpc546xxEthInitGpio(NetInterface *interface)
   //Configure ENET_TXD1 (PA0_17)
   //Configure ENET_TXD0 (PA4_8)
   //Configure ENET_RX_DV (PA4_10)
   //Configure ENET_RXD0 (PA4_11)
   //Configure ENET_RXD1 (PA4_12)
   //Configure ENET_TX_EN (PA4_13)
   //Configure ENET_RX_CLK (PA4_14)
   //Configure ENET_MDC (PA4_15)
   //Configure ENET_MDIO (PA4_16)
   //Configure ENET_RST as an output
   GPIO_WritePinOutput(GPIO, 2, 26, 0);
   GPIO_WritePinOutput(GPIO, 2, 26, 1);
void lpc546xxEthInitDmaDesc(NetInterface *interface)
   for(i = 0; i < LPC546XX_ETH_TX_BUFFER_COUNT; i++)
   for(i = 0; i < LPC546XX_ETH_RX_BUFFER_COUNT; i++)
   ENET->DMA_CH[0].DMA_CHX_TXDESC_RING_LENGTH = LPC546XX_ETH_TX_BUFFER_COUNT - 1;
   ENET->DMA_CH[0].DMA_CHX_RXDESC_RING_LENGTH = LPC546XX_ETH_RX_BUFFER_COUNT - 1;
 * @brief LPC546xx Ethernet MAC timer handler
void lpc546xxEthTick(NetInterface *interface)
void lpc546xxEthEnableIrq(NetInterface *interface)
void lpc546xxEthDisableIrq(NetInterface *interface)
 * @brief LPC546xx Ethernet MAC interrupt service routine
 * @brief LPC546xx Ethernet MAC event handler
void lpc546xxEthEventHandler(NetInterface *interface)
         error = lpc546xxEthReceivePacket(interface);
error_t lpc546xxEthSendPacket(NetInterface *interface,
   if(length > LPC546XX_ETH_TX_BUFFER_SIZE)
   if(++txIndex >= LPC546XX_ETH_TX_BUFFER_COUNT)
error_t lpc546xxEthReceivePacket(NetInterface *interface)
            n = MIN(n, LPC546XX_ETH_RX_BUFFER_SIZE);
      if(++rxIndex >= LPC546XX_ETH_RX_BUFFER_COUNT)
error_t lpc546xxEthUpdateMacAddrFilter(NetInterface *interface)
error_t lpc546xxEthUpdateMacConfig(NetInterface *interface)
void lpc546xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
uint16_t lpc546xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
 * @file lpc546xx_eth_driver.h
 * @brief LPC54608/LPC54618/LPC54628 Ethernet MAC driver
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
#ifndef _LPC546XX_ETH_DRIVER_H
#define _LPC546XX_ETH_DRIVER_H
#ifndef LPC546XX_ETH_TX_BUFFER_COUNT
   #define LPC546XX_ETH_TX_BUFFER_COUNT 3
#elif (LPC546XX_ETH_TX_BUFFER_COUNT < 1)
   #error LPC546XX_ETH_TX_BUFFER_COUNT parameter is not valid
#ifndef LPC546XX_ETH_TX_BUFFER_SIZE
   #define LPC546XX_ETH_TX_BUFFER_SIZE 1536
#elif (LPC546XX_ETH_TX_BUFFER_SIZE != 1536)
   #error LPC546XX_ETH_TX_BUFFER_SIZE parameter is not valid
#ifndef LPC546XX_ETH_RX_BUFFER_COUNT
   #define LPC546XX_ETH_RX_BUFFER_COUNT 6
#elif (LPC546XX_ETH_RX_BUFFER_COUNT < 1)
   #error LPC546XX_ETH_RX_BUFFER_COUNT parameter is not valid
#ifndef LPC546XX_ETH_RX_BUFFER_SIZE
   #define LPC546XX_ETH_RX_BUFFER_SIZE 1536
#elif (LPC546XX_ETH_RX_BUFFER_SIZE != 1536)
   #error LPC546XX_ETH_RX_BUFFER_SIZE parameter is not valid
#ifndef LPC546XX_ETH_IRQ_PRIORITY_GROUPING
   #define LPC546XX_ETH_IRQ_PRIORITY_GROUPING 4
#elif (LPC546XX_ETH_IRQ_PRIORITY_GROUPING < 0)
   #error LPC546XX_ETH_IRQ_PRIORITY_GROUPING parameter is not valid
#ifndef LPC546XX_ETH_IRQ_GROUP_PRIORITY
   #define LPC546XX_ETH_IRQ_GROUP_PRIORITY 6
#elif (LPC546XX_ETH_IRQ_GROUP_PRIORITY < 0)
   #error LPC546XX_ETH_IRQ_GROUP_PRIORITY parameter is not valid
#ifndef LPC546XX_ETH_IRQ_SUB_PRIORITY
   #define LPC546XX_ETH_IRQ_SUB_PRIORITY 0
#elif (LPC546XX_ETH_IRQ_SUB_PRIORITY < 0)
   #error LPC546XX_ETH_IRQ_SUB_PRIORITY parameter is not valid
} Lpc546xxTxDmaDesc;
} Lpc546xxRxDmaDesc;
//LPC546xx Ethernet MAC driver
extern const NicDriver lpc546xxEthDriver;
//LPC546xx Ethernet MAC related functions
error_t lpc546xxEthInit(NetInterface *interface);
void lpc546xxEthInitGpio(NetInterface *interface);
void lpc546xxEthInitDmaDesc(NetInterface *interface);
void lpc546xxEthTick(NetInterface *interface);
void lpc546xxEthEnableIrq(NetInterface *interface);
void lpc546xxEthDisableIrq(NetInterface *interface);
void lpc546xxEthEventHandler(NetInterface *interface);
error_t lpc546xxEthSendPacket(NetInterface *interface,
error_t lpc546xxEthReceivePacket(NetInterface *interface);
error_t lpc546xxEthUpdateMacAddrFilter(NetInterface *interface);
error_t lpc546xxEthUpdateMacConfig(NetInterface *interface);
void lpc546xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
uint16_t lpc546xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
//Keil MDK-ARM or GCC compiler?
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
//RDK RX62N evaluation board?
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
//RDK RX63N or RSK RX63N evaluation board?
#if defined(USE_RDK_RX63N) || defined(USE_RSK_RX63N)
#elif defined(USE_RSK_RX63N)
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   __attribute__((section(".BSS_DMAC_SAMPLE_INTERNAL_RAM"), aligned(32)));
   __attribute__((section(".BSS_DMAC_SAMPLE_INTERNAL_RAM"), aligned(32)));
   __attribute__((section(".BSS_DMAC_SAMPLE_INTERNAL_RAM"), aligned(32)));
   __attribute__((section(".BSS_DMAC_SAMPLE_INTERNAL_RAM"), aligned(32)));
   ETHER.EESIPR0 =  ETHER_EESIPR0_TWBIP | ETHER_EESIPR0_FRIP;
//RSK RZ/A1H, Stream it! RZ, Hachiko or VK-RZ/A1H evaluation board?
   ETHER.EESIPR0 =  ETHER_EESIPR0_TWBIP | ETHER_EESIPR0_FRIP;
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
//STM32F743I-EVAL, STM32F747I-EVAL, STM32H745I-Discovery, STM32H747I-Discovery,
//STM32H750B-DK, Nucleo-H743ZI, Nucleo-H743ZI2 or Nucleo-H745ZI-Q evaluation board?
   defined(USE_STM32H745I_DISCO) || defined(USE_STM32H747I_DISCO) || \
   defined(USE_STM32H750B_DISCO) || defined(USE_STM32H7XX_NUCLEO_144) || \
   defined(USE_STM32H7XX_NUCLEO_144_MB1363) || \
   defined(USE_STM32H7XX_NUCLEO_144_MB1364)
//Nucleo-H743ZI, Nucleo-H743ZI2 or Nucleo-H745ZI-Q evaluation board?
#elif defined(USE_STM32H7XX_NUCLEO_144) || defined(USE_STM32H7XX_NUCLEO_144_MB1363) || \
   defined(USE_STM32H7XX_NUCLEO_144_MB1364)
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
//Keil MDK-ARM or GCC compiler?
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
//Keil MDK-ARM or GCC compiler?
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   value |= TJA1100_CONFIG1_MII_MODE_RMII_25MHZ;
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
#define TJA1100_BASIC_CTRL                           0x00
#define TJA1100_BASIC_STAT                           0x01
#define TJA1100_PHY_ID1                              0x02
#define TJA1100_PHY_ID2                              0x03
#define TJA1100_EXTENDED_STAT                        0x0F
#define TJA1100_PHY_ID3                              0x10
#define TJA1100_EXTENDED_CTRL                        0x11
#define TJA1100_CONFIG1                              0x12
#define TJA1100_CONFIG2                              0x13
#define TJA1100_SYM_ERR_COUNTER                      0x14
#define TJA1100_INT_SRC                              0x15
#define TJA1100_INT_EN                               0x16
#define TJA1100_COMM_STAT                            0x17
#define TJA1100_GENERAL_STAT                         0x18
#define TJA1100_EXTERNAL_STAT                        0x19
#define TJA1100_LINK_FAIL_COUNTER                    0x1A
#define TJA1100_BASIC_CTRL_RESET                     0x8000
#define TJA1100_BASIC_CTRL_LOOPBACK                  0x4000
#define TJA1100_BASIC_CTRL_SPEED_SEL_LSB             0x2000
#define TJA1100_BASIC_CTRL_AUTONEG_EN                0x1000
#define TJA1100_BASIC_CTRL_POWER_DOWN                0x0800
#define TJA1100_BASIC_CTRL_ISOLATE                   0x0400
#define TJA1100_BASIC_CTRL_RE_AUTONEG                0x0200
#define TJA1100_BASIC_CTRL_DUPLEX_MODE               0x0100
#define TJA1100_BASIC_CTRL_COL_TEST                  0x0080
#define TJA1100_BASIC_CTRL_SPEED_SEL_MSB             0x0040
#define TJA1100_BASIC_CTRL_UNIDIRECT_EN              0x0020
#define TJA1100_BASIC_STAT_100BT4                    0x8000
#define TJA1100_BASIC_STAT_100BTX_FD                 0x4000
#define TJA1100_BASIC_STAT_100BTX_HD                 0x2000
#define TJA1100_BASIC_STAT_10BT_FD                   0x1000
#define TJA1100_BASIC_STAT_10BT_HD                   0x0800
#define TJA1100_BASIC_STAT_100BT2_FD                 0x0400
#define TJA1100_BASIC_STAT_100BT2_HD                 0x0200
#define TJA1100_BASIC_STAT_EXTENDED_STATUS           0x0100
#define TJA1100_BASIC_STAT_UNIDIRECT_ABILITY         0x0080
#define TJA1100_BASIC_STAT_MF_PREAMBLE_SUPPR         0x0040
#define TJA1100_BASIC_STAT_AUTONEG_COMPLETE          0x0020
#define TJA1100_BASIC_STAT_REMOTE_FAULT              0x0010
#define TJA1100_BASIC_STAT_AUTONEG_ABILITY           0x0008
#define TJA1100_BASIC_STAT_LINK_STATUS               0x0004
#define TJA1100_BASIC_STAT_JABBER_DETECT             0x0002
#define TJA1100_BASIC_STAT_EXTENDED_CAPABILITY       0x0001
#define TJA1100_PHY_ID1_OUI_MSB                      0xFFFF
#define TJA1100_PHY_ID1_OUI_MSB_DEFAULT              0x0180
#define TJA1100_PHY_ID2_OUI_LSB                      0xFC00
#define TJA1100_PHY_ID2_OUI_LSB_DEFAULT              0xDC00
#define TJA1100_PHY_ID2_TYPE_NO                      0x03F0
#define TJA1100_PHY_ID2_TYPE_NO_DEFAULT              0x0040
#define TJA1100_PHY_ID2_REVISION_NO                  0x000F
#define TJA1100_EXTENDED_STAT_1000BX_FD              0x8000
#define TJA1100_EXTENDED_STAT_1000BX_HD              0x4000
#define TJA1100_EXTENDED_STAT_1000BT_FD              0x2000
#define TJA1100_EXTENDED_STAT_1000BT_HD              0x1000
#define TJA1100_EXTENDED_STAT_100BT1                 0x0080
#define TJA1100_EXTENDED_STAT_1000BT1                0x0040
#define TJA1100_PHY_ID3_VERSION_NO                   0x00FF
#define TJA1100_EXTENDED_CTRL_LINK_CONTROL           0x8000
#define TJA1100_EXTENDED_CTRL_POWER_MODE             0x7800
#define TJA1100_EXTENDED_CTRL_POWER_MODE_NO_CHANGE   0x0000
#define TJA1100_EXTENDED_CTRL_POWER_MODE_NORMAL      0x1800
#define TJA1100_EXTENDED_CTRL_POWER_MODE_SLEEP_REQ   0x5800
#define TJA1100_EXTENDED_CTRL_POWER_MODE_STANDBY     0x6000
#define TJA1100_EXTENDED_CTRL_SLAVE_JITTER_TEST      0x0400
#define TJA1100_EXTENDED_CTRL_TRAINING_RESTART       0x0200
#define TJA1100_EXTENDED_CTRL_TEST_MODE              0x01C0
#define TJA1100_EXTENDED_CTRL_TEST_MODE_0            0x0000
#define TJA1100_EXTENDED_CTRL_TEST_MODE_1            0x0040
#define TJA1100_EXTENDED_CTRL_TEST_MODE_2            0x0080
#define TJA1100_EXTENDED_CTRL_TEST_MODE_3            0x00C0
#define TJA1100_EXTENDED_CTRL_TEST_MODE_4            0x0100
#define TJA1100_EXTENDED_CTRL_TEST_MODE_5            0x0140
#define TJA1100_EXTENDED_CTRL_TEST_MODE_6            0x0180
#define TJA1100_EXTENDED_CTRL_CABLE_TEST             0x0020
#define TJA1100_EXTENDED_CTRL_LOOPBACK_MODE          0x0018
#define TJA1100_EXTENDED_CTRL_LOOPBACK_MODE_INTERNAL 0x0000
#define TJA1100_EXTENDED_CTRL_LOOPBACK_MODE_EXTERNAL 0x0008
#define TJA1100_EXTENDED_CTRL_LOOPBACK_MODE_REMOTE   0x0018
#define TJA1100_EXTENDED_CTRL_CONFIG_EN              0x0004
#define TJA1100_EXTENDED_CTRL_CONFIG_INH             0x0002
#define TJA1100_EXTENDED_CTRL_WAKE_REQUEST           0x0001
#define TJA1100_CONFIG1_MASTER_SLAVE                 0x8000
#define TJA1100_CONFIG1_AUTO_OP                      0x4000
#define TJA1100_CONFIG1_LINK_LENGTH                  0x2000
#define TJA1100_CONFIG1_TX_AMPLITUDE                 0x0C00
#define TJA1100_CONFIG1_TX_AMPLITUDE_500MV           0x0000
#define TJA1100_CONFIG1_TX_AMPLITUDE_750MV           0x0400
#define TJA1100_CONFIG1_TX_AMPLITUDE_1000MV          0x0800
#define TJA1100_CONFIG1_TX_AMPLITUDE_1250MV          0x0C00
#define TJA1100_CONFIG1_MII_MODE                     0x0300
#define TJA1100_CONFIG1_MII_MODE_MII                 0x0000
#define TJA1100_CONFIG1_MII_MODE_RMII_50MHZ          0x0100
#define TJA1100_CONFIG1_MII_MODE_RMII_25MHZ          0x0200
#define TJA1100_CONFIG1_MII_MODE_REV_MII             0x0300
#define TJA1100_CONFIG1_MII_DRIVER                   0x0080
#define TJA1100_CONFIG1_LED_MODE                     0x0030
#define TJA1100_CONFIG1_LED_MODE_LINK_UP             0x0000
#define TJA1100_CONFIG1_LED_MODE_FRAME_RX            0x0010
#define TJA1100_CONFIG1_LED_MODE_SYM_ERR             0x0020
#define TJA1100_CONFIG1_LED_MODE_CRS                 0x0030
#define TJA1100_CONFIG1_LED_ENABLE                   0x0008
#define TJA1100_CONFIG1_CONFIG_WAKE                  0x0004
#define TJA1100_CONFIG1_AUTO_PWD                     0x0002
#define TJA1100_CONFIG2_PHYAD                        0xF800
#define TJA1100_CONFIG2_SQI_AVERAGING                0x0600
#define TJA1100_CONFIG2_SQI_AVERAGING_32_SYMBOLS     0x0000
#define TJA1100_CONFIG2_SQI_AVERAGING_64_SYMBOLS     0x0200
#define TJA1100_CONFIG2_SQI_AVERAGING_128_SYMBOLS    0x0400
#define TJA1100_CONFIG2_SQI_AVERAGING_256_SYMBOLS    0x0600
#define TJA1100_CONFIG2_SQI_WLIMIT                   0x01C0
#define TJA1100_CONFIG2_SQI_WLIMIT_NONE              0x0000
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_A           0x0040
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_B           0x0080
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_C           0x00C0
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_D           0x0100
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_E           0x0140
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_F           0x0180
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_G           0x01C0
#define TJA1100_CONFIG2_SQI_FAILLIMIT                0x0038
#define TJA1100_CONFIG2_SQI_FAILLIMIT_NONE           0x0000
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_A        0x0008
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_B        0x0010
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_C        0x0018
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_D        0x0020
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_E        0x0028
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_F        0x0030
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_G        0x0038
#define TJA1100_CONFIG2_JUMBO_ENABLE                 0x0004
#define TJA1100_CONFIG2_SLEEP_REQUEST_TO             0x0003
#define TJA1100_CONFIG2_SLEEP_REQUEST_TO_0_4MS       0x0000
#define TJA1100_CONFIG2_SLEEP_REQUEST_TO_1MS         0x0001
#define TJA1100_CONFIG2_SLEEP_REQUEST_TO_4MS         0x0002
#define TJA1100_CONFIG2_SLEEP_REQUEST_TO_16MS        0x0003
#define TJA1100_SYM_ERR_COUNTER_SYM_ERR_CNT          0xFFFF
#define TJA1100_INT_SRC_PWON                         0x8000
#define TJA1100_INT_SRC_WAKEUP                       0x4000
#define TJA1100_INT_SRC_PHY_INIT_FAIL                0x0800
#define TJA1100_INT_SRC_LINK_STATUS_FAIL             0x0400
#define TJA1100_INT_SRC_LINK_STATUS_UP               0x0200
#define TJA1100_INT_SRC_SYM_ERR                      0x0100
#define TJA1100_INT_SRC_TRAINING_FAILED              0x0080
#define TJA1100_INT_SRC_SQI_WARNING                  0x0040
#define TJA1100_INT_SRC_CONTROL_ERR                  0x0020
#define TJA1100_INT_SRC_UV_ERR                       0x0008
#define TJA1100_INT_SRC_UV_RECOVERY                  0x0004
#define TJA1100_INT_SRC_TEMP_ERR                     0x0002
#define TJA1100_INT_SRC_SLEEP_ABORT                  0x0001
#define TJA1100_INT_EN_PWON                          0x8000
#define TJA1100_INT_EN_WAKEUP                        0x4000
#define TJA1100_INT_EN_PHY_INIT_FAIL                 0x0800
#define TJA1100_INT_EN_LINK_STATUS_FAIL              0x0400
#define TJA1100_INT_EN_LINK_STATUS_UP                0x0200
#define TJA1100_INT_EN_SYM_ERR                       0x0100
#define TJA1100_INT_EN_TRAINING_FAILED               0x0080
#define TJA1100_INT_EN_SQI_WARNING                   0x0040
#define TJA1100_INT_EN_CONTROL_ERR                   0x0020
#define TJA1100_INT_EN_UV_ERR                        0x0008
#define TJA1100_INT_EN_UV_RECOVERY                   0x0004
#define TJA1100_INT_EN_TEMP_ERR                      0x0002
#define TJA1100_INT_EN_SLEEP_ABORT                   0x0001
#define TJA1100_COMM_STAT_LINK_UP                    0x8000
#define TJA1100_COMM_STAT_TX_MODE                    0x6000
#define TJA1100_COMM_STAT_TX_MODE_DISABLED           0x0000
#define TJA1100_COMM_STAT_TX_MODE_SEND_N             0x2000
#define TJA1100_COMM_STAT_TX_MODE_SEND_I             0x4000
#define TJA1100_COMM_STAT_TX_MODE_SEND_Z             0x6000
#define TJA1100_COMM_STAT_LOC_RCVR_STATUS            0x1000
#define TJA1100_COMM_STAT_REM_RCVR_STATUS            0x0800
#define TJA1100_COMM_STAT_SCR_LOCKED                 0x0400
#define TJA1100_COMM_STAT_SSD_ERR                    0x0200
#define TJA1100_COMM_STAT_ESD_ERR                    0x0100
#define TJA1100_COMM_STAT_SQI                        0x00E0
#define TJA1100_COMM_STAT_SQI_WORSE_THAN_CLASS_A     0x0000
#define TJA1100_COMM_STAT_SQI_CLASS_A                0x0020
#define TJA1100_COMM_STAT_SQI_CLASS_B                0x0040
#define TJA1100_COMM_STAT_SQI_CLASS_C                0x0060
#define TJA1100_COMM_STAT_SQI_CLASS_D                0x0080
#define TJA1100_COMM_STAT_SQI_CLASS_E                0x00A0
#define TJA1100_COMM_STAT_SQI_CLASS_F                0x00C0
#define TJA1100_COMM_STAT_SQI_CLASS_G                0x00E0
#define TJA1100_COMM_STAT_RECEIVE_ERR                0x0010
#define TJA1100_COMM_STAT_TRANSMIT_ERR               0x0008
#define TJA1100_COMM_STAT_PHY_STATE                  0x0007
#define TJA1100_COMM_STAT_PHY_STATE_IDLE             0x0000
#define TJA1100_COMM_STAT_PHY_STATE_INITIALIZING     0x0001
#define TJA1100_COMM_STAT_PHY_STATE_CONFIGURED       0x0002
#define TJA1100_COMM_STAT_PHY_STATE_OFFLINE          0x0003
#define TJA1100_COMM_STAT_PHY_STATE_ACTIVE           0x0004
#define TJA1100_COMM_STAT_PHY_STATE_ISOLATE          0x0005
#define TJA1100_COMM_STAT_PHY_STATE_CABLE_TEST       0x0006
#define TJA1100_COMM_STAT_PHY_STATE_TEST_MODE        0x0007
#define TJA1100_GENERAL_STAT_INT_STATUS              0x8000
#define TJA1100_GENERAL_STAT_PLL_LOCKED              0x4000
#define TJA1100_GENERAL_STAT_LOCAL_WU                0x2000
#define TJA1100_GENERAL_STAT_REMOTE_WU               0x1000
#define TJA1100_GENERAL_STAT_DATA_DET_WU             0x0800
#define TJA1100_GENERAL_STAT_EN_STATUS               0x0400
#define TJA1100_GENERAL_STAT_RESET_STATUS            0x0200
#define TJA1100_GENERAL_STAT_LINKFAIL_CNT            0x00F8
#define TJA1100_EXTERNAL_STAT_UV_VDDA_3V3            0x4000
#define TJA1100_EXTERNAL_STAT_UV_VDDD_1V8            0x2000
#define TJA1100_EXTERNAL_STAT_UV_VDDA_1V8            0x1000
#define TJA1100_EXTERNAL_STAT_UV_VDDIO               0x0800
#define TJA1100_EXTERNAL_STAT_TEMP_HIGH              0x0400
#define TJA1100_EXTERNAL_STAT_TEMP_WARN              0x0200
#define TJA1100_EXTERNAL_STAT_SHORT_DETECT           0x0100
#define TJA1100_EXTERNAL_STAT_OPEN_DETECT            0x0080
#define TJA1100_EXTERNAL_STAT_POLARITY_DETECT        0x0040
#define TJA1100_EXTERNAL_STAT_INTERLEAVE_DETECT      0x0020
#define TJA1100_LINK_FAIL_COUNTER_LOC_RCVR_CNT       0xFF00
#define TJA1100_LINK_FAIL_COUNTER_REM_RCVR_CNT       0x00FF
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   //Select RMII mode (25MHz XTAL)
   value |= TJA1101_CONFIG1_MII_MODE_RMII_25MHZ;
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
#define TJA1101_BASIC_CTRL                           0x00
#define TJA1101_BASIC_STAT                           0x01
#define TJA1101_PHY_ID1                              0x02
#define TJA1101_PHY_ID2                              0x03
#define TJA1101_EXTENDED_STAT                        0x0F
#define TJA1101_PHY_ID3                              0x10
#define TJA1101_EXTENDED_CTRL                        0x11
#define TJA1101_CONFIG1                              0x12
#define TJA1101_CONFIG2                              0x13
#define TJA1101_SYM_ERR_COUNTER                      0x14
#define TJA1101_INT_SRC                              0x15
#define TJA1101_INT_EN                               0x16
#define TJA1101_COMM_STAT                            0x17
#define TJA1101_GENERAL_STAT                         0x18
#define TJA1101_EXTERNAL_STAT                        0x19
#define TJA1101_LINK_FAIL_COUNTER                    0x1A
#define TJA1101_COMM_CTRL                            0x1B
#define TJA1101_CONFIG3                              0x1C
#define TJA1101_BASIC_CTRL_RESET                     0x8000
#define TJA1101_BASIC_CTRL_LOOPBACK                  0x4000
#define TJA1101_BASIC_CTRL_SPEED_SEL_LSB             0x2000
#define TJA1101_BASIC_CTRL_AUTONEG_EN                0x1000
#define TJA1101_BASIC_CTRL_POWER_DOWN                0x0800
#define TJA1101_BASIC_CTRL_ISOLATE                   0x0400
#define TJA1101_BASIC_CTRL_RE_AUTONEG                0x0200
#define TJA1101_BASIC_CTRL_DUPLEX_MODE               0x0100
#define TJA1101_BASIC_CTRL_COL_TEST                  0x0080
#define TJA1101_BASIC_CTRL_SPEED_SEL_MSB             0x0040
#define TJA1101_BASIC_CTRL_UNIDIRECT_EN              0x0020
#define TJA1101_BASIC_STAT_100BT4                    0x8000
#define TJA1101_BASIC_STAT_100BTX_FD                 0x4000
#define TJA1101_BASIC_STAT_100BTX_HD                 0x2000
#define TJA1101_BASIC_STAT_10BT_FD                   0x1000
#define TJA1101_BASIC_STAT_10BT_HD                   0x0800
#define TJA1101_BASIC_STAT_100BT2_FD                 0x0400
#define TJA1101_BASIC_STAT_100BT2_HD                 0x0200
#define TJA1101_BASIC_STAT_EXTENDED_STATUS           0x0100
#define TJA1101_BASIC_STAT_UNIDIRECT_ABILITY         0x0080
#define TJA1101_BASIC_STAT_MF_PREAMBLE_SUPPR         0x0040
#define TJA1101_BASIC_STAT_AUTONEG_COMPLETE          0x0020
#define TJA1101_BASIC_STAT_REMOTE_FAULT              0x0010
#define TJA1101_BASIC_STAT_AUTONEG_ABILITY           0x0008
#define TJA1101_BASIC_STAT_LINK_STATUS               0x0004
#define TJA1101_BASIC_STAT_JABBER_DETECT             0x0002
#define TJA1101_BASIC_STAT_EXTENDED_CAPABILITY       0x0001
#define TJA1101_PHY_ID1_OUI_MSB                      0xFFFF
#define TJA1101_PHY_ID1_OUI_MSB_DEFAULT              0x0180
#define TJA1101_PHY_ID2_OUI_LSB                      0xFC00
#define TJA1101_PHY_ID2_OUI_LSB_DEFAULT              0xDC00
#define TJA1101_PHY_ID2_TYPE_NO                      0x03F0
#define TJA1101_PHY_ID2_TYPE_NO_DEFAULT              0x0100
#define TJA1101_PHY_ID2_REVISION_NO                  0x000F
#define TJA1101_EXTENDED_STAT_1000BX_FD              0x8000
#define TJA1101_EXTENDED_STAT_1000BX_HD              0x4000
#define TJA1101_EXTENDED_STAT_1000BT_FD              0x2000
#define TJA1101_EXTENDED_STAT_1000BT_HD              0x1000
#define TJA1101_EXTENDED_STAT_100BT1                 0x0080
#define TJA1101_EXTENDED_STAT_1000BT1                0x0040
#define TJA1101_PHY_ID3_VERSION_NO                   0x00FF
#define TJA1101_EXTENDED_CTRL_LINK_CONTROL           0x8000
#define TJA1101_EXTENDED_CTRL_POWER_MODE             0x7800
#define TJA1101_EXTENDED_CTRL_POWER_MODE_NO_CHANGE   0x0000
#define TJA1101_EXTENDED_CTRL_POWER_MODE_NORMAL      0x1800
#define TJA1101_EXTENDED_CTRL_POWER_MODE_SLEEP_REQ   0x5800
#define TJA1101_EXTENDED_CTRL_POWER_MODE_STANDBY     0x6000
#define TJA1101_EXTENDED_CTRL_SLAVE_JITTER_TEST      0x0400
#define TJA1101_EXTENDED_CTRL_TRAINING_RESTART       0x0200
#define TJA1101_EXTENDED_CTRL_TEST_MODE              0x01C0
#define TJA1101_EXTENDED_CTRL_TEST_MODE_0            0x0000
#define TJA1101_EXTENDED_CTRL_TEST_MODE_1            0x0040
#define TJA1101_EXTENDED_CTRL_TEST_MODE_2            0x0080
#define TJA1101_EXTENDED_CTRL_TEST_MODE_3            0x00C0
#define TJA1101_EXTENDED_CTRL_TEST_MODE_4            0x0100
#define TJA1101_EXTENDED_CTRL_TEST_MODE_5            0x0140
#define TJA1101_EXTENDED_CTRL_TEST_MODE_6            0x0180
#define TJA1101_EXTENDED_CTRL_CABLE_TEST             0x0020
#define TJA1101_EXTENDED_CTRL_LOOPBACK_MODE          0x0018
#define TJA1101_EXTENDED_CTRL_LOOPBACK_MODE_INTERNAL 0x0000
#define TJA1101_EXTENDED_CTRL_LOOPBACK_MODE_EXTERNAL 0x0008
#define TJA1101_EXTENDED_CTRL_LOOPBACK_MODE_REMOTE   0x0018
#define TJA1101_EXTENDED_CTRL_CONFIG_EN              0x0004
#define TJA1101_EXTENDED_CTRL_CONFIG_INH             0x0002
#define TJA1101_EXTENDED_CTRL_WAKE_REQUEST           0x0001
#define TJA1101_CONFIG1_MASTER_SLAVE                 0x8000
#define TJA1101_CONFIG1_FWDPHYLOC                    0x4000
#define TJA1101_CONFIG1_LINK_LENGTH                  0x2000
#define TJA1101_CONFIG1_REMWUPHY                     0x0800
#define TJA1101_CONFIG1_LOCWUPHY                     0x0400
#define TJA1101_CONFIG1_MII_MODE                     0x0300
#define TJA1101_CONFIG1_MII_MODE_MII                 0x0000
#define TJA1101_CONFIG1_MII_MODE_RMII_50MHZ          0x0100
#define TJA1101_CONFIG1_MII_MODE_RMII_25MHZ          0x0200
#define TJA1101_CONFIG1_MII_MODE_REV_MII             0x0300
#define TJA1101_CONFIG1_MII_DRIVER                   0x0080
#define TJA1101_CONFIG1_SLEEP_CONFIRM                0x0040
#define TJA1101_CONFIG1_FWDPHYREM                    0x0004
#define TJA1101_CONFIG1_AUTO_PWD                     0x0002
#define TJA1101_CONFIG1_LPS_ACTIVE                   0x0001
#define TJA1101_CONFIG2_PHYAD                        0xF800
#define TJA1101_CONFIG2_SQI_AVERAGING                0x0600
#define TJA1101_CONFIG2_SQI_AVERAGING_32_SYMBOLS     0x0000
#define TJA1101_CONFIG2_SQI_AVERAGING_64_SYMBOLS     0x0200
#define TJA1101_CONFIG2_SQI_AVERAGING_128_SYMBOLS    0x0400
#define TJA1101_CONFIG2_SQI_AVERAGING_256_SYMBOLS    0x0600
#define TJA1101_CONFIG2_SQI_WLIMIT                   0x01C0
#define TJA1101_CONFIG2_SQI_WLIMIT_NONE              0x0000
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_A           0x0040
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_B           0x0080
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_C           0x00C0
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_D           0x0100
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_E           0x0140
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_F           0x0180
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_G           0x01C0
#define TJA1101_CONFIG2_SQI_FAILLIMIT                0x0038
#define TJA1101_CONFIG2_SQI_FAILLIMIT_NONE           0x0000
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_A        0x0008
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_B        0x0010
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_C        0x0018
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_D        0x0020
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_E        0x0028
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_F        0x0030
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_G        0x0038
#define TJA1101_CONFIG2_JUMBO_ENABLE                 0x0004
#define TJA1101_CONFIG2_SLEEP_REQUEST_TO             0x0003
#define TJA1101_CONFIG2_SLEEP_REQUEST_TO_0_4MS       0x0000
#define TJA1101_CONFIG2_SLEEP_REQUEST_TO_1MS         0x0001
#define TJA1101_CONFIG2_SLEEP_REQUEST_TO_4MS         0x0002
#define TJA1101_CONFIG2_SLEEP_REQUEST_TO_16MS        0x0003
#define TJA1101_SYM_ERR_COUNTER_SYM_ERR_CNT          0xFFFF
#define TJA1101_INT_SRC_PWON                         0x8000
#define TJA1101_INT_SRC_WAKEUP                       0x4000
#define TJA1101_INT_SRC_WUR_RECEIVED                 0x2000
#define TJA1101_INT_SRC_LPS_RECEIVED                 0x1000
#define TJA1101_INT_SRC_PHY_INIT_FAIL                0x0800
#define TJA1101_INT_SRC_LINK_STATUS_FAIL             0x0400
#define TJA1101_INT_SRC_LINK_STATUS_UP               0x0200
#define TJA1101_INT_SRC_SYM_ERR                      0x0100
#define TJA1101_INT_SRC_TRAINING_FAILED              0x0080
#define TJA1101_INT_SRC_SQI_WARNING                  0x0040
#define TJA1101_INT_SRC_CONTROL_ERR                  0x0020
#define TJA1101_INT_SRC_UV_ERR                       0x0008
#define TJA1101_INT_SRC_UV_RECOVERY                  0x0004
#define TJA1101_INT_SRC_TEMP_ERR                     0x0002
#define TJA1101_INT_SRC_SLEEP_ABORT                  0x0001
#define TJA1101_INT_EN_PWON                          0x8000
#define TJA1101_INT_EN_WAKEUP                        0x4000
#define TJA1101_INT_EN_WUR_RECEIVED                  0x2000
#define TJA1101_INT_EN_LPS_RECEIVED                  0x1000
#define TJA1101_INT_EN_PHY_INIT_FAIL                 0x0800
#define TJA1101_INT_EN_LINK_STATUS_FAIL              0x0400
#define TJA1101_INT_EN_LINK_STATUS_UP                0x0200
#define TJA1101_INT_EN_SYM_ERR                       0x0100
#define TJA1101_INT_EN_TRAINING_FAILED               0x0080
#define TJA1101_INT_EN_SQI_WARNING                   0x0040
#define TJA1101_INT_EN_CONTROL_ERR                   0x0020
#define TJA1101_INT_EN_TXEN_CLAMPED                  0x0010
#define TJA1101_INT_EN_UV_ERR                        0x0008
#define TJA1101_INT_EN_UV_RECOVERY                   0x0004
#define TJA1101_INT_EN_TEMP_ERR                      0x0002
#define TJA1101_INT_EN_SLEEP_ABORT                   0x0001
#define TJA1101_COMM_STAT_LINK_UP                    0x8000
#define TJA1101_COMM_STAT_TX_MODE                    0x6000
#define TJA1101_COMM_STAT_TX_MODE_DISABLED           0x0000
#define TJA1101_COMM_STAT_TX_MODE_SEND_N             0x2000
#define TJA1101_COMM_STAT_TX_MODE_SEND_I             0x4000
#define TJA1101_COMM_STAT_TX_MODE_SEND_Z             0x6000
#define TJA1101_COMM_STAT_LOC_RCVR_STATUS            0x1000
#define TJA1101_COMM_STAT_REM_RCVR_STATUS            0x0800
#define TJA1101_COMM_STAT_SCR_LOCKED                 0x0400
#define TJA1101_COMM_STAT_SSD_ERR                    0x0200
#define TJA1101_COMM_STAT_ESD_ERR                    0x0100
#define TJA1101_COMM_STAT_SQI                        0x00E0
#define TJA1101_COMM_STAT_SQI_WORSE_THAN_CLASS_A     0x0000
#define TJA1101_COMM_STAT_SQI_CLASS_A                0x0020
#define TJA1101_COMM_STAT_SQI_CLASS_B                0x0040
#define TJA1101_COMM_STAT_SQI_CLASS_C                0x0060
#define TJA1101_COMM_STAT_SQI_CLASS_D                0x0080
#define TJA1101_COMM_STAT_SQI_CLASS_E                0x00A0
#define TJA1101_COMM_STAT_SQI_CLASS_F                0x00C0
#define TJA1101_COMM_STAT_SQI_CLASS_G                0x00E0
#define TJA1101_COMM_STAT_RECEIVE_ERR                0x0010
#define TJA1101_COMM_STAT_TRANSMIT_ERR               0x0008
#define TJA1101_COMM_STAT_PHY_STATE                  0x0007
#define TJA1101_COMM_STAT_PHY_STATE_IDLE             0x0000
#define TJA1101_COMM_STAT_PHY_STATE_INITIALIZING     0x0001
#define TJA1101_COMM_STAT_PHY_STATE_CONFIGURED       0x0002
#define TJA1101_COMM_STAT_PHY_STATE_OFFLINE          0x0003
#define TJA1101_COMM_STAT_PHY_STATE_ACTIVE           0x0004
#define TJA1101_COMM_STAT_PHY_STATE_ISOLATE          0x0005
#define TJA1101_COMM_STAT_PHY_STATE_CABLE_TEST       0x0006
#define TJA1101_COMM_STAT_PHY_STATE_TEST_MODE        0x0007
#define TJA1101_GENERAL_STAT_INT_STATUS              0x8000
#define TJA1101_GENERAL_STAT_PLL_LOCKED              0x4000
#define TJA1101_GENERAL_STAT_LOCAL_WU                0x2000
#define TJA1101_GENERAL_STAT_REMOTE_WU               0x1000
#define TJA1101_GENERAL_STAT_DATA_DET_WU             0x0800
#define TJA1101_GENERAL_STAT_EN_STATUS               0x0400
#define TJA1101_GENERAL_STAT_RESET_STATUS            0x0200
#define TJA1101_GENERAL_STAT_LINKFAIL_CNT            0x00F8
#define TJA1101_EXTERNAL_STAT_UV_VDDA_3V3            0x4000
#define TJA1101_EXTERNAL_STAT_UV_VDDD_1V8            0x2000
#define TJA1101_EXTERNAL_STAT_UV_VDDA_1V8            0x1000
#define TJA1101_EXTERNAL_STAT_UV_VDDIO               0x0800
#define TJA1101_EXTERNAL_STAT_TEMP_HIGH              0x0400
#define TJA1101_EXTERNAL_STAT_TEMP_WARN              0x0200
#define TJA1101_EXTERNAL_STAT_SHORT_DETECT           0x0100
#define TJA1101_EXTERNAL_STAT_OPEN_DETECT            0x0080
#define TJA1101_EXTERNAL_STAT_POLARITY_DETECT        0x0040
#define TJA1101_EXTERNAL_STAT_INTERLEAVE_DETECT      0x0020
#define TJA1101_LINK_FAIL_COUNTER_LOC_RCVR_CNT       0xFF00
#define TJA1101_LINK_FAIL_COUNTER_REM_RCVR_CNT       0x00FF
#define TJA1101_COMM_CTRL_AUTO_OP                    0x8000
#define TJA1101_CONFIG3_SHORT_DETECT                 0x0100
#define TJA1101_CONFIG3_OPEN_DETECT                  0x0080
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * @return Duplex mode
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
#elif (RNDIS_TX_BUFFER_COUNT != 1)
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   p = strchr(context->buffer, '\"');
         if(strstr(token, "PM") != NULL)
      if(strchr(token, 'd') != NULL)
      if(strchr(token, 'w') == NULL)
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   p = strchr(context->buffer, ' ');
   p = strchr(context->buffer, ' ');
   p = strchr(context->buffer, ' ');
      q = strchr(p + 1, ' ');
   p = strchr(context->buffer, ' ');
      p = strchr(p + 1, ' ');
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      q = strchr(context->buffer, ' ');
      q = strchr(uri, ' ');
         if(strchr(", \t", param->value[i + n]))
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      separator = strchr(line, ':');
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      if(strchr("!#$%&'*+-.^_`|~", c))
         else if(isalnum(c) || strchr("!#$%&'*+-.^_`|~", c) || c >= 128)
         else if(isalnum(c) || strchr("!#$%&'*+-.^_`|~", c) || c >= 128)
         else if(isalnum(c) || strchr("!#$%&'*+-.^_`|~", c) || c >= 128)
         else if(isalnum(c) || strchr("!#$%&'*+-.^_`|~", c) || c >= 128)
            else if(isalnum(c) || strchr("!#$%&'*+-.^_`|~", c) || c >= 128)
 * @return Error code
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
            separator = strchr(token, ':');
         separator = strchr(token, '=');
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
         separator = strchr(connection->buffer, ':');
   s = strchr(token, '?');
 * @return Error code
 * @return Error code
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   separator = strchr(connection->buffer, '=');
   separator = strchr(connection->buffer, '=');
   separator = strchr(connection->buffer, '=');
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
         separator = strchr(context->buffer, ':');
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      //Sucessful processing
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      //Sucessful processing
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      //Jump to next the next option
      //Jump to next the next option
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
               if(strchr(topicName, '#') == NULL && strchr(topicName, '+') == NULL)
error_t mqttSnClientDisconnect(MqttSnClientContext *context)
         error = mqttSnClientSendDisconnect(context, 0);
            error = mqttSnClientSendDisconnect(context, 0);
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
error_t mqttSnClientDisconnect(MqttSnClientContext *context);
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      if(osStrlen(topicName) == 2 && strchr(topicName, '#') == NULL &&
         strchr(topicName, '+') == NULL)
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      if(strchr(topicName, '#') == NULL && strchr(topicName, '+') == NULL)
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
      separator = strchr(token, '=');
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
   s = strchr(token, '?');
   separator = strchr(line, ':');
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0
 * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.0

Fixed code:
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
   {
   }
            {
            }
            {
            }
            {
            }
            {
            }
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   COAP_CODE_HOP_LIMIT_REACHED            = COAP_CODE(5, 8),
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   COAP_CONTENT_FORMAT_SENML_ETCH_JSON           = 320,
   COAP_CONTENT_FORMAT_SENML_ETCH_CBOR           = 322,
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * @param[in] data Pointer to the incoming CoAP message
 * @param[in] length Length of the CoAP message, in bytes
   //Successful processing
   //Successful processing
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * @param[in] context Pointer to the CoAP server context
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * @param[in] context Pointer to the DTLS context
 * @param[in] clientParams Client's parameters
 * @param[in] param Pointer to the DTLS session
 * @param[in] context Pointer to the DTLS context
 * @param[in] clientParams Client's parameters
 * @param[in] param Pointer to the DTLS session
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   ETH_TYPE_VMAN  = 0x88A8,
   ETH_TYPE_LLDP  = 0x88CC
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   if(osStrchr(str, ':') != NULL)
   if(osStrchr(str, '.') != NULL)
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
#define CYCLONE_TCP_VERSION_STRING "2.0.2"
#define CYCLONE_TCP_REV_NUMBER 2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   //Gather entropy
   netContext.entropy += netGetSystemTickCount();

 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   //Network interface where the packet was received
   queueItem->interface = interface;
   //Network interface where the packet was received
   queueItem->interface = interface;

   //Select the relevant network interface
   if(message->interface != NULL)
   {
      interface = message->interface;
   }
   else
   {
      interface = socket->interface;
   }
   if(message->interface != NULL)
   {
      interface = message->interface;
   }
   else if(socket->interface != NULL)
 * @param[out] message Received IP packet and ancillary data
      //Network interface where the packet was received
      message->interface = queueItem->interface;
 * @param[out] message Received Ethernet packet and ancillary data
      //Network interface where the packet was received
      message->interface = queueItem->interface;

 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   NULL,    //Underlying network interface
         else if(n <= 15 && !osStrchr(name, '.') && type == HOST_TYPE_IPV4)
         else if(!osStrchr(name, '.'))
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   void *data;              ///<Pointer to the payload
   size_t size;             ///<Size of the payload, in bytes
   size_t length;           ///<Actual length of the payload, in bytes
   uint8_t ttl;             ///<Time-to-live value
   NetInterface *interface; ///<Underlying network interface
   IpAddr srcIpAddr;        ///<Source IP address
   uint16_t srcPort;        ///<Source port
   IpAddr destIpAddr;       ///<Destination IP address
   uint16_t destPort;       ///<Destination port
   MacAddr srcMacAddr;      ///<Source MAC address
   MacAddr destMacAddr;     ///<Destination MAC address
   uint8_t switchPort;      ///<Switch port identifier
   int32_t timestampId;     ///<Unique identifier for hardware time stamping
   NetTimestamp timestamp;  ///<Captured time stamp
   NetInterface *interface;
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      {
      }

      {
      }

   error_t error;
   size_t i;
   //The option-length counts the two octets of option-kind and option-length
   //as well as the option-data octets (refer to RFC 793, section 3.1)
   //Make sure there is enough room to add the option
   if((segment->dataOffset * 4 + length) <= TCP_MAX_HEADER_LENGTH)
   {
      //Index of the first available byte
      i = (segment->dataOffset * 4) - sizeof(TcpHeader);
      //Calculate the number of padding bytes
      paddingSize = (length % 4) ? 4 - (length % 4) : 0;
      //Write padding bytes
      while(paddingSize--)
      {
         segment->options[i++] = TCP_OPTION_NOP;
      }
      //Point to the current location
      option = (TcpOption *) (segment->options + i);
      //Format option
      option->kind = kind;
      option->length = length;
      osMemcpy(option->value, value, length - sizeof(TcpOption));
      //Adjust index value
      i += length;

      //Update the length of the TCP header
      segment->dataOffset = (sizeof(TcpHeader) + i) / 4;

      //Successful processing
      error = NO_ERROR;
   }
   else
   {
      //Report an error
      error = ERROR_FAILURE;
   }

   //Return status code
   return error;
   size_t i;
   if(segment->dataOffset >= (sizeof(TcpHeader) / 4))
   {
      //Compute the length of the options field
      length = (segment->dataOffset * 4) - sizeof(TcpHeader);
      //Point to the very first option
      i = 0;
      //Loop through the list of options
      while(i < length)
      {
         //Point to the current option
         option = (TcpOption *) (segment->options + i);
         //Check option code
         if(option->kind == TCP_OPTION_END)
         {
            //This option code indicates the end of the option list
            break;
         }
         else if(option->kind == TCP_OPTION_NOP)
         {
            //This option consists of a single octet
            i++;
         }
         else
         {
            //The option code is followed by a one-byte length field
            if((i + 1) >= length)
               break;
            //Check the length of the option
            if(option->length < sizeof(TcpOption) || (i + option->length) > length)
               break;
            //Matching option code?
            if(option->kind == kind)
               return option;
            //Jump to the next option
            i += option->length;
         }
      }
   //The specified option code does not exist
      //If an incoming segment is not acceptable, an acknowledgment should
      //be sent in reply (unless the RST bit is set)
      {
         tcpSendSegment(socket, TCP_FLAG_ACK, socket->sndNxt, socket->rcvNxt,
            0, FALSE);
      }
      {
      }
      {
      }
      {
      }
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   //Network interface where the packet was received
   queueItem->interface = interface;
   NetInterface *interface;
   //Select the relevant network interface
   if(message->interface != NULL)
   {
      interface = message->interface;
   }
   else
   {
      interface = socket->interface;
   }

      error = udpSendBuffer(interface, &message->srcIpAddr, socket->localPort,
         &message->destIpAddr, message->destPort, buffer, offset, &ancillary);
 * @param[out] message Received UDP datagram and ancillary data
      //Network interface where the packet was received
      message->interface = queueItem->interface;
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   if(length < sizeof(DhcpMessage) || length > DHCP_MAX_MSG_SIZE)








 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      //Jump to the next option
      //Jump to the next option
   size_t i;
   if(length >= sizeof(DhcpMessage))
      //Get the length of the options field
      length -= sizeof(DhcpMessage);

      //Loop through the list of options
      for(i = 0; i < length; i++)
      {
         //Point to the current option
         option = (DhcpOption *) (message->options + i);

         //Check option code
         if(option->code == DHCP_OPT_PAD)
         {
            //The pad option can be used to cause subsequent fields to align
            //on word boundaries
         }
         else if(option->code == DHCP_OPT_END)
         {
            //The end option marks the end of valid information in the vendor
            //field
            break;
         }
         else
         {
            //The option code is followed by a one-byte length field
            if((i + 1) >= length)
               break;

            //Check the length of the option
            if((i + sizeof(DhcpOption) + option->length) > length)
               break;

            //Matching option code?
            if(option->code == optionCode)
               return option;

            //Jump to the next option
            i += option->length + 1;
         }
      }
   //The specified option code does not exist
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      //Successful processing
               //Successful processing
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   uint8_t chipRev;
   vendorId = (dm9000ReadReg(DM9000_VIDH) << 8) | dm9000ReadReg(DM9000_VIDL);
   productId = (dm9000ReadReg(DM9000_PIDH) << 8) | dm9000ReadReg(DM9000_PIDL);
   chipRev = dm9000ReadReg(DM9000_CHIPR);
   if(chipRev != DM9000_CHIPR_REV_A && chipRev != DM9000_CHIPR_REV_B)
   dm9000WriteReg(DM9000_GPR, 0x00);
   dm9000WriteReg(DM9000_NCR, DM9000_NCR_RST);
   while((dm9000ReadReg(DM9000_NCR) & DM9000_NCR_RST) != 0)
   dm9000WritePhyReg(DM9000_BMCR, DM9000_BMCR_RST);
   while((dm9000ReadPhyReg(DM9000_BMCR) & DM9000_BMCR_RST) != 0)
   TRACE_INFO("  CHIPR = 0x%02" PRIX8 "\r\n", chipRev);
   TRACE_INFO("  PHYIDR1 = 0x%04" PRIX16 "\r\n", dm9000ReadPhyReg(DM9000_PHYIDR1));
   TRACE_INFO("  PHYIDR2 = 0x%04" PRIX16 "\r\n", dm9000ReadPhyReg(DM9000_PHYIDR2));
   //Enable loopback mode
   dm9000WriteReg(DM9000_NCR, DM9000_NCR_LBK_PHY);

   //Set operation mode
   dm9000WritePhyReg(DM9000_BMCR, DM9000_BMCR_LOOPBACK | DM9000_BMCR_SPEED_SEL |
      DM9000_BMCR_AN_EN | DM9000_BMCR_DUPLEX_MODE);
      dm9000WriteReg(DM9000_PAR0 + i, interface->macAddr.b[i]);
      dm9000WriteReg(DM9000_MAR0 + i, 0x00);
   dm9000WriteReg(DM9000_MAR7, 0x80);
   dm9000WriteReg(DM9000_IMR, DM9000_IMR_PAR);

   dm9000WriteReg(DM9000_NSR, DM9000_NSR_WAKEST | DM9000_NSR_TX2END |
      DM9000_NSR_TX1END);

   dm9000WriteReg(DM9000_ISR, DM9000_ISR_LNKCHG | DM9000_ISR_UDRUN |
      DM9000_ISR_ROO | DM9000_ISR_ROS | DM9000_ISR_PT | DM9000_ISR_PR);

   dm9000WriteReg(DM9000_IMR, DM9000_IMR_PAR | DM9000_IMR_LNKCHGI |
      DM9000_IMR_PTI | DM9000_IMR_PRI);

   dm9000WriteReg(DM9000_RCR, DM9000_RCR_DIS_LONG | DM9000_RCR_DIS_CRC |
      DM9000_RCR_RXEN);
   status = dm9000ReadReg(DM9000_ISR);
   if((status & DM9000_ISR_LNKCHG) != 0)
      mask = dm9000ReadReg(DM9000_IMR);
      dm9000WriteReg(DM9000_IMR, mask & ~DM9000_IMR_LNKCHGI);
   if((status & DM9000_ISR_PT) != 0)
      if((dm9000ReadReg(DM9000_NSR) & (DM9000_NSR_TX2END | DM9000_NSR_TX1END)) != 0)
      dm9000WriteReg(DM9000_ISR, DM9000_ISR_PT);
   if((status & DM9000_ISR_PR) != 0)
      mask = dm9000ReadReg(DM9000_IMR);
      dm9000WriteReg(DM9000_IMR, mask & ~DM9000_IMR_PRI);
   status = dm9000ReadReg(DM9000_ISR);
   if((status & DM9000_ISR_LNKCHG) != 0)
      dm9000WriteReg(DM9000_ISR, DM9000_ISR_LNKCHG);
      status = dm9000ReadReg(DM9000_NSR);
      if((status & DM9000_NSR_LINKST) != 0)
         if((status & DM9000_NSR_SPEED) != 0)
         status = dm9000ReadReg(DM9000_NCR);
         if((status & DM9000_NCR_FDX) != 0)
   if((status & DM9000_ISR_PR) != 0)
      dm9000WriteReg(DM9000_ISR, DM9000_ISR_PR);
   dm9000WriteReg(DM9000_IMR, DM9000_IMR_PAR | DM9000_IMR_LNKCHGI |
      DM9000_IMR_PTI | DM9000_IMR_PRI);
   dm9000WriteReg(DM9000_MWCMDX, 0);
   DM9000_INDEX_REG = DM9000_MWCMD;
   dm9000WriteReg(DM9000_TXPLL, LSB(length));
   dm9000WriteReg(DM9000_TXPLH, MSB(length));
   dm9000WriteReg(DM9000_ISR, DM9000_ISR_PT);
   dm9000WriteReg(DM9000_TCR, DM9000_TCR_TXREQ);
   data = dm9000ReadReg(DM9000_MRCMDX);
   DM9000_INDEX_REG = DM9000_MRCMDX1;
      DM9000_INDEX_REG = DM9000_MRCMD;
      if((status & (DM9000_RSR_LCS | DM9000_RSR_RWTO | DM9000_RSR_PLE |
         DM9000_RSR_AE | DM9000_RSR_CE | DM9000_RSR_FOE)) == 0)
      dm9000WriteReg(DM9000_MAR0 + i, hashTable[i]);
      dm9000ReadReg(DM9000_MAR0), dm9000ReadReg(DM9000_MAR1),
      dm9000ReadReg(DM9000_MAR2), dm9000ReadReg(DM9000_MAR3),
      dm9000ReadReg(DM9000_MAR4), dm9000ReadReg(DM9000_MAR5),
      dm9000ReadReg(DM9000_MAR6), dm9000ReadReg(DM9000_MAR7));
   dm9000WriteReg(DM9000_EPAR, 0x40 | address);
   dm9000WriteReg(DM9000_EPDRL, LSB(data));
   dm9000WriteReg(DM9000_EPDRH, MSB(data));
   dm9000WriteReg(DM9000_EPCR, DM9000_EPCR_EPOS | DM9000_EPCR_ERPRW);

   while((dm9000ReadReg(DM9000_EPCR) & DM9000_EPCR_ERRE) != 0)
   dm9000WriteReg(DM9000_EPCR, DM9000_EPCR_EPOS);
   dm9000WriteReg(DM9000_EPAR, 0x40 | address);
   dm9000WriteReg(DM9000_EPCR, DM9000_EPCR_EPOS | DM9000_EPCR_ERPRR);

   while((dm9000ReadReg(DM9000_EPCR) & DM9000_EPCR_ERRE) != 0)
   dm9000WriteReg(DM9000_EPCR, DM9000_EPCR_EPOS);
   return (dm9000ReadReg(DM9000_EPDRH) << 8) | dm9000ReadReg(DM9000_EPDRL);
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
#define DM9000_VID ((DM9000_VIDH_DEFAULT << 8) | DM9000_VIDL_DEFAULT)
#define DM9000_PID ((DM9000_PIDH_DEFAULT << 8) | DM9000_PIDL_DEFAULT)
#define DM9000_NCR                      0x00
#define DM9000_NSR                      0x01
#define DM9000_TCR                      0x02
#define DM9000_TSR1                     0x03
#define DM9000_TSR2                     0x04
#define DM9000_RCR                      0x05
#define DM9000_RSR                      0x06
#define DM9000_ROCR                     0x07
#define DM9000_BPTR                     0x08
#define DM9000_FCTR                     0x09
#define DM9000_FCR                      0x0A
#define DM9000_EPCR                     0x0B
#define DM9000_EPAR                     0x0C
#define DM9000_EPDRL                    0x0D
#define DM9000_EPDRH                    0x0E
#define DM9000_WCR                      0x0F
#define DM9000_PAR0                     0x10
#define DM9000_PAR1                     0x11
#define DM9000_PAR2                     0x12
#define DM9000_PAR3                     0x13
#define DM9000_PAR4                     0x14
#define DM9000_PAR5                     0x15
#define DM9000_MAR0                     0x16
#define DM9000_MAR1                     0x17
#define DM9000_MAR2                     0x18
#define DM9000_MAR3                     0x19
#define DM9000_MAR4                     0x1A
#define DM9000_MAR5                     0x1B
#define DM9000_MAR6                     0x1C
#define DM9000_MAR7                     0x1D
#define DM9000_GPCR                     0x1E
#define DM9000_GPR                      0x1F
#define DM9000_TRPAL                    0x22
#define DM9000_TRPAH                    0x23
#define DM9000_RWPAL                    0x24
#define DM9000_RWPAH                    0x25
#define DM9000_VIDL                     0x28
#define DM9000_VIDH                     0x29
#define DM9000_PIDL                     0x2A
#define DM9000_PIDH                     0x2B
#define DM9000_CHIPR                    0x2C
#define DM9000_TCR2                     0x2D
#define DM9000_OCR                      0x2E
#define DM9000_SMCR                     0x2F
#define DM9000_ETXCSR                   0x30
#define DM9000_TCSCR                    0x31
#define DM9000_RCSCSR                   0x32
#define DM9000_MPAR                     0x33
#define DM9000_LEDCR                    0x34
#define DM9000_BUSCR                    0x38
#define DM9000_INTCR                    0x39
#define DM9000_SCCR                     0x50
#define DM9000_RSCCR                    0x51
#define DM9000_MRCMDX                   0xF0
#define DM9000_MRCMDX1                  0xF1
#define DM9000_MRCMD                    0xF2
#define DM9000_MRRL                     0xF4
#define DM9000_MRRH                     0xF5
#define DM9000_MWCMDX                   0xF6
#define DM9000_MWCMD                    0xF8
#define DM9000_MWRL                     0xFA
#define DM9000_MWRH                     0xFB
#define DM9000_TXPLL                    0xFC
#define DM9000_TXPLH                    0xFD
#define DM9000_ISR                      0xFE
#define DM9000_IMR                      0xFF
#define DM9000_BMCR                     0x00
#define DM9000_BMSR                     0x01
#define DM9000_PHYIDR1                  0x02
#define DM9000_PHYIDR2                  0x03
#define DM9000_ANAR                     0x04
#define DM9000_ANLPAR                   0x05
#define DM9000_ANER                     0x06
#define DM9000_DSCR                     0x10
#define DM9000_DSCSR                    0x11
#define DM9000_10BTCSR                  0x12
#define DM9000_PWDOR                    0x13
#define DM9000_SCR                      0x14
#define DM9000_DSPCR                    0x1B
#define DM9000_PSCR                     0x1D

//Network Control register
#define DM9000_NCR_WAKEEN               0x40
#define DM9000_NCR_FCOL                 0x10
#define DM9000_NCR_FDX                  0x08
#define DM9000_NCR_LBK                  0x06
#define DM9000_NCR_LBK_NORMAL           0x00
#define DM9000_NCR_LBK_MAC              0x02
#define DM9000_NCR_LBK_PHY              0x04
#define DM9000_NCR_RST                  0x01

//Network Status register
#define DM9000_NSR_SPEED                0x80
#define DM9000_NSR_LINKST               0x40
#define DM9000_NSR_WAKEST               0x20
#define DM9000_NSR_TX2END               0x08
#define DM9000_NSR_TX1END               0x04
#define DM9000_NSR_RXOV                 0x02

//TX Control register
#define DM9000_TCR_TJDIS                0x40
#define DM9000_TCR_EXCECM               0x20
#define DM9000_TCR_PAD_DIS2             0x10
#define DM9000_TCR_CRC_DIS2             0x08
#define DM9000_TCR_PAD_DIS1             0x04
#define DM9000_TCR_CRC_DIS1             0x02
#define DM9000_TCR_TXREQ                0x01

//TX Status 1 register
#define DM9000_TSR1_TJTO                0x80
#define DM9000_TSR1_LC                  0x40
#define DM9000_TSR1_NC                  0x20
#define DM9000_TSR1_LCOL                0x10
#define DM9000_TSR1_COL                 0x08
#define DM9000_TSR1_EC                  0x04

//TX Status 2 register
#define DM9000_TSR2_TJTO                0x80
#define DM9000_TSR2_LC                  0x40
#define DM9000_TSR2_NC                  0x20
#define DM9000_TSR2_LCOL                0x10
#define DM9000_TSR2_COL                 0x08
#define DM9000_TSR2_EC                  0x04

//RX Control register
#define DM9000_RCR_WTDIS                0x40
#define DM9000_RCR_DIS_LONG             0x20
#define DM9000_RCR_DIS_CRC              0x10
#define DM9000_RCR_ALL                  0x08
#define DM9000_RCR_RUNT                 0x04
#define DM9000_RCR_PRMSC                0x02
#define DM9000_RCR_RXEN                 0x01

//RX Status register
#define DM9000_RSR_RF                   0x80
#define DM9000_RSR_MF                   0x40
#define DM9000_RSR_LCS                  0x20
#define DM9000_RSR_RWTO                 0x10
#define DM9000_RSR_PLE                  0x08
#define DM9000_RSR_AE                   0x04
#define DM9000_RSR_CE                   0x02
#define DM9000_RSR_FOE                  0x01

//Receive Overflow Counter register
#define DM9000_ROCR_RXFU                0x80
#define DM9000_ROCR_ROC                 0x7F

//Back Pressure Threshold register
#define DM9000_BPTR_BPHW                0xF0
#define DM9000_BPTR_JPT                 0x0F

//Flow Control Threshold register
#define DM9000_FCTR_HWOT                0xF0
#define DM9000_FCTR_LWOT                0x0F

//RX Flow Control register
#define DM9000_FCR_TXP0                 0x80
#define DM9000_FCR_TXPF                 0x40
#define DM9000_FCR_TXPEN                0x20
#define DM9000_FCR_BKPA                 0x10
#define DM9000_FCR_BKPM                 0x08
#define DM9000_FCR_RXPS                 0x04
#define DM9000_FCR_RXPCS                0x02
#define DM9000_FCR_FLCE                 0x01

//EEPROM & PHY Control register
#define DM9000_EPCR_REEP                0x20
#define DM9000_EPCR_WEP                 0x10
#define DM9000_EPCR_EPOS                0x08
#define DM9000_EPCR_ERPRR               0x04
#define DM9000_EPCR_ERPRW               0x02
#define DM9000_EPCR_ERRE                0x01

//EEPROM & PHY Address register
#define DM9000_EPAR_PHY_ADR             0xC0
#define DM9000_EPAR_EROA                0x3F

//Wake Up Control register
#define DM9000_WCR_LINKEN               0x20
#define DM9000_WCR_SAMPLEEN             0x10
#define DM9000_WCR_MAGICEN              0x08
#define DM9000_WCR_LINKST               0x04
#define DM9000_WCR_SAMPLEST             0x02
#define DM9000_WCR_MAGICST              0x01

//General Purpose Control register
#define DM9000_GPCR_GPC6                0x40
#define DM9000_GPCR_GPC5                0x20
#define DM9000_GPCR_GPC4                0x10
#define DM9000_GPCR_GPC3                0x08
#define DM9000_GPCR_GPC2                0x04
#define DM9000_GPCR_GPC1                0x02

//General Purpose register
#define DM9000_GPR_GPO6                 0x40
#define DM9000_GPR_GPO5                 0x20
#define DM9000_GPR_GPO4                 0x10
#define DM9000_GPR_GPIO3                0x08
#define DM9000_GPR_GPIO2                0x04
#define DM9000_GPR_GPIO1                0x02
#define DM9000_GPR_PHYPD                0x01

//Vendor ID Low Byte register
#define DM9000_VIDL_DEFAULT             0x46

//Vendor ID High Byte register
#define DM9000_VIDH_DEFAULT             0x0A

//Product ID Low Byte register
#define DM9000_PIDL_DEFAULT             0x00

//Product ID High Byte register
#define DM9000_PIDH_DEFAULT             0x90

//Chip Revision register
#define DM9000_CHIPR_REV_A              0x19
#define DM9000_CHIPR_REV_B              0x1A

//TX Control 2 register
#define DM9000_TCR2_LED                 0x80
#define DM9000_TCR2_RLCP                0x40
#define DM9000_TCR2_DTU                 0x20
#define DM9000_TCR2_ONEPM               0x10
#define DM9000_TCR2_IFGS                0x0F
#define DM9000_TCR2_IFGS_64_BIT         0x08
#define DM9000_TCR2_IFGS_72_BIT         0x09
#define DM9000_TCR2_IFGS_80_BIT         0x0A
#define DM9000_TCR2_IFGS_88_BIT         0x0B
#define DM9000_TCR2_IFGS_96_BIT         0x0C
#define DM9000_TCR2_IFGS_104_BIT        0x0D
#define DM9000_TCR2_IFGS_112_BIT        0x0E
#define DM9000_TCR2_IFGS_120_BIT        0x0F

//Operation Control register
#define DM9000_OCR_SCC                  0xC0
#define DM9000_OCR_SCC_50MHZ            0x00
#define DM9000_OCR_SCC_20MHZ            0x40
#define DM9000_OCR_SCC_100MHZ           0x80
#define DM9000_OCR_SOE                  0x10
#define DM9000_OCR_SCS                  0x08
#define DM9000_OCR_PHYOP                0x07

//Special Mode Control register
#define DM9000_SMCR_SM_EN               0x80
#define DM9000_SMCR_FLC                 0x04
#define DM9000_SMCR_FB1                 0x02
#define DM9000_SMCR_FB0                 0x01

//Early Transmit Control/Status register
#define DM9000_ETXCSR_ETE               0x80
#define DM9000_ETXCSR_ETS2              0x40
#define DM9000_ETXCSR_ETS1              0x20
#define DM9000_ETXCSR_ETT               0x03
#define DM9000_ETXCSR_ETT_12_5_PERCENT  0x00
#define DM9000_ETXCSR_ETT_25_PERCENT    0x01
#define DM9000_ETXCSR_ETT_50_PERCENT    0x02
#define DM9000_ETXCSR_ETT_75_PERCENT    0x03

//Transmit Check Sum Control register
#define DM9000_TCSCR_UDPCSE             0x04
#define DM9000_TCSCR_TCPCSE             0x02
#define DM9000_TCSCR_IPCSE              0x01

//Receive Check Sum Control Status register
#define DM9000_RCSCSR_UDPS              0x80
#define DM9000_RCSCSR_TCPS              0x40
#define DM9000_RCSCSR_IPS               0x20
#define DM9000_RCSCSR_UDPP              0x10
#define DM9000_RCSCSR_TCPP              0x08
#define DM9000_RCSCSR_IPP               0x04
#define DM9000_RCSCSR_RCSEN             0x02
#define DM9000_RCSCSR_DCSE              0x01

//MII PHY Address register
#define DM9000_MPAR_ADR_EN              0x80
#define DM9000_MPAR_EPHYADR             0x1F

//LED Pin Control register
#define DM9000_LEDCR_GPIO               0x02
#define DM9000_LEDCR_MII                0x01

//Processor Bus Control register
#define DM9000_BUSCR_CURR               0x60
#define DM9000_BUSCR_CURR_2MA           0x00
#define DM9000_BUSCR_CURR_4MA           0x20
#define DM9000_BUSCR_CURR_6MA           0x40
#define DM9000_BUSCR_CURR_8MA           0x60
#define DM9000_BUSCR_EST                0x08
#define DM9000_BUSCR_IOW_SPIKE          0x02
#define DM9000_BUSCR_IOR_SPIKE          0x01

//INT Pin Control register
#define DM9000_INTCR_INT_TYPE           0x02
#define DM9000_INTCR_INT_TYPE_DIRECT    0x00
#define DM9000_INTCR_INT_TYPE_OC        0x02
#define DM9000_INTCR_INT_POL            0x01
#define DM9000_INTCR_INT_POL_HIGH       0x00
#define DM9000_INTCR_INT_POL_LOW        0x01

//System Clock Turn On Control register
#define DM9000_SCCR_DIS_CLK             0x01

//Interrupt Status register
#define DM9000_ISR_IOMODE               0x80
#define DM9000_ISR_IOMODE_16_BIT        0x00
#define DM9000_ISR_IOMODE_8_BIT         0x80
#define DM9000_ISR_LNKCHG               0x20
#define DM9000_ISR_UDRUN                0x10
#define DM9000_ISR_ROO                  0x08
#define DM9000_ISR_ROS                  0x04
#define DM9000_ISR_PT                   0x02
#define DM9000_ISR_PR                   0x01

//Interrupt Mask register
#define DM9000_IMR_PAR                  0x80
#define DM9000_IMR_LNKCHGI              0x20
#define DM9000_IMR_UDRUNI               0x10
#define DM9000_IMR_ROOI                 0x08
#define DM9000_IMR_ROI                  0x04
#define DM9000_IMR_PTI                  0x02
#define DM9000_IMR_PRI                  0x01

//Basic Mode Control register
#define DM9000_BMCR_RST                 0x8000
#define DM9000_BMCR_LOOPBACK            0x4000
#define DM9000_BMCR_SPEED_SEL           0x2000
#define DM9000_BMCR_AN_EN               0x1000
#define DM9000_BMCR_POWER_DOWN          0x0800
#define DM9000_BMCR_ISOLATE             0x0400
#define DM9000_BMCR_RESTART_AN          0x0200
#define DM9000_BMCR_DUPLEX_MODE         0x0100
#define DM9000_BMCR_COL_TEST            0x0080

//Basic Mode Status register
#define DM9000_BMSR_100BT4              0x8000
#define DM9000_BMSR_100BTX_FD           0x4000
#define DM9000_BMSR_100BTX_HD           0x2000
#define DM9000_BMSR_10BT_FD             0x1000
#define DM9000_BMSR_10BT_HD             0x0800
#define DM9000_BMSR_MF_PREAMBLE_SUPPR   0x0040
#define DM9000_BMSR_AN_COMPLETE         0x0020
#define DM9000_BMSR_REMOTE_FAULT        0x0010
#define DM9000_BMSR_AN_CAPABLE          0x0008
#define DM9000_BMSR_LINK_STATUS         0x0004
#define DM9000_BMSR_JABBER_DETECT       0x0002
#define DM9000_BMSR_EXTENDED_CAPABLE    0x0001

//PHY ID Identifier 1 register
#define DM9000_PHYIDR1_OUI_MSB          0xFFFF
#define DM9000_PHYIDR1_OUI_MSB_DEFAULT  0x0181

//PHY ID Identifier 2 register
#define DM9000_PHYIDR2_OUI_LSB          0xFC00
#define DM9000_PHYIDR2_OUI_LSB_DEFAULT  0xB800
#define DM9000_PHYIDR2_VNDR_MDL         0x03F0
#define DM9000_PHYIDR2_VNDR_MDL_DEFAULT 0x0070
#define DM9000_PHYIDR2_MDL_REV          0x000F
#define DM9000_PHYIDR2_MDL_REV_DEFAULT  0x0000

//Auto-Negotiation Advertisement register
#define DM9000_ANAR_NP                  0x8000
#define DM9000_ANAR_ACK                 0x4000
#define DM9000_ANAR_RF                  0x2000
#define DM9000_ANAR_FCS                 0x0400
#define DM9000_ANAR_100BT4              0x0200
#define DM9000_ANAR_100BTX_FD           0x0100
#define DM9000_ANAR_100BTX_HD           0x0080
#define DM9000_ANAR_10BT_FD             0x0040
#define DM9000_ANAR_10BT_HD             0x0020
#define DM9000_ANAR_SELECTOR            0x001F
#define DM9000_ANAR_SELECTOR_DEFAULT    0x0001

//Auto-Negotiation Link Partner Ability register
#define DM9000_ANLPAR_NP                0x8000
#define DM9000_ANLPAR_ACK               0x4000
#define DM9000_ANLPAR_RF                0x2000
#define DM9000_ANLPAR_FCS               0x0400
#define DM9000_ANLPAR_100BT4            0x0200
#define DM9000_ANLPAR_100BTX_FD         0x0100
#define DM9000_ANLPAR_100BTX_HD         0x0080
#define DM9000_ANLPAR_10BT_FD           0x0040
#define DM9000_ANLPAR_10BT_HD           0x0020
#define DM9000_ANLPAR_SELECTOR          0x001F
#define DM9000_ANLPAR_SELECTOR_DEFAULT  0x0001

//Auto-Negotiation Expansion register
#define DM9000_ANER_PDF                 0x0010
#define DM9000_ANER_LP_NP_ABLE          0x0008
#define DM9000_ANER_NP_ABLE             0x0004
#define DM9000_ANER_PAGE_RX             0x0002
#define DM9000_ANER_LP_AN_ABLE          0x0001

//Davicom Specified Configuration register
#define DM9000_DSCR_BP_4B5B             0x8000
#define DM9000_DSCR_BP_SCR              0x4000
#define DM9000_DSCR_BP_ALIGN            0x2000
#define DM9000_DSCR_BP_ADPOK            0x1000
#define DM9000_DSCR_TX_FX               0x0400
#define DM9000_DSCR_F_LINK_100          0x0080
#define DM9000_DSCR_SPLED_CTL           0x0040
#define DM9000_DSCR_COLLED_CTL          0x0020
#define DM9000_DSCR_RPDCTR_EN           0x0010
#define DM9000_DSCR_SMRST               0x0008
#define DM9000_DSCR_MFPSC               0x0004
#define DM9000_DSCR_SLEEP               0x0002
#define DM9000_DSCR_RLOUT               0x0001

//Davicom Specified Configuration/Status register
#define DM9000_DSCSR_100FDX             0x8000
#define DM9000_DSCSR_100HDX             0x4000
#define DM9000_DSCSR_10FDX              0x2000
#define DM9000_DSCSR_10HDX              0x1000
#define DM9000_DSCSR_PHYADR             0x01F0
#define DM9000_DSCSR_ANMB               0x000F

//10BASE-T Configuration/Status register
#define DM9000_10BTCSR_LP_EN            0x4000
#define DM9000_10BTCSR_HBE              0x2000
#define DM9000_10BTCSR_SQUELCH          0x1000
#define DM9000_10BTCSR_JABEN            0x0800
#define DM9000_10BTCSR_POLR             0x0001

//Power Down Control register
#define DM9000_PWDOR_PD10DRV            0x0100
#define DM9000_PWDOR_PD100DL            0x0080
#define DM9000_PWDOR_PDCHIP             0x0040
#define DM9000_PWDOR_PDCOM              0x0020
#define DM9000_PWDOR_PDAEQ              0x0010
#define DM9000_PWDOR_PDDRV              0x0008
#define DM9000_PWDOR_PDEDI              0x0004
#define DM9000_PWDOR_PDEDO              0x0002
#define DM9000_PWDOR_PD10               0x0001

//Specified Configuration register
#define DM9000_SCR_TSTSE1               0x8000
#define DM9000_SCR_TSTSE2               0x4000
#define DM9000_SCR_FORCE_TXSD           0x2000
#define DM9000_SCR_FORCE_FEF            0x1000
#define DM9000_SCR_PREAMBLEX            0x0800
#define DM9000_SCR_TX10M_PWR            0x0400
#define DM9000_SCR_NWAY_PWR             0x0200
#define DM9000_SCR_MDIX_CNTL            0x0080
#define DM9000_SCR_AUTONEG_LPBK         0x0040
#define DM9000_SCR_MDIX_FIX             0x0020
#define DM9000_SCR_MDIX_DOWN            0x0010
#define DM9000_SCR_MONSEL1              0x0008
#define DM9000_SCR_MONSEL0              0x0004
#define DM9000_SCR_PD_VALUE             0x0001

//DSP Control register
#define DM9000_DSPCR_DSP                0xFFFF

//Power Saving Control register
#define DM9000_PSCR_PREAMBLEX           0x0800
#define DM9000_PSCR_AMPLITUDE           0x0400
#define DM9000_PSCR_TX_PWR              0x0200
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   revisionId = enc28j60ReadReg(interface, ENC28J60_EREVID);
   enc28j60WriteReg(interface, ENC28J60_ECOCON, ENC28J60_ECOCON_COCON_DISABLED);
   enc28j60WriteReg(interface, ENC28J60_MAADR5, interface->macAddr.b[0]);
   enc28j60WriteReg(interface, ENC28J60_MAADR4, interface->macAddr.b[1]);
   enc28j60WriteReg(interface, ENC28J60_MAADR3, interface->macAddr.b[2]);
   enc28j60WriteReg(interface, ENC28J60_MAADR2, interface->macAddr.b[3]);
   enc28j60WriteReg(interface, ENC28J60_MAADR1, interface->macAddr.b[4]);
   enc28j60WriteReg(interface, ENC28J60_MAADR0, interface->macAddr.b[5]);
   enc28j60WriteReg(interface, ENC28J60_ERXSTL, LSB(ENC28J60_RX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_ERXSTH, MSB(ENC28J60_RX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_ERXNDL, LSB(ENC28J60_RX_BUFFER_STOP));
   enc28j60WriteReg(interface, ENC28J60_ERXNDH, MSB(ENC28J60_RX_BUFFER_STOP));
   //The ERXRDPT register defines a location within the FIFO where the receive
   //hardware is forbidden to write to
   enc28j60WriteReg(interface, ENC28J60_ERXRDPTL, LSB(ENC28J60_RX_BUFFER_STOP));
   enc28j60WriteReg(interface, ENC28J60_ERXRDPTH, MSB(ENC28J60_RX_BUFFER_STOP));
   enc28j60WriteReg(interface, ENC28J60_ERXFCON, ENC28J60_ERXFCON_UCEN |
      ENC28J60_ERXFCON_CRCEN | ENC28J60_ERXFCON_HTEN | ENC28J60_ERXFCON_BCEN);
   enc28j60WriteReg(interface, ENC28J60_EHT0, 0x00);
   enc28j60WriteReg(interface, ENC28J60_EHT1, 0x00);
   enc28j60WriteReg(interface, ENC28J60_EHT2, 0x00);
   enc28j60WriteReg(interface, ENC28J60_EHT3, 0x00);
   enc28j60WriteReg(interface, ENC28J60_EHT4, 0x00);
   enc28j60WriteReg(interface, ENC28J60_EHT5, 0x00);
   enc28j60WriteReg(interface, ENC28J60_EHT6, 0x00);
   enc28j60WriteReg(interface, ENC28J60_EHT7, 0x00);
   enc28j60WriteReg(interface, ENC28J60_MACON2, 0x00);
   enc28j60WriteReg(interface, ENC28J60_MACON1, ENC28J60_MACON1_TXPAUS |
      ENC28J60_MACON1_RXPAUS | ENC28J60_MACON1_MARXEN);
   //Enable automatic padding, always append a valid CRC and check frame
   //length. MAC can operate in half-duplex or full-duplex mode
   enc28j60WriteReg(interface, ENC28J60_MACON3, ENC28J60_MACON3_PADCFG_AUTO |
      ENC28J60_MACON3_TXCRCEN | ENC28J60_MACON3_FRMLNEN |
      ENC28J60_MACON3_FULDPX);
   enc28j60WriteReg(interface, ENC28J60_MACON3, ENC28J60_MACON3_PADCFG_AUTO |
      ENC28J60_MACON3_TXCRCEN | ENC28J60_MACON3_FRMLNEN);
   enc28j60WriteReg(interface, ENC28J60_MACON4, ENC28J60_MACON4_DEFER);
   enc28j60WriteReg(interface, ENC28J60_MAMXFLL, LSB(ETH_MAX_FRAME_SIZE));
   enc28j60WriteReg(interface, ENC28J60_MAMXFLH, MSB(ETH_MAX_FRAME_SIZE));
   enc28j60WriteReg(interface, ENC28J60_MABBIPG, ENC28J60_MABBIPG_DEFAULT_FD);
   enc28j60WriteReg(interface, ENC28J60_MABBIPG, ENC28J60_MABBIPG_DEFAULT_HD);
   enc28j60WriteReg(interface, ENC28J60_MAIPGL, ENC28J60_MAIPGL_DEFAULT);
   enc28j60WriteReg(interface, ENC28J60_MAIPGH, ENC28J60_MAIPGH_DEFAULT);
   enc28j60WriteReg(interface, ENC28J60_MACLCON2,
      ENC28J60_MACLCON2_COLWIN_DEFAULT);
   enc28j60WritePhyReg(interface, ENC28J60_PHCON1, ENC28J60_PHCON1_PDPXMD);
   enc28j60WritePhyReg(interface, ENC28J60_PHCON1, 0x0000);
   enc28j60WritePhyReg(interface, ENC28J60_PHCON2, ENC28J60_PHCON2_HDLDIS);
   enc28j60WritePhyReg(interface, ENC28J60_PHLCON,
      ENC28J60_PHLCON_LACFG_LINK | ENC28J60_PHLCON_LBCFG_TX_RX |
      ENC28J60_PHLCON_LFRQ_40_MS | ENC28J60_PHLCON_STRCH);
   enc28j60WriteReg(interface, ENC28J60_EIR, 0x00);
   enc28j60WriteReg(interface, ENC28J60_EIE, ENC28J60_EIE_INTIE |
      ENC28J60_EIE_PKTIE | ENC28J60_EIE_LINKIE | ENC28J60_EIE_TXIE |
      ENC28J60_EIE_TXERIE);
   enc28j60WritePhyReg(interface, ENC28J60_PHIE, ENC28J60_PHIE_PLNKIE |
      ENC28J60_PHIE_PGEIE);
   enc28j60SetBit(interface, ENC28J60_ECON1, ENC28J60_ECON1_RXEN);
   enc28j60ClearBit(interface, ENC28J60_EIE, ENC28J60_EIE_INTIE);
   status = enc28j60ReadReg(interface, ENC28J60_EIR);
   if((status & ENC28J60_EIR_LINKIF) != 0)
      enc28j60ClearBit(interface, ENC28J60_EIE, ENC28J60_EIE_LINKIE);
   if(enc28j60ReadReg(interface, ENC28J60_EPKTCNT) != 0)
      enc28j60ClearBit(interface, ENC28J60_EIE, ENC28J60_EIE_PKTIE);
   if((status & (ENC28J60_EIR_TXIF | ENC28J60_EIE_TXERIE)) != 0)
      enc28j60ClearBit(interface, ENC28J60_EIR, ENC28J60_EIR_TXIF |
         ENC28J60_EIE_TXERIE);
   enc28j60SetBit(interface, ENC28J60_EIE, ENC28J60_EIE_INTIE);
   status = enc28j60ReadReg(interface, ENC28J60_EIR);
   if((status & ENC28J60_EIR_LINKIF) != 0)
      enc28j60ReadPhyReg(interface, ENC28J60_PHIR);
      enc28j60ClearBit(interface, ENC28J60_EIR, ENC28J60_EIR_LINKIF);
      value = enc28j60ReadPhyReg(interface, ENC28J60_PHSTAT2);
      if((value & ENC28J60_PHSTAT2_LSTAT) != 0)
   if(enc28j60ReadReg(interface, ENC28J60_EPKTCNT) != 0)
      enc28j60ClearBit(interface, ENC28J60_EIR, ENC28J60_EIR_PKTIF);
   enc28j60SetBit(interface, ENC28J60_EIE, ENC28J60_EIE_LINKIE |
      ENC28J60_EIE_PKTIE);
   enc28j60SetBit(interface, ENC28J60_ECON1, ENC28J60_ECON1_TXRST);
   enc28j60ClearBit(interface, ENC28J60_ECON1, ENC28J60_ECON1_TXRST);
   enc28j60ClearBit(interface, ENC28J60_EIR, ENC28J60_EIR_TXIF |
      ENC28J60_EIR_TXERIF);
   enc28j60WriteReg(interface, ENC28J60_ETXSTL, LSB(ENC28J60_TX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_ETXSTH, MSB(ENC28J60_TX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_EWRPTL, LSB(ENC28J60_TX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_EWRPTH, MSB(ENC28J60_TX_BUFFER_START));
   enc28j60WriteReg(interface, ENC28J60_ETXNDL, LSB(ENC28J60_TX_BUFFER_START + length));
   enc28j60WriteReg(interface, ENC28J60_ETXNDH, MSB(ENC28J60_TX_BUFFER_START + length));
   enc28j60SetBit(interface, ENC28J60_ECON1, ENC28J60_ECON1_TXRTS);
   uint16_t length;
   uint8_t header[6];
   if(enc28j60ReadReg(interface, ENC28J60_EPKTCNT) != 0)
      enc28j60WriteReg(interface, ENC28J60_ERDPTL, LSB(context->nextPacket));
      enc28j60WriteReg(interface, ENC28J60_ERDPTH, MSB(context->nextPacket));
      //The packet is preceded by a 6-byte header
      enc28j60ReadBuffer(interface, header, sizeof(header));

      //The first two bytes are the address of the next packet
      context->nextPacket = LOAD16LE(header);
      //Get the length of the received packet
      length = LOAD16LE(header + 2);
      //Get the receive status vector (RSV)
      status = LOAD16LE(header + 4);
      if((status & ENC28J60_RSV_RECEIVED_OK) != 0)
         length = MIN(length, ETH_MAX_FRAME_SIZE);
         enc28j60ReadBuffer(interface, context->rxBuffer, length);
         enc28j60WriteReg(interface, ENC28J60_ERXRDPTL, LSB(ENC28J60_RX_BUFFER_STOP));
         enc28j60WriteReg(interface, ENC28J60_ERXRDPTH, MSB(ENC28J60_RX_BUFFER_STOP));
         enc28j60WriteReg(interface, ENC28J60_ERXRDPTL, LSB(context->nextPacket - 1));
         enc28j60WriteReg(interface, ENC28J60_ERXRDPTH, MSB(context->nextPacket - 1));
      enc28j60SetBit(interface, ENC28J60_ECON2, ENC28J60_ECON2_PKTDEC);
      nicProcessPacket(interface, context->rxBuffer, length, &ancillary);
   enc28j60WriteReg(interface, ENC28J60_EHT0, hashTable[0]);
   enc28j60WriteReg(interface, ENC28J60_EHT1, hashTable[1]);
   enc28j60WriteReg(interface, ENC28J60_EHT2, hashTable[2]);
   enc28j60WriteReg(interface, ENC28J60_EHT3, hashTable[3]);
   enc28j60WriteReg(interface, ENC28J60_EHT4, hashTable[4]);
   enc28j60WriteReg(interface, ENC28J60_EHT5, hashTable[5]);
   enc28j60WriteReg(interface, ENC28J60_EHT6, hashTable[6]);
   enc28j60WriteReg(interface, ENC28J60_EHT7, hashTable[7]);
   TRACE_DEBUG("  EHT0 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_EHT0));
   TRACE_DEBUG("  EHT1 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_EHT1));
   TRACE_DEBUG("  EHT2 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_EHT2));
   TRACE_DEBUG("  EHT3 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_EHT3));
   TRACE_DEBUG("  EHT0 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_EHT4));
   TRACE_DEBUG("  EHT1 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_EHT5));
   TRACE_DEBUG("  EHT2 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_EHT6));
   TRACE_DEBUG("  EHT3 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_EHT7));
      //Select the relevant bank
      if(bank == BANK_0)
         enc28j60ClearBit(interface, ENC28J60_ECON1, ENC28J60_ECON1_BSEL1 |
            ENC28J60_ECON1_BSEL0);
      }
      else if(bank == BANK_1)
      {
         enc28j60SetBit(interface, ENC28J60_ECON1, ENC28J60_ECON1_BSEL0);
         enc28j60ClearBit(interface, ENC28J60_ECON1, ENC28J60_ECON1_BSEL1);
      }
      else if(bank == BANK_2)
      {
         enc28j60ClearBit(interface, ENC28J60_ECON1, ENC28J60_ECON1_BSEL0);
         enc28j60SetBit(interface, ENC28J60_ECON1, ENC28J60_ECON1_BSEL1);
      }
      else
      {
         enc28j60SetBit(interface, ENC28J60_ECON1, ENC28J60_ECON1_BSEL1 |
            ENC28J60_ECON1_BSEL0);
   enc28j60WriteReg(interface, ENC28J60_MIREGADR, address & REG_ADDR_MASK);
   enc28j60WriteReg(interface, ENC28J60_MIWRL, LSB(data));
   enc28j60WriteReg(interface, ENC28J60_MIWRH, MSB(data));
   while((enc28j60ReadReg(interface, ENC28J60_MISTAT) & ENC28J60_MISTAT_BUSY) != 0)
   enc28j60WriteReg(interface, ENC28J60_MIREGADR, address & REG_ADDR_MASK);
   enc28j60WriteReg(interface, ENC28J60_MICMD, ENC28J60_MICMD_MIIRD);
   while((enc28j60ReadReg(interface, ENC28J60_MISTAT) & ENC28J60_MISTAT_BUSY) != 0)
   enc28j60WriteReg(interface, ENC28J60_MICMD, 0);
   data = enc28j60ReadReg(interface, ENC28J60_MIRDL);
   data |= enc28j60ReadReg(interface, ENC28J60_MIRDH) << 8;
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
//ENC28J60 registers
#define ENC28J60_ERDPTL                      (ETH_REG_TYPE | BANK_0 | 0x00)
#define ENC28J60_ERDPTH                      (ETH_REG_TYPE | BANK_0 | 0x01)
#define ENC28J60_EWRPTL                      (ETH_REG_TYPE | BANK_0 | 0x02)
#define ENC28J60_EWRPTH                      (ETH_REG_TYPE | BANK_0 | 0x03)
#define ENC28J60_ETXSTL                      (ETH_REG_TYPE | BANK_0 | 0x04)
#define ENC28J60_ETXSTH                      (ETH_REG_TYPE | BANK_0 | 0x05)
#define ENC28J60_ETXNDL                      (ETH_REG_TYPE | BANK_0 | 0x06)
#define ENC28J60_ETXNDH                      (ETH_REG_TYPE | BANK_0 | 0x07)
#define ENC28J60_ERXSTL                      (ETH_REG_TYPE | BANK_0 | 0x08)
#define ENC28J60_ERXSTH                      (ETH_REG_TYPE | BANK_0 | 0x09)
#define ENC28J60_ERXNDL                      (ETH_REG_TYPE | BANK_0 | 0x0A)
#define ENC28J60_ERXNDH                      (ETH_REG_TYPE | BANK_0 | 0x0B)
#define ENC28J60_ERXRDPTL                    (ETH_REG_TYPE | BANK_0 | 0x0C)
#define ENC28J60_ERXRDPTH                    (ETH_REG_TYPE | BANK_0 | 0x0D)
#define ENC28J60_ERXWRPTL                    (ETH_REG_TYPE | BANK_0 | 0x0E)
#define ENC28J60_ERXWRPTH                    (ETH_REG_TYPE | BANK_0 | 0x0F)
#define ENC28J60_EDMASTL                     (ETH_REG_TYPE | BANK_0 | 0x10)
#define ENC28J60_EDMASTH                     (ETH_REG_TYPE | BANK_0 | 0x11)
#define ENC28J60_EDMANDL                     (ETH_REG_TYPE | BANK_0 | 0x12)
#define ENC28J60_EDMANDH                     (ETH_REG_TYPE | BANK_0 | 0x13)
#define ENC28J60_EDMADSTL                    (ETH_REG_TYPE | BANK_0 | 0x14)
#define ENC28J60_EDMADSTH                    (ETH_REG_TYPE | BANK_0 | 0x15)
#define ENC28J60_EDMACSL                     (ETH_REG_TYPE | BANK_0 | 0x16)
#define ENC28J60_EDMACSH                     (ETH_REG_TYPE | BANK_0 | 0x17)
#define ENC28J60_EIE                         (ETH_REG_TYPE | BANK_0 | 0x1B)
#define ENC28J60_EIR                         (ETH_REG_TYPE | BANK_0 | 0x1C)
#define ENC28J60_ESTAT                       (ETH_REG_TYPE | BANK_0 | 0x1D)
#define ENC28J60_ECON2                       (ETH_REG_TYPE | BANK_0 | 0x1E)
#define ENC28J60_ECON1                       (ETH_REG_TYPE | BANK_0 | 0x1F)
#define ENC28J60_EHT0                        (ETH_REG_TYPE | BANK_1 | 0x00)
#define ENC28J60_EHT1                        (ETH_REG_TYPE | BANK_1 | 0x01)
#define ENC28J60_EHT2                        (ETH_REG_TYPE | BANK_1 | 0x02)
#define ENC28J60_EHT3                        (ETH_REG_TYPE | BANK_1 | 0x03)
#define ENC28J60_EHT4                        (ETH_REG_TYPE | BANK_1 | 0x04)
#define ENC28J60_EHT5                        (ETH_REG_TYPE | BANK_1 | 0x05)
#define ENC28J60_EHT6                        (ETH_REG_TYPE | BANK_1 | 0x06)
#define ENC28J60_EHT7                        (ETH_REG_TYPE | BANK_1 | 0x07)
#define ENC28J60_EPMM0                       (ETH_REG_TYPE | BANK_1 | 0x08)
#define ENC28J60_EPMM1                       (ETH_REG_TYPE | BANK_1 | 0x09)
#define ENC28J60_EPMM2                       (ETH_REG_TYPE | BANK_1 | 0x0A)
#define ENC28J60_EPMM3                       (ETH_REG_TYPE | BANK_1 | 0x0B)
#define ENC28J60_EPMM4                       (ETH_REG_TYPE | BANK_1 | 0x0C)
#define ENC28J60_EPMM5                       (ETH_REG_TYPE | BANK_1 | 0x0D)
#define ENC28J60_EPMM6                       (ETH_REG_TYPE | BANK_1 | 0x0E)
#define ENC28J60_EPMM7                       (ETH_REG_TYPE | BANK_1 | 0x0F)
#define ENC28J60_EPMCSL                      (ETH_REG_TYPE | BANK_1 | 0x10)
#define ENC28J60_EPMCSH                      (ETH_REG_TYPE | BANK_1 | 0x11)
#define ENC28J60_EPMOL                       (ETH_REG_TYPE | BANK_1 | 0x14)
#define ENC28J60_EPMOH                       (ETH_REG_TYPE | BANK_1 | 0x15)
#define ENC28J60_EWOLIE                      (ETH_REG_TYPE | BANK_1 | 0x16)
#define ENC28J60_EWOLIR                      (ETH_REG_TYPE | BANK_1 | 0x17)
#define ENC28J60_ERXFCON                     (ETH_REG_TYPE | BANK_1 | 0x18)
#define ENC28J60_EPKTCNT                     (ETH_REG_TYPE | BANK_1 | 0x19)
#define ENC28J60_MACON1                      (MAC_REG_TYPE | BANK_2 | 0x00)
#define ENC28J60_MACON2                      (MAC_REG_TYPE | BANK_2 | 0x01)
#define ENC28J60_MACON3                      (MAC_REG_TYPE | BANK_2 | 0x02)
#define ENC28J60_MACON4                      (MAC_REG_TYPE | BANK_2 | 0x03)
#define ENC28J60_MABBIPG                     (MAC_REG_TYPE | BANK_2 | 0x04)
#define ENC28J60_MAIPGL                      (MAC_REG_TYPE | BANK_2 | 0x06)
#define ENC28J60_MAIPGH                      (MAC_REG_TYPE | BANK_2 | 0x07)
#define ENC28J60_MACLCON1                    (MAC_REG_TYPE | BANK_2 | 0x08)
#define ENC28J60_MACLCON2                    (MAC_REG_TYPE | BANK_2 | 0x09)
#define ENC28J60_MAMXFLL                     (MAC_REG_TYPE | BANK_2 | 0x0A)
#define ENC28J60_MAMXFLH                     (MAC_REG_TYPE | BANK_2 | 0x0B)
#define ENC28J60_MAPHSUP                     (MAC_REG_TYPE | BANK_2 | 0x0D)
#define ENC28J60_MICON                       (MII_REG_TYPE | BANK_2 | 0x11)
#define ENC28J60_MICMD                       (MII_REG_TYPE | BANK_2 | 0x12)
#define ENC28J60_MIREGADR                    (MII_REG_TYPE | BANK_2 | 0x14)
#define ENC28J60_MIWRL                       (MII_REG_TYPE | BANK_2 | 0x16)
#define ENC28J60_MIWRH                       (MII_REG_TYPE | BANK_2 | 0x17)
#define ENC28J60_MIRDL                       (MII_REG_TYPE | BANK_2 | 0x18)
#define ENC28J60_MIRDH                       (MII_REG_TYPE | BANK_2 | 0x19)
#define ENC28J60_MAADR1                      (MAC_REG_TYPE | BANK_3 | 0x00)
#define ENC28J60_MAADR0                      (MAC_REG_TYPE | BANK_3 | 0x01)
#define ENC28J60_MAADR3                      (MAC_REG_TYPE | BANK_3 | 0x02)
#define ENC28J60_MAADR2                      (MAC_REG_TYPE | BANK_3 | 0x03)
#define ENC28J60_MAADR5                      (MAC_REG_TYPE | BANK_3 | 0x04)
#define ENC28J60_MAADR4                      (MAC_REG_TYPE | BANK_3 | 0x05)
#define ENC28J60_EBSTSD                      (ETH_REG_TYPE | BANK_3 | 0x06)
#define ENC28J60_EBSTCON                     (ETH_REG_TYPE | BANK_3 | 0x07)
#define ENC28J60_EBSTCSL                     (ETH_REG_TYPE | BANK_3 | 0x08)
#define ENC28J60_EBSTCSH                     (ETH_REG_TYPE | BANK_3 | 0x09)
#define ENC28J60_MISTAT                      (MII_REG_TYPE | BANK_3 | 0x0A)
#define ENC28J60_EREVID                      (ETH_REG_TYPE | BANK_3 | 0x12)
#define ENC28J60_ECOCON                      (ETH_REG_TYPE | BANK_3 | 0x15)
#define ENC28J60_EFLOCON                     (ETH_REG_TYPE | BANK_3 | 0x17)
#define ENC28J60_EPAUSL                      (ETH_REG_TYPE | BANK_3 | 0x18)
#define ENC28J60_EPAUSH                      (ETH_REG_TYPE | BANK_3 | 0x19)

//ENC28J60 PHY registers
#define ENC28J60_PHCON1                      (PHY_REG_TYPE | 0x00)
#define ENC28J60_PHSTAT1                     (PHY_REG_TYPE | 0x01)
#define ENC28J60_PHID1                       (PHY_REG_TYPE | 0x02)
#define ENC28J60_PHID2                       (PHY_REG_TYPE | 0x03)
#define ENC28J60_PHCON2                      (PHY_REG_TYPE | 0x10)
#define ENC28J60_PHSTAT2                     (PHY_REG_TYPE | 0x11)
#define ENC28J60_PHIE                        (PHY_REG_TYPE | 0x12)
#define ENC28J60_PHIR                        (PHY_REG_TYPE | 0x13)
#define ENC28J60_PHLCON                      (PHY_REG_TYPE | 0x14)

//Ethernet Interrupt Enable register
#define ENC28J60_EIE_INTIE                   0x80
#define ENC28J60_EIE_PKTIE                   0x40
#define ENC28J60_EIE_DMAIE                   0x20
#define ENC28J60_EIE_LINKIE                  0x10
#define ENC28J60_EIE_TXIE                    0x08
#define ENC28J60_EIE_WOLIE                   0x04
#define ENC28J60_EIE_TXERIE                  0x02
#define ENC28J60_EIE_RXERIE                  0x01

//Ethernet Interrupt Request register
#define ENC28J60_EIR_PKTIF                   0x40
#define ENC28J60_EIR_DMAIF                   0x20
#define ENC28J60_EIR_LINKIF                  0x10
#define ENC28J60_EIR_TXIF                    0x08
#define ENC28J60_EIR_WOLIF                   0x04
#define ENC28J60_EIR_TXERIF                  0x02
#define ENC28J60_EIR_RXERIF                  0x01

//Ethernet Status register
#define ENC28J60_ESTAT_INT                   0x80
#define ENC28J60_ESTAT_R6                    0x40
#define ENC28J60_ESTAT_R5                    0x20
#define ENC28J60_ESTAT_LATECOL               0x10
#define ENC28J60_ESTAT_RXBUSY                0x04
#define ENC28J60_ESTAT_TXABRT                0x02
#define ENC28J60_ESTAT_CLKRDY                0x01

//Ethernet Control 2 register
#define ENC28J60_ECON2_AUTOINC               0x80
#define ENC28J60_ECON2_PKTDEC                0x40
#define ENC28J60_ECON2_PWRSV                 0x20
#define ENC28J60_ECON2_VRPS                  0x08

//Ethernet Control 1 register
#define ENC28J60_ECON1_TXRST                 0x80
#define ENC28J60_ECON1_RXRST                 0x40
#define ENC28J60_ECON1_DMAST                 0x20
#define ENC28J60_ECON1_CSUMEN                0x10
#define ENC28J60_ECON1_TXRTS                 0x08
#define ENC28J60_ECON1_RXEN                  0x04
#define ENC28J60_ECON1_BSEL1                 0x02
#define ENC28J60_ECON1_BSEL0                 0x01

//Ethernet Wake-Up On LAN Interrupt Enable register
#define ENC28J60_EWOLIE_UCWOLIE              0x80
#define ENC28J60_EWOLIE_AWOLIE               0x40
#define ENC28J60_EWOLIE_PMWOLIE              0x10
#define ENC28J60_EWOLIE_MPWOLIE              0x08
#define ENC28J60_EWOLIE_HTWOLIE              0x04
#define ENC28J60_EWOLIE_MCWOLIE              0x02
#define ENC28J60_EWOLIE_BCWOLIE              0x01

//Ethernet Wake-Up On LAN Interrupt Request register
#define ENC28J60_EWOLIR_UCWOLIF              0x80
#define ENC28J60_EWOLIR_AWOLIF               0x40
#define ENC28J60_EWOLIR_PMWOLIF              0x10
#define ENC28J60_EWOLIR_MPWOLIF              0x08
#define ENC28J60_EWOLIR_HTWOLIF              0x04
#define ENC28J60_EWOLIR_MCWOLIF              0x02
#define ENC28J60_EWOLIR_BCWOLIF              0x01

//Receive Filter Control register
#define ENC28J60_ERXFCON_UCEN                0x80
#define ENC28J60_ERXFCON_ANDOR               0x40
#define ENC28J60_ERXFCON_CRCEN               0x20
#define ENC28J60_ERXFCON_PMEN                0x10
#define ENC28J60_ERXFCON_MPEN                0x08
#define ENC28J60_ERXFCON_HTEN                0x04
#define ENC28J60_ERXFCON_MCEN                0x02
#define ENC28J60_ERXFCON_BCEN                0x01

//MAC Control 1 register
#define ENC28J60_MACON1_LOOPBK               0x10
#define ENC28J60_MACON1_TXPAUS               0x08
#define ENC28J60_MACON1_RXPAUS               0x04
#define ENC28J60_MACON1_PASSALL              0x02
#define ENC28J60_MACON1_MARXEN               0x01

//MAC Control 2 register
#define ENC28J60_MACON2_MARST                0x80
#define ENC28J60_MACON2_RNDRST               0x40
#define ENC28J60_MACON2_MARXRST              0x08
#define ENC28J60_MACON2_RFUNRST              0x04
#define ENC28J60_MACON2_MATXRST              0x02
#define ENC28J60_MACON2_TFUNRST              0x01

//MAC Control 3 register
#define ENC28J60_MACON3_PADCFG               0xE0
#define ENC28J60_MACON3_PADCFG_NO            0x00
#define ENC28J60_MACON3_PADCFG_60_BYTES      0x20
#define ENC28J60_MACON3_PADCFG_64_BYTES      0x60
#define ENC28J60_MACON3_PADCFG_AUTO          0xA0
#define ENC28J60_MACON3_TXCRCEN              0x10
#define ENC28J60_MACON3_PHDRLEN              0x08
#define ENC28J60_MACON3_HFRMEN               0x04
#define ENC28J60_MACON3_FRMLNEN              0x02
#define ENC28J60_MACON3_FULDPX               0x01

//MAC Control 4 register
#define ENC28J60_MACON4_DEFER                0x40
#define ENC28J60_MACON4_BPEN                 0x20
#define ENC28J60_MACON4_NOBKOFF              0x10
#define ENC28J60_MACON4_LONGPRE              0x02
#define ENC28J60_MACON4_PUREPRE              0x01

//Back-to-Back Inter-Packet Gap register
#define ENC28J60_MABBIPG_DEFAULT_HD          0x12
#define ENC28J60_MABBIPG_DEFAULT_FD          0x15

//Non-Back-to-Back Inter-Packet Gap Low Byte register
#define ENC28J60_MAIPGL_DEFAULT              0x12

//Non-Back-to-Back Inter-Packet Gap High Byte register
#define ENC28J60_MAIPGH_DEFAULT              0x0C

//Retransmission Maximum register
#define ENC28J60_MACLCON1_RETMAX             0x0F

//Collision Window register
#define ENC28J60_MACLCON2_COLWIN             0x3F
#define ENC28J60_MACLCON2_COLWIN_DEFAULT     0x37

//MAC-PHY Support register
#define ENC28J60_MAPHSUP_RSTINTFC            0x80
#define ENC28J60_MAPHSUP_R4                  0x10
#define ENC28J60_MAPHSUP_RSTRMII             0x08
#define ENC28J60_MAPHSUP_R0                  0x01

//MII Control register
#define ENC28J60_MICON_RSTMII                0x80

//MII Command register
#define ENC28J60_MICMD_MIISCAN               0x02
#define ENC28J60_MICMD_MIIRD                 0x01

//MII Register Addres register
#define ENC28J60_MIREGADR_VAL                0x1F

//Self-Test Control register
#define ENC28J60_EBSTCON_PSV                 0xE0
#define ENC28J60_EBSTCON_PSEL                0x10
#define ENC28J60_EBSTCON_TMSEL               0x0C
#define ENC28J60_EBSTCON_TMSEL_RANDOM        0x00
#define ENC28J60_EBSTCON_TMSEL_ADDR          0x04
#define ENC28J60_EBSTCON_TMSEL_PATTERN_SHIFT 0x08
#define ENC28J60_EBSTCON_TMSEL_RACE_MODE     0x0C
#define ENC28J60_EBSTCON_TME                 0x02
#define ENC28J60_EBSTCON_BISTST              0x01

//MII Status register
#define ENC28J60_MISTAT_R3                   0x08
#define ENC28J60_MISTAT_NVALID               0x04
#define ENC28J60_MISTAT_SCAN                 0x02
#define ENC28J60_MISTAT_BUSY                 0x01

//Ethernet Revision ID register
#define ENC28J60_EREVID_REV                  0x1F
#define ENC28J60_EREVID_REV_B1               0x02
#define ENC28J60_EREVID_REV_B4               0x04
#define ENC28J60_EREVID_REV_B5               0x05
#define ENC28J60_EREVID_REV_B7               0x06

//Clock Output Control register
#define ENC28J60_ECOCON_COCON                0x07
#define ENC28J60_ECOCON_COCON_DISABLED       0x00
#define ENC28J60_ECOCON_COCON_DIV1           0x01
#define ENC28J60_ECOCON_COCON_DIV2           0x02
#define ENC28J60_ECOCON_COCON_DIV3           0x03
#define ENC28J60_ECOCON_COCON_DIV4           0x04
#define ENC28J60_ECOCON_COCON_DIV8           0x05

//Ethernet Flow Control register
#define ENC28J60_EFLOCON_FULDPXS             0x04
#define ENC28J60_EFLOCON_FCEN                0x03
#define ENC28J60_EFLOCON_FCEN_OFF            0x00
#define ENC28J60_EFLOCON_FCEN_ON_HD          0x01
#define ENC28J60_EFLOCON_FCEN_ON_FD          0x02
#define ENC28J60_EFLOCON_FCEN_SEND_PAUSE     0x03

//PHY Control 1 register
#define ENC28J60_PHCON1_PRST                 0x8000
#define ENC28J60_PHCON1_PLOOPBK              0x4000
#define ENC28J60_PHCON1_PPWRSV               0x0800
#define ENC28J60_PHCON1_PDPXMD               0x0100

//Physical Layer Status 1 register
#define ENC28J60_PHSTAT1_PFDPX               0x1000
#define ENC28J60_PHSTAT1_PHDPX               0x0800
#define ENC28J60_PHSTAT1_LLSTAT              0x0004
#define ENC28J60_PHSTAT1_JBRSTAT             0x0002

//PHY Identifier 1 register
#define ENC28J60_PHID1_PIDH                  0xFFFF
#define ENC28J60_PHID1_PIDH_DEFAULT          0x0083

//PHY Identifier 2 register
#define ENC28J60_PHID2_PIDL                  0xFC00
#define ENC28J60_PHID2_PIDL_DEFAULT          0x1400
#define ENC28J60_PHID2_PPN                   0x03F0
#define ENC28J60_PHID2_PPN_DEFAULT           0x0000
#define ENC28J60_PHID2_PREV                  0x000F

//PHY Control 2 register
#define ENC28J60_PHCON2_FRCLNK               0x4000
#define ENC28J60_PHCON2_TXDIS                0x2000
#define ENC28J60_PHCON2_JABBER               0x0400
#define ENC28J60_PHCON2_HDLDIS               0x0100

//Physical Layer Status 2 register
#define ENC28J60_PHSTAT2_TXSTAT              0x2000
#define ENC28J60_PHSTAT2_RXSTAT              0x1000
#define ENC28J60_PHSTAT2_COLSTAT             0x0800
#define ENC28J60_PHSTAT2_LSTAT               0x0400
#define ENC28J60_PHSTAT2_DPXSTAT             0x0200
#define ENC28J60_PHSTAT2_PLRITY              0x0010

//PHY Interrupt Enable register
#define ENC28J60_PHIE_PLNKIE                 0x0010
#define ENC28J60_PHIE_PGEIE                  0x0002

//PHY Interrupt Request register
#define ENC28J60_PHIR_PLNKIF                 0x0010
#define ENC28J60_PHIR_PGIF                   0x0004

//PHY Module LED Control register
#define ENC28J60_PHLCON_LACFG                0x0F00
#define ENC28J60_PHLCON_LACFG_TX             0x0100
#define ENC28J60_PHLCON_LACFG_RX             0x0200
#define ENC28J60_PHLCON_LACFG_COL            0x0300
#define ENC28J60_PHLCON_LACFG_LINK           0x0400
#define ENC28J60_PHLCON_LACFG_DUPLEX         0x0500
#define ENC28J60_PHLCON_LACFG_TX_RX          0x0700
#define ENC28J60_PHLCON_LACFG_ON             0x0800
#define ENC28J60_PHLCON_LACFG_OFF            0x0900
#define ENC28J60_PHLCON_LACFG_BLINK_FAST     0x0A00
#define ENC28J60_PHLCON_LACFG_BLINK_SLOW     0x0B00
#define ENC28J60_PHLCON_LACFG_LINK_RX        0x0C00
#define ENC28J60_PHLCON_LACFG_LINK_TX_RX     0x0D00
#define ENC28J60_PHLCON_LACFG_DUPLEX_COL     0x0E00
#define ENC28J60_PHLCON_LBCFG                0x00F0
#define ENC28J60_PHLCON_LBCFG_TX             0x0010
#define ENC28J60_PHLCON_LBCFG_RX             0x0020
#define ENC28J60_PHLCON_LBCFG_COL            0x0030
#define ENC28J60_PHLCON_LBCFG_LINK           0x0040
#define ENC28J60_PHLCON_LBCFG_DUPLEX         0x0050
#define ENC28J60_PHLCON_LBCFG_TX_RX          0x0070
#define ENC28J60_PHLCON_LBCFG_ON             0x0080
#define ENC28J60_PHLCON_LBCFG_OFF            0x0090
#define ENC28J60_PHLCON_LBCFG_BLINK_FAST     0x00A0
#define ENC28J60_PHLCON_LBCFG_BLINK_SLOW     0x00B0
#define ENC28J60_PHLCON_LBCFG_LINK_RX        0x00C0
#define ENC28J60_PHLCON_LBCFG_LINK_TX_RX     0x00D0
#define ENC28J60_PHLCON_LBCFG_DUPLEX_COL     0x00E0
#define ENC28J60_PHLCON_LFRQ                 0x000C
#define ENC28J60_PHLCON_LFRQ_40_MS           0x0000
#define ENC28J60_PHLCON_LFRQ_73_MS           0x0004
#define ENC28J60_PHLCON_LFRQ_139_MS          0x0008
#define ENC28J60_PHLCON_STRCH                0x0002
#define ENC28J60_TX_CTRL_PHUGEEN             0x08
#define ENC28J60_TX_CTRL_PPADEN              0x04
#define ENC28J60_TX_CTRL_PCRCEN              0x02
#define ENC28J60_TX_CTRL_POVERRIDE           0x01
#define ENC28J60_RSV_VLAN_TYPE               0x4000
#define ENC28J60_RSV_UNKNOWN_OPCODE          0x2000
#define ENC28J60_RSV_PAUSE_CONTROL_FRAME     0x1000
#define ENC28J60_RSV_CONTROL_FRAME           0x0800
#define ENC28J60_RSV_DRIBBLE_NIBBLE          0x0400
#define ENC28J60_RSV_BROADCAST_PACKET        0x0200
#define ENC28J60_RSV_MULTICAST_PACKET        0x0100
#define ENC28J60_RSV_RECEIVED_OK             0x0080
#define ENC28J60_RSV_LENGTH_OUT_OF_RANGE     0x0040
#define ENC28J60_RSV_LENGTH_CHECK_ERROR      0x0020
#define ENC28J60_RSV_CRC_ERROR               0x0010
#define ENC28J60_RSV_CARRIER_EVENT           0x0004
#define ENC28J60_RSV_DROP_EVENT              0x0001
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   enc624j600WriteReg(interface, ENC624J600_ECON2, ENC624J600_ECON2_ETHEN |
      ENC624J600_ECON2_STRCH);
      temp = enc624j600ReadReg(interface, ENC624J600_MAADR1);
      temp = enc624j600ReadReg(interface, ENC624J600_MAADR2);
      temp = enc624j600ReadReg(interface, ENC624J600_MAADR3);
      enc624j600WriteReg(interface, ENC624J600_MAADR1, temp);
      enc624j600WriteReg(interface, ENC624J600_MAADR2, temp);
      enc624j600WriteReg(interface, ENC624J600_MAADR3, temp);
   enc624j600WriteReg(interface, ENC624J600_ERXST, ENC624J600_RX_BUFFER_START);
   enc624j600WriteReg(interface, ENC624J600_ERXTAIL, ENC624J600_RX_BUFFER_STOP);
   enc624j600WriteReg(interface, ENC624J600_ERXFCON, ENC624J600_ERXFCON_HTEN |
      ENC624J600_ERXFCON_CRCEN | ENC624J600_ERXFCON_RUNTEN |
      ENC624J600_ERXFCON_UCEN | ENC624J600_ERXFCON_BCEN);
   enc624j600WriteReg(interface, ENC624J600_EHT1, 0x0000);
   enc624j600WriteReg(interface, ENC624J600_EHT2, 0x0000);
   enc624j600WriteReg(interface, ENC624J600_EHT3, 0x0000);
   enc624j600WriteReg(interface, ENC624J600_EHT4, 0x0000);
   //All short frames will be zero-padded to 60 bytes and a valid CRC is then
   //appended
   enc624j600WriteReg(interface, ENC624J600_MACON2, ENC624J600_MACON2_DEFER |
      ENC624J600_MACON2_PADCFG_AUTO | ENC624J600_MACON2_TXCRCEN |
      ENC624J600_MACON2_R1_DEFAULT);
   enc624j600WriteReg(interface, ENC624J600_MAMXFL, ETH_MAX_FRAME_SIZE);
   enc624j600WritePhyReg(interface, ENC624J600_PHANA, ENC624J600_PHANA_ADPAUS0 |
      ENC624J600_PHANA_AD100FD | ENC624J600_PHANA_AD100 | ENC624J600_PHANA_AD10FD |
      ENC624J600_PHANA_AD10 | ENC624J600_PHANA_ADIEEE_DEFAULT);
   enc624j600WriteReg(interface, ENC624J600_EIR, 0x0000);
   enc624j600WriteReg(interface, ENC624J600_EIE, ENC624J600_EIE_INTIE |
      ENC624J600_EIE_LINKIE | ENC624J600_EIE_PKTIE | ENC624J600_EIE_TXIE |
      ENC624J600_EIE_TXABTIE);
   enc624j600SetBit(interface, ENC624J600_ECON1, ENC624J600_ECON1_RXEN);
   enc624j600ClearBit(interface, ENC624J600_EIE, ENC624J600_EIE_INTIE);
   status = enc624j600ReadReg(interface, ENC624J600_EIR);
   if((status & ENC624J600_EIR_LINKIF) != 0)
      enc624j600ClearBit(interface, ENC624J600_EIE, ENC624J600_EIE_LINKIE);
   if((status & ENC624J600_EIR_PKTIF) != 0)
      enc624j600ClearBit(interface, ENC624J600_EIE, ENC624J600_EIE_PKTIE);
   if((status & (ENC624J600_EIR_TXIF | ENC624J600_EIR_TXABTIF)) != 0)
      enc624j600ClearBit(interface, ENC624J600_EIR, ENC624J600_EIR_TXIF |
         ENC624J600_EIR_TXABTIF);
   enc624j600SetBit(interface, ENC624J600_EIE, ENC624J600_EIE_INTIE);
   status = enc624j600ReadReg(interface, ENC624J600_EIR);
   if((status & ENC624J600_EIR_LINKIF) != 0)
      enc624j600ClearBit(interface, ENC624J600_EIR, ENC624J600_EIR_LINKIF);
      value = enc624j600ReadReg(interface, ENC624J600_ESTAT);
      if((value & ENC624J600_ESTAT_PHYLNK) != 0)
         value = enc624j600ReadPhyReg(interface, ENC624J600_PHSTAT3);
         if((value & ENC624J600_PHSTAT3_SPDDPX1) != 0)
         if((value & ENC624J600_PHSTAT3_SPDDPX2) != 0)
   if((status & ENC624J600_EIR_PKTIF) != 0)
      enc624j600ClearBit(interface, ENC624J600_EIR, ENC624J600_EIR_PKTIF);
   enc624j600SetBit(interface, ENC624J600_EIE, ENC624J600_EIE_LINKIE |
      ENC624J600_EIE_PKTIE);
   if(enc624j600ReadReg(interface, ENC624J600_ECON1) & ENC624J600_ECON1_TXRTS)
   enc624j600WriteReg(interface, ENC624J600_EGPWRPT, ENC624J600_TX_BUFFER_START);
   enc624j600WriteReg(interface, ENC624J600_ETXST, ENC624J600_TX_BUFFER_START);
   enc624j600WriteReg(interface, ENC624J600_ETXLEN, length);
   enc624j600ClearBit(interface, ENC624J600_EIR, ENC624J600_EIR_TXIF |
      ENC624J600_EIR_TXABTIF);

   enc624j600SetBit(interface, ENC624J600_ECON1, ENC624J600_ECON1_TXRTS);
   uint16_t length;
   uint8_t header[8];
   if(enc624j600ReadReg(interface, ENC624J600_ESTAT) & ENC624J600_ESTAT_PKTCNT)
      enc624j600WriteReg(interface, ENC624J600_ERXRDPT, context->nextPacket);
      //The packet is preceded by a 8-byte header
      enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA, header, sizeof(header));
      //The first two bytes are the address of the next packet
      context->nextPacket = LOAD16LE(header);
      //Get the length of the received packet
      length = LOAD16LE(header + 2);
      //Get the receive status vector (RSV)
      status = LOAD32LE(header + 4);
      if((status & ENC624J600_RSV_RECEIVED_OK) != 0)
         length = MIN(length, ETH_MAX_FRAME_SIZE);

         enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA,
            context->rxBuffer, length);

         enc624j600WriteReg(interface, ENC624J600_ERXTAIL,
            ENC624J600_RX_BUFFER_STOP);
         enc624j600WriteReg(interface, ENC624J600_ERXTAIL,
            context->nextPacket - 2);
      enc624j600SetBit(interface, ENC624J600_ECON1, ENC624J600_ECON1_PKTDEC);
      nicProcessPacket(interface, context->rxBuffer, length, &ancillary);
   enc624j600WriteReg(interface, ENC624J600_EHT1, hashTable[0]);
   enc624j600WriteReg(interface, ENC624J600_EHT2, hashTable[1]);
   enc624j600WriteReg(interface, ENC624J600_EHT3, hashTable[2]);
   enc624j600WriteReg(interface, ENC624J600_EHT4, hashTable[3]);
   TRACE_DEBUG("  EHT1 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_EHT1));
   TRACE_DEBUG("  EHT2 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_EHT2));
   TRACE_DEBUG("  EHT3 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_EHT3));
   TRACE_DEBUG("  EHT4 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_EHT4));
   duplexMode = enc624j600ReadReg(interface, ENC624J600_ESTAT) & ENC624J600_ESTAT_PHYDPX;
      enc624j600WriteReg(interface, ENC624J600_MACON2, ENC624J600_MACON2_DEFER |
         ENC624J600_MACON2_PADCFG_AUTO | ENC624J600_MACON2_TXCRCEN |
         ENC624J600_MACON2_R1_DEFAULT | ENC624J600_MACON2_FULDPX);

      enc624j600WriteReg(interface, ENC624J600_MABBIPG,
         ENC624J600_MABBIPG_BBIPG_DEFAULT_FD);
      enc624j600WriteReg(interface, ENC624J600_MACON2, ENC624J600_MACON2_DEFER |
         ENC624J600_MACON2_PADCFG_AUTO | ENC624J600_MACON2_TXCRCEN |
         ENC624J600_MACON2_R1_DEFAULT);

      enc624j600WriteReg(interface, ENC624J600_MABBIPG,
         ENC624J600_MABBIPG_BBIPG_DEFAULT_HD);
      enc624j600WriteReg(interface, ENC624J600_EUDAST, 0x1234);
   } while(enc624j600ReadReg(interface, ENC624J600_EUDAST) != 0x1234);
   while((enc624j600ReadReg(interface, ENC624J600_ESTAT) & ENC624J600_ESTAT_CLKRDY) == 0)
   enc624j600SetBit(interface, ENC624J600_ECON2, ENC624J600_ECON2_ETHRST);
   if(enc624j600ReadReg(interface, ENC624J600_EUDAST) != 0x0000)
   uint16_t status;

   enc624j600WriteReg(interface, ENC624J600_MIREGADR,
      ENC624J600_MIREGADR_R12_8_DEFAULT | address);

   enc624j600WriteReg(interface, ENC624J600_MIWR, data);
   do
      //Read MII Management Status register
      status = enc624j600ReadReg(interface, ENC624J600_MISTAT);
      //Check the value of the busy status bit
   } while((status & ENC624J600_MISTAT_BUSY) != 0);
   uint16_t status;

   enc624j600WriteReg(interface, ENC624J600_MIREGADR,
      ENC624J600_MIREGADR_R12_8_DEFAULT | address);

   enc624j600WriteReg(interface, ENC624J600_MICMD, ENC624J600_MICMD_MIIRD);

   do
      //Read MII Management Status register
      status = enc624j600ReadReg(interface, ENC624J600_MISTAT);
      //Check the value of the busy status bit
   } while((status & ENC624J600_MISTAT_BUSY) != 0);
   enc624j600WriteReg(interface, ENC624J600_MICMD, 0x00);
   return enc624j600ReadReg(interface, ENC624J600_MIRD);
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
#define ENC624J600_ETXST                          0x00
#define ENC624J600_ETXLEN                         0x02
#define ENC624J600_ERXST                          0x04
#define ENC624J600_ERXTAIL                        0x06
#define ENC624J600_ERXHEAD                        0x08
#define ENC624J600_EDMAST                         0x0A
#define ENC624J600_EDMALEN                        0x0C
#define ENC624J600_EDMADST                        0x0E
#define ENC624J600_EDMACS                         0x10
#define ENC624J600_ETXSTAT                        0x12
#define ENC624J600_ETXWIRE                        0x14
#define ENC624J600_EUDAST                         0x16
#define ENC624J600_EUDAND                         0x18
#define ENC624J600_ESTAT                          0x1A
#define ENC624J600_EIR                            0x1C
#define ENC624J600_ECON1                          0x1E
#define ENC624J600_EHT1                           0x20
#define ENC624J600_EHT2                           0x22
#define ENC624J600_EHT3                           0x24
#define ENC624J600_EHT4                           0x26
#define ENC624J600_EPMM1                          0x28
#define ENC624J600_EPMM2                          0x2A
#define ENC624J600_EPMM3                          0x2C
#define ENC624J600_EPMM4                          0x2E
#define ENC624J600_EPMCS                          0x30
#define ENC624J600_EPMO                           0x32
#define ENC624J600_ERXFCON                        0x34
#define ENC624J600_MACON1                         0x40
#define ENC624J600_MACON2                         0x42
#define ENC624J600_MABBIPG                        0x44
#define ENC624J600_MAIPG                          0x46
#define ENC624J600_MACLCON                        0x48
#define ENC624J600_MAMXFL                         0x4A
#define ENC624J600_MICMD                          0x52
#define ENC624J600_MIREGADR                       0x54
#define ENC624J600_MAADR3                         0x60
#define ENC624J600_MAADR2                         0x62
#define ENC624J600_MAADR1                         0x64
#define ENC624J600_MIWR                           0x66
#define ENC624J600_MIRD                           0x68
#define ENC624J600_MISTAT                         0x6A
#define ENC624J600_EPAUS                          0x6C
#define ENC624J600_ECON2                          0x6E
#define ENC624J600_ERXWM                          0x70
#define ENC624J600_EIE                            0x72
#define ENC624J600_EIDLED                         0x74
#define ENC624J600_EGPDATA                        0x80
#define ENC624J600_ERXDATA                        0x82
#define ENC624J600_EUDADATA                       0x84
#define ENC624J600_EGPRDPT                        0x86
#define ENC624J600_EGPWRPT                        0x88
#define ENC624J600_ERXRDPT                        0x8A
#define ENC624J600_ERXWRPT                        0x8C
#define ENC624J600_EUDARDPT                       0x8E
#define ENC624J600_EUDAWRPT                       0x90
#define ENC624J600_PHCON1                         0x00
#define ENC624J600_PHSTAT1                        0x01
#define ENC624J600_PHANA                          0x04
#define ENC624J600_PHANLPA                        0x05
#define ENC624J600_PHANE                          0x06
#define ENC624J600_PHCON2                         0x11
#define ENC624J600_PHSTAT2                        0x1B
#define ENC624J600_PHSTAT3                        0x1F

//TX Start Address register
#define ENC624J600_ETXST_VAL                      0x7FFF

//TX Length register
#define ENC624J600_ETXLEN_VAL                     0x7FFF

//RX Buffer Start Address register
#define ENC624J600_ERXST_VAL                      0x7FFF

//RX Tail Pointer register
#define ENC624J600_ERXTAIL_VAL                    0x7FFF

//RX Head Pointer register
#define ENC624J600_ERXHEAD_VAL                    0x7FFF

//DMA Start Address register
#define ENC624J600_EDMAST_VAL                     0x7FFF

//DMA Length register
#define ENC624J600_EDMALEN_VAL                    0x7FFF

//DMA Destination Address register
#define ENC624J600_EDMADST_VAL                    0x7FFF

//Ethernet Transmit Status register
#define ENC624J600_ETXSTAT_R12                    0x1000
#define ENC624J600_ETXSTAT_R11                    0x0800
#define ENC624J600_ETXSTAT_LATECOL                0x0400
#define ENC624J600_ETXSTAT_MAXCOL                 0x0200
#define ENC624J600_ETXSTAT_EXDEFER                0x0100
#define ENC624J600_ETXSTAT_DEFER                  0x0080
#define ENC624J600_ETXSTAT_R6                     0x0040
#define ENC624J600_ETXSTAT_R5                     0x0020
#define ENC624J600_ETXSTAT_CRCBAD                 0x0010
#define ENC624J600_ETXSTAT_COLCNT                 0x000F

//User-Defined Area Start Pointer register
#define ENC624J600_EUDAST_VAL                     0x7FFF

//User-Defined Area End Pointer register
#define ENC624J600_EUDAND_VAL                     0x7FFF

//Ethernet Status register
#define ENC624J600_ESTAT_INT                      0x8000
#define ENC624J600_ESTAT_FCIDLE                   0x4000
#define ENC624J600_ESTAT_RXBUSY                   0x2000
#define ENC624J600_ESTAT_CLKRDY                   0x1000
#define ENC624J600_ESTAT_R11                      0x0800
#define ENC624J600_ESTAT_PHYDPX                   0x0400
#define ENC624J600_ESTAT_R9                       0x0200
#define ENC624J600_ESTAT_PHYLNK                   0x0100
#define ENC624J600_ESTAT_PKTCNT                   0x00FF

//Ethernet Interrupt Flag register
#define ENC624J600_EIR_CRYPTEN                    0x8000
#define ENC624J600_EIR_MODEXIF                    0x4000
#define ENC624J600_EIR_HASHIF                     0x2000
#define ENC624J600_EIR_AESIF                      0x1000
#define ENC624J600_EIR_LINKIF                     0x0800
#define ENC624J600_EIR_R10                        0x0400
#define ENC624J600_EIR_R9                         0x0200
#define ENC624J600_EIR_R8                         0x0100
#define ENC624J600_EIR_R7                         0x0080
#define ENC624J600_EIR_PKTIF                      0x0040
#define ENC624J600_EIR_DMAIF                      0x0020
#define ENC624J600_EIR_R4                         0x0010
#define ENC624J600_EIR_TXIF                       0x0008
#define ENC624J600_EIR_TXABTIF                    0x0004
#define ENC624J600_EIR_RXABTIF                    0x0002
#define ENC624J600_EIR_PCFULIF                    0x0001

//Ethernet Control 1 register
#define ENC624J600_ECON1_MODEXST                  0x8000
#define ENC624J600_ECON1_HASHEN                   0x4000
#define ENC624J600_ECON1_HASHOP                   0x2000
#define ENC624J600_ECON1_HASHLST                  0x1000
#define ENC624J600_ECON1_AESST                    0x0800
#define ENC624J600_ECON1_AESOP1                   0x0400
#define ENC624J600_ECON1_AESOP0                   0x0200
#define ENC624J600_ECON1_PKTDEC                   0x0100
#define ENC624J600_ECON1_FCOP1                    0x0080
#define ENC624J600_ECON1_FCOP0                    0x0040
#define ENC624J600_ECON1_DMAST                    0x0020
#define ENC624J600_ECON1_DMACPY                   0x0010
#define ENC624J600_ECON1_DMACSSD                  0x0008
#define ENC624J600_ECON1_DMANOCS                  0x0004
#define ENC624J600_ECON1_TXRTS                    0x0002
#define ENC624J600_ECON1_RXEN                     0x0001

//Ethernet RX Filter Control register
#define ENC624J600_ERXFCON_HTEN                   0x8000
#define ENC624J600_ERXFCON_MPEN                   0x4000
#define ENC624J600_ERXFCON_NOTPM                  0x1000
#define ENC624J600_ERXFCON_PMEN                   0x0F00
#define ENC624J600_ERXFCON_PMEN_DISABLED          0x0000
#define ENC624J600_ERXFCON_PMEN_CHECKSUM          0x0100
#define ENC624J600_ERXFCON_PMEN_UNICAST           0x0200
#define ENC624J600_ERXFCON_PMEN_NOT_UNICAST       0x0300
#define ENC624J600_ERXFCON_PMEN_MULTICAST         0x0400
#define ENC624J600_ERXFCON_PMEN_NOT_MULTICAST     0x0500
#define ENC624J600_ERXFCON_PMEN_BROADCAST         0x0600
#define ENC624J600_ERXFCON_PMEN_NOT_BROADCAST     0x0700
#define ENC624J600_ERXFCON_PMEN_HASH              0x0800
#define ENC624J600_ERXFCON_PMEN_MAGIC_PKT         0x0900
#define ENC624J600_ERXFCON_CRCEEN                 0x0080
#define ENC624J600_ERXFCON_CRCEN                  0x0040
#define ENC624J600_ERXFCON_RUNTEEN                0x0020
#define ENC624J600_ERXFCON_RUNTEN                 0x0010
#define ENC624J600_ERXFCON_UCEN                   0x0008
#define ENC624J600_ERXFCON_NOTMEEN                0x0004
#define ENC624J600_ERXFCON_MCEN                   0x0002
#define ENC624J600_ERXFCON_BCEN                   0x0001

//MAC Control 1 register
#define ENC624J600_MACON1_R15_14                  0xC000
#define ENC624J600_MACON1_R11_8                   0x0F00
#define ENC624J600_MACON1_LOOPBK                  0x0010
#define ENC624J600_MACON1_R3                      0x0008
#define ENC624J600_MACON1_R3_DEFAULT              0x0008
#define ENC624J600_MACON1_RXPAUS                  0x0004
#define ENC624J600_MACON1_PASSALL                 0x0002
#define ENC624J600_MACON1_R0                      0x0001
#define ENC624J600_MACON1_R0_DEFAULT              0x0001

//MAC Control 2 register
#define ENC624J600_MACON2_DEFER                   0x4000
#define ENC624J600_MACON2_BPEN                    0x2000
#define ENC624J600_MACON2_NOBKOFF                 0x1000
#define ENC624J600_MACON2_R9_8                    0x0300
#define ENC624J600_MACON2_PADCFG                  0x00E0
#define ENC624J600_MACON2_PADCFG_NO               0x0000
#define ENC624J600_MACON2_PADCFG_60_BYTES         0x0020
#define ENC624J600_MACON2_PADCFG_64_BYTES         0x0060
#define ENC624J600_MACON2_PADCFG_AUTO             0x00A0
#define ENC624J600_MACON2_TXCRCEN                 0x0010
#define ENC624J600_MACON2_PHDREN                  0x0008
#define ENC624J600_MACON2_HFRMEN                  0x0004
#define ENC624J600_MACON2_R1                      0x0002
#define ENC624J600_MACON2_R1_DEFAULT              0x0002
#define ENC624J600_MACON2_FULDPX                  0x0001

//MAC Back-To-Back Inter-Packet Gap register
#define ENC624J600_MABBIPG_BBIPG                  0x007F
#define ENC624J600_MABBIPG_BBIPG_DEFAULT_HD       0x0012
#define ENC624J600_MABBIPG_BBIPG_DEFAULT_FD       0x0015

//MAC Inter-Packet Gap register
#define ENC624J600_MAIPG_R14_8                    0x7F00
#define ENC624J600_MAIPG_R14_8_DEFAULT            0x0C00
#define ENC624J600_MAIPG_IPG                      0x007F
#define ENC624J600_MAIPG_IPG_DEFAULT              0x0012

//MAC Collision Control register
#define ENC624J600_MACLCON_R13_8                  0x3F00
#define ENC624J600_MACLCON_R13_8_DEFAULT          0x3700
#define ENC624J600_MACLCON_MAXRET                 0x000F

//MII Management Command register
#define ENC624J600_MICMD_MIISCAN                  0x0002
#define ENC624J600_MICMD_MIIRD                    0x0001

//MII Management Address register
#define ENC624J600_MIREGADR_R12_8                 0x1F00
#define ENC624J600_MIREGADR_R12_8_DEFAULT         0x0100
#define ENC624J600_MIREGADR_PHREG                 0x001F

//MII Management Status register
#define ENC624J600_MISTAT_R3                      0x0008
#define ENC624J600_MISTAT_NVALID                  0x0004
#define ENC624J600_MISTAT_SCAN                    0x0002
#define ENC624J600_MISTAT_BUSY                    0x0001

//Ethernet Control 2 register
#define ENC624J600_ECON2_ETHEN                    0x8000
#define ENC624J600_ECON2_STRCH                    0x4000
#define ENC624J600_ECON2_TXMAC                    0x2000
#define ENC624J600_ECON2_SHA1MD5                  0x1000
#define ENC624J600_ECON2_COCON                    0x0F00
#define ENC624J600_ECON2_COCON_NONE               0x0000
#define ENC624J600_ECON2_COCON_33_33_MHZ          0x0100
#define ENC624J600_ECON2_COCON_25_00_MHZ          0x0200
#define ENC624J600_ECON2_COCON_20_00_MHZ          0x0300
#define ENC624J600_ECON2_COCON_16_67_MHZ          0x0400
#define ENC624J600_ECON2_COCON_12_50_MHZ          0x0500
#define ENC624J600_ECON2_COCON_10_00_MHZ          0x0600
#define ENC624J600_ECON2_COCON_8_333_MHZ          0x0700
#define ENC624J600_ECON2_COCON_8_000_MHZ          0x0800
#define ENC624J600_ECON2_COCON_6_250_MHZ          0x0900
#define ENC624J600_ECON2_COCON_5_000_MHZ          0x0A00
#define ENC624J600_ECON2_COCON_4_000_MHZ          0x0B00
#define ENC624J600_ECON2_COCON_3_125_MHZ          0x0C00
#define ENC624J600_ECON2_COCON_100_KHZ            0x0E00
#define ENC624J600_ECON2_COCON_50_KHZ             0x0F00
#define ENC624J600_ECON2_AUTOFC                   0x0080
#define ENC624J600_ECON2_TXRST                    0x0040
#define ENC624J600_ECON2_RXRST                    0x0020
#define ENC624J600_ECON2_ETHRST                   0x0010
#define ENC624J600_ECON2_MODLEN                   0x000C
#define ENC624J600_ECON2_MODLEN_512_BITS          0x0000
#define ENC624J600_ECON2_MODLEN_768_BITS          0x0004
#define ENC624J600_ECON2_MODLEN_1024_BITS         0x0008
#define ENC624J600_ECON2_AESLEN                   0x0003
#define ENC624J600_ECON2_AESLEN_128_BITS          0x0000
#define ENC624J600_ECON2_AESLEN_192_BITS          0x0001
#define ENC624J600_ECON2_AESLEN_256_BITS          0x0002

//Receive Watermark register
#define ENC624J600_ERXWM_RXFWM                    0xFF00
#define ENC624J600_ERXWM_RXEWM                    0x00FF

//Ethernet Interrupt Enable register
#define ENC624J600_EIE_INTIE                      0x8000
#define ENC624J600_EIE_MODEXIE                    0x4000
#define ENC624J600_EIE_HASHIE                     0x2000
#define ENC624J600_EIE_AESIE                      0x1000
#define ENC624J600_EIE_LINKIE                     0x0800
#define ENC624J600_EIE_R10_7                      0x0780
#define ENC624J600_EIE_PKTIE                      0x0040
#define ENC624J600_EIE_DMAIE                      0x0020
#define ENC624J600_EIE_R4                         0x0010
#define ENC624J600_EIE_R4_DEFAULT                 0x0010
#define ENC624J600_EIE_TXIE                       0x0008
#define ENC624J600_EIE_TXABTIE                    0x0004
#define ENC624J600_EIE_RXABTIE                    0x0002
#define ENC624J600_EIE_PCFULIE                    0x0001

//Ethernet ID Status/LED Control register
#define ENC624J600_EIDLED_LACFG                   0xF000
#define ENC624J600_EIDLED_LACFG_OFF               0x0000
#define ENC624J600_EIDLED_LACFG_ON                0x1000
#define ENC624J600_EIDLED_LACFG_LINK              0x2000
#define ENC624J600_EIDLED_LACFG_COL               0x3000
#define ENC624J600_EIDLED_LACFG_TX                0x4000
#define ENC624J600_EIDLED_LACFG_RX                0x5000
#define ENC624J600_EIDLED_LACFG_TX_RX             0x6000
#define ENC624J600_EIDLED_LACFG_DUPLEX            0x7000
#define ENC624J600_EIDLED_LACFG_SPEED             0x8000
#define ENC624J600_EIDLED_LACFG_LINK_TX           0x9000
#define ENC624J600_EIDLED_LACFG_LINK_RX           0xA000
#define ENC624J600_EIDLED_LACFG_LINK_TX_RX        0xB000
#define ENC624J600_EIDLED_LACFG_LINK_COL          0xC000
#define ENC624J600_EIDLED_LACFG_LINK_DUPLEX_TX_RX 0xE000
#define ENC624J600_EIDLED_LACFG_LINK_SPEED_TX_RX  0xF000
#define ENC624J600_EIDLED_LBCFG                   0x0F00
#define ENC624J600_EIDLED_LBCFG_OFF               0x0000
#define ENC624J600_EIDLED_LBCFG_ON                0x0100
#define ENC624J600_EIDLED_LBCFG_LINK              0x0200
#define ENC624J600_EIDLED_LBCFG_COL               0x0300
#define ENC624J600_EIDLED_LBCFG_TX                0x0400
#define ENC624J600_EIDLED_LBCFG_RX                0x0500
#define ENC624J600_EIDLED_LBCFG_TX_RX             0x0600
#define ENC624J600_EIDLED_LBCFG_DUPLEX            0x0700
#define ENC624J600_EIDLED_LBCFG_SPEED             0x0800
#define ENC624J600_EIDLED_LBCFG_LINK_TX           0x0900
#define ENC624J600_EIDLED_LBCFG_LINK_RX           0x0A00
#define ENC624J600_EIDLED_LBCFG_LINK_TX_RX        0x0B00
#define ENC624J600_EIDLED_LBCFG_LINK_COL          0x0C00
#define ENC624J600_EIDLED_LBCFG_LINK_DUPLEX_TX_RX 0x0E00
#define ENC624J600_EIDLED_LBCFG_LINK_SPEED_TX_RX  0x0F00
#define ENC624J600_EIDLED_DEVID                   0x00E0
#define ENC624J600_EIDLED_DEVID_DEFAULT           0x0020
#define ENC624J600_EIDLED_REVID                   0x001F

//General Purpose Data Window register
#define ENC624J600_EGPDATA_R15_8                  0xFF00
#define ENC624J600_EGPDATA_VAL                    0x00FF

//Ethernet RX Data Window register
#define ENC624J600_ERXDATA_R15_8                  0xFF00
#define ENC624J600_ERXDATA_VAL                    0x00FF

//User-Defined Area Data Window register
#define ENC624J600_EUDADATA_R15_8                 0xFF00
#define ENC624J600_EUDADATA_VAL                   0x00FF

//General Purpose Window Read Pointer register
#define ENC624J600_EGPRDPT_VAL                    0x7FFF

//General Purpose Window Write Pointer register
#define ENC624J600_EGPWRPT_VAL                    0x7FFF

//RX Window Read Pointer register
#define ENC624J600_ERXRDPT_VAL                    0x7FFF

//RX Window Write Pointer register
#define ENC624J600_ERXWRPT_VAL                    0x7FFF

//UDA Window Read Pointer register
#define ENC624J600_EUDARDPT_VAL                   0x7FFF

//UDA Window Write Pointer register
#define ENC624J600_EUDAWRPT_VAL                   0x7FFF

//PHY Control 1 register
#define ENC624J600_PHCON1_PRST                    0x8000
#define ENC624J600_PHCON1_PLOOPBK                 0x4000
#define ENC624J600_PHCON1_SPD100                  0x2000
#define ENC624J600_PHCON1_ANEN                    0x1000
#define ENC624J600_PHCON1_PSLEEP                  0x0800
#define ENC624J600_PHCON1_RENEG                   0x0200
#define ENC624J600_PHCON1_PFULDPX                 0x0100

//PHY Status 1 register
#define ENC624J600_PHSTAT1_FULL100                0x4000
#define ENC624J600_PHSTAT1_HALF100                0x2000
#define ENC624J600_PHSTAT1_FULL10                 0x1000
#define ENC624J600_PHSTAT1_HALF10                 0x0800
#define ENC624J600_PHSTAT1_ANDONE                 0x0020
#define ENC624J600_PHSTAT1_LRFAULT                0x0010
#define ENC624J600_PHSTAT1_ANABLE                 0x0008
#define ENC624J600_PHSTAT1_LLSTAT                 0x0004
#define ENC624J600_PHSTAT1_EXTREGS                0x0001

//PHY Auto-Negotiation Advertisement register
#define ENC624J600_PHANA_ADNP                     0x8000
#define ENC624J600_PHANA_ADFAULT                  0x2000
#define ENC624J600_PHANA_ADPAUS1                  0x0800
#define ENC624J600_PHANA_ADPAUS0                  0x0400
#define ENC624J600_PHANA_AD100FD                  0x0100
#define ENC624J600_PHANA_AD100                    0x0080
#define ENC624J600_PHANA_AD10FD                   0x0040
#define ENC624J600_PHANA_AD10                     0x0020
#define ENC624J600_PHANA_ADIEEE                   0x001F
#define ENC624J600_PHANA_ADIEEE_DEFAULT           0x0001

//PHY Auto-Negotiation Link Partner Ability register
#define ENC624J600_PHANLPA_LPNP                   0x8000
#define ENC624J600_PHANLPA_LPACK                  0x4000
#define ENC624J600_PHANLPA_LPFAULT                0x2000
#define ENC624J600_PHANLPA_LPPAUS1                0x0800
#define ENC624J600_PHANLPA_LPPAUS0                0x0400
#define ENC624J600_PHANLPA_LP100T4                0x0200
#define ENC624J600_PHANLPA_LP100FD                0x0100
#define ENC624J600_PHANLPA_LP100                  0x0080
#define ENC624J600_PHANLPA_LP10FD                 0x0040
#define ENC624J600_PHANLPA_LP10                   0x0020
#define ENC624J600_PHANLPA_LPIEEE                 0x001F

//PHY Auto-Negotiation Expansion register
#define ENC624J600_PHANE_PDFLT                    0x0010
#define ENC624J600_PHANE_LPARCD                   0x0002
#define ENC624J600_PHANE_LPANABL                  0x0001

//PHY Control 2 register
#define ENC624J600_PHCON2_EDPWRDN                 0x2000
#define ENC624J600_PHCON2_EDTHRES                 0x0800
#define ENC624J600_PHCON2_FRCLNK                  0x0004
#define ENC624J600_PHCON2_EDSTAT                  0x0002

//PHY Status 2 register
#define ENC624J600_PHSTAT2_PLRITY                 0x0010

//PHY Status 3 register
#define ENC624J600_PHSTAT3_R6                     0x0040
#define ENC624J600_PHSTAT3_R6_DEFAULT             0x0040
#define ENC624J600_PHSTAT3_SPDDPX2                0x0010
#define ENC624J600_PHSTAT3_SPDDPX1                0x0008
#define ENC624J600_PHSTAT3_SPDDPX0                0x0004
#define ENC624J600_RSV_UNICAST_FILTER             0x00100000
#define ENC624J600_RSV_PATTERN_MATCH_FILTER       0x00080000
#define ENC624J600_RSV_MAGIC_PACKET_FILTER        0x00040000
#define ENC624J600_RSV_HASH_FILTER                0x00020000
#define ENC624J600_RSV_NOT_ME_FILTER              0x00010000
#define ENC624J600_RSV_RUNT_FILTER                0x00008000
#define ENC624J600_RSV_VLAN_TYPE                  0x00004000
#define ENC624J600_RSV_UNKNOWN_OPCODE             0x00002000
#define ENC624J600_RSV_PAUSE_CONTROL_FRAME        0x00001000
#define ENC624J600_RSV_CONTROL_FRAME              0x00000800
#define ENC624J600_RSV_DRIBBLE_NIBBLE             0x00000400
#define ENC624J600_RSV_BROADCAST_PACKET           0x00000200
#define ENC624J600_RSV_MULTICAST_PACKET           0x00000100
#define ENC624J600_RSV_RECEIVED_OK                0x00000080
#define ENC624J600_RSV_LENGTH_OUT_OF_RANGE        0x00000040
#define ENC624J600_RSV_LENGTH_CHECK_ERROR         0x00000020
#define ENC624J600_RSV_CRC_ERROR                  0x00000010
#define ENC624J600_RSV_CARRIER_EVENT              0x00000004
#define ENC624J600_RSV_PACKET_IGNORED             0x00000001
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   TRACE_DEBUG("CIDER=0x%04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_CIDER));
   TRACE_DEBUG("PHY1ILR=0x%04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_PHY1ILR));
   TRACE_DEBUG("PHY1IHR=0x%04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_PHY1IHR));
   if(ksz8851ReadReg(interface, KSZ8851_CIDER) != (KSZ8851_CIDER_FAMILY_ID_DEFAULT |
      KSZ8851_CIDER_CHIP_ID_DEFAULT | KSZ8851_CIDER_REV_ID_A3))
   ksz8851WriteReg(interface, KSZ8851_MARH, htons(interface->macAddr.w[0]));
   ksz8851WriteReg(interface, KSZ8851_MARM, htons(interface->macAddr.w[1]));
   ksz8851WriteReg(interface, KSZ8851_MARL, htons(interface->macAddr.w[2]));

   //Packets shorter than 64 bytes are padded and the CRC is automatically
   //generated
   ksz8851WriteReg(interface, KSZ8851_TXCR, KSZ8851_TXCR_TXFCE |
      KSZ8851_TXCR_TXPE | KSZ8851_TXCR_TXCE);
   ksz8851WriteReg(interface, KSZ8851_TXFDPR, KSZ8851_TXFDPR_TXFPAI);
   ksz8851WriteReg(interface, KSZ8851_RXCR1, KSZ8851_RXCR1_RXPAFMA |
      KSZ8851_RXCR1_RXFCE | KSZ8851_RXCR1_RXBE | KSZ8851_RXCR1_RXME |
      KSZ8851_RXCR1_RXUE);
   ksz8851WriteReg(interface, KSZ8851_RXCR2, KSZ8851_RXCR2_SRDBL_SINGLE_FRAME |
      KSZ8851_RXCR2_IUFFP | KSZ8851_RXCR2_RXIUFCEZ);
   ksz8851WriteReg(interface, KSZ8851_RXQCR, KSZ8851_RXQCR_RXFCTE |
      KSZ8851_RXQCR_ADRFE);

   ksz8851WriteReg(interface, KSZ8851_RXFDPR, KSZ8851_RXFDPR_RXFPAI);
   ksz8851WriteReg(interface, KSZ8851_RXFCTR, 1);
   ksz8851ClearBit(interface, KSZ8851_P1CR, KSZ8851_P1CR_FORCE_DUPLEX);
   ksz8851SetBit(interface, KSZ8851_P1CR, KSZ8851_P1CR_RESTART_AN);
   ksz8851SetBit(interface, KSZ8851_ISR, KSZ8851_ISR_LCIS |
      KSZ8851_ISR_TXIS | KSZ8851_ISR_RXIS | KSZ8851_ISR_RXOIS |
      KSZ8851_ISR_TXPSIS | KSZ8851_ISR_RXPSIS | KSZ8851_ISR_TXSAIS |
      KSZ8851_ISR_RXWFDIS | KSZ8851_ISR_RXMPDIS | KSZ8851_ISR_LDIS |
      KSZ8851_ISR_EDIS | KSZ8851_ISR_SPIBEIS);
   ksz8851SetBit(interface, KSZ8851_IER, KSZ8851_IER_LCIE |
      KSZ8851_IER_TXIE | KSZ8851_IER_RXIE);
   ksz8851SetBit(interface, KSZ8851_TXCR, KSZ8851_TXCR_TXE);
   ksz8851SetBit(interface, KSZ8851_RXCR1, KSZ8851_RXCR1_RXE);
   ier = ksz8851ReadReg(interface, KSZ8851_IER);
   ksz8851WriteReg(interface, KSZ8851_IER, 0);
   isr = ksz8851ReadReg(interface, KSZ8851_ISR);
   if((isr & KSZ8851_ISR_LCIS) != 0)
      ier &= ~KSZ8851_IER_LCIE;
   if((isr & KSZ8851_ISR_TXIS) != 0)
      ksz8851WriteReg(interface, KSZ8851_ISR, KSZ8851_ISR_TXIS);
      n = ksz8851ReadReg(interface, KSZ8851_TXMIR) & KSZ8851_TXMIR_TXMA;
   if((isr & KSZ8851_ISR_RXIS) != 0)
      ier &= ~KSZ8851_IER_RXIE;
   ksz8851WriteReg(interface, KSZ8851_IER, ier);
   status = ksz8851ReadReg(interface, KSZ8851_ISR);
   if((status & KSZ8851_ISR_LCIS) != 0)
      ksz8851WriteReg(interface, KSZ8851_ISR, KSZ8851_ISR_LCIS);
      status = ksz8851ReadReg(interface, KSZ8851_P1SR);
      if((status & KSZ8851_P1SR_LINK_GOOD) != 0)
         if((status & KSZ8851_P1SR_OPERATION_SPEED) != 0)
         if((status & KSZ8851_P1SR_OPERATION_DUPLEX) != 0)
   if((status & KSZ8851_ISR_RXIS) != 0)
      ksz8851WriteReg(interface, KSZ8851_ISR, KSZ8851_ISR_RXIS);
      frameCount = MSB(ksz8851ReadReg(interface, KSZ8851_RXFCTR));
   ksz8851SetBit(interface, KSZ8851_IER, KSZ8851_IER_LCIE | KSZ8851_IER_RXIE);
   n = ksz8851ReadReg(interface, KSZ8851_TXMIR) & KSZ8851_TXMIR_TXMA;
   header.controlWord = htole16(KSZ8851_TX_CTRL_TXIC |
      (context->frameId++ & KSZ8851_TX_CTRL_TXFID));

   ksz8851SetBit(interface, KSZ8851_RXQCR, KSZ8851_RXQCR_SDA);
   ksz8851ClearBit(interface, KSZ8851_RXQCR, KSZ8851_RXQCR_SDA);
   ksz8851SetBit(interface, KSZ8851_TXQCR, KSZ8851_TXQCR_METFE);
   n = ksz8851ReadReg(interface, KSZ8851_TXMIR) & KSZ8851_TXMIR_TXMA;
   status = ksz8851ReadReg(interface, KSZ8851_RXFHSR);
   if((status & KSZ8851_RXFHSR_RXFV) != 0)
      if((status & (KSZ8851_RXFHSR_RXMR | KSZ8851_RXFHSR_RXFTL |
         KSZ8851_RXFHSR_RXRF | KSZ8851_RXFHSR_RXCE)) == 0)
         n = ksz8851ReadReg(interface, KSZ8851_RXFHBCR) & KSZ8851_RXFHBCR_RXBC;
            ksz8851WriteReg(interface, KSZ8851_RXFDPR, KSZ8851_RXFDPR_RXFPAI);
            ksz8851SetBit(interface, KSZ8851_RXQCR, KSZ8851_RXQCR_SDA);
            ksz8851ClearBit(interface, KSZ8851_RXQCR, KSZ8851_RXQCR_SDA);
   ksz8851SetBit(interface, KSZ8851_RXQCR, KSZ8851_RXQCR_RRXEF);
   ksz8851WriteReg(interface, KSZ8851_MAHTR0, hashTable[0]);
   ksz8851WriteReg(interface, KSZ8851_MAHTR1, hashTable[1]);
   ksz8851WriteReg(interface, KSZ8851_MAHTR2, hashTable[2]);
   ksz8851WriteReg(interface, KSZ8851_MAHTR3, hashTable[3]);
   TRACE_DEBUG("  MAHTR0 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_MAHTR0));
   TRACE_DEBUG("  MAHTR1 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_MAHTR1));
   TRACE_DEBUG("  MAHTR2 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_MAHTR2));
   TRACE_DEBUG("  MAHTR3 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_MAHTR3));
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
#define KSZ8851_CMD_RD_REG  0x00
#define KSZ8851_CMD_WR_REG  0x40
#define KSZ8851_CMD_RD_FIFO 0x80
#define KSZ8851_CMD_WR_FIFO 0xC0
   #define KSZ8851_CMD_B0 0x04
   #define KSZ8851_CMD_B1 0x08
   #define KSZ8851_CMD_B2 0x10
   #define KSZ8851_CMD_B3 0x20
   #define KSZ8851_CMD_B0 0x1000
   #define KSZ8851_CMD_B1 0x2000
   #define KSZ8851_CMD_B2 0x4000
   #define KSZ8851_CMD_B3 0x8000
#define KSZ8851_CCR                                   0x08
#define KSZ8851_MARL                                  0x10
#define KSZ8851_MARM                                  0x12
#define KSZ8851_MARH                                  0x14
#define KSZ8851_OBCR                                  0x20
#define KSZ8851_EEPCR                                 0x22
#define KSZ8851_MBIR                                  0x24
#define KSZ8851_GRR                                   0x26
#define KSZ8851_WFCR                                  0x2A
#define KSZ8851_WF0CRC0                               0x30
#define KSZ8851_WF0CRC1                               0x32
#define KSZ8851_WF0BM0                                0x34
#define KSZ8851_WF0BM1                                0x36
#define KSZ8851_WF0BM2                                0x38
#define KSZ8851_WF0BM3                                0x3A
#define KSZ8851_WF1CRC0                               0x40
#define KSZ8851_WF1CRC1                               0x42
#define KSZ8851_WF1BM0                                0x44
#define KSZ8851_WF1BM1                                0x46
#define KSZ8851_WF1BM2                                0x48
#define KSZ8851_WF1BM3                                0x4A
#define KSZ8851_WF2CRC0                               0x50
#define KSZ8851_WF2CRC1                               0x52
#define KSZ8851_WF2BM0                                0x54
#define KSZ8851_WF2BM1                                0x56
#define KSZ8851_WF2BM2                                0x58
#define KSZ8851_WF2BM3                                0x5A
#define KSZ8851_WF3CRC0                               0x60
#define KSZ8851_WF3CRC1                               0x62
#define KSZ8851_WF3BM0                                0x64
#define KSZ8851_WF3BM1                                0x66
#define KSZ8851_WF3BM2                                0x68
#define KSZ8851_WF3BM3                                0x6A
#define KSZ8851_TXCR                                  0x70
#define KSZ8851_TXSR                                  0x72
#define KSZ8851_RXCR1                                 0x74
#define KSZ8851_RXCR2                                 0x76
#define KSZ8851_TXMIR                                 0x78
#define KSZ8851_RXFHSR                                0x7C
#define KSZ8851_RXFHBCR                               0x7E
#define KSZ8851_TXQCR                                 0x80
#define KSZ8851_RXQCR                                 0x82
#define KSZ8851_TXFDPR                                0x84
#define KSZ8851_RXFDPR                                0x86
#define KSZ8851_RXDTTR                                0x8C
#define KSZ8851_RXDBCTR                               0x8E
#define KSZ8851_IER                                   0x90
#define KSZ8851_ISR                                   0x92
#define KSZ8851_RXFCTR                                0x9C
#define KSZ8851_TXNTFSR                               0x9E
#define KSZ8851_MAHTR0                                0xA0
#define KSZ8851_MAHTR1                                0xA2
#define KSZ8851_MAHTR2                                0xA4
#define KSZ8851_MAHTR3                                0xA6
#define KSZ8851_FCLWR                                 0xB0
#define KSZ8851_FCHWR                                 0xB2
#define KSZ8851_FCOWR                                 0xB4
#define KSZ8851_CIDER                                 0xC0
#define KSZ8851_CGCR                                  0xC6
#define KSZ8851_IACR                                  0xC8
#define KSZ8851_IADLR                                 0xD0
#define KSZ8851_IADHR                                 0xD2
#define KSZ8851_PMECR                                 0xD4
#define KSZ8851_GSWUTR                                0xD6
#define KSZ8851_PHYRR                                 0xD8
#define KSZ8851_P1MBCR                                0xE4
#define KSZ8851_P1MBSR                                0xE6
#define KSZ8851_PHY1ILR                               0xE8
#define KSZ8851_PHY1IHR                               0xEA
#define KSZ8851_P1ANAR                                0xEC
#define KSZ8851_P1ANLPR                               0xEE
#define KSZ8851_P1SCLMD                               0xF4
#define KSZ8851_P1CR                                  0xF6
#define KSZ8851_P1SR                                  0xF8

//Chip Configuration register
#define KSZ8851_CCR_BUS_ENDIAN_MODE                   0x0400
#define KSZ8851_CCR_EEPROM_PRESENCE                   0x0200
#define KSZ8851_CCR_SPI_BUS_MODE                      0x0100
#define KSZ8851_CCR_8_BIT_DATA_BUS                    0x0080
#define KSZ8851_CCR_16_BIT_DATA_BUS                   0x0040
#define KSZ8851_CCR_32_BIT_DATA_BUS                   0x0020
#define KSZ8851_CCR_SHARED_BUS_MODE                   0x0010
#define KSZ8851_CCR_128_PIN_PACKAGE                   0x0008
#define KSZ8851_CCR_48_PIN_PACKAGE                    0x0002
#define KSZ8851_CCR_32_PIN_PACKAGE                    0x0001

//On-Chip Bus Control register
#define KSZ8851_OBCR_OUT_PIN_DRIVE_STRENGTH           0x0040
#define KSZ8851_OBCR_BUS_CLK_SEL                      0x0004
#define KSZ8851_OBCR_BUS_CLK_DIV                      0x0003
#define KSZ8851_OBCR_BUS_CLK_DIV_1                    0x0000
#define KSZ8851_OBCR_BUS_CLK_DIV_2                    0x0001
#define KSZ8851_OBCR_BUS_CLK_DIV_3                    0x0002

//EEPROM Control register
#define KSZ8851_EEPCR_EESRWA                          0x0020
#define KSZ8851_EEPCR_EESA                            0x0010
#define KSZ8851_EEPCR_EESB                            0x0008
#define KSZ8851_EEPCR_EECB                            0x0007
#define KSZ8851_EEPCR_EECB_EED_IO                     0x0004
#define KSZ8851_EEPCR_EECB_EESK                       0x0002
#define KSZ8851_EEPCR_EECB_EECS                       0x0001

//Memory BIST Info register
#define KSZ8851_MBIR_TXMBF                            0x1000
#define KSZ8851_MBIR_TXMBFA                           0x0800
#define KSZ8851_MBIR_TXMBFC                           0x0700
#define KSZ8851_MBIR_RXMBF                            0x0010
#define KSZ8851_MBIR_RXMBFA                           0x0008
#define KSZ8851_MBIR_RXMBFC                           0x0007

//Global Reset register
#define KSZ8851_GRR_QMU_MODULE_SOFT_RESET             0x0002
#define KSZ8851_GRR_GLOBAL_SOFT_RESET                 0x0001

//Wakeup Frame Control register
#define KSZ8851_WFCR_MPRXE                            0x0080
#define KSZ8851_WFCR_WF3E                             0x0008
#define KSZ8851_WFCR_WF2E                             0x0004
#define KSZ8851_WFCR_WF1E                             0x0002
#define KSZ8851_WFCR_WF0E                             0x0001

//Transmit Control register
#define KSZ8851_TXCR_TCGICMP                          0x0100
#define KSZ8851_TXCR_TCGTCP                           0x0040
#define KSZ8851_TXCR_TCGIP                            0x0020
#define KSZ8851_TXCR_FTXQ                             0x0010
#define KSZ8851_TXCR_TXFCE                            0x0008
#define KSZ8851_TXCR_TXPE                             0x0004
#define KSZ8851_TXCR_TXCE                             0x0002
#define KSZ8851_TXCR_TXE                              0x0001

//Transmit Status register
#define KSZ8851_TXSR_TXLC                             0x2000
#define KSZ8851_TXSR_TXMC                             0x1000
#define KSZ8851_TXSR_TXFID                            0x003F

//Receive Control 1 register
#define KSZ8851_RXCR1_FRXQ                            0x8000
#define KSZ8851_RXCR1_RXUDPFCC                        0x4000
#define KSZ8851_RXCR1_RXTCPFCC                        0x2000
#define KSZ8851_RXCR1_RXIPFCC                         0x1000
#define KSZ8851_RXCR1_RXPAFMA                         0x0800
#define KSZ8851_RXCR1_RXFCE                           0x0400
#define KSZ8851_RXCR1_RXEFE                           0x0200
#define KSZ8851_RXCR1_RXMAFMA                         0x0100
#define KSZ8851_RXCR1_RXBE                            0x0080
#define KSZ8851_RXCR1_RXME                            0x0040
#define KSZ8851_RXCR1_RXUE                            0x0020
#define KSZ8851_RXCR1_RXAE                            0x0010
#define KSZ8851_RXCR1_RXINVF                          0x0002
#define KSZ8851_RXCR1_RXE                             0x0001

//Receive Control 2 register
#define KSZ8851_RXCR2_SRDBL                           0x00E0
#define KSZ8851_RXCR2_SRDBL_4_BYTES                   0x0000
#define KSZ8851_RXCR2_SRDBL_8_BYTES                   0x0020
#define KSZ8851_RXCR2_SRDBL_16_BYTES                  0x0040
#define KSZ8851_RXCR2_SRDBL_32_BYTES                  0x0060
#define KSZ8851_RXCR2_SRDBL_SINGLE_FRAME              0x0080
#define KSZ8851_RXCR2_IUFFP                           0x0010
#define KSZ8851_RXCR2_RXIUFCEZ                        0x0008
#define KSZ8851_RXCR2_UDPLFE                          0x0004
#define KSZ8851_RXCR2_RXICMPFCC                       0x0002
#define KSZ8851_RXCR2_RXSAF                           0x0001

//TXQ Memory Information register
#define KSZ8851_TXMIR_TXMA                            0x1FFF

//Receive Frame Header Status register
#define KSZ8851_RXFHSR_RXFV                           0x8000
#define KSZ8851_RXFHSR_RXICMPFCS                      0x2000
#define KSZ8851_RXFHSR_RXIPFCS                        0x1000
#define KSZ8851_RXFHSR_RXTCPFCS                       0x0800
#define KSZ8851_RXFHSR_RXUDPFCS                       0x0400
#define KSZ8851_RXFHSR_RXBF                           0x0080
#define KSZ8851_RXFHSR_RXMF                           0x0040
#define KSZ8851_RXFHSR_RXUF                           0x0020
#define KSZ8851_RXFHSR_RXMR                           0x0010
#define KSZ8851_RXFHSR_RXFT                           0x0008
#define KSZ8851_RXFHSR_RXFTL                          0x0004
#define KSZ8851_RXFHSR_RXRF                           0x0002
#define KSZ8851_RXFHSR_RXCE                           0x0001

//Receive Frame Header Byte Count register
#define KSZ8851_RXFHBCR_RXBC                          0x0FFF

//TXQ Command register
#define KSZ8851_TXQCR_AETFE                           0x0004
#define KSZ8851_TXQCR_TXQMAM                          0x0002
#define KSZ8851_TXQCR_METFE                           0x0001

//RXQ Command register
#define KSZ8851_RXQCR_RXDTTS                          0x1000
#define KSZ8851_RXQCR_RXDBCTS                         0x0800
#define KSZ8851_RXQCR_RXFCTS                          0x0400
#define KSZ8851_RXQCR_RXIPHTOE                        0x0200
#define KSZ8851_RXQCR_RXDTTE                          0x0080
#define KSZ8851_RXQCR_RXDBCTE                         0x0040
#define KSZ8851_RXQCR_RXFCTE                          0x0020
#define KSZ8851_RXQCR_ADRFE                           0x0010
#define KSZ8851_RXQCR_SDA                             0x0008
#define KSZ8851_RXQCR_RRXEF                           0x0001

//TX Frame Data Pointer register
#define KSZ8851_TXFDPR_TXFPAI                         0x4000
#define KSZ8851_TXFDPR_TXFP                           0x07FF

//RX Frame Data Pointer register
#define KSZ8851_RXFDPR_RXFPAI                         0x4000
#define KSZ8851_RXFDPR_WST                            0x1000
#define KSZ8851_RXFDPR_EMS                            0x0800
#define KSZ8851_RXFDPR_RXFP                           0x07FF

//Interrupt Enable register
#define KSZ8851_IER_LCIE                              0x8000
#define KSZ8851_IER_TXIE                              0x4000
#define KSZ8851_IER_RXIE                              0x2000
#define KSZ8851_IER_RXOIE                             0x0800
#define KSZ8851_IER_TXPSIE                            0x0200
#define KSZ8851_IER_RXPSIE                            0x0100
#define KSZ8851_IER_TXSAIE                            0x0040
#define KSZ8851_IER_RXWFDIE                           0x0020
#define KSZ8851_IER_RXMPDIE                           0x0010
#define KSZ8851_IER_LDIE                              0x0008
#define KSZ8851_IER_EDIE                              0x0004
#define KSZ8851_IER_SPIBEIE                           0x0002
#define KSZ8851_IER_DEDIE                             0x0001

//Interrupt Status register
#define KSZ8851_ISR_LCIS                              0x8000
#define KSZ8851_ISR_TXIS                              0x4000
#define KSZ8851_ISR_RXIS                              0x2000
#define KSZ8851_ISR_RXOIS                             0x0800
#define KSZ8851_ISR_TXPSIS                            0x0200
#define KSZ8851_ISR_RXPSIS                            0x0100
#define KSZ8851_ISR_TXSAIS                            0x0040
#define KSZ8851_ISR_RXWFDIS                           0x0020
#define KSZ8851_ISR_RXMPDIS                           0x0010
#define KSZ8851_ISR_LDIS                              0x0008
#define KSZ8851_ISR_EDIS                              0x0004
#define KSZ8851_ISR_SPIBEIS                           0x0002

//RX Frame Count & Threshold register
#define KSZ8851_RXFCTR_RXFC                           0xFF00
#define KSZ8851_RXFCTR_RXFCT                          0x00FF

//Flow Control Low Watermark register
#define KSZ8851_FCLWR_FCLWC                           0x0FFF

//Flow Control High Watermark register
#define KSZ8851_FCHWR_FCHWC                           0x0FFF

//Flow Control Overrun Watermark register
#define KSZ8851_FCOWR_FCLWC                           0x0FFF

//Chip ID and Enable register
#define KSZ8851_CIDER_FAMILY_ID                       0xFF00
#define KSZ8851_CIDER_FAMILY_ID_DEFAULT               0x8800
#define KSZ8851_CIDER_CHIP_ID                         0x00F0
#define KSZ8851_CIDER_CHIP_ID_DEFAULT                 0x0070
#define KSZ8851_CIDER_REV_ID                          0x000E
#define KSZ8851_CIDER_REV_ID_A2                       0x0000
#define KSZ8851_CIDER_REV_ID_A3                       0x0002

//Chip Global Control register
#define KSZ8851_CGCR_LEDSEL0                          0x0200

//Indirect Access Control register
#define KSZ8851_IACR_READ_EN                          0x1000
#define KSZ8851_IACR_TABLE_SEL                        0x0C00
#define KSZ8851_IACR_TABLE_SEL_MIB_COUNTER            0x0C00
#define KSZ8851_IACR_INDIRECT_ADDR                    0x001F

//Power Management Event Control register
#define KSZ8851_PMECR_PME_DELAY_EN                    0x4000
#define KSZ8851_PMECR_PME_OUT_POLARITY                0x1000
#define KSZ8851_PMECR_WOL_TO_PME_OUT_EN               0x0F00
#define KSZ8851_PMECR_WOL_TO_PME_OUT_EN_WUP_FRAME     0x0800
#define KSZ8851_PMECR_WOL_TO_PME_OUT_EN_MAGIC_PKT     0x0400
#define KSZ8851_PMECR_WOL_TO_PME_OUT_EN_LINK_UP       0x0200
#define KSZ8851_PMECR_WOL_TO_PME_OUT_EN_ENERGY_DETECT 0x0100
#define KSZ8851_PMECR_AUTO_WUP_EN                     0x0080
#define KSZ8851_PMECR_WUP_TO_NORMAL_OP_MODE           0x0040
#define KSZ8851_PMECR_WUP_EVENT                       0x003C
#define KSZ8851_PMECR_WUP_EVENT_NONE                  0x0000
#define KSZ8851_PMECR_WUP_EVENT_ENERGY_DETECT         0x0004
#define KSZ8851_PMECR_WUP_EVENT_LINK_UP               0x0008
#define KSZ8851_PMECR_WUP_EVENT_MAGIC_PKT             0x0010
#define KSZ8851_PMECR_WUP_EVENT_WUP_FRAME             0x0020
#define KSZ8851_PMECR_PWR_MGMT_MODE                   0x0003
#define KSZ8851_PMECR_PWR_MGMT_MODE_NORMAL            0x0000
#define KSZ8851_PMECR_PWR_MGMT_MODE_ENERGY_DETECT     0x0001
#define KSZ8851_PMECR_PWR_MGMT_MODE_PWR_SAVING        0x0003

//Go-Sleep & Wake-Up Time register
#define KSZ8851_GSWUTR_WUP_TIME                       0xFF00
#define KSZ8851_GSWUTR_GO_SLEEP_TIME                  0x00FF

//PHY Reset register
#define KSZ8851_PHYRR_PHY_RESET                       0x0001

//PHY 1 MII Basic Control register
#define KSZ8851_P1MBCR_LOCAL_LOOPBACK                 0x4000
#define KSZ8851_P1MBCR_FORCE_100                      0x2000
#define KSZ8851_P1MBCR_AN_ENABLE                      0x1000
#define KSZ8851_P1MBCR_RESTART_AN                     0x0200
#define KSZ8851_P1MBCR_FORCE_FULL_DUPLEX              0x0100
#define KSZ8851_P1MBCR_HP_MDIX                        0x0020
#define KSZ8851_P1MBCR_FORCE_MDIX                     0x0010
#define KSZ8851_P1MBCR_DISABLE_MDIX                   0x0008
#define KSZ8851_P1MBCR_DISABLE_TRANSMIT               0x0002
#define KSZ8851_P1MBCR_DISABLE_LED                    0x0001

//PHY 1 MII Basic Status register
#define KSZ8851_P1MBSR_T4_CAPABLE                     0x8000
#define KSZ8851_P1MBSR_100_FULL_CAPABLE               0x4000
#define KSZ8851_P1MBSR_100_HALF_CAPABLE               0x2000
#define KSZ8851_P1MBSR_10_FULL_CAPABLE                0x1000
#define KSZ8851_P1MBSR_10_HALF_CAPABLE                0x0800
#define KSZ8851_P1MBSR_PREAMBLE_SUPPR                 0x0040
#define KSZ8851_P1MBSR_AN_COMPLETE                    0x0020
#define KSZ8851_P1MBSR_AN_CAPABLE                     0x0008
#define KSZ8851_P1MBSR_LINK_STATUS                    0x0004
#define KSZ8851_P1MBSR_JABBER_TEST                    0x0002
#define KSZ8851_P1MBSR_EXTENDED_CAPABLE               0x0001

//PHY 1 ID Low register
#define KSZ8851_PHY1ILR_DEFAULT                       0x1430

//PHY 1 ID High register
#define KSZ8851_PHY1IHR_DEFAULT                       0x0022

//PHY 1 Auto-Negotiation Advertisement register
#define KSZ8851_P1ANAR_NEXT_PAGE                      0x8000
#define KSZ8851_P1ANAR_REMOTE_FAULT                   0x2000
#define KSZ8851_P1ANAR_PAUSE                          0x0400
#define KSZ8851_P1ANAR_ADV_100_FULL                   0x0100
#define KSZ8851_P1ANAR_ADV_100_HALF                   0x0080
#define KSZ8851_P1ANAR_ADV_10_FULL                    0x0040
#define KSZ8851_P1ANAR_ADV_10_HALF                    0x0020
#define KSZ8851_P1ANAR_SELECTOR                       0x001F

//PHY 1 Auto-Negotiation Link Partner Ability register
#define KSZ8851_P1ANLPR_NEXT_PAGE                     0x8000
#define KSZ8851_P1ANLPR_LP_ACK                        0x4000
#define KSZ8851_P1ANLPR_REMOTE_FAULT                  0x2000
#define KSZ8851_P1ANLPR_PAUSE                         0x0400
#define KSZ8851_P1ANLPR_ADV_100_FULL                  0x0100
#define KSZ8851_P1ANLPR_ADV_100_HALF                  0x0080
#define KSZ8851_P1ANLPR_ADV_10_FULL                   0x0040
#define KSZ8851_P1ANLPR_ADV_10_HALF                   0x0020

//Port 1 PHY Special Control/Status & LinkMD register
#define KSZ8851_P1SCLMD_VCT_RESULT                    0x6000
#define KSZ8851_P1SCLMD_VCT_EN                        0x1000
#define KSZ8851_P1SCLMD_FORCE_LNK                     0x0800
#define KSZ8851_P1SCLMD_REMOTE_LOOPBACK               0x0200
#define KSZ8851_P1SCLMD_VCT_FAULT_COUNT               0x01FF

//Port 1 Control register
#define KSZ8851_P1CR_LED_OFF                          0x8000
#define KSZ8851_P1CR_TX_DISABLE                       0x4000
#define KSZ8851_P1CR_RESTART_AN                       0x2000
#define KSZ8851_P1CR_DISABLE_AUTO_MDIX                0x0400
#define KSZ8851_P1CR_FORCE_MDIX                       0x0200
#define KSZ8851_P1CR_AN_ENABLE                        0x0080
#define KSZ8851_P1CR_FORCE_SPEED                      0x0040
#define KSZ8851_P1CR_FORCE_DUPLEX                     0x0020
#define KSZ8851_P1CR_ADV_PAUSE                        0x0010
#define KSZ8851_P1CR_ADV_100_FULL                     0x0008
#define KSZ8851_P1CR_ADV_100_HALF                     0x0004
#define KSZ8851_P1CR_ADV_10_FULL                      0x0002
#define KSZ8851_P1CR_ADV_10_HALF                      0x0001

//Port 1 Status register
#define KSZ8851_P1SR_HP_MDIX                          0x8000
#define KSZ8851_P1SR_POLARITY_REVERSE                 0x2000
#define KSZ8851_P1SR_OPERATION_SPEED                  0x0400
#define KSZ8851_P1SR_OPERATION_DUPLEX                 0x0200
#define KSZ8851_P1SR_MDIX_STATUS                      0x0080
#define KSZ8851_P1SR_AN_DONE                          0x0040
#define KSZ8851_P1SR_LINK_GOOD                        0x0020
#define KSZ8851_P1SR_LP_PAUSE                         0x0010
#define KSZ8851_P1SR_LP_100_FULL                      0x0008
#define KSZ8851_P1SR_LP_100_HALF                      0x0004
#define KSZ8851_P1SR_LP_10_FULL                       0x0002
#define KSZ8851_P1SR_LP_10_HALF                       0x0001
#define KSZ8851_TX_CTRL_TXIC                          0x8000
#define KSZ8851_TX_CTRL_TXFID                         0x003F
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
//GCC compiler?
      //Successful processing
      //Successful processing
      //Successful processing
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
//GCC compiler?
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * @file lpc54xxx_eth_driver.c
 * @brief LPC540xx/LPC546xx Ethernet MAC driver
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
#include "drivers/mac/lpc54xxx_eth_driver.h"
static uint8_t txBuffer[LPC54XXX_ETH_TX_BUFFER_COUNT][LPC54XXX_ETH_TX_BUFFER_SIZE];
static uint8_t rxBuffer[LPC54XXX_ETH_RX_BUFFER_COUNT][LPC54XXX_ETH_RX_BUFFER_SIZE];
static Lpc54xxxTxDmaDesc txDmaDesc[LPC54XXX_ETH_TX_BUFFER_COUNT];
static Lpc54xxxRxDmaDesc rxDmaDesc[LPC54XXX_ETH_RX_BUFFER_COUNT];
static uint8_t txBuffer[LPC54XXX_ETH_TX_BUFFER_COUNT][LPC54XXX_ETH_TX_BUFFER_SIZE]
static uint8_t rxBuffer[LPC54XXX_ETH_RX_BUFFER_COUNT][LPC54XXX_ETH_RX_BUFFER_SIZE]
static Lpc54xxxTxDmaDesc txDmaDesc[LPC54XXX_ETH_TX_BUFFER_COUNT]
static Lpc54xxxRxDmaDesc rxDmaDesc[LPC54XXX_ETH_RX_BUFFER_COUNT]
 * @brief LPC54xxx Ethernet MAC driver
const NicDriver lpc54xxxEthDriver =
   lpc54xxxEthInit,
   lpc54xxxEthTick,
   lpc54xxxEthEnableIrq,
   lpc54xxxEthDisableIrq,
   lpc54xxxEthEventHandler,
   lpc54xxxEthSendPacket,
   lpc54xxxEthUpdateMacAddrFilter,
   lpc54xxxEthUpdateMacConfig,
   lpc54xxxEthWritePhyReg,
   lpc54xxxEthReadPhyReg,
 * @brief LPC54xxx Ethernet MAC initialization
error_t lpc54xxxEthInit(NetInterface *interface)
   TRACE_INFO("Initializing LPC54xxx Ethernet MAC...\r\n");
   lpc54xxxEthInitGpio(interface);
      ENET_DMA_CH_DMA_CHX_RX_CTRL_RBSZ(LPC54XXX_ETH_RX_BUFFER_SIZE / 4);
   lpc54xxxEthInitDmaDesc(interface);
   NVIC_SetPriorityGrouping(LPC54XXX_ETH_IRQ_PRIORITY_GROUPING);
   NVIC_SetPriority(ETHERNET_IRQn, NVIC_EncodePriority(LPC54XXX_ETH_IRQ_PRIORITY_GROUPING,
      LPC54XXX_ETH_IRQ_GROUP_PRIORITY, LPC54XXX_ETH_IRQ_SUB_PRIORITY));
//LPCXpresso54S018, LPCXpresso54S018M, LPCXpresso54608, LPCXpresso54628 or
//LPC54018-IoT-Module evaluation board?
#if defined(USE_LPCXPRESSO_54S018) || defined(USE_LPCXPRESSO_54S018M) || \
   defined(USE_LPCXPRESSO_54608) || defined(USE_LPCXPRESSO_54628) || \
   defined(USE_LPC54018_IOT_MODULE)
void lpc54xxxEthInitGpio(NetInterface *interface)
//LPCXpresso54S018, LPCXpresso54608, LPCXpresso54628 or LPC54018-IoT-Module
//evaluation board?
#if defined(USE_LPCXPRESSO_54S018) || defined(USE_LPCXPRESSO_54608) || \
   defined(USE_LPCXPRESSO_54628) || defined(USE_LPC54018_IOT_MODULE)
   CLOCK_EnableClock(kCLOCK_Gpio2);
   //Configure ENET_TXD1 (P0_17)
   //Configure ENET_TXD0 (P4_8)
   //Configure ENET_RX_DV (P4_10)
   //Configure ENET_RXD0 (P4_11)
   //Configure ENET_RXD1 (P4_12)
   //Configure ENET_TX_EN (P4_13)
   //Configure ENET_RX_CLK (P4_14)
   //Configure ENET_MDC (P4_15)
   //Configure ENET_MDIO (P4_16)
   //Configure ENET_RST (P2_26) as an output
   GPIO_PinWrite(GPIO, 2, 26, 0);
   GPIO_PinWrite(GPIO, 2, 26, 1);

//LPCXpresso54S018M evaluation board?
#elif defined(USE_LPCXPRESSO_54S018M)
   //Select RMII interface mode
   SYSCON->ETHPHYSEL |= SYSCON_ETHPHYSEL_PHY_SEL_MASK;

   //Enable IOCON clock
   CLOCK_EnableClock(kCLOCK_Iocon);

   //Enable GPIO clocks
   CLOCK_EnableClock(kCLOCK_Gpio0);
   CLOCK_EnableClock(kCLOCK_Gpio1);
   CLOCK_EnableClock(kCLOCK_Gpio2);
   CLOCK_EnableClock(kCLOCK_Gpio4);

   //Configure ENET_TXD1 (P0_17)
   IOCON_PinMuxSet(IOCON, 0, 17, IOCON_FUNC7 | IOCON_MODE_INACT |
      IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);

   //Configure ENET_MDC (P1_16)
   IOCON_PinMuxSet(IOCON, 1, 16, IOCON_FUNC1 | IOCON_MODE_INACT |
      IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);

   //Configure ENET_MDIO (P1_23)
   IOCON_PinMuxSet(IOCON, 1, 23, IOCON_FUNC4 | IOCON_MODE_PULLUP |
      IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);

   //Configure ENET_TXD0 (P4_8)
   IOCON_PinMuxSet(IOCON, 4, 8, IOCON_FUNC1 | IOCON_MODE_INACT |
      IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);

   //Configure ENET_RX_DV (P4_10)
   IOCON_PinMuxSet(IOCON, 4, 10, IOCON_FUNC1 | IOCON_MODE_INACT |
      IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);

   //Configure ENET_RXD0 (P4_11)
   IOCON_PinMuxSet(IOCON, 4, 11, IOCON_FUNC1 | IOCON_MODE_INACT |
      IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);

   //Configure ENET_RXD1 (P4_12)
   IOCON_PinMuxSet(IOCON, 4, 12, IOCON_FUNC1 | IOCON_MODE_INACT |
      IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);

   //Configure ENET_TX_EN (P4_13)
   IOCON_PinMuxSet(IOCON, 4, 13, IOCON_FUNC1 | IOCON_MODE_INACT |
      IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);

   //Configure ENET_RX_CLK (P4_14)
   IOCON_PinMuxSet(IOCON, 4, 14, IOCON_FUNC1 | IOCON_MODE_INACT |
      IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);

   //Configure ENET_RST (P2_26) as an output
   pinConfig.pinDirection = kGPIO_DigitalOutput;
   pinConfig.outputLogic = 0;
   GPIO_PinInit(GPIO, 2, 26, &pinConfig);

   //Reset PHY transceiver (hard reset)
   GPIO_PinWrite(GPIO, 2, 26, 0);
   sleep(10);
   GPIO_PinWrite(GPIO, 2, 26, 1);
   sleep(10);
#endif
void lpc54xxxEthInitDmaDesc(NetInterface *interface)
   for(i = 0; i < LPC54XXX_ETH_TX_BUFFER_COUNT; i++)
   for(i = 0; i < LPC54XXX_ETH_RX_BUFFER_COUNT; i++)
   ENET->DMA_CH[0].DMA_CHX_TXDESC_RING_LENGTH = LPC54XXX_ETH_TX_BUFFER_COUNT - 1;
   ENET->DMA_CH[0].DMA_CHX_RXDESC_RING_LENGTH = LPC54XXX_ETH_RX_BUFFER_COUNT - 1;
 * @brief LPC54xxx Ethernet MAC timer handler
void lpc54xxxEthTick(NetInterface *interface)
void lpc54xxxEthEnableIrq(NetInterface *interface)
void lpc54xxxEthDisableIrq(NetInterface *interface)
 * @brief LPC54xxx Ethernet MAC interrupt service routine
 * @brief LPC54xxx Ethernet MAC event handler
void lpc54xxxEthEventHandler(NetInterface *interface)
         error = lpc54xxxEthReceivePacket(interface);
error_t lpc54xxxEthSendPacket(NetInterface *interface,
   if(length > LPC54XXX_ETH_TX_BUFFER_SIZE)
   if(++txIndex >= LPC54XXX_ETH_TX_BUFFER_COUNT)
error_t lpc54xxxEthReceivePacket(NetInterface *interface)
            n = MIN(n, LPC54XXX_ETH_RX_BUFFER_SIZE);
      if(++rxIndex >= LPC54XXX_ETH_RX_BUFFER_COUNT)
error_t lpc54xxxEthUpdateMacAddrFilter(NetInterface *interface)
error_t lpc54xxxEthUpdateMacConfig(NetInterface *interface)
void lpc54xxxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
uint16_t lpc54xxxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
 * @file lpc54xxx_eth_driver.h
 * @brief LPC540xx/LPC546xx Ethernet MAC driver
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
#ifndef _LPC54XXX_ETH_DRIVER_H
#define _LPC54XXX_ETH_DRIVER_H
#ifndef LPC54XXX_ETH_TX_BUFFER_COUNT
   #define LPC54XXX_ETH_TX_BUFFER_COUNT 3
#elif (LPC54XXX_ETH_TX_BUFFER_COUNT < 1)
   #error LPC54XXX_ETH_TX_BUFFER_COUNT parameter is not valid
#ifndef LPC54XXX_ETH_TX_BUFFER_SIZE
   #define LPC54XXX_ETH_TX_BUFFER_SIZE 1536
#elif (LPC54XXX_ETH_TX_BUFFER_SIZE != 1536)
   #error LPC54XXX_ETH_TX_BUFFER_SIZE parameter is not valid
#ifndef LPC54XXX_ETH_RX_BUFFER_COUNT
   #define LPC54XXX_ETH_RX_BUFFER_COUNT 6
#elif (LPC54XXX_ETH_RX_BUFFER_COUNT < 1)
   #error LPC54XXX_ETH_RX_BUFFER_COUNT parameter is not valid
#ifndef LPC54XXX_ETH_RX_BUFFER_SIZE
   #define LPC54XXX_ETH_RX_BUFFER_SIZE 1536
#elif (LPC54XXX_ETH_RX_BUFFER_SIZE != 1536)
   #error LPC54XXX_ETH_RX_BUFFER_SIZE parameter is not valid
#ifndef LPC54XXX_ETH_IRQ_PRIORITY_GROUPING
   #define LPC54XXX_ETH_IRQ_PRIORITY_GROUPING 4
#elif (LPC54XXX_ETH_IRQ_PRIORITY_GROUPING < 0)
   #error LPC54XXX_ETH_IRQ_PRIORITY_GROUPING parameter is not valid
#ifndef LPC54XXX_ETH_IRQ_GROUP_PRIORITY
   #define LPC54XXX_ETH_IRQ_GROUP_PRIORITY 6
#elif (LPC54XXX_ETH_IRQ_GROUP_PRIORITY < 0)
   #error LPC54XXX_ETH_IRQ_GROUP_PRIORITY parameter is not valid
#ifndef LPC54XXX_ETH_IRQ_SUB_PRIORITY
   #define LPC54XXX_ETH_IRQ_SUB_PRIORITY 0
#elif (LPC54XXX_ETH_IRQ_SUB_PRIORITY < 0)
   #error LPC54XXX_ETH_IRQ_SUB_PRIORITY parameter is not valid
} Lpc54xxxTxDmaDesc;
} Lpc54xxxRxDmaDesc;
//LPC54xxx Ethernet MAC driver
extern const NicDriver lpc54xxxEthDriver;
//LPC54xxx Ethernet MAC related functions
error_t lpc54xxxEthInit(NetInterface *interface);
void lpc54xxxEthInitGpio(NetInterface *interface);
void lpc54xxxEthInitDmaDesc(NetInterface *interface);
void lpc54xxxEthTick(NetInterface *interface);
void lpc54xxxEthEnableIrq(NetInterface *interface);
void lpc54xxxEthDisableIrq(NetInterface *interface);
void lpc54xxxEthEventHandler(NetInterface *interface);
error_t lpc54xxxEthSendPacket(NetInterface *interface,
error_t lpc54xxxEthReceivePacket(NetInterface *interface);
error_t lpc54xxxEthUpdateMacAddrFilter(NetInterface *interface);
error_t lpc54xxxEthUpdateMacConfig(NetInterface *interface);
void lpc54xxxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
uint16_t lpc54xxxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
//GCC compiler?
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
//RDK-RX62N evaluation board?
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
//RDK-RX63N, RSK-RX63N or RSK-RX63N-256K evaluation board?
#if defined(USE_RDK_RX63N) || defined(USE_RSK_RX63N) || \
   defined(USE_RSK_RX63N_256K)
#elif defined(USE_RSK_RX63N) || defined(USE_RSK_RX63N_256K)
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
#pragma location = RZA1_ETH_RAM_SECTION
#pragma location = RZA1_ETH_RAM_SECTION
#pragma location = RZA1_ETH_RAM_SECTION
#pragma location = RZA1_ETH_RAM_SECTION
   __attribute__((aligned(32), section(RZA1_ETH_RAM_SECTION)));
   __attribute__((aligned(32), section(RZA1_ETH_RAM_SECTION)));
   __attribute__((aligned(32), section(RZA1_ETH_RAM_SECTION)));
   __attribute__((aligned(32), section(RZA1_ETH_RAM_SECTION)));
   ETHER.EESIPR0 = ETHER_EESIPR0_TWBIP | ETHER_EESIPR0_FRIP;
//RSK-RZ/A1H, Stream it! RZ, Hachiko or VK-RZ/A1H evaluation board?
   ETHER.EESIPR0 = ETHER_EESIPR0_TWBIP | ETHER_EESIPR0_FRIP;
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
//Name of the section where to place DMA buffers
#ifndef RZA1_ETH_RAM_SECTION
   #define RZA1_ETH_RAM_SECTION ".BSS_DMAC_SAMPLE_INTERNAL_RAM"
#endif

 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
//STM32F743I-EVAL, STM32F747I-EVAL, STM32H735G-DK, STM32H745I-Discovery,
//STM32H747I-Discovery, STM32H750B-DK, Nucleo-H723ZG, Nucleo-H743ZI,
//Nucleo-H743ZI2 or Nucleo-H745ZI-Q evaluation board?
   defined(USE_STM32H735G_DK) || defined(USE_STM32H745I_DISCO) || \
   defined(USE_STM32H747I_DISCO) || defined(USE_STM32H750B_DISCO) || \
   defined(USE_NUCLEO_H723ZG) || defined(USE_NUCLEO_H743ZI) || \
   defined(USE_NUCLEO_H743ZI2) || defined(USE_NUCLEO_H745ZI_Q)
//STM32H735G-DK evaluation board?
#elif defined(USE_STM32H735G_DK)
   //Enable SYSCFG clock
   __HAL_RCC_SYSCFG_CLK_ENABLE();

   //Enable GPIO clocks
   __HAL_RCC_GPIOA_CLK_ENABLE();
   __HAL_RCC_GPIOB_CLK_ENABLE();
   __HAL_RCC_GPIOC_CLK_ENABLE();

   //Select RMII interface mode
   HAL_SYSCFG_ETHInterfaceSelect(SYSCFG_ETH_RMII);

   //Configure RMII pins
   GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
   GPIO_InitStructure.Pull = GPIO_NOPULL;
   GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
   GPIO_InitStructure.Alternate = GPIO_AF11_ETH;

   //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
   GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
   HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

   //Configure RMII_RX_ER (PB10), RMII_TX_EN (PB11), ETH_RMII_TXD1 (PB12)
   //and ETH_RMII_TXD0 (PB13)
   GPIO_InitStructure.Pin = GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
   HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

   //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
   GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
   HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

//Nucleo-H723ZG, Nucleo-H743ZI, Nucleo-H743ZI2 or Nucleo-H745ZI-Q evaluation
//board?
#elif defined(USE_NUCLEO_H723ZG) || defined(USE_NUCLEO_H743ZI) || \
   defined(USE_NUCLEO_H743ZI2) || defined(USE_NUCLEO_H745ZI_Q)
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
//GCC compiler?
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
/**
 * @file xmc4400_eth_driver.c
 * @brief Infineon XMC4400 Ethernet MAC driver
 *
 * @section License
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 *
 * This file is part of CycloneTCP Open.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @author Oryx Embedded SARL (www.oryx-embedded.com)
 * @version 2.0.2
 **/

//Switch to the appropriate trace level
#define TRACE_LEVEL NIC_TRACE_LEVEL

//Dependencies
#include "xmc4400.h"
#include "core/net.h"
#include "drivers/mac/xmc4400_eth_driver.h"
#include "debug.h"

//Underlying network interface
static NetInterface *nicDriverInterface;

//IAR EWARM compiler?
#if defined(__ICCARM__)

//Transmit buffer
#pragma data_alignment = 4
#pragma location = XMC4400_ETH_RAM_SECTION
static uint8_t txBuffer[XMC4400_ETH_TX_BUFFER_COUNT][XMC4400_ETH_TX_BUFFER_SIZE];
//Receive buffer
#pragma data_alignment = 4
#pragma location = XMC4400_ETH_RAM_SECTION
static uint8_t rxBuffer[XMC4400_ETH_RX_BUFFER_COUNT][XMC4400_ETH_RX_BUFFER_SIZE];
//Transmit DMA descriptors
#pragma data_alignment = 4
#pragma location = XMC4400_ETH_RAM_SECTION
static Xmc4400TxDmaDesc txDmaDesc[XMC4400_ETH_TX_BUFFER_COUNT];
//Receive DMA descriptors
#pragma data_alignment = 4
#pragma location = XMC4400_ETH_RAM_SECTION
static Xmc4400RxDmaDesc rxDmaDesc[XMC4400_ETH_RX_BUFFER_COUNT];

//Keil MDK-ARM or GCC compiler?
#else

//Transmit buffer
static uint8_t txBuffer[XMC4400_ETH_TX_BUFFER_COUNT][XMC4400_ETH_TX_BUFFER_SIZE]
   __attribute__((aligned(4), __section__(XMC4400_ETH_RAM_SECTION)));
//Receive buffer
static uint8_t rxBuffer[XMC4400_ETH_RX_BUFFER_COUNT][XMC4400_ETH_RX_BUFFER_SIZE]
   __attribute__((aligned(4), __section__(XMC4400_ETH_RAM_SECTION)));
//Transmit DMA descriptors
static Xmc4400TxDmaDesc txDmaDesc[XMC4400_ETH_TX_BUFFER_COUNT]
   __attribute__((aligned(4), __section__(XMC4400_ETH_RAM_SECTION)));
//Receive DMA descriptors
static Xmc4400RxDmaDesc rxDmaDesc[XMC4400_ETH_RX_BUFFER_COUNT]
   __attribute__((aligned(4), __section__(XMC4400_ETH_RAM_SECTION)));

#endif

//Pointer to the current TX DMA descriptor
static Xmc4400TxDmaDesc *txCurDmaDesc;
//Pointer to the current RX DMA descriptor
static Xmc4400RxDmaDesc *rxCurDmaDesc;


/**
 * @brief XMC4400 Ethernet MAC driver
 **/

const NicDriver xmc4400EthDriver =
{
   NIC_TYPE_ETHERNET,
   ETH_MTU,
   xmc4400EthInit,
   xmc4400EthTick,
   xmc4400EthEnableIrq,
   xmc4400EthDisableIrq,
   xmc4400EthEventHandler,
   xmc4400EthSendPacket,
   xmc4400EthUpdateMacAddrFilter,
   xmc4400EthUpdateMacConfig,
   xmc4400EthWritePhyReg,
   xmc4400EthReadPhyReg,
   TRUE,
   TRUE,
   TRUE,
   FALSE
};


/**
 * @brief XMC4400 Ethernet MAC initialization
 * @param[in] interface Underlying network interface
 * @return Error code
 **/

error_t xmc4400EthInit(NetInterface *interface)
{
   error_t error;

   //Debug message
   TRACE_INFO("Initializing XMC4400 Ethernet MAC...\r\n");

   //Save underlying network interface
   nicDriverInterface = interface;

   //Disable parity error trap
   SCU_PARITY->PETE = 0;
   //Disable unaligned access trap
   PPB->CCR &= ~PPB_CCR_UNALIGN_TRP_Msk;

   //Enable ETH0 peripheral clock
   SCU_CLK->CLKSET = SCU_CLK_CLKSET_ETH0CEN_Msk;

   //GPIO configuration
   xmc4400EthInitGpio(interface);

   //Reset ETH0 peripheral
   SCU_RESET->PRSET2 = SCU_RESET_PRSET2_ETH0RS_Msk;
   SCU_RESET->PRCLR2 = SCU_RESET_PRCLR2_ETH0RS_Msk;

   //Reset DMA controller
   ETH0->BUS_MODE |= ETH_BUS_MODE_SWR_Msk;
   //Wait for the reset to complete
   while((ETH0->BUS_MODE & ETH_BUS_MODE_SWR_Msk) != 0)
   {
   }

   //Adjust MDC clock range depending on ETH clock frequency
   ETH0->GMII_ADDRESS = ETH_GMII_ADDRESS_CR_DIV62;

   //Valid Ethernet PHY or switch driver?
   if(interface->phyDriver != NULL)
   {
      //Ethernet PHY initialization
      error = interface->phyDriver->init(interface);
   }
   else if(interface->switchDriver != NULL)
   {
      //Ethernet switch initialization
      error = interface->switchDriver->init(interface);
   }
   else
   {
      //The interface is not properly configured
      error = ERROR_FAILURE;
   }

   //Any error to report?
   if(error)
   {
      return error;
   }

   //Use default MAC configuration
   ETH0->MAC_CONFIGURATION = ETH_MAC_CONFIGURATION_RESERVED15_Msk |
      ETH_MAC_CONFIGURATION_DO_Msk;

   //Set the MAC address of the station
   ETH0->MAC_ADDRESS0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
   ETH0->MAC_ADDRESS0_HIGH = interface->macAddr.w[2];

   //The MAC supports 3 additional addresses for unicast perfect filtering
   ETH0->MAC_ADDRESS1_LOW = 0;
   ETH0->MAC_ADDRESS1_HIGH = 0;
   ETH0->MAC_ADDRESS2_LOW = 0;
   ETH0->MAC_ADDRESS2_HIGH = 0;
   ETH0->MAC_ADDRESS3_LOW = 0;
   ETH0->MAC_ADDRESS3_HIGH = 0;

   //Initialize hash table
   ETH0->HASH_TABLE_LOW = 0;
   ETH0->HASH_TABLE_HIGH = 0;

   //Configure the receive filter
   ETH0->MAC_FRAME_FILTER = ETH_MAC_FRAME_FILTER_HPF_Msk | ETH_MAC_FRAME_FILTER_HMC_Msk;
   //Disable flow control
   ETH0->FLOW_CONTROL = 0;
   //Enable store and forward mode
   ETH0->OPERATION_MODE = ETH_OPERATION_MODE_RSF_Msk | ETH_OPERATION_MODE_TSF_Msk;

   //Configure DMA bus mode
   ETH0->BUS_MODE = ETH_BUS_MODE_AAL_Msk | ETH_BUS_MODE_USP_Msk |
      ETH_BUS_MODE_RPBL_1 | ETH_BUS_MODE_PR_1_1 | ETH_BUS_MODE_PBL_1;

   //Initialize DMA descriptor lists
   xmc4400EthInitDmaDesc(interface);

   //Prevent interrupts from being generated when statistic counters reach
   //half their maximum value
   ETH0->MMC_TRANSMIT_INTERRUPT_MASK = 0xFFFFFFFF;
   ETH0->MMC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;
   ETH0->MMC_IPC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;

   //Disable MAC interrupts
   ETH0->INTERRUPT_MASK = ETH_INTERRUPT_MASK_TSIM_Msk | ETH_INTERRUPT_MASK_PMTIM_Msk;

   //Enable the desired DMA interrupts
   ETH0->INTERRUPT_ENABLE = ETH_INTERRUPT_ENABLE_NIE_Msk |
      ETH_INTERRUPT_ENABLE_RIE_Msk | ETH_INTERRUPT_ENABLE_TIE_Msk;

   //Set priority grouping (6 bits for pre-emption priority, no bits for subpriority)
   NVIC_SetPriorityGrouping(XMC4400_ETH_IRQ_PRIORITY_GROUPING);

   //Configure Ethernet interrupt priority
   NVIC_SetPriority(ETH0_0_IRQn, NVIC_EncodePriority(XMC4400_ETH_IRQ_PRIORITY_GROUPING,
      XMC4400_ETH_IRQ_GROUP_PRIORITY, XMC4400_ETH_IRQ_SUB_PRIORITY));

   //Enable MAC transmission and reception
   ETH0->MAC_CONFIGURATION |= ETH_MAC_CONFIGURATION_TE_Msk | ETH_MAC_CONFIGURATION_RE_Msk;
   //Enable DMA transmission and reception
   ETH0->OPERATION_MODE |= ETH_OPERATION_MODE_ST_Msk | ETH_OPERATION_MODE_SR_Msk;

   //Accept any packets from the upper layer
   osSetEvent(&interface->nicTxEvent);

   //Successful initialization
   return NO_ERROR;
}


//XMC4400 Platform2GO Kit?
#if defined(USE_XMC4400_PLT2GO_KIT)

/**
 * @brief GPIO configuration
 * @param[in] interface Underlying network interface
 **/

void xmc4400EthInitGpio(NetInterface *interface)
{
   uint32_t temp;

   //Configure ETH0.TX_EN (P0.4)
   temp = PORT0->IOCR4;
   temp &= ~PORT0_IOCR4_PC4_Msk;
   temp |= (17UL << PORT0_IOCR4_PC4_Pos);
   PORT0->IOCR4 = temp;

   //Configure ETH0.MDIO (P2.0), ETH0.RXD0A (P2.2) and ETH0.RXD1A (P2.3)
   temp = PORT2->IOCR0;
   temp &= ~(PORT2_IOCR0_PC0_Msk | PORT2_IOCR0_PC2_Msk | PORT2_IOCR0_PC3_Msk);
   temp |= (0UL << PORT2_IOCR0_PC0_Pos) | (0UL << PORT2_IOCR0_PC2_Pos) | (0UL << PORT2_IOCR0_PC3_Pos);
   PORT2->IOCR0 = temp;

   //Configure ETH0.RXERA (P2.4)and ETH0.MDC (P2.7)
   temp = PORT2->IOCR4;
   temp &= ~(PORT2_IOCR4_PC4_Msk | PORT2_IOCR4_PC7_Msk);
   temp |= (0UL << PORT2_IOCR4_PC4_Pos) | (17UL << PORT2_IOCR4_PC7_Pos);
   PORT2->IOCR4 = temp;

   //Configure ETH0.TXD0 (P2.8) and ETH0.TXD1 (P2.9)
   temp = PORT2->IOCR8;
   temp &= ~(PORT2_IOCR8_PC8_Msk | PORT2_IOCR8_PC9_Msk);
   temp |= (17UL << PORT2_IOCR8_PC8_Pos) | (17UL << PORT2_IOCR8_PC9_Pos);
   PORT2->IOCR8 = temp;

   //Configure ETH0.CLK_RMIIC (P15.8) and ETH0.CRS_DVC (P15.9)
   temp = PORT15->IOCR8;
   temp &= ~(PORT15_IOCR8_PC8_Msk | PORT15_IOCR8_PC9_Msk);
   temp |= (0UL << PORT15_IOCR8_PC8_Pos) | (0UL << PORT15_IOCR8_PC9_Pos);
   PORT15->IOCR8 = temp;

   //Assign ETH_MDIO (P2.0) to HW0
   temp = PORT2->HWSEL & ~PORT2_HWSEL_HW0_Msk;
   PORT2->HWSEL = temp | (1UL << PORT2_HWSEL_HW0_Pos);

   //Select output driver strength for ETH0.TX_EN (P2.5)
   temp = PORT2->PDR0;
   temp &= ~PORT2_PDR0_PD5_Msk;
   temp |= (0UL << PORT2_PDR0_PD5_Pos);
   PORT2->PDR0 = temp;

   //Select output driver strength for ETH0.TXD0 (P2.8) and ETH0.TXD1 (P2.9)
   temp = PORT2->PDR1;
   temp &= ~(PORT2_PDR1_PD8_Msk | PORT2_PDR1_PD9_Msk);
   temp |= (0UL << PORT2_PDR1_PD8_Pos) | (0UL << PORT2_PDR1_PD9_Pos);
   PORT2->PDR1 = temp;

   //Use ETH0.CLK_RMIIC (P15.8) and ETH0.CRS_DVC (P15.9) as digital inputs
   PORT15->PDISC &= ~(PORT15_PDISC_PDIS8_Msk | PORT15_PDISC_PDIS9_Msk);

   //Select RMII operation mode
   ETH0_CON->CON = ETH_CON_INFSEL_Msk | ETH_CON_MDIO_B | ETH_CON_RXER_A |
      ETH_CON_CRS_DV_C | ETH_CON_CLK_RMII_C | ETH_CON_RXD1_A | ETH_CON_RXD0_A;
}

#endif


/**
 * @brief Initialize DMA descriptor lists
 * @param[in] interface Underlying network interface
 **/

void xmc4400EthInitDmaDesc(NetInterface *interface)
{
   uint_t i;

   //Initialize TX DMA descriptor list
   for(i = 0; i < XMC4400_ETH_TX_BUFFER_COUNT; i++)
   {
      //Use chain structure rather than ring structure
      txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
      //Initialize transmit buffer size
      txDmaDesc[i].tdes1 = 0;
      //Transmit buffer address
      txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
      //Next descriptor address
      txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
   }

   //The last descriptor is chained to the first entry
   txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
   //Point to the very first descriptor
   txCurDmaDesc = &txDmaDesc[0];

   //Initialize RX DMA descriptor list
   for(i = 0; i < XMC4400_ETH_RX_BUFFER_COUNT; i++)
   {
      //The descriptor is initially owned by the DMA
      rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
      //Use chain structure rather than ring structure
      rxDmaDesc[i].rdes1 = ETH_RDES1_RCH | (XMC4400_ETH_RX_BUFFER_SIZE & ETH_RDES1_RBS1);
      //Receive buffer address
      rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
      //Next descriptor address
      rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
   }

   //The last descriptor is chained to the first entry
   rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
   //Point to the very first descriptor
   rxCurDmaDesc = &rxDmaDesc[0];

   //Start location of the TX descriptor list
   ETH0->TRANSMIT_DESCRIPTOR_LIST_ADDRESS = (uint32_t) txDmaDesc;
   //Start location of the RX descriptor list
   ETH0->RECEIVE_DESCRIPTOR_LIST_ADDRESS = (uint32_t) rxDmaDesc;
}


/**
 * @brief XMC4400 Ethernet MAC timer handler
 *
 * This routine is periodically called by the TCP/IP stack to handle periodic
 * operations such as polling the link state
 *
 * @param[in] interface Underlying network interface
 **/

void xmc4400EthTick(NetInterface *interface)
{
   //Valid Ethernet PHY or switch driver?
   if(interface->phyDriver != NULL)
   {
      //Handle periodic operations
      interface->phyDriver->tick(interface);
   }
   else if(interface->switchDriver != NULL)
   {
      //Handle periodic operations
      interface->switchDriver->tick(interface);
   }
   else
   {
      //Just for sanity
   }
}


/**
 * @brief Enable interrupts
 * @param[in] interface Underlying network interface
 **/

void xmc4400EthEnableIrq(NetInterface *interface)
{
   //Enable Ethernet MAC interrupts
   NVIC_EnableIRQ(ETH0_0_IRQn);

   //Valid Ethernet PHY or switch driver?
   if(interface->phyDriver != NULL)
   {
      //Enable Ethernet PHY interrupts
      interface->phyDriver->enableIrq(interface);
   }
   else if(interface->switchDriver != NULL)
   {
      //Enable Ethernet switch interrupts
      interface->switchDriver->enableIrq(interface);
   }
   else
   {
      //Just for sanity
   }
}


/**
 * @brief Disable interrupts
 * @param[in] interface Underlying network interface
 **/

void xmc4400EthDisableIrq(NetInterface *interface)
{
   //Disable Ethernet MAC interrupts
   NVIC_DisableIRQ(ETH0_0_IRQn);

   //Valid Ethernet PHY or switch driver?
   if(interface->phyDriver != NULL)
   {
      //Disable Ethernet PHY interrupts
      interface->phyDriver->disableIrq(interface);
   }
   else if(interface->switchDriver != NULL)
   {
      //Disable Ethernet switch interrupts
      interface->switchDriver->disableIrq(interface);
   }
   else
   {
      //Just for sanity
   }
}


/**
 * @brief XMC4400 Ethernet MAC interrupt service routine
 **/

void ETH0_0_IRQHandler(void)
{
   bool_t flag;
   uint32_t status;

   //Interrupt service routine prologue
   osEnterIsr();

   //This flag will be set if a higher priority task must be woken
   flag = FALSE;

   //Read DMA status register
   status = ETH0->STATUS;

   //Packet transmitted?
   if((status & ETH_STATUS_TI_Msk) != 0)
   {
      //Clear TI interrupt flag
      ETH0->STATUS = ETH_STATUS_TI_Msk;

      //Check whether the TX buffer is available for writing
      if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
      {
         //Notify the TCP/IP stack that the transmitter is ready to send
         flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
      }
   }

   //Packet received?
   if((status & ETH_STATUS_RI_Msk) != 0)
   {
      //Disable RIE interrupt
      ETH0->INTERRUPT_ENABLE &= ~ETH_INTERRUPT_ENABLE_RIE_Msk;

      //Set event flag
      nicDriverInterface->nicEvent = TRUE;
      //Notify the TCP/IP stack of the event
      flag |= osSetEventFromIsr(&netEvent);
   }

   //Clear NIS interrupt flag
   ETH0->STATUS = ETH_STATUS_NIS_Msk;

   //Interrupt service routine epilogue
   osExitIsr(flag);
}


/**
 * @brief XMC4400 Ethernet MAC event handler
 * @param[in] interface Underlying network interface
 **/

void xmc4400EthEventHandler(NetInterface *interface)
{
   error_t error;

   //Packet received?
   if((ETH0->STATUS & ETH_STATUS_RI_Msk) != 0)
   {
      //Clear interrupt flag
      ETH0->STATUS = ETH_STATUS_RI_Msk;

      //Process all pending packets
      do
      {
         //Read incoming packet
         error = xmc4400EthReceivePacket(interface);

         //No more data in the receive buffer?
      } while(error != ERROR_BUFFER_EMPTY);
   }

   //Re-enable DMA interrupts
   ETH0->INTERRUPT_ENABLE = ETH_INTERRUPT_ENABLE_NIE_Msk |
      ETH_INTERRUPT_ENABLE_RIE_Msk | ETH_INTERRUPT_ENABLE_TIE_Msk;
}


/**
 * @brief Send a packet
 * @param[in] interface Underlying network interface
 * @param[in] buffer Multi-part buffer containing the data to send
 * @param[in] offset Offset to the first data byte
 * @param[in] ancillary Additional options passed to the stack along with
 *   the packet
 * @return Error code
 **/

error_t xmc4400EthSendPacket(NetInterface *interface,
   const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
{
   size_t length;

   //Retrieve the length of the packet
   length = netBufferGetLength(buffer) - offset;

   //Check the frame length
   if(length > XMC4400_ETH_TX_BUFFER_SIZE)
   {
      //The transmitter can accept another packet
      osSetEvent(&interface->nicTxEvent);
      //Report an error
      return ERROR_INVALID_LENGTH;
   }

   //Make sure the current buffer is available for writing
   if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) != 0)
   {
      return ERROR_FAILURE;
   }

   //Copy user data to the transmit buffer
   netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);

   //Write the number of bytes to send
   txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
   //Set LS and FS flags as the data fits in a single buffer
   txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
   //Give the ownership of the descriptor to the DMA
   txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;

   //Clear TU flag to resume processing
   ETH0->STATUS = ETH_STATUS_TU_Msk;
   //Instruct the DMA to poll the transmit descriptor list
   ETH0->TRANSMIT_POLL_DEMAND = 0;

   //Point to the next descriptor in the list
   txCurDmaDesc = (Xmc4400TxDmaDesc *) txCurDmaDesc->tdes3;

   //Check whether the next buffer is available for writing
   if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
   {
      //The transmitter can accept another packet
      osSetEvent(&interface->nicTxEvent);
   }

   //Data successfully written
   return NO_ERROR;
}


/**
 * @brief Receive a packet
 * @param[in] interface Underlying network interface
 * @return Error code
 **/

error_t xmc4400EthReceivePacket(NetInterface *interface)
{
   error_t error;
   size_t n;
   NetRxAncillary ancillary;

   //The current buffer is available for reading?
   if((rxCurDmaDesc->rdes0 & ETH_RDES0_OWN) == 0)
   {
      //FS and LS flags should be set
      if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) != 0 &&
         (rxCurDmaDesc->rdes0 & ETH_RDES0_LS) != 0)
      {
         //Make sure no error occurred
         if((rxCurDmaDesc->rdes0 & ETH_RDES0_ES) == 0)
         {
            //Retrieve the length of the frame
            n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
            //Limit the number of data to read
            n = MIN(n, XMC4400_ETH_RX_BUFFER_SIZE);

            //Additional options can be passed to the stack along with the packet
            ancillary = NET_DEFAULT_RX_ANCILLARY;

            //Pass the packet to the upper layer
            nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
               &ancillary);

            //Valid packet received
            error = NO_ERROR;
         }
         else
         {
            //The received packet contains an error
            error = ERROR_INVALID_PACKET;
         }
      }
      else
      {
         //The packet is not valid
         error = ERROR_INVALID_PACKET;
      }

      //Give the ownership of the descriptor back to the DMA
      rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
      //Point to the next descriptor in the list
      rxCurDmaDesc = (Xmc4400RxDmaDesc *) rxCurDmaDesc->rdes3;
   }
   else
   {
      //No more data in the receive buffer
      error = ERROR_BUFFER_EMPTY;
   }

   //Clear RU flag to resume processing
   ETH0->STATUS = ETH_STATUS_RU_Msk;
   //Instruct the DMA to poll the receive descriptor list
   ETH0->RECEIVE_POLL_DEMAND = 0;

   //Return status code
   return error;
}


/**
 * @brief Configure MAC address filtering
 * @param[in] interface Underlying network interface
 * @return Error code
 **/

error_t xmc4400EthUpdateMacAddrFilter(NetInterface *interface)
{
   uint_t i;
   uint_t j;
   uint_t k;
   uint32_t crc;
   uint32_t hashTable[2];
   MacAddr unicastMacAddr[3];
   MacFilterEntry *entry;

   //Debug message
   TRACE_DEBUG("Updating MAC filter...\r\n");

   //Set the MAC address of the station
   ETH0->MAC_ADDRESS0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
   ETH0->MAC_ADDRESS0_HIGH = interface->macAddr.w[2];

   //The MAC supports 3 additional addresses for unicast perfect filtering
   unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
   unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
   unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;

   //The hash table is used for multicast address filtering
   hashTable[0] = 0;
   hashTable[1] = 0;

   //The MAC address filter contains the list of MAC addresses to accept
   //when receiving an Ethernet frame
   for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
   {
      //Point to the current entry
      entry = &interface->macAddrFilter[i];

      //Valid entry?
      if(entry->refCount > 0)
      {
         //Multicast address?
         if(macIsMulticastAddr(&entry->addr))
         {
            //Compute CRC over the current MAC address
            crc = xmc4400EthCalcCrc(&entry->addr, sizeof(MacAddr));

            //The upper 6 bits in the CRC register are used to index the
            //contents of the hash table
            k = (crc >> 26) & 0x3F;

            //Update hash table contents
            hashTable[k / 32] |= (1 << (k % 32));
         }
         else
         {
            //Up to 3 additional MAC addresses can be specified
            if(j < 3)
            {
               //Save the unicast address
               unicastMacAddr[j++] = entry->addr;
            }
         }
      }
   }

   //Configure the first unicast address filter
   if(j >= 1)
   {
      //When the AE bit is set, the entry is used for perfect filtering
      ETH0->MAC_ADDRESS1_LOW = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
      ETH0->MAC_ADDRESS1_HIGH = unicastMacAddr[0].w[2] | ETH_MAC_ADDRESS1_HIGH_AE_Msk;
   }
   else
   {
      //When the AE bit is cleared, the entry is ignored
      ETH0->MAC_ADDRESS1_LOW = 0;
      ETH0->MAC_ADDRESS1_HIGH = 0;
   }

   //Configure the second unicast address filter
   if(j >= 2)
   {
      //When the AE bit is set, the entry is used for perfect filtering
      ETH0->MAC_ADDRESS2_LOW = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
      ETH0->MAC_ADDRESS2_HIGH = unicastMacAddr[1].w[2] | ETH_MAC_ADDRESS2_HIGH_AE_Msk;
   }
   else
   {
      //When the AE bit is cleared, the entry is ignored
      ETH0->MAC_ADDRESS2_LOW = 0;
      ETH0->MAC_ADDRESS2_HIGH = 0;
   }

   //Configure the third unicast address filter
   if(j >= 3)
   {
      //When the AE bit is set, the entry is used for perfect filtering
      ETH0->MAC_ADDRESS3_LOW = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
      ETH0->MAC_ADDRESS3_HIGH = unicastMacAddr[2].w[2] | ETH_MAC_ADDRESS3_HIGH_AE_Msk;
   }
   else
   {
      //When the AE bit is cleared, the entry is ignored
      ETH0->MAC_ADDRESS3_LOW = 0;
      ETH0->MAC_ADDRESS3_HIGH = 0;
   }

   //Configure the multicast address filter
   ETH0->HASH_TABLE_LOW = hashTable[0];
   ETH0->HASH_TABLE_HIGH = hashTable[1];

   //Debug message
   TRACE_DEBUG("  HASH_TABLE_LOW = %08" PRIX32 "\r\n", ETH0->HASH_TABLE_LOW);
   TRACE_DEBUG("  HASH_TABLE_HIGH = %08" PRIX32 "\r\n", ETH0->HASH_TABLE_HIGH);

   //Successful processing
   return NO_ERROR;
}


/**
 * @brief Adjust MAC configuration parameters for proper operation
 * @param[in] interface Underlying network interface
 * @return Error code
 **/

error_t xmc4400EthUpdateMacConfig(NetInterface *interface)
{
   uint32_t config;

   //Read current MAC configuration
   config = ETH0->MAC_CONFIGURATION;

   //10BASE-T or 100BASE-TX operation mode?
   if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
   {
      config |= ETH_MAC_CONFIGURATION_FES_Msk;
   }
   else
   {
      config &= ~ETH_MAC_CONFIGURATION_FES_Msk;
   }

   //Half-duplex or full-duplex mode?
   if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
   {
      config |= ETH_MAC_CONFIGURATION_DM_Msk;
   }
   else
   {
      config &= ~ETH_MAC_CONFIGURATION_DM_Msk;
   }

   //Update MAC configuration register
   ETH0->MAC_CONFIGURATION = config;

   //Successful processing
   return NO_ERROR;
}


/**
 * @brief Write PHY register
 * @param[in] opcode Access type (2 bits)
 * @param[in] phyAddr PHY address (5 bits)
 * @param[in] regAddr Register address (5 bits)
 * @param[in] data Register value
 **/

void xmc4400EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
   uint8_t regAddr, uint16_t data)
{
   uint32_t temp;

   //Valid opcode?
   if(opcode == SMI_OPCODE_WRITE)
   {
      //Take care not to alter MDC clock configuration
      temp = ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk;
      //Set up a write operation
      temp |= ETH_GMII_ADDRESS_MW_Msk | ETH_GMII_ADDRESS_MB_Msk;
      //PHY address
      temp |= (phyAddr << ETH_GMII_ADDRESS_PA_Pos) & ETH_GMII_ADDRESS_PA_Msk;
      //Register address
      temp |= (regAddr << ETH_GMII_ADDRESS_MR_Pos) & ETH_GMII_ADDRESS_MR_Msk;

      //Data to be written in the PHY register
      ETH0->GMII_DATA = data & ETH_GMII_DATA_MD_Msk;

      //Start a write operation
      ETH0->GMII_ADDRESS = temp;
      //Wait for the write to complete
      while((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0)
      {
      }
   }
   else
   {
      //The MAC peripheral only supports standard Clause 22 opcodes
   }
}


/**
 * @brief Read PHY register
 * @param[in] opcode Access type (2 bits)
 * @param[in] phyAddr PHY address (5 bits)
 * @param[in] regAddr Register address (5 bits)
 * @return Register value
 **/

uint16_t xmc4400EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
   uint8_t regAddr)
{
   uint16_t data;
   uint32_t temp;

   //Valid opcode?
   if(opcode == SMI_OPCODE_READ)
   {
      //Take care not to alter MDC clock configuration
      temp = ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk;
      //Set up a read operation
      temp |= ETH_GMII_ADDRESS_MB_Msk;
      //PHY address
      temp |= (phyAddr << ETH_GMII_ADDRESS_PA_Pos) & ETH_GMII_ADDRESS_PA_Msk;
      //Register address
      temp |= (regAddr << ETH_GMII_ADDRESS_MR_Pos) & ETH_GMII_ADDRESS_MR_Msk;

      //Start a read operation
      ETH0->GMII_ADDRESS = temp;
      //Wait for the read to complete
      while((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0)
      {
      }

      //Get register value
      data = ETH0->GMII_DATA & ETH_GMII_DATA_MD_Msk;
   }
   else
   {
      //The MAC peripheral only supports standard Clause 22 opcodes
      data = 0;
   }

   //Return the value of the PHY register
   return data;
}


/**
 * @brief CRC calculation
 * @param[in] data Pointer to the data over which to calculate the CRC
 * @param[in] length Number of bytes to process
 * @return Resulting CRC value
 **/

uint32_t xmc4400EthCalcCrc(const void *data, size_t length)
{
   uint_t i;
   uint_t j;
   uint32_t crc;
   const uint8_t *p;

   //Point to the data over which to calculate the CRC
   p = (uint8_t *) data;
   //CRC preset value
   crc = 0xFFFFFFFF;

   //Loop through data
   for(i = 0; i < length; i++)
   {
      //The message is processed bit by bit
      for(j = 0; j < 8; j++)
      {
         //Update CRC value
         if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
         {
            crc = (crc << 1) ^ 0x04C11DB7;
         }
         else
         {
            crc = crc << 1;
         }
      }
   }

   //Return CRC value
   return ~crc;
}
/**
 * @file xmc4400_eth_driver.h
 * @brief Infineon XMC4400 Ethernet MAC driver
 *
 * @section License
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 *
 * This file is part of CycloneTCP Open.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @author Oryx Embedded SARL (www.oryx-embedded.com)
 * @version 2.0.2
 **/

#ifndef _XMC4400_ETH_DRIVER_H
#define _XMC4400_ETH_DRIVER_H

//Dependencies
#include "core/nic.h"

//Number of TX buffers
#ifndef XMC4400_ETH_TX_BUFFER_COUNT
   #define XMC4400_ETH_TX_BUFFER_COUNT 2
#elif (XMC4400_ETH_TX_BUFFER_COUNT < 1)
   #error XMC4400_ETH_TX_BUFFER_COUNT parameter is not valid
#endif

//TX buffer size
#ifndef XMC4400_ETH_TX_BUFFER_SIZE
   #define XMC4400_ETH_TX_BUFFER_SIZE 1536
#elif (XMC4400_ETH_TX_BUFFER_SIZE != 1536)
   #error XMC4400_ETH_TX_BUFFER_SIZE parameter is not valid
#endif

//Number of RX buffers
#ifndef XMC4400_ETH_RX_BUFFER_COUNT
   #define XMC4400_ETH_RX_BUFFER_COUNT 4
#elif (XMC4400_ETH_RX_BUFFER_COUNT < 1)
   #error XMC4400_ETH_RX_BUFFER_COUNT parameter is not valid
#endif

//RX buffer size
#ifndef XMC4400_ETH_RX_BUFFER_SIZE
   #define XMC4400_ETH_RX_BUFFER_SIZE 1536
#elif (XMC4400_ETH_RX_BUFFER_SIZE != 1536)
   #error XMC4400_ETH_RX_BUFFER_SIZE parameter is not valid
#endif

//Interrupt priority grouping
#ifndef XMC4400_ETH_IRQ_PRIORITY_GROUPING
   #define XMC4400_ETH_IRQ_PRIORITY_GROUPING 1
#elif (XMC4400_ETH_IRQ_PRIORITY_GROUPING < 0)
   #error XMC4400_ETH_IRQ_PRIORITY_GROUPING parameter is not valid
#endif

//Ethernet interrupt group priority
#ifndef XMC4400_ETH_IRQ_GROUP_PRIORITY
   #define XMC4400_ETH_IRQ_GROUP_PRIORITY 48
#elif (XMC4400_ETH_IRQ_GROUP_PRIORITY < 0)
   #error XMC4400_ETH_IRQ_GROUP_PRIORITY parameter is not valid
#endif

//Ethernet interrupt subpriority
#ifndef XMC4400_ETH_IRQ_SUB_PRIORITY
   #define XMC4400_ETH_IRQ_SUB_PRIORITY 0
#elif (XMC4400_ETH_IRQ_SUB_PRIORITY < 0)
   #error XMC4400_ETH_IRQ_SUB_PRIORITY parameter is not valid
#endif

//Name of the section where to place DMA buffers
#ifndef XMC4400_ETH_RAM_SECTION
   #define XMC4400_ETH_RAM_SECTION "ETH_RAM"
#endif

//ETH0_CON register
#define ETH_CON_MDIO_A     (0 << ETH_CON_MDIO_Pos)
#define ETH_CON_MDIO_B     (1 << ETH_CON_MDIO_Pos)
#define ETH_CON_MDIO_C     (2 << ETH_CON_MDIO_Pos)
#define ETH_CON_MDIO_D     (3 << ETH_CON_MDIO_Pos)

#define ETH_CON_CLK_TX_A   (0 << ETH_CON_CLK_TX_Pos)
#define ETH_CON_CLK_TX_B   (1 << ETH_CON_CLK_TX_Pos)
#define ETH_CON_CLK_TX_C   (2 << ETH_CON_CLK_TX_Pos)
#define ETH_CON_CLK_TX_D   (3 << ETH_CON_CLK_TX_Pos)

#define ETH_CON_COL_A      (0 << ETH_CON_COL_Pos)
#define ETH_CON_COL_B      (1 << ETH_CON_COL_Pos)
#define ETH_CON_COL_C      (2 << ETH_CON_COL_Pos)
#define ETH_CON_COL_D      (3 << ETH_CON_COL_Pos)

#define ETH_CON_RXER_A     (0 << ETH_CON_RXER_Pos)
#define ETH_CON_RXER_B     (1 << ETH_CON_RXER_Pos)
#define ETH_CON_RXER_C     (2 << ETH_CON_RXER_Pos)
#define ETH_CON_RXER_D     (3 << ETH_CON_RXER_Pos)

#define ETH_CON_CRS_A      (0 << ETH_CON_CRS_Pos)
#define ETH_CON_CRS_B      (1 << ETH_CON_CRS_Pos)
#define ETH_CON_CRS_C      (2 << ETH_CON_CRS_Pos)
#define ETH_CON_CRS_D      (3 << ETH_CON_CRS_Pos)

#define ETH_CON_CRS_DV_A   (0 << ETH_CON_CRS_DV_Pos)
#define ETH_CON_CRS_DV_B   (1 << ETH_CON_CRS_DV_Pos)
#define ETH_CON_CRS_DV_C   (2 << ETH_CON_CRS_DV_Pos)
#define ETH_CON_CRS_DV_D   (3 << ETH_CON_CRS_DV_Pos)

#define ETH_CON_CLK_RMII_A (0 << ETH_CON_CLK_RMII_Pos)
#define ETH_CON_CLK_RMII_B (1 << ETH_CON_CLK_RMII_Pos)
#define ETH_CON_CLK_RMII_C (2 << ETH_CON_CLK_RMII_Pos)
#define ETH_CON_CLK_RMII_D (3 << ETH_CON_CLK_RMII_Pos)

#define ETH_CON_RXD3_A     (0 << ETH_CON_RXD3_Pos)
#define ETH_CON_RXD3_B     (1 << ETH_CON_RXD3_Pos)
#define ETH_CON_RXD3_C     (2 << ETH_CON_RXD3_Pos)
#define ETH_CON_RXD3_D     (3 << ETH_CON_RXD3_Pos)

#define ETH_CON_RXD2_A     (0 << ETH_CON_RXD2_Pos)
#define ETH_CON_RXD2_B     (1 << ETH_CON_RXD2_Pos)
#define ETH_CON_RXD2_C     (2 << ETH_CON_RXD2_Pos)
#define ETH_CON_RXD2_D     (3 << ETH_CON_RXD2_Pos)

#define ETH_CON_RXD1_A     (0 << ETH_CON_RXD1_Pos)
#define ETH_CON_RXD1_B     (1 << ETH_CON_RXD1_Pos)
#define ETH_CON_RXD1_C     (2 << ETH_CON_RXD1_Pos)
#define ETH_CON_RXD1_D     (3 << ETH_CON_RXD1_Pos)

#define ETH_CON_RXD0_A     (0 << ETH_CON_RXD0_Pos)
#define ETH_CON_RXD0_B     (1 << ETH_CON_RXD0_Pos)
#define ETH_CON_RXD0_C     (2 << ETH_CON_RXD0_Pos)
#define ETH_CON_RXD0_D     (3 << ETH_CON_RXD0_Pos)

//ETH0_MAC_CONFIGURATION register
#define ETH_MAC_CONFIGURATION_RESERVED15_Msk (1 << 15)

//ETH0_GMII_ADDRESS register
#define ETH_GMII_ADDRESS_CR_DIV42  (0 << ETH_GMII_ADDRESS_CR_Pos)
#define ETH_GMII_ADDRESS_CR_DIV62  (1 << ETH_GMII_ADDRESS_CR_Pos)
#define ETH_GMII_ADDRESS_CR_DIV16  (2 << ETH_GMII_ADDRESS_CR_Pos)
#define ETH_GMII_ADDRESS_CR_DIV26  (3 << ETH_GMII_ADDRESS_CR_Pos)
#define ETH_GMII_ADDRESS_CR_DIV102 (4 << ETH_GMII_ADDRESS_CR_Pos)
#define ETH_GMII_ADDRESS_CR_DIV124 (5 << ETH_GMII_ADDRESS_CR_Pos)

//ETH0_BUS_MODE register
#define ETH_BUS_MODE_RPBL_1  (1 << ETH_BUS_MODE_RPBL_Pos)
#define ETH_BUS_MODE_RPBL_2  (2 << ETH_BUS_MODE_RPBL_Pos)
#define ETH_BUS_MODE_RPBL_4  (4 << ETH_BUS_MODE_RPBL_Pos)
#define ETH_BUS_MODE_RPBL_8  (8 << ETH_BUS_MODE_RPBL_Pos)
#define ETH_BUS_MODE_RPBL_16 (16 << ETH_BUS_MODE_RPBL_Pos)
#define ETH_BUS_MODE_RPBL_32 (32 << ETH_BUS_MODE_RPBL_Pos)

#define ETH_BUS_MODE_PR_1_1  (0 << ETH_BUS_MODE_PR_Pos)
#define ETH_BUS_MODE_PR_2_1  (1 << ETH_BUS_MODE_PR_Pos)
#define ETH_BUS_MODE_PR_3_1  (2 << ETH_BUS_MODE_PR_Pos)
#define ETH_BUS_MODE_PR_4_1  (3 << ETH_BUS_MODE_PR_Pos)

#define ETH_BUS_MODE_PBL_1   (1 << ETH_BUS_MODE_PBL_Pos)
#define ETH_BUS_MODE_PBL_2   (2 << ETH_BUS_MODE_PBL_Pos)
#define ETH_BUS_MODE_PBL_4   (4 << ETH_BUS_MODE_PBL_Pos)
#define ETH_BUS_MODE_PBL_8   (8 << ETH_BUS_MODE_PBL_Pos)
#define ETH_BUS_MODE_PBL_16  (16 << ETH_BUS_MODE_PBL_Pos)
#define ETH_BUS_MODE_PBL_32  (32 << ETH_BUS_MODE_PBL_Pos)

//Transmit DMA descriptor flags
#define ETH_TDES0_OWN     0x80000000
#define ETH_TDES0_IC      0x40000000
#define ETH_TDES0_LS      0x20000000
#define ETH_TDES0_FS      0x10000000
#define ETH_TDES0_DC      0x08000000
#define ETH_TDES0_DP      0x04000000
#define ETH_TDES0_TTSE    0x02000000
#define ETH_TDES0_CIC     0x00C00000
#define ETH_TDES0_TER     0x00200000
#define ETH_TDES0_TCH     0x00100000
#define ETH_TDES0_TTSS    0x00020000
#define ETH_TDES0_IHE     0x00010000
#define ETH_TDES0_ES      0x00008000
#define ETH_TDES0_JT      0x00004000
#define ETH_TDES0_FF      0x00002000
#define ETH_TDES0_IPE     0x00001000
#define ETH_TDES0_LCA     0x00000800
#define ETH_TDES0_NC      0x00000400
#define ETH_TDES0_LCO     0x00000200
#define ETH_TDES0_EC      0x00000100
#define ETH_TDES0_VF      0x00000080
#define ETH_TDES0_CC      0x00000078
#define ETH_TDES0_ED      0x00000004
#define ETH_TDES0_UF      0x00000002
#define ETH_TDES0_DB      0x00000001
#define ETH_TDES1_TBS2    0x1FFF0000
#define ETH_TDES1_TBS1    0x00001FFF
#define ETH_TDES2_TBAP1   0xFFFFFFFF
#define ETH_TDES3_TBAP2   0xFFFFFFFF

//Receive DMA descriptor flags
#define ETH_RDES0_OWN     0x80000000
#define ETH_RDES0_AFM     0x40000000
#define ETH_RDES0_FL      0x3FFF0000
#define ETH_RDES0_ES      0x00008000
#define ETH_RDES0_DE      0x00004000
#define ETH_RDES0_SAF     0x00002000
#define ETH_RDES0_LE      0x00001000
#define ETH_RDES0_OE      0x00000800
#define ETH_RDES0_VLAN    0x00000400
#define ETH_RDES0_FS      0x00000200
#define ETH_RDES0_LS      0x00000100
#define ETH_RDES0_IPCE_GF 0x00000080
#define ETH_RDES0_LCO     0x00000040
#define ETH_RDES0_FT      0x00000020
#define ETH_RDES0_RWT     0x00000010
#define ETH_RDES0_RE      0x00000008
#define ETH_RDES0_DBE     0x00000004
#define ETH_RDES0_CE      0x00000002
#define ETH_RDES0_PCE     0x00000001
#define ETH_RDES1_DIC     0x80000000
#define ETH_RDES1_RBS2    0x1FFF0000
#define ETH_RDES1_RER     0x00008000
#define ETH_RDES1_RCH     0x00004000
#define ETH_RDES1_RBS1    0x00001FFF
#define ETH_RDES2_RBAP1   0xFFFFFFFF
#define ETH_RDES3_RBAP2   0xFFFFFFFF

//C++ guard
#ifdef __cplusplus
extern "C" {
#endif


/**
 * @brief Transmit DMA descriptor
 **/

typedef struct
{
   uint32_t tdes0;
   uint32_t tdes1;
   uint32_t tdes2;
   uint32_t tdes3;
} Xmc4400TxDmaDesc;


/**
 * @brief Receive DMA descriptor
 **/

typedef struct
{
   uint32_t rdes0;
   uint32_t rdes1;
   uint32_t rdes2;
   uint32_t rdes3;
} Xmc4400RxDmaDesc;


//XMC4400 Ethernet MAC driver
extern const NicDriver xmc4400EthDriver;

//XMC4400 Ethernet MAC related functions
error_t xmc4400EthInit(NetInterface *interface);
void xmc4400EthInitGpio(NetInterface *interface);
void xmc4400EthInitDmaDesc(NetInterface *interface);

void xmc4400EthTick(NetInterface *interface);

void xmc4400EthEnableIrq(NetInterface *interface);
void xmc4400EthDisableIrq(NetInterface *interface);
void xmc4400EthEventHandler(NetInterface *interface);

error_t xmc4400EthSendPacket(NetInterface *interface,
   const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary);

error_t xmc4400EthReceivePacket(NetInterface *interface);

error_t xmc4400EthUpdateMacAddrFilter(NetInterface *interface);
error_t xmc4400EthUpdateMacConfig(NetInterface *interface);

void xmc4400EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
   uint8_t regAddr, uint16_t data);

uint16_t xmc4400EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
   uint8_t regAddr);

uint32_t xmc4400EthCalcCrc(const void *data, size_t length);

//C++ guard
#ifdef __cplusplus
}
#endif

#endif
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
//GCC compiler?
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
/**
 * @file ksz9131_driver.c
 * @brief KSZ9131 Gigabit Ethernet PHY driver
 *
 * @section License
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 *
 * This file is part of CycloneTCP Open.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @author Oryx Embedded SARL (www.oryx-embedded.com)
 * @version 2.0.2
 **/

//Switch to the appropriate trace level
#define TRACE_LEVEL NIC_TRACE_LEVEL

//Dependencies
#include "core/net.h"
#include "drivers/phy/ksz9131_driver.h"
#include "debug.h"


/**
 * @brief KSZ9131 Ethernet PHY driver
 **/

const PhyDriver ksz9131PhyDriver =
{
   ksz9131Init,
   ksz9131Tick,
   ksz9131EnableIrq,
   ksz9131DisableIrq,
   ksz9131EventHandler
};


/**
 * @brief KSZ9131 PHY transceiver initialization
 * @param[in] interface Underlying network interface
 * @return Error code
 **/

error_t ksz9131Init(NetInterface *interface)
{
   //Debug message
   TRACE_INFO("Initializing KSZ9131...\r\n");

   //Undefined PHY address?
   if(interface->phyAddr >= 32)
   {
      //Use the default address
      interface->phyAddr = KSZ9131_PHY_ADDR;
   }

   //Initialize serial management interface
   if(interface->smiDriver != NULL)
   {
      interface->smiDriver->init();
   }

   //Initialize external interrupt line driver
   if(interface->extIntDriver != NULL)
   {
      interface->extIntDriver->init();
   }

   //Reset PHY transceiver
   ksz9131WritePhyReg(interface, KSZ9131_BMCR, KSZ9131_BMCR_RESET);

   //Wait for the reset to complete
   while(ksz9131ReadPhyReg(interface, KSZ9131_BMCR) & KSZ9131_BMCR_RESET)
   {
   }

   //Dump PHY registers for debugging purpose
   ksz9131DumpPhyReg(interface);

   //The PHY will generate interrupts when link status changes are detected
   ksz9131WritePhyReg(interface, KSZ9131_ICSR, KSZ9131_ICSR_LINK_DOWN_IE |
      KSZ9131_ICSR_LINK_UP_IE);

   //Force the TCP/IP stack to poll the link state at startup
   interface->phyEvent = TRUE;
   //Notify the TCP/IP stack of the event
   osSetEvent(&netEvent);

   //Successful initialization
   return NO_ERROR;
}


/**
 * @brief KSZ9131 timer handler
 * @param[in] interface Underlying network interface
 **/

void ksz9131Tick(NetInterface *interface)
{
   uint16_t value;
   bool_t linkState;

   //No external interrupt line driver?
   if(interface->extIntDriver == NULL)
   {
      //Read basic status register
      value = ksz9131ReadPhyReg(interface, KSZ9131_BMSR);
      //Retrieve current link state
      linkState = (value & KSZ9131_BMSR_LINK_STATUS) ? TRUE : FALSE;

      //Link up event?
      if(linkState && !interface->linkState)
      {
         //Set event flag
         interface->phyEvent = TRUE;
         //Notify the TCP/IP stack of the event
         osSetEvent(&netEvent);
      }
      //Link down event?
      else if(!linkState && interface->linkState)
      {
         //Set event flag
         interface->phyEvent = TRUE;
         //Notify the TCP/IP stack of the event
         osSetEvent(&netEvent);
      }
   }
}


/**
 * @brief Enable interrupts
 * @param[in] interface Underlying network interface
 **/

void ksz9131EnableIrq(NetInterface *interface)
{
   //Enable PHY transceiver interrupts
   if(interface->extIntDriver != NULL)
   {
      interface->extIntDriver->enableIrq();
   }
}


/**
 * @brief Disable interrupts
 * @param[in] interface Underlying network interface
 **/

void ksz9131DisableIrq(NetInterface *interface)
{
   //Disable PHY transceiver interrupts
   if(interface->extIntDriver != NULL)
   {
      interface->extIntDriver->disableIrq();
   }
}


/**
 * @brief KSZ9131 event handler
 * @param[in] interface Underlying network interface
 **/

void ksz9131EventHandler(NetInterface *interface)
{
   uint16_t value;

   //Read status register to acknowledge the interrupt
   value = ksz9131ReadPhyReg(interface, KSZ9131_ICSR);

   //Link status change?
   if((value & (KSZ9131_ICSR_LINK_DOWN_IF | KSZ9131_ICSR_LINK_UP_IF)) != 0)
   {
      //Any link failure condition is latched in the BMSR register. Reading
      //the register twice will always return the actual link status
      value = ksz9131ReadPhyReg(interface, KSZ9131_BMSR);
      value = ksz9131ReadPhyReg(interface, KSZ9131_BMSR);

      //Link is up?
      if((value & KSZ9131_BMSR_LINK_STATUS) != 0)
      {
         //Read PHY control register
         value = ksz9131ReadPhyReg(interface, KSZ9131_PHYCON);

         //Check current speed
         if((value & KSZ9131_PHYCON_SPEED_1000BT) != 0)
         {
            //1000BASE-T
            interface->linkSpeed = NIC_LINK_SPEED_1GBPS;
         }
         else if((value & KSZ9131_PHYCON_SPEED_100BTX) != 0)
         {
            //100BASE-TX
            interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
         }
         else if((value & KSZ9131_PHYCON_SPEED_10BT) != 0)
         {
            //10BASE-T
            interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
         }
         else
         {
            //Debug message
            TRACE_WARNING("Invalid speed!\r\n");
         }

         //Check current duplex mode
         if((value & KSZ9131_PHYCON_DUPLEX_STATUS) != 0)
         {
            interface->duplexMode = NIC_FULL_DUPLEX_MODE;
         }
         else
         {
            interface->duplexMode = NIC_HALF_DUPLEX_MODE;
         }

         //Update link state
         interface->linkState = TRUE;

         //Adjust MAC configuration parameters for proper operation
         interface->nicDriver->updateMacConfig(interface);
      }
      else
      {
         //Update link state
         interface->linkState = FALSE;
      }

      //Process link state change event
      nicNotifyLinkChange(interface);
   }
}


/**
 * @brief Write PHY register
 * @param[in] interface Underlying network interface
 * @param[in] address PHY register address
 * @param[in] data Register value
 **/

void ksz9131WritePhyReg(NetInterface *interface, uint8_t address,
   uint16_t data)
{
   //Write the specified PHY register
   if(interface->smiDriver != NULL)
   {
      interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE,
         interface->phyAddr, address, data);
   }
   else
   {
      interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE,
         interface->phyAddr, address, data);
   }
}


/**
 * @brief Read PHY register
 * @param[in] interface Underlying network interface
 * @param[in] address PHY register address
 * @return Register value
 **/

uint16_t ksz9131ReadPhyReg(NetInterface *interface, uint8_t address)
{
   uint16_t data;

   //Read the specified PHY register
   if(interface->smiDriver != NULL)
   {
      data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ,
         interface->phyAddr, address);
   }
   else
   {
      data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ,
         interface->phyAddr, address);
   }

   //Return the value of the PHY register
   return data;
}


/**
 * @brief Dump PHY registers for debugging purpose
 * @param[in] interface Underlying network interface
 **/

void ksz9131DumpPhyReg(NetInterface *interface)
{
   uint8_t i;

   //Loop through PHY registers
   for(i = 0; i < 32; i++)
   {
      //Display current PHY register
      TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
         ksz9131ReadPhyReg(interface, i));
   }

   //Terminate with a line feed
   TRACE_DEBUG("\r\n");
}
/**
 * @file ksz9131_driver.h
 * @brief KSZ9131 Gigabit Ethernet PHY driver
 *
 * @section License
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 *
 * This file is part of CycloneTCP Open.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @author Oryx Embedded SARL (www.oryx-embedded.com)
 * @version 2.0.2
 **/

#ifndef _KSZ9131_DRIVER_H
#define _KSZ9131_DRIVER_H

//Dependencies
#include "core/nic.h"

//PHY address
#ifndef KSZ9131_PHY_ADDR
   #define KSZ9131_PHY_ADDR 7
#elif (KSZ9131_PHY_ADDR < 0 || KSZ9131_PHY_ADDR > 31)
   #error KSZ9131_PHY_ADDR parameter is not valid
#endif

//KSZ9131 PHY registers
#define KSZ9131_BMCR                              0x00
#define KSZ9131_BMSR                              0x01
#define KSZ9131_PHYID1                            0x02
#define KSZ9131_PHYID2                            0x03
#define KSZ9131_ANAR                              0x04
#define KSZ9131_ANLPAR                            0x05
#define KSZ9131_ANER                              0x06
#define KSZ9131_ANNPR                             0x07
#define KSZ9131_ANLPNPR                           0x08
#define KSZ9131_GBCR                              0x09
#define KSZ9131_GBSR                              0x0A
#define KSZ9131_MMDACR                            0x0D
#define KSZ9131_MMDAADR                           0x0E
#define KSZ9131_GBESR                             0x0F
#define KSZ9131_RLB                               0x11
#define KSZ9131_LINKMD                            0x12
#define KSZ9131_DPMAPCSS                          0x13
#define KSZ9131_RXERCTR                           0x15
#define KSZ9131_LED_MODE_SEL                      0x16
#define KSZ9131_LED_BEHAVIOR                      0x17
#define KSZ9131_MDIO_DRIVE                        0x19
#define KSZ9131_LEGACY_LED_MODE                   0x1A
#define KSZ9131_ICSR                              0x1B
#define KSZ9131_AUTOMDI                           0x1C
#define KSZ9131_SPDC                              0x1D
#define KSZ9131_EXT_LOOPBACK                      0x1E
#define KSZ9131_PHYCON                            0x1F

//Basic Control register
#define KSZ9131_BMCR_RESET                        0x8000
#define KSZ9131_BMCR_LOOPBACK                     0x4000
#define KSZ9131_BMCR_SPEED_SEL_LSB                0x2000
#define KSZ9131_BMCR_AN_EN                        0x1000
#define KSZ9131_BMCR_POWER_DOWN                   0x0800
#define KSZ9131_BMCR_ISOLATE                      0x0400
#define KSZ9131_BMCR_RESTART_AN                   0x0200
#define KSZ9131_BMCR_DUPLEX_MODE                  0x0100
#define KSZ9131_BMCR_COL_TEST                     0x0080
#define KSZ9131_BMCR_SPEED_SEL_MSB                0x0040

//Basic Status register
#define KSZ9131_BMSR_100BT4                       0x8000
#define KSZ9131_BMSR_100BTX_FD                    0x4000
#define KSZ9131_BMSR_100BTX_HD                    0x2000
#define KSZ9131_BMSR_10BT_FD                      0x1000
#define KSZ9131_BMSR_10BT_HD                      0x0800
#define KSZ9131_BMSR_100BT2_FD                    0x0400
#define KSZ9131_BMSR_100BT2_HD                    0x0200
#define KSZ9131_BMSR_EXTENDED_STATUS              0x0100
#define KSZ9131_BMSR_UNIDIRECTIONAL_ABLE          0x0080
#define KSZ9131_BMSR_MF_PREAMBLE_SUPPR            0x0040
#define KSZ9131_BMSR_AN_COMPLETE                  0x0020
#define KSZ9131_BMSR_REMOTE_FAULT                 0x0010
#define KSZ9131_BMSR_AN_CAPABLE                   0x0008
#define KSZ9131_BMSR_LINK_STATUS                  0x0004
#define KSZ9131_BMSR_JABBER_DETECT                0x0002
#define KSZ9131_BMSR_EXTENDED_CAPABLE             0x0001

//PHY Identifier 1 register
#define KSZ9131_PHYID1_PHY_ID_MSB                 0xFFFF
#define KSZ9131_PHYID1_PHY_ID_MSB_DEFAULT         0x0022

//PHY Identifier 2 register
#define KSZ9131_PHYID2_PHY_ID_LSB                 0xFC00
#define KSZ9131_PHYID2_PHY_ID_LSB_DEFAULT         0x1400
#define KSZ9131_PHYID2_MODEL_NUM                  0x03F0
#define KSZ9131_PHYID2_MODEL_NUM_DEFAULT          0x0240
#define KSZ9131_PHYID2_REVISION_NUM               0x000F

//Auto-Negotiation Advertisement register
#define KSZ9131_ANAR_NEXT_PAGE                    0x8000
#define KSZ9131_ANAR_REMOTE_FAULT                 0x2000
#define KSZ9131_ANAR_EXTENDED_NEXT_PAGE           0x1000
#define KSZ9131_ANAR_ASYM_PAUSE                   0x0800
#define KSZ9131_ANAR_SYM_PAUSE                    0x0400
#define KSZ9131_ANAR_100BT4                       0x0200
#define KSZ9131_ANAR_100BTX_FD                    0x0100
#define KSZ9131_ANAR_100BTX_HD                    0x0080
#define KSZ9131_ANAR_10BT_FD                      0x0040
#define KSZ9131_ANAR_10BT_HD                      0x0020
#define KSZ9131_ANAR_SELECTOR                     0x001F
#define KSZ9131_ANAR_SELECTOR_DEFAULT             0x0001

//Auto-Negotiation Link Partner Ability register
#define KSZ9131_ANLPAR_NEXT_PAGE                  0x8000
#define KSZ9131_ANLPAR_ACK                        0x4000
#define KSZ9131_ANLPAR_REMOTE_FAULT               0x2000
#define KSZ9131_ANLPAR_EXTENDED_NEXT_PAGE         0x1000
#define KSZ9131_ANLPAR_ASYM_PAUSE                 0x0800
#define KSZ9131_ANLPAR_PAUSE                      0x0400
#define KSZ9131_ANLPAR_100BT4                     0x0200
#define KSZ9131_ANLPAR_100BTX_FD                  0x0100
#define KSZ9131_ANLPAR_100BTX_HD                  0x0080
#define KSZ9131_ANLPAR_10BT_FD                    0x0040
#define KSZ9131_ANLPAR_10BT_HD                    0x0020
#define KSZ9131_ANLPAR_SELECTOR                   0x001F
#define KSZ9131_ANLPAR_SELECTOR_DEFAULT           0x0001

//Auto-Negotiation Expansion register
#define KSZ9131_ANER_RECEIVE_NP_LOC_ABLE          0x0040
#define KSZ9131_ANER_RECEIVE_NP_STOR_LOC          0x0020
#define KSZ9131_ANER_PAR_DETECT_FAULT             0x0010
#define KSZ9131_ANER_LP_NEXT_PAGE_ABLE            0x0008
#define KSZ9131_ANER_NEXT_PAGE_ABLE               0x0004
#define KSZ9131_ANER_PAGE_RECEIVED                0x0002
#define KSZ9131_ANER_LP_AN_ABLE                   0x0001

//Auto-Negotiation Next Page TX register
#define KSZ9131_ANNPR_NEXT_PAGE                   0x8000
#define KSZ9131_ANNPR_MSG_PAGE                    0x2000
#define KSZ9131_ANNPR_ACK2                        0x1000
#define KSZ9131_ANNPR_TOGGLE                      0x0800
#define KSZ9131_ANNPR_MESSAGE                     0x07FF

//Auto-Negotiation Next Page RX register
#define KSZ9131_ANLPNPR_NEXT_PAGE                 0x8000
#define KSZ9131_ANLPNPR_ACK                       0x4000
#define KSZ9131_ANLPNPR_MSG_PAGE                  0x2000
#define KSZ9131_ANLPNPR_ACK2                      0x1000
#define KSZ9131_ANLPNPR_TOGGLE                    0x0800
#define KSZ9131_ANLPNPR_MESSAGE                   0x07FF

//Auto-Negotiation Master Slave Control register
#define KSZ9131_GBCR_TEST_MODE                    0xE000
#define KSZ9131_GBCR_MS_MAN_CONF_EN               0x1000
#define KSZ9131_GBCR_MS_MAN_CONF_VAL              0x0800
#define KSZ9131_GBCR_PORT_TYPE                    0x0400
#define KSZ9131_GBCR_1000BT_FD                    0x0200
#define KSZ9131_GBCR_1000BT_HD                    0x0100

//Auto-Negotiation Master Slave Status register
#define KSZ9131_GBSR_MS_CONF_FAULT                0x8000
#define KSZ9131_GBSR_MS_CONF_RES                  0x4000
#define KSZ9131_GBSR_LOCAL_RECEIVER_STATUS        0x2000
#define KSZ9131_GBSR_REMOTE_RECEIVER_STATUS       0x1000
#define KSZ9131_GBSR_LP_1000BT_FD                 0x0800
#define KSZ9131_GBSR_LP_1000BT_HD                 0x0400
#define KSZ9131_GBSR_IDLE_ERR_COUNT               0x00FF

//MMD Access Control register
#define KSZ9131_MMDACR_FUNC                       0xC000
#define KSZ9131_MMDACR_FUNC_ADDR                  0x0000
#define KSZ9131_MMDACR_FUNC_DATA_NO_POST_INC      0x4000
#define KSZ9131_MMDACR_FUNC_DATA_POST_INC_RW      0x8000
#define KSZ9131_MMDACR_FUNC_DATA_POST_INC_W       0xC000
#define KSZ9131_MMDACR_DEVAD                      0x001F

//Extended Status register
#define KSZ9131_GBESR_1000BX_FD                   0x8000
#define KSZ9131_GBESR_1000BX_HD                   0x4000
#define KSZ9131_GBESR_1000BT_FD                   0x2000
#define KSZ9131_GBESR_1000BT_HD                   0x1000

//Remote Loopback register
#define KSZ9131_RLB_REMOTE_LOOPBACK               0x0100

//LinkMD Cable Diagnostic register
#define KSZ9131_LINKMD_TEST_EN                    0x8000
#define KSZ9131_LINKMD_TX_DIS                     0x4000
#define KSZ9131_LINKMD_PAIR                       0x3000
#define KSZ9131_LINKMD_PAIR_A                     0x0000
#define KSZ9131_LINKMD_PAIR_B                     0x1000
#define KSZ9131_LINKMD_PAIR_C                     0x2000
#define KSZ9131_LINKMD_PAIR_D                     0x3000
#define KSZ9131_LINKMD_SEL                        0x0C00
#define KSZ9131_LINKMD_STATUS                     0x0300
#define KSZ9131_LINKMD_STATUS_NORMAL              0x0000
#define KSZ9131_LINKMD_STATUS_OPEN                0x0100
#define KSZ9131_LINKMD_STATUS_SHORT               0x0200
#define KSZ9131_LINKMD_STATUS_TEST_FAILED         0x0300
#define KSZ9131_LINKMD_FAULT_DATA                 0x00FF

//Digital PMA/PCS Status register
#define KSZ9131_DPMAPCSS_1000BT_LINK_STATUS       0x0002
#define KSZ9131_DPMAPCSS_100BTX_LINK_STATUS       0x0001

//LED Mode Select register
#define KSZ9131_LED_MODE_SEL_LED2_CONFIG          0x00F0
#define KSZ9131_LED_MODE_SEL_LED1_CONFIG          0x000F

//LED Behavior register
#define KSZ9131_LED_BEHAVIOR_LED_ACT_OUT_SEL      0x4000
#define KSZ9131_LED_BEHAVIOR_LED_PULSING_EN       0x1000
#define KSZ9131_LED_BEHAVIOR_LED_BLINK_RATE       0x0C00
#define KSZ9131_LED_BEHAVIOR_LED_BLINK_RATE_2_5HZ 0x0000
#define KSZ9131_LED_BEHAVIOR_LED_BLINK_RATE_5HZ   0x0400
#define KSZ9131_LED_BEHAVIOR_LED_BLINK_RATE_10HZ  0x0800
#define KSZ9131_LED_BEHAVIOR_LED_BLINK_RATE_20HZ  0x0C00
#define KSZ9131_LED_BEHAVIOR_LED_PULSE_STRECH_EN  0x0060
#define KSZ9131_LED_BEHAVIOR_LED_COMBINATION      0x0003

//MDIO Drive register
#define KSZ9131_MDIO_DRIVE_MDIO_DRIVE             0x0002

//KSZ9031 LED Mode register
#define KSZ9131_LEGACY_LED_MODE_KSZ9031_LED_MODE  0x4000

//Interrupt Control/Status register
#define KSZ9131_ICSR_JABBER_IE                    0x8000
#define KSZ9131_ICSR_RECEIVE_ERROR_IE             0x4000
#define KSZ9131_ICSR_PAGE_RECEIVED_IE             0x2000
#define KSZ9131_ICSR_PAR_DETECT_FAULT_IE          0x1000
#define KSZ9131_ICSR_LP_ACK_IE                    0x0800
#define KSZ9131_ICSR_LINK_DOWN_IE                 0x0400
#define KSZ9131_ICSR_REMOTE_FAULT_IE              0x0200
#define KSZ9131_ICSR_LINK_UP_IE                   0x0100
#define KSZ9131_ICSR_JABBER_IF                    0x0080
#define KSZ9131_ICSR_RECEIVE_ERROR_IF             0x0040
#define KSZ9131_ICSR_PAGE_RECEIVED_IF             0x0020
#define KSZ9131_ICSR_PAR_DETECT_FAULT_IF          0x0010
#define KSZ9131_ICSR_LP_ACK_IF                    0x0008
#define KSZ9131_ICSR_LINK_DOWN_IF                 0x0004
#define KSZ9131_ICSR_REMOTE_FAULT_IF              0x0002
#define KSZ9131_ICSR_LINK_UP_IF                   0x0001

//Auto MDI/MDI-X register
#define KSZ9131_AUTOMDI_MDI_SET                   0x0080
#define KSZ9131_AUTOMDI_SWAP_OFF                  0x0040

//Software Power Down Control register
#define KSZ9131_SPDC_CLK_GATE_OVERRIDE            0x0800
#define KSZ9131_SPDC_PLL_DIS                      0x0400
#define KSZ9131_SPDC_IO_DC_TEST_EN                0x0080
#define KSZ9131_SPDC_VOH                          0x0040

//External Loopback register
#define KSZ9131_EXT_LOOPBACK_EXT_LPBK             0x0008

//Control register
#define KSZ9131_PHYCON_INT_POL_INVERT             0x4000
#define KSZ9131_PHYCON_JABBER_EN                  0x0200
#define KSZ9131_PHYCON_SQE_TEST_EN                0x0100
#define KSZ9131_PHYCON_SPEED_1000BT               0x0040
#define KSZ9131_PHYCON_SPEED_100BTX               0x0020
#define KSZ9131_PHYCON_SPEED_10BT                 0x0010
#define KSZ9131_PHYCON_DUPLEX_STATUS              0x0008
#define KSZ9131_PHYCON_1000BT_MS_STATUS           0x0004
#define KSZ9131_PHYCON_SOFT_RESET                 0x0002
#define KSZ9131_PHYCON_LINK_STATUS_CHECK_FAIL     0x0001

//C++ guard
#ifdef __cplusplus
extern "C" {
#endif

//KSZ9131 Ethernet PHY driver
extern const PhyDriver ksz9131PhyDriver;

//KSZ9131 related functions
error_t ksz9131Init(NetInterface *interface);

void ksz9131Tick(NetInterface *interface);

void ksz9131EnableIrq(NetInterface *interface);
void ksz9131DisableIrq(NetInterface *interface);

void ksz9131EventHandler(NetInterface *interface);

void ksz9131WritePhyReg(NetInterface *interface, uint8_t address,
   uint16_t data);

uint16_t ksz9131ReadPhyReg(NetInterface *interface, uint8_t address);

void ksz9131DumpPhyReg(NetInterface *interface);

//C++ guard
#ifdef __cplusplus
}
#endif

#endif
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
/**
 * @file pef7071_driver.c
 * @brief PEF7071 Gigabit Ethernet PHY driver
 *
 * @section License
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 *
 * This file is part of CycloneTCP Open.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @author Oryx Embedded SARL (www.oryx-embedded.com)
 * @version 2.0.2
 **/

//Switch to the appropriate trace level
#define TRACE_LEVEL NIC_TRACE_LEVEL

//Dependencies
#include "core/net.h"
#include "drivers/phy/pef7071_driver.h"
#include "debug.h"


/**
 * @brief PEF7071 Ethernet PHY driver
 **/

const PhyDriver pef7071PhyDriver =
{
   pef7071Init,
   pef7071Tick,
   pef7071EnableIrq,
   pef7071DisableIrq,
   pef7071EventHandler
};


/**
 * @brief PEF7071 PHY transceiver initialization
 * @param[in] interface Underlying network interface
 * @return Error code
 **/

error_t pef7071Init(NetInterface *interface)
{
   //Debug message
   TRACE_INFO("Initializing PEF7071...\r\n");

   //Undefined PHY address?
   if(interface->phyAddr >= 32)
   {
      //Use the default address
      interface->phyAddr = PEF7071_PHY_ADDR;
   }

   //Initialize serial management interface
   if(interface->smiDriver != NULL)
   {
      interface->smiDriver->init();
   }

   //Reset PHY transceiver
   pef7071WritePhyReg(interface, PEF7071_CTRL, PEF7071_CTRL_RST);

   //Wait for the reset to complete
   while(pef7071ReadPhyReg(interface, PEF7071_CTRL) & PEF7071_CTRL_RST)
   {
   }

   //Select RMII mode
   pef7071WritePhyReg(interface, PEF7071_MIICTRL, PEF7071_MIICTRL_RXCOFF |
      PEF7071_MIICTRL_MODE_RMII);

   //The link speed is forced to 10/100 Mbit/s only
   pef7071WritePhyReg(interface, PEF7071_GCTRL, 0);

   //Restart auto-negotiation
   pef7071WritePhyReg(interface, PEF7071_CTRL, PEF7071_CTRL_ANEN |
      PEF7071_CTRL_ANRS);

   //Dump PHY registers for debugging purpose
   pef7071DumpPhyReg(interface);

   //Force the TCP/IP stack to poll the link state at startup
   interface->phyEvent = TRUE;
   //Notify the TCP/IP stack of the event
   osSetEvent(&netEvent);

   //Successful initialization
   return NO_ERROR;
}


/**
 * @brief PEF7071 timer handler
 * @param[in] interface Underlying network interface
 **/

void pef7071Tick(NetInterface *interface)
{
   uint16_t value;
   bool_t linkState;

   //Read status register
   value = pef7071ReadPhyReg(interface, PEF7071_STAT);
   //Retrieve current link state
   linkState = (value & PEF7071_STAT_LS) ? TRUE : FALSE;

   //Link up event?
   if(linkState && !interface->linkState)
   {
      //Set event flag
      interface->phyEvent = TRUE;
      //Notify the TCP/IP stack of the event
      osSetEvent(&netEvent);
   }
   //Link down event?
   else if(!linkState && interface->linkState)
   {
      //Set event flag
      interface->phyEvent = TRUE;
      //Notify the TCP/IP stack of the event
      osSetEvent(&netEvent);
   }
}


/**
 * @brief Enable interrupts
 * @param[in] interface Underlying network interface
 **/

void pef7071EnableIrq(NetInterface *interface)
{
}


/**
 * @brief Disable interrupts
 * @param[in] interface Underlying network interface
 **/

void pef7071DisableIrq(NetInterface *interface)
{
}


/**
 * @brief PEF7071 event handler
 * @param[in] interface Underlying network interface
 **/

void pef7071EventHandler(NetInterface *interface)
{
   uint16_t status;

   //Read status register
   status = pef7071ReadPhyReg(interface, PEF7071_STAT);

   //Link is up?
   if((status & PEF7071_STAT_LS) != 0)
   {
      //Read MII status register
      status = pef7071ReadPhyReg(interface, PEF7071_MIISTAT);

      //Check current speed
      switch(status & PEF7071_MIISTAT_SPEED)
      {
      //10BASE-T
      case PEF7071_MIISTAT_SPEED_TEN:
         interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
         break;
      //100BASE-TX
      case PEF7071_MIISTAT_SPEED_FAST:
         interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
         break;
      //1000BASE-T
      case PEF7071_MIISTAT_SPEED_GIGA:
         interface->linkSpeed = NIC_LINK_SPEED_1GBPS;
         break;
      //Unknown speed
      default:
         //Debug message
         TRACE_WARNING("Invalid speed\r\n");
         break;
      }

      //Check current duplex mode
      if((status & PEF7071_MIISTAT_DPX) != 0)
      {
         interface->duplexMode = NIC_FULL_DUPLEX_MODE;
      }
      else
      {
         interface->duplexMode = NIC_HALF_DUPLEX_MODE;
      }

      //Update link state
      interface->linkState = TRUE;

      //Adjust MAC configuration parameters for proper operation
      interface->nicDriver->updateMacConfig(interface);
   }
   else
   {
      //Update link state
      interface->linkState = FALSE;
   }

   //Process link state change event
   nicNotifyLinkChange(interface);
}


/**
 * @brief Write PHY register
 * @param[in] interface Underlying network interface
 * @param[in] address PHY register address
 * @param[in] data Register value
 **/

void pef7071WritePhyReg(NetInterface *interface, uint8_t address,
   uint16_t data)
{
   //Write the specified PHY register
   if(interface->smiDriver != NULL)
   {
      interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE,
         interface->phyAddr, address, data);
   }
   else
   {
      interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE,
         interface->phyAddr, address, data);
   }
}


/**
 * @brief Read PHY register
 * @param[in] interface Underlying network interface
 * @param[in] address PHY register address
 * @return Register value
 **/

uint16_t pef7071ReadPhyReg(NetInterface *interface, uint8_t address)
{
   uint16_t data;

   //Read the specified PHY register
   if(interface->smiDriver != NULL)
   {
      data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ,
         interface->phyAddr, address);
   }
   else
   {
      data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ,
         interface->phyAddr, address);
   }

   //Return the value of the PHY register
   return data;
}


/**
 * @brief Dump PHY registers for debugging purpose
 * @param[in] interface Underlying network interface
 **/

void pef7071DumpPhyReg(NetInterface *interface)
{
   uint8_t i;

   //Loop through PHY registers
   for(i = 0; i < 32; i++)
   {
      //Display current PHY register
      TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
         pef7071ReadPhyReg(interface, i));
   }

   //Terminate with a line feed
   TRACE_DEBUG("\r\n");
}
/**
 * @file pef7071_driver.h
 * @brief PEF7071 Gigabit Ethernet PHY driver
 *
 * @section License
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 *
 * This file is part of CycloneTCP Open.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * @author Oryx Embedded SARL (www.oryx-embedded.com)
 * @version 2.0.2
 **/

#ifndef _PEF7071_DRIVER_H
#define _PEF7071_DRIVER_H

//Dependencies
#include "core/nic.h"

//PHY address
#ifndef PEF7071_PHY_ADDR
   #define PEF7071_PHY_ADDR 0
#elif (PEF7071_PHY_ADDR < 0 || PEF7071_PHY_ADDR > 31)
   #error PEF7071_PHY_ADDR parameter is not valid
#endif

//PEF7071 PHY registers
#define PEF7071_CTRL                        0x00
#define PEF7071_STAT                        0x01
#define PEF7071_PHYID1                      0x02
#define PEF7071_PHYID2                      0x03
#define PEF7071_AN_ADV                      0x04
#define PEF7071_AN_LPA                      0x05
#define PEF7071_AN_EXP                      0x06
#define PEF7071_AN_NPTX                     0x07
#define PEF7071_AN_NPRX                     0x08
#define PEF7071_GCTRL                       0x09
#define PEF7071_GSTAT                       0x0A
#define PEF7071_RES11                       0x0B
#define PEF7071_RES12                       0x0C
#define PEF7071_MMDCTRL                     0x0D
#define PEF7071_MMDDATA                     0x0E
#define PEF7071_XSTAT                       0x0F
#define PEF7071_PHYPHYPERF                  0x10
#define PEF7071_PHYSTAT1                    0x11
#define PEF7071_PHYSTAT2                    0x12
#define PEF7071_PHYCTL1                     0x13
#define PEF7071_PHYCTL2                     0x14
#define PEF7071_ERRCNT                      0x15
#define PEF7071_EECTRL                      0x16
#define PEF7071_MIICTRL                     0x17
#define PEF7071_MIISTAT                     0x18
#define PEF7071_IMASK                       0x19
#define PEF7071_ISTAT                       0x1A
#define PEF7071_LED                         0x1B
#define PEF7071_TPGCTRL                     0x1C
#define PEF7071_TPGDATA                     0x1D
#define PEF7071_FWV                         0x1E
#define PEF7071_RES1F                       0x1F

//PEF7071 MMD registers
#define PEF7071_EEE_CTRL1                   0x03, 0x0000
#define PEF7071_EEE_STAT1                   0x03, 0x0001
#define PEF7071_EEE_CAP                     0x03, 0x0014
#define PEF7071_EEE_WAKERR                  0x03, 0x0016
#define PEF7071_ANEGEEE_AN_ADV              0x07, 0x003C
#define PEF7071_EEE_AN_LPADV                0x07, 0x003D
#define PEF7071_EEPROM                      0x1E, 0x0000
#define PEF7071_LEDCH                       0x1F, 0x01E0
#define PEF7071_LEDCL                       0x1F, 0x01E1
#define PEF7071_LED0H                       0x1F, 0x01E2
#define PEF7071_LED0L                       0x1F, 0x01E3
#define PEF7071_LED1H                       0x1F, 0x01E4
#define PEF7071_LED1L                       0x1F, 0x01E5
#define PEF7071_LED2H                       0x1F, 0x01E6
#define PEF7071_LED2L                       0x1F, 0x01E7
#define PEF7071_EEE_RXERR_LINK_FAIL_H       0x1F, 0x01EA
#define PEF7071_EEE_RXERR_LINK_FAIL_L       0x1F, 0x01EB
#define PEF7071_MII2CTRL                    0x1F, 0x01EC
#define PEF7071_LEG_LPI_CFG0                0x1F, 0x01ED
#define PEF7071_LEG_LPI_CFG1                0x1F, 0x01EE
#define PEF7071_WOLCTRL                     0x1F, 0x0781
#define PEF7071_WOLAD0                      0x1F, 0x0783
#define PEF7071_WOLAD1                      0x1F, 0x0784
#define PEF7071_WOLAD2                      0x1F, 0x0785
#define PEF7071_WOLAD3                      0x1F, 0x0786
#define PEF7071_WOLAD4                      0x1F, 0x0787
#define PEF7071_WOLAD5                      0x1F, 0x0788
#define PEF7071_WOLPW0                      0x1F, 0x0789
#define PEF7071_WOLPW1                      0x1F, 0x078A
#define PEF7071_WOLPW2                      0x1F, 0x078B
#define PEF7071_WOLPW3                      0x1F, 0x078C
#define PEF7071_WOLPW4                      0x1F, 0x078D
#define PEF7071_WOLPW5                      0x1F, 0x078E
#define PEF7071_LEG_LPI_CFG2                0x1F, 0x0EB5
#define PEF7071_LEG_LPI_CFG3                0x1F, 0x0EB7

//Control register
#define PEF7071_CTRL_RST                    0x8000
#define PEF7071_CTRL_LB                     0x4000
#define PEF7071_CTRL_SSL                    0x2000
#define PEF7071_CTRL_ANEN                   0x1000
#define PEF7071_CTRL_PD                     0x0800
#define PEF7071_CTRL_ISOL                   0x0400
#define PEF7071_CTRL_ANRS                   0x0200
#define PEF7071_CTRL_DPLX                   0x0100
#define PEF7071_CTRL_COL                    0x0080
#define PEF7071_CTRL_SSM                    0x0040

//Status register
#define PEF7071_STAT_CBT4                   0x8000
#define PEF7071_STAT_CBTXF                  0x4000
#define PEF7071_STAT_CBTXH                  0x2000
#define PEF7071_STAT_XBTF                   0x1000
#define PEF7071_STAT_XBTH                   0x0800
#define PEF7071_STAT_CBT2F                  0x0400
#define PEF7071_STAT_CBT2H                  0x0200
#define PEF7071_STAT_EXT                    0x0100
#define PEF7071_STAT_MFPS                   0x0040
#define PEF7071_STAT_ANOK                   0x0020
#define PEF7071_STAT_RF                     0x0010
#define PEF7071_STAT_ANAB                   0x0008
#define PEF7071_STAT_LS                     0x0004
#define PEF7071_STAT_JD                     0x0002
#define PEF7071_STAT_XCAP                   0x0001

//PHY Identifier 1 register
#define PEF7071_PHYID1_OUI_MSB              0xFFFF
#define PEF7071_PHYID1_OUI_MSB_DEFAULT      0x0000

//PHY Identifier 2 register
#define PEF7071_PHYID2_OUI_LSB              0xFC00
#define PEF7071_PHYID2_OUI_LSB_DEFAULT      0x0000
#define PEF7071_PHYID2_LDN                  0x03F0
#define PEF7071_PHYID2_LDN_DEFAULT          0x0000
#define PEF7071_PHYID2_LDRN                 0x000F

//Auto-Negotiation Advertisement register
#define PEF7071_AN_ADV_NP                   0x8000
#define PEF7071_AN_ADV_RF                   0x2000
#define PEF7071_AN_ADV_TAF                  0x1FE0
#define PEF7071_AN_ADV_TAF_XBT_HDX          0x0020
#define PEF7071_AN_ADV_TAF_XBT_FDX          0x0040
#define PEF7071_AN_ADV_TAF_DBT_HDX          0x0080
#define PEF7071_AN_ADV_TAF_DBT_FDX          0x0100
#define PEF7071_AN_ADV_TAF_DBT4             0x0200
#define PEF7071_AN_ADV_TAF_PS_SYM           0x0400
#define PEF7071_AN_ADV_TAF_PS_ASYM          0x0800
#define PEF7071_AN_ADV_TAF_RES              0x1000
#define PEF7071_AN_ADV_SF                   0x001F
#define PEF7071_AN_ADV_SF_DEFAULT           0x0001

//Auto-Negotiation Link-Partner Ability register
#define PEF7071_AN_LPA_NP                   0x8000
#define PEF7071_AN_LPA_ACK                  0x4000
#define PEF7071_AN_LPA_RF                   0x2000
#define PEF7071_AN_LPA_TAF                  0x1FE0
#define PEF7071_AN_LPA_TAF_XBT_HDX          0x0020
#define PEF7071_AN_LPA_TAF_XBT_FDX          0x0040
#define PEF7071_AN_LPA_TAF_DBT_HDX          0x0080
#define PEF7071_AN_LPA_TAF_DBT_FDX          0x0100
#define PEF7071_AN_LPA_TAF_DBT4             0x0200
#define PEF7071_AN_LPA_TAF_PS_SYM           0x0400
#define PEF7071_AN_LPA_TAF_PS_ASYM          0x0800
#define PEF7071_AN_LPA_TAF_RES              0x1000
#define PEF7071_AN_LPA_SF                   0x001F
#define PEF7071_AN_LPA_SF_DEFAULT           0x0001

//Auto-Negotiation Expansion register
#define PEF7071_AN_EXP_RESD                 0xFFE0
#define PEF7071_AN_EXP_PDF                  0x0010
#define PEF7071_AN_EXP_LPNPC                0x0008
#define PEF7071_AN_EXP_NPC                  0x0004
#define PEF7071_AN_EXP_PR                   0x0002
#define PEF7071_AN_EXP_LPANC                0x0001

//Auto-Negotiation Next-Page Transmit register
#define PEF7071_AN_NPTX_NP                  0x8000
#define PEF7071_AN_NPTX_MP                  0x2000
#define PEF7071_AN_NPTX_ACK2                0x1000
#define PEF7071_AN_NPTX_TOGG                0x0800
#define PEF7071_AN_NPTX_MCF                 0x07FF

//Auto-Negotiation Link-Partner Received Next-Page register
#define PEF7071_AN_NPRX_NP                  0x8000
#define PEF7071_AN_NPRX_ACK                 0x4000
#define PEF7071_AN_NPRX_MP                  0x2000
#define PEF7071_AN_NPRX_ACK2                0x1000
#define PEF7071_AN_NPRX_TOGG                0x0800
#define PEF7071_AN_NPRX_MCF                 0x07FF

//Gigabit Control register
#define PEF7071_GCTRL_TM                    0xE000
#define PEF7071_GCTRL_MSEN                  0x1000
#define PEF7071_GCTRL_MS                    0x0800
#define PEF7071_GCTRL_MSPT                  0x0400
#define PEF7071_GCTRL_MBTFD                 0x0200
#define PEF7071_GCTRL_MBTHD                 0x0100

//Gigabit Status register
#define PEF7071_GSTAT_MSFAULT               0x8000
#define PEF7071_GSTAT_MSRES                 0x4000
#define PEF7071_GSTAT_LRXSTAT               0x2000
#define PEF7071_GSTAT_RRXSTAT               0x1000
#define PEF7071_GSTAT_MBTFD                 0x0800
#define PEF7071_GSTAT_MBTHD                 0x0400
#define PEF7071_GSTAT_IEC                   0x00FF

//MMD Access Control register
#define PEF7071_MMDCTRL_ACTYPE              0xC000
#define PEF7071_MMDCTRL_ACTYPE_ADDRESS      0x0000
#define PEF7071_MMDCTRL_ACTYPE_DATA         0x4000
#define PEF7071_MMDCTRL_ACTYPE_DATA_PI      0x8000
#define PEF7071_MMDCTRL_ACTYPE_DATA_PIWR    0xC000
#define PEF7071_MMDCTRL_RESH                0x3F00
#define PEF7071_MMDCTRL_RESL                0x00E0
#define PEF7071_MMDCTRL_DEVAD               0x001F

//MMD Access Data register
#define PEF7071_MMDDATA_ADDR_DATA           0xFFFF

//Extended Status register
#define PEF7071_XSTAT_MBXF                  0x8000
#define PEF7071_XSTAT_MBXH                  0x4000
#define PEF7071_XSTAT_MBTF                  0x2000
#define PEF7071_XSTAT_MBTH                  0x1000
#define PEF7071_XSTAT_RESH                  0x0F00
#define PEF7071_XSTAT_RESL                  0x00FF

//Physical Layer Performance Status register
#define PEF7071_PHYPHYPERF_FREQ             0xFF00
#define PEF7071_PHYPHYPERF_SNR              0x00F0
#define PEF7071_PHYPHYPERF_LEN              0x000F

//Physical Layer Status 1 register
#define PEF7071_PHYSTAT1_RESH               0xFE00
#define PEF7071_PHYSTAT1_LSADS              0x0100
#define PEF7071_PHYSTAT1_POLD               0x0080
#define PEF7071_PHYSTAT1_POLC               0x0040
#define PEF7071_PHYSTAT1_POLB               0x0020
#define PEF7071_PHYSTAT1_POLA               0x0010
#define PEF7071_PHYSTAT1_MDICD              0x0008
#define PEF7071_PHYSTAT1_MDIAB              0x0004
#define PEF7071_PHYSTAT1_RESL               0x0003

//Physical Layer Status 2 register
#define PEF7071_PHYSTAT2_RESD               0x8000
#define PEF7071_PHYSTAT2_SKEWD              0x7000
#define PEF7071_PHYSTAT2_RESC               0x0800
#define PEF7071_PHYSTAT2_SKEWC              0x0700
#define PEF7071_PHYSTAT2_RESB               0x0080
#define PEF7071_PHYSTAT2_SKEWB              0x0070
#define PEF7071_PHYSTAT2_RESA               0x0008
#define PEF7071_PHYSTAT2_SKEWA              0x0007

//Physical Layer Control 1 register
#define PEF7071_PHYCTL1_TLOOP               0xE000
#define PEF7071_PHYCTL1_TXOFF               0x1000
#define PEF7071_PHYCTL1_TXADJ               0x0F00
#define PEF7071_PHYCTL1_POLD                0x0080
#define PEF7071_PHYCTL1_POLC                0x0040
#define PEF7071_PHYCTL1_POLB                0x0020
#define PEF7071_PHYCTL1_POLA                0x0010
#define PEF7071_PHYCTL1_MDICD               0x0008
#define PEF7071_PHYCTL1_MDIAB               0x0004
#define PEF7071_PHYCTL1_TXEEE10             0x0002
#define PEF7071_PHYCTL1_AMDIX               0x0001

//Physical Layer Control 2 register
#define PEF7071_PHYCTL2_LSADS               0xC000
#define PEF7071_PHYCTL2_LSADS_OFF           0x0000
#define PEF7071_PHYCTL2_LSADS_ADS2          0x4000
#define PEF7071_PHYCTL2_LSADS_ADS3          0x8000
#define PEF7071_PHYCTL2_LSADS_ADS4          0xC000
#define PEF7071_PHYCTL2_RESH                0x3800
#define PEF7071_PHYCTL2_CLKSEL              0x0400
#define PEF7071_PHYCTL2_CLKSEL_CLK25M       0x0000
#define PEF7071_PHYCTL2_CLKSEL_CLK125M      0x0400
#define PEF7071_PHYCTL2_SDETP               0x0200
#define PEF7071_PHYCTL2_SDETP_LOWACTIVE     0x0000
#define PEF7071_PHYCTL2_SDETP_HIGHACTIVE    0x0200
#define PEF7071_PHYCTL2_STICKY              0x0100
#define PEF7071_PHYCTL2_RESL                0x00F0
#define PEF7071_PHYCTL2_ADCR                0x0008
#define PEF7071_PHYCTL2_ADCR_DEFAULT        0x0000
#define PEF7071_PHYCTL2_ADCR_BOOST          0x0008
#define PEF7071_PHYCTL2_PSCL                0x0004
#define PEF7071_PHYCTL2_ANPD                0x0002
#define PEF7071_PHYCTL2_LPI                 0x0001

//Error Counter register
#define PEF7071_ERRCNT_SEL                  0x0F00
#define PEF7071_ERRCNT_SEL_RXERR            0x0000
#define PEF7071_ERRCNT_SEL_RXACT            0x0100
#define PEF7071_ERRCNT_SEL_ESDERR           0x0200
#define PEF7071_ERRCNT_SEL_SSDERR           0x0300
#define PEF7071_ERRCNT_SEL_TXERR            0x0400
#define PEF7071_ERRCNT_SEL_TXACT            0x0500
#define PEF7071_ERRCNT_SEL_COL              0x0600
#define PEF7071_ERRCNT_COUNT                0x00FF

//EEPROM Control register
#define PEF7071_EECTRL_EESCAN               0x8000
#define PEF7071_EECTRL_EEAF                 0x4000
#define PEF7071_EECTRL_CSRDET               0x2000
#define PEF7071_EECTRL_EEDET                0x1000
#define PEF7071_EECTRL_SIZE                 0x0F00
#define PEF7071_EECTRL_SIZE_SIZE1K          0x0000
#define PEF7071_EECTRL_SIZE_SIZE2K          0x0100
#define PEF7071_EECTRL_SIZE_SIZE4K          0x0200
#define PEF7071_EECTRL_SIZE_SIZE8K          0x0300
#define PEF7071_EECTRL_SIZE_SIZE16K         0x0400
#define PEF7071_EECTRL_SIZE_SIZE32K         0x0500
#define PEF7071_EECTRL_SIZE_SIZE64K         0x0600
#define PEF7071_EECTRL_SIZE_SIZE128K        0x0700
#define PEF7071_EECTRL_SIZE_SIZE256K        0x0800
#define PEF7071_EECTRL_SIZE_SIZE512K        0x0900
#define PEF7071_EECTRL_SIZE_SIZE1024K       0x0A00
#define PEF7071_EECTRL_ADRMODE              0x0080
#define PEF7071_EECTRL_ADRMODE_MODE11       0x0000
#define PEF7071_EECTRL_ADRMODE_MODE16       0x0080
#define PEF7071_EECTRL_DADR                 0x0070
#define PEF7071_EECTRL_SPEED                0x000C
#define PEF7071_EECTRL_SPEED_FRQ_100KHZ     0x0000
#define PEF7071_EECTRL_SPEED_FRQ_400KHZ     0x0004
#define PEF7071_EECTRL_SPEED_FRQ_1_0MHZ     0x0008
#define PEF7071_EECTRL_SPEED_FRQ_3_4MHZ     0x000C
#define PEF7071_EECTRL_RDWR                 0x0002
#define PEF7071_EECTRL_EXEC                 0x0001

//Media-Independent Interface Control register
#define PEF7071_MIICTRL_RXCOFF              0x8000
#define PEF7071_MIICTRL_RXSKEW              0x7000
#define PEF7071_MIICTRL_RXSKEW_SKEW_0N0     0x0000
#define PEF7071_MIICTRL_RXSKEW_SKEW_0N5     0x1000
#define PEF7071_MIICTRL_RXSKEW_SKEW_1N0     0x2000
#define PEF7071_MIICTRL_RXSKEW_SKEW_1N5     0x3000
#define PEF7071_MIICTRL_RXSKEW_SKEW_2N0     0x4000
#define PEF7071_MIICTRL_RXSKEW_SKEW_2N5     0x5000
#define PEF7071_MIICTRL_RXSKEW_SKEW_3N0     0x6000
#define PEF7071_MIICTRL_RXSKEW_SKEW_3N5     0x7000
#define PEF7071_MIICTRL_V25_33              0x0800
#define PEF7071_MIICTRL_TXSKEW              0x0700
#define PEF7071_MIICTRL_TXSKEW_SKEW_0N0     0x0000
#define PEF7071_MIICTRL_TXSKEW_SKEW_0N5     0x0100
#define PEF7071_MIICTRL_TXSKEW_SKEW_1N0     0x0200
#define PEF7071_MIICTRL_TXSKEW_SKEW_1N5     0x0300
#define PEF7071_MIICTRL_TXSKEW_SKEW_2N0     0x0400
#define PEF7071_MIICTRL_TXSKEW_SKEW_2N5     0x0500
#define PEF7071_MIICTRL_TXSKEW_SKEW_3N0     0x0600
#define PEF7071_MIICTRL_TXSKEW_SKEW_3N5     0x0700
#define PEF7071_MIICTRL_CRS                 0x00C0
#define PEF7071_MIICTRL_FLOW                0x0030
#define PEF7071_MIICTRL_FLOW_COPPER         0x0000
#define PEF7071_MIICTRL_FLOW_CONVERTER      0x0030
#define PEF7071_MIICTRL_MODE                0x000F
#define PEF7071_MIICTRL_MODE_RGMII          0x0000
#define PEF7071_MIICTRL_MODE_SGMII          0x0001
#define PEF7071_MIICTRL_MODE_RMII           0x0002
#define PEF7071_MIICTRL_MODE_RTBI           0x0003
#define PEF7071_MIICTRL_MODE_GMII           0x0004
#define PEF7071_MIICTRL_MODE_TBI            0x0005
#define PEF7071_MIICTRL_MODE_SGMIINC        0x0006
#define PEF7071_MIICTRL_MODE_TEST           0x000F
#define PEF7071_MIICTRL_MODE_CONV_X2T1000   0x0000
#define PEF7071_MIICTRL_MODE_CONV_X2T1000A  0x0001

//Media-Independent Interface Status register
#define PEF7071_MIISTAT_RESH                0xFF00
#define PEF7071_MIISTAT_PHY                 0x00C0
#define PEF7071_MIISTAT_PHY_TP              0x0000
#define PEF7071_MIISTAT_PHY_FIBER           0x0040
#define PEF7071_MIISTAT_PHY_MII2            0x0080
#define PEF7071_MIISTAT_PHY_SGMII           0x00C0
#define PEF7071_MIISTAT_PS                  0x0030
#define PEF7071_MIISTAT_PS_NONE             0x0000
#define PEF7071_MIISTAT_PS_TX               0x0010
#define PEF7071_MIISTAT_PS_RX               0x0020
#define PEF7071_MIISTAT_PS_TXRX             0x0030
#define PEF7071_MIISTAT_DPX                 0x0008
#define PEF7071_MIISTAT_EEE                 0x0004
#define PEF7071_MIISTAT_EEE_OFF             0x0000
#define PEF7071_MIISTAT_EEE_ON              0x0004
#define PEF7071_MIISTAT_SPEED               0x0003
#define PEF7071_MIISTAT_SPEED_TEN           0x0000
#define PEF7071_MIISTAT_SPEED_FAST          0x0001
#define PEF7071_MIISTAT_SPEED_GIGA          0x0002
#define PEF7071_MIISTAT_SPEED_RES           0x0003

//Interrupt Mask register
#define PEF7071_IMASK_WOL                   0x8000
#define PEF7071_IMASK_MSRE                  0x4000
#define PEF7071_IMASK_NPRX                  0x2000
#define PEF7071_IMASK_NPTX                  0x1000
#define PEF7071_IMASK_ANE                   0x0800
#define PEF7071_IMASK_ANC                   0x0400
#define PEF7071_IMASK_RESH                  0x0300
#define PEF7071_IMASK_RESL                  0x00C0
#define PEF7071_IMASK_ADSC                  0x0020
#define PEF7071_IMASK_MDIPC                 0x0010
#define PEF7071_IMASK_MDIXC                 0x0008
#define PEF7071_IMASK_DXMC                  0x0004
#define PEF7071_IMASK_LSPC                  0x0002
#define PEF7071_IMASK_LSTC                  0x0001

//Interrupt Status register
#define PEF7071_ISTAT_WOL                   0x8000
#define PEF7071_ISTAT_MSRE                  0x4000
#define PEF7071_ISTAT_NPRX                  0x2000
#define PEF7071_ISTAT_NPTX                  0x1000
#define PEF7071_ISTAT_ANE                   0x0800
#define PEF7071_ISTAT_ANC                   0x0400
#define PEF7071_ISTAT_RESH                  0x0300
#define PEF7071_ISTAT_RESL                  0x00C0
#define PEF7071_ISTAT_ADSC                  0x0020
#define PEF7071_ISTAT_MDIPC                 0x0010
#define PEF7071_ISTAT_MDIXC                 0x0008
#define PEF7071_ISTAT_DXMC                  0x0004
#define PEF7071_ISTAT_LSPC                  0x0002
#define PEF7071_ISTAT_LSTC                  0x0001

//LED Control register
#define PEF7071_LED_RESH                    0xF000
#define PEF7071_LED_LED3EN                  0x0800
#define PEF7071_LED_LED2EN                  0x0400
#define PEF7071_LED_LED1EN                  0x0200
#define PEF7071_LED_LED0EN                  0x0100
#define PEF7071_LED_RESL                    0x00F0
#define PEF7071_LED_LED3DA                  0x0008
#define PEF7071_LED_LED3DA_OFF              0x0000
#define PEF7071_LED_LED3DA_ON               0x0008
#define PEF7071_LED_LED2DA                  0x0004
#define PEF7071_LED_LED2DA_OFF              0x0000
#define PEF7071_LED_LED2DA_ON               0x0004
#define PEF7071_LED_LED1DA                  0x0002
#define PEF7071_LED_LED1DA_OFF              0x0000
#define PEF7071_LED_LED1DA_ON               0x0002
#define PEF7071_LED_LED0DA                  0x0001
#define PEF7071_LED_LED0DA_OFF              0x0000
#define PEF7071_LED_LED0DA_ON               0x0001

//Test-Packet Generator Control register
#define PEF7071_TPGCTRL_RESH1               0xC000
#define PEF7071_TPGCTRL_MODE                0x2000
#define PEF7071_TPGCTRL_MODE_BURST          0x0000
#define PEF7071_TPGCTRL_MODE_SINGLE         0x2000
#define PEF7071_TPGCTRL_RESH0               0x1000
#define PEF7071_TPGCTRL_IPGL                0x0C00
#define PEF7071_TPGCTRL_IPGL_BT48           0x0000
#define PEF7071_TPGCTRL_IPGL_BT96           0x0400
#define PEF7071_TPGCTRL_IPGL_BT960          0x0800
#define PEF7071_TPGCTRL_IPGL_BT9600         0x0C00
#define PEF7071_TPGCTRL_TYPE                0x0300
#define PEF7071_TPGCTRL_TYPE_RANDOM         0x0000
#define PEF7071_TPGCTRL_TYPE_BYTEINC        0x0100
#define PEF7071_TPGCTRL_TYPE_PREDEF         0x0200
#define PEF7071_TPGCTRL_RESL1               0x0080
#define PEF7071_TPGCTRL_SIZE                0x0070
#define PEF7071_TPGCTRL_SIZE_B64            0x0000
#define PEF7071_TPGCTRL_SIZE_B128           0x0010
#define PEF7071_TPGCTRL_SIZE_B256           0x0020
#define PEF7071_TPGCTRL_SIZE_B512           0x0030
#define PEF7071_TPGCTRL_SIZE_B1024          0x0040
#define PEF7071_TPGCTRL_SIZE_B1518          0x0050
#define PEF7071_TPGCTRL_SIZE_B9600          0x0060
#define PEF7071_TPGCTRL_RESL0               0x000C
#define PEF7071_TPGCTRL_START               0x0002
#define PEF7071_TPGCTRL_EN                  0x0001

//Test-Packet Generator Data register
#define PEF7071_TPGDATA_DA                  0xF000
#define PEF7071_TPGDATA_SA                  0x0F00
#define PEF7071_TPGDATA_DATA                0x00FF

//Firmware Version register
#define PEF7071_FWV_REL                     0x8000
#define PEF7071_FWV_REL_TEST                0x0000
#define PEF7071_FWV_REL_RELEASE             0x8000
#define PEF7071_FWV_MAJOR                   0x7F00
#define PEF7071_FWV_MINOR                   0x00FF

//EEE Control 1 register
#define PEF7071_EEE_CTRL1_RXCKST            0x0400

//EEE Status 1 register
#define PEF7071_EEE_STAT1_TXLPI_RCVD        0x0800
#define PEF7071_EEE_STAT1_TXLPI_IND         0x0200
#define PEF7071_EEE_STAT1_RXLPI_IND         0x0100
#define PEF7071_EEE_STAT1_TXCKST            0x0040

//EEE Capability register
#define PEF7071_EEE_CAP_EEE_10GBKR          0x0040
#define PEF7071_EEE_CAP_EEE_10GBKX4         0x0020
#define PEF7071_EEE_CAP_EEE_1000BKX         0x0010
#define PEF7071_EEE_CAP_EEE_10GBT           0x0008
#define PEF7071_EEE_CAP_EEE_1000BT          0x0004
#define PEF7071_EEE_CAP_EEE_100BTX          0x0002

//EEE Wake Time Fault Count register
#define PEF7071_EEE_WAKERR_ERRCNT           0xFFFF

//EEE Auto-Negotiation Advertisement register
#define PEF7071_ANEGEEE_AN_ADV_EEE_10GBKR   0x0040
#define PEF7071_ANEGEEE_AN_ADV_EEE_10GBKX4  0x0020
#define PEF7071_ANEGEEE_AN_ADV_EEE_1000BKX  0x0010
#define PEF7071_ANEGEEE_AN_ADV_EEE_10GBT    0x0008
#define PEF7071_ANEGEEE_AN_ADV_EEE_1000BT   0x0004
#define PEF7071_ANEGEEE_AN_ADV_EEE_100BTX   0x0002

//EEE Auto-Negotiation Link-Partner Advertisement register
#define PEF7071_EEE_AN_LPADV_EEE_10GBKR     0x0040
#define PEF7071_EEE_AN_LPADV_EEE_10GBKX4    0x0020
#define PEF7071_EEE_AN_LPADV_EEE_1000BKX    0x0010
#define PEF7071_EEE_AN_LPADV_EEE_10GBT      0x0008
#define PEF7071_EEE_AN_LPADV_EEE_1000BT     0x0004
#define PEF7071_EEE_AN_LPADV_EEE_100BTX     0x0002

//EEPROM Content register
#define PEF7071_EEPROM_DATA                 0x00FF

//LED Configuration H register
#define PEF7071_LEDCH_FBF                   0x00C0
#define PEF7071_LEDCH_FBF_F02HZ             0x0000
#define PEF7071_LEDCH_FBF_F04HZ             0x0040
#define PEF7071_LEDCH_FBF_F08HZ             0x0080
#define PEF7071_LEDCH_FBF_F16HZ             0x00C0
#define PEF7071_LEDCH_SBF                   0x0030
#define PEF7071_LEDCH_SBF_F02HZ             0x0000
#define PEF7071_LEDCH_SBF_F04HZ             0x0010
#define PEF7071_LEDCH_SBF_F08HZ             0x0020
#define PEF7071_LEDCH_SBF_F16HZ             0x0030
#define PEF7071_LEDCH_NACS                  0x0007
#define PEF7071_LEDCH_NACS_NONE             0x0000
#define PEF7071_LEDCH_NACS_LINK             0x0001
#define PEF7071_LEDCH_NACS_PDOWN            0x0002
#define PEF7071_LEDCH_NACS_EEE              0x0003
#define PEF7071_LEDCH_NACS_ANEG             0x0004
#define PEF7071_LEDCH_NACS_ABIST            0x0005
#define PEF7071_LEDCH_NACS_CDIAG            0x0006
#define PEF7071_LEDCH_NACS_TEST             0x0007

//LED Configuration L register
#define PEF7071_LEDCL_SCAN                  0x0070
#define PEF7071_LEDCL_SCAN_NONE             0x0000
#define PEF7071_LEDCL_SCAN_LINK             0x0010
#define PEF7071_LEDCL_SCAN_PDOWN            0x0020
#define PEF7071_LEDCL_SCAN_EEE              0x0030
#define PEF7071_LEDCL_SCAN_ANEG             0x0040
#define PEF7071_LEDCL_SCAN_ABIST            0x0050
#define PEF7071_LEDCL_SCAN_CDIAG            0x0060
#define PEF7071_LEDCL_SCAN_TEST             0x0070
#define PEF7071_LEDCL_CBLINK                0x0007
#define PEF7071_LEDCL_CBLINK_NONE           0x0000
#define PEF7071_LEDCL_CBLINK_LINK           0x0001
#define PEF7071_LEDCL_CBLINK_PDOWN          0x0002
#define PEF7071_LEDCL_CBLINK_EEE            0x0003
#define PEF7071_LEDCL_CBLINK_ANEG           0x0004
#define PEF7071_LEDCL_CBLINK_ABIST          0x0005
#define PEF7071_LEDCL_CBLINK_CDIAG          0x0006
#define PEF7071_LEDCL_CBLINK_TEST           0x0007

//Configuration for LED Pin 0 H register
#define PEF7071_LED0H_CON                   0x00F0
#define PEF7071_LED0H_CON_NONE              0x0000
#define PEF7071_LED0H_CON_LINK10            0x0010
#define PEF7071_LED0H_CON_LINK100           0x0020
#define PEF7071_LED0H_CON_LINK10X           0x0030
#define PEF7071_LED0H_CON_LINK1000          0x0040
#define PEF7071_LED0H_CON_LINK10_0          0x0050
#define PEF7071_LED0H_CON_LINK100X          0x0060
#define PEF7071_LED0H_CON_LINK10XX          0x0070
#define PEF7071_LED0H_CON_PDOWN             0x0080
#define PEF7071_LED0H_CON_EEE               0x0090
#define PEF7071_LED0H_CON_ANEG              0x00A0
#define PEF7071_LED0H_CON_ABIST             0x00B0
#define PEF7071_LED0H_CON_CDIAG             0x00C0
#define PEF7071_LED0H_CON_COPPER            0x00D0
#define PEF7071_LED0H_CON_FIBER             0x00E0
#define PEF7071_LED0H_BLINKF                0x000F
#define PEF7071_LED0H_BLINKF_NONE           0x0000
#define PEF7071_LED0H_BLINKF_LINK10         0x0001
#define PEF7071_LED0H_BLINKF_LINK100        0x0002
#define PEF7071_LED0H_BLINKF_LINK10X        0x0003
#define PEF7071_LED0H_BLINKF_LINK1000       0x0004
#define PEF7071_LED0H_BLINKF_LINK10_0       0x0005
#define PEF7071_LED0H_BLINKF_LINK100X       0x0006
#define PEF7071_LED0H_BLINKF_LINK10XX       0x0007
#define PEF7071_LED0H_BLINKF_PDOWN          0x0008
#define PEF7071_LED0H_BLINKF_EEE            0x0009
#define PEF7071_LED0H_BLINKF_ANEG           0x000A
#define PEF7071_LED0H_BLINKF_ABIST          0x000B
#define PEF7071_LED0H_BLINKF_CDIAG          0x000C

//Configuration for LED Pin 0 L register
#define PEF7071_LED0L_BLINKS                0x00F0
#define PEF7071_LED0L_BLINKS_NONE           0x0000
#define PEF7071_LED0L_BLINKS_LINK10         0x0010
#define PEF7071_LED0L_BLINKS_LINK100        0x0020
#define PEF7071_LED0L_BLINKS_LINK10X        0x0030
#define PEF7071_LED0L_BLINKS_LINK1000       0x0040
#define PEF7071_LED0L_BLINKS_LINK10_0       0x0050
#define PEF7071_LED0L_BLINKS_LINK100X       0x0060
#define PEF7071_LED0L_BLINKS_LINK10XX       0x0070
#define PEF7071_LED0L_BLINKS_PDOWN          0x0080
#define PEF7071_LED0L_BLINKS_EEE            0x0090
#define PEF7071_LED0L_BLINKS_ANEG           0x00A0
#define PEF7071_LED0L_BLINKS_ABIST          0x00B0
#define PEF7071_LED0L_BLINKS_CDIAG          0x00C0
#define PEF7071_LED0L_PULSE                 0x000F
#define PEF7071_LED0L_PULSE_NONE            0x0000
#define PEF7071_LED0L_PULSE_TXACT           0x0001
#define PEF7071_LED0L_PULSE_RXACT           0x0002
#define PEF7071_LED0L_PULSE_COL             0x0004

//Configuration for LED Pin 1 H register
#define PEF7071_LED1H_CON                   0x00F0
#define PEF7071_LED1H_CON_NONE              0x0000
#define PEF7071_LED1H_CON_LINK10            0x0010
#define PEF7071_LED1H_CON_LINK100           0x0020
#define PEF7071_LED1H_CON_LINK10X           0x0030
#define PEF7071_LED1H_CON_LINK1000          0x0040
#define PEF7071_LED1H_CON_LINK10_0          0x0050
#define PEF7071_LED1H_CON_LINK100X          0x0060
#define PEF7071_LED1H_CON_LINK10XX          0x0070
#define PEF7071_LED1H_CON_PDOWN             0x0080
#define PEF7071_LED1H_CON_EEE               0x0090
#define PEF7071_LED1H_CON_ANEG              0x00A0
#define PEF7071_LED1H_CON_ABIST             0x00B0
#define PEF7071_LED1H_CON_CDIAG             0x00C0
#define PEF7071_LED1H_CON_COPPER            0x00D0
#define PEF7071_LED1H_CON_FIBER             0x00E0
#define PEF7071_LED1H_BLINKF                0x000F
#define PEF7071_LED1H_BLINKF_NONE           0x0000
#define PEF7071_LED1H_BLINKF_LINK10         0x0001
#define PEF7071_LED1H_BLINKF_LINK100        0x0002
#define PEF7071_LED1H_BLINKF_LINK10X        0x0003
#define PEF7071_LED1H_BLINKF_LINK1000       0x0004
#define PEF7071_LED1H_BLINKF_LINK10_0       0x0005
#define PEF7071_LED1H_BLINKF_LINK100X       0x0006
#define PEF7071_LED1H_BLINKF_LINK10XX       0x0007
#define PEF7071_LED1H_BLINKF_PDOWN          0x0008
#define PEF7071_LED1H_BLINKF_EEE            0x0009
#define PEF7071_LED1H_BLINKF_ANEG           0x000A
#define PEF7071_LED1H_BLINKF_ABIST          0x000B
#define PEF7071_LED1H_BLINKF_CDIAG          0x000C

//Configuration for LED Pin 1 L register
#define PEF7071_LED1L_BLINKS                0x00F0
#define PEF7071_LED1L_BLINKS_NONE           0x0000
#define PEF7071_LED1L_BLINKS_LINK10         0x0010
#define PEF7071_LED1L_BLINKS_LINK100        0x0020
#define PEF7071_LED1L_BLINKS_LINK10X        0x0030
#define PEF7071_LED1L_BLINKS_LINK1000       0x0040
#define PEF7071_LED1L_BLINKS_LINK10_0       0x0050
#define PEF7071_LED1L_BLINKS_LINK100X       0x0060
#define PEF7071_LED1L_BLINKS_LINK10XX       0x0070
#define PEF7071_LED1L_BLINKS_PDOWN          0x0080
#define PEF7071_LED1L_BLINKS_EEE            0x0090
#define PEF7071_LED1L_BLINKS_ANEG           0x00A0
#define PEF7071_LED1L_BLINKS_ABIST          0x00B0
#define PEF7071_LED1L_BLINKS_CDIAG          0x00C0
#define PEF7071_LED1L_PULSE                 0x000F
#define PEF7071_LED1L_PULSE_NONE            0x0000
#define PEF7071_LED1L_PULSE_TXACT           0x0001
#define PEF7071_LED1L_PULSE_RXACT           0x0002
#define PEF7071_LED1L_PULSE_COL             0x0004

//Configuration for LED Pin 2 H register
#define PEF7071_LED2H_CON                   0x00F0
#define PEF7071_LED2H_CON_NONE              0x0000
#define PEF7071_LED2H_CON_LINK10            0x0010
#define PEF7071_LED2H_CON_LINK100           0x0020
#define PEF7071_LED2H_CON_LINK10X           0x0030
#define PEF7071_LED2H_CON_LINK1000          0x0040
#define PEF7071_LED2H_CON_LINK10_0          0x0050
#define PEF7071_LED2H_CON_LINK100X          0x0060
#define PEF7071_LED2H_CON_LINK10XX          0x0070
#define PEF7071_LED2H_CON_PDOWN             0x0080
#define PEF7071_LED2H_CON_EEE               0x0090
#define PEF7071_LED2H_CON_ANEG              0x00A0
#define PEF7071_LED2H_CON_ABIST             0x00B0
#define PEF7071_LED2H_CON_CDIAG             0x00C0
#define PEF7071_LED2H_CON_COPPER            0x00D0
#define PEF7071_LED2H_CON_FIBER             0x00E0
#define PEF7071_LED2H_BLINKF                0x000F
#define PEF7071_LED2H_BLINKF_NONE           0x0000
#define PEF7071_LED2H_BLINKF_LINK10         0x0001
#define PEF7071_LED2H_BLINKF_LINK100        0x0002
#define PEF7071_LED2H_BLINKF_LINK10X        0x0003
#define PEF7071_LED2H_BLINKF_LINK1000       0x0004
#define PEF7071_LED2H_BLINKF_LINK10_0       0x0005
#define PEF7071_LED2H_BLINKF_LINK100X       0x0006
#define PEF7071_LED2H_BLINKF_LINK10XX       0x0007
#define PEF7071_LED2H_BLINKF_PDOWN          0x0008
#define PEF7071_LED2H_BLINKF_EEE            0x0009
#define PEF7071_LED2H_BLINKF_ANEG           0x000A
#define PEF7071_LED2H_BLINKF_ABIST          0x000B
#define PEF7071_LED2H_BLINKF_CDIAG          0x000C

//Configuration for LED Pin 2 L register
#define PEF7071_LED2L_BLINKS                0x00F0
#define PEF7071_LED2L_BLINKS_NONE           0x0000
#define PEF7071_LED2L_BLINKS_LINK10         0x0010
#define PEF7071_LED2L_BLINKS_LINK100        0x0020
#define PEF7071_LED2L_BLINKS_LINK10X        0x0030
#define PEF7071_LED2L_BLINKS_LINK1000       0x0040
#define PEF7071_LED2L_BLINKS_LINK10_0       0x0050
#define PEF7071_LED2L_BLINKS_LINK100X       0x0060
#define PEF7071_LED2L_BLINKS_LINK10XX       0x0070
#define PEF7071_LED2L_BLINKS_PDOWN          0x0080
#define PEF7071_LED2L_BLINKS_EEE            0x0090
#define PEF7071_LED2L_BLINKS_ANEG           0x00A0
#define PEF7071_LED2L_BLINKS_ABIST          0x00B0
#define PEF7071_LED2L_BLINKS_CDIAG          0x00C0
#define PEF7071_LED2L_PULSE                 0x000F
#define PEF7071_LED2L_PULSE_NONE            0x0000
#define PEF7071_LED2L_PULSE_TXACT           0x0001
#define PEF7071_LED2L_PULSE_RXACT           0x0002
#define PEF7071_LED2L_PULSE_COL             0x0004

//EEE Link-Fail Counter H register
#define PEF7071_EEE_RXERR_LINK_FAIL_H_VAL   0x00FF

//EEE Link-Fail Counter L register
#define PEF7071_EEE_RXERR_LINK_FAIL_L_VAL   0x00FF

//MII2 Control register
#define PEF7071_MII2CTRL_RXSKEW             0x0070
#define PEF7071_MII2CTRL_RXSKEW_SKEW_0N0    0x0000
#define PEF7071_MII2CTRL_RXSKEW_SKEW_0N5    0x0010
#define PEF7071_MII2CTRL_RXSKEW_SKEW_1N0    0x0020
#define PEF7071_MII2CTRL_RXSKEW_SKEW_1N5    0x0030
#define PEF7071_MII2CTRL_RXSKEW_SKEW_2N0    0x0040
#define PEF7071_MII2CTRL_RXSKEW_SKEW_2N5    0x0050
#define PEF7071_MII2CTRL_RXSKEW_SKEW_3N0    0x0060
#define PEF7071_MII2CTRL_RXSKEW_SKEW_3N5    0x0070
#define PEF7071_MII2CTRL_TXSKEW             0x0007
#define PEF7071_MII2CTRL_TXSKEW_SKEW_0N0    0x0000
#define PEF7071_MII2CTRL_TXSKEW_SKEW_0N5    0x0001
#define PEF7071_MII2CTRL_TXSKEW_SKEW_1N0    0x0002
#define PEF7071_MII2CTRL_TXSKEW_SKEW_1N5    0x0003
#define PEF7071_MII2CTRL_TXSKEW_SKEW_2N0    0x0004
#define PEF7071_MII2CTRL_TXSKEW_SKEW_2N5    0x0005
#define PEF7071_MII2CTRL_TXSKEW_SKEW_3N0    0x0006
#define PEF7071_MII2CTRL_TXSKEW_SKEW_3N5    0x0007

//Legacy LPI Configuration 0 register
#define PEF7071_LEG_LPI_CFG0_HOLDOFF_100BT  0x00FF

//Legacy LPI Configuration 1 register
#define PEF7071_LEG_LPI_CFG1_HOLDOFF_1000BT 0x00FF

//Wake-On-LAN Control register
#define PEF7071_WOLCTRL_SPWD_EN             0x0004
#define PEF7071_WOLCTRL_RES                 0x0002
#define PEF7071_WOLCTRL_EN                  0x0001

//Wake-On-LAN Address Byte 0 register
#define PEF7071_WOLAD0_VAL                  0x00FF

//Wake-On-LAN Address Byte 1 register
#define PEF7071_WOLAD1_VAL                  0x00FF

//Wake-On-LAN Address Byte 2 register
#define PEF7071_WOLAD2_VAL                  0x00FF

//Wake-On-LAN Address Byte 3 register
#define PEF7071_WOLAD3_VAL                  0x00FF

//Wake-On-LAN Address Byte 4 register
#define PEF7071_WOLAD4_VAL                  0x00FF

//Wake-On-LAN Address Byte 5 register
#define PEF7071_WOLAD5_VAL                  0x00FF

//Wake-On-LAN SecureON Password Byte 0 register
#define PEF7071_WOLPW0_VAL                  0x00FF

//Wake-On-LAN SecureON Password Byte 1 register
#define PEF7071_WOLPW1_VAL                  0x00FF

//Wake-On-LAN SecureON Password Byte 2 register
#define PEF7071_WOLPW2_VAL                  0x00FF

//Wake-On-LAN SecureON Password Byte 3 register
#define PEF7071_WOLPW3_VAL                  0x00FF

//Wake-On-LAN SecureON Password Byte 4 register
#define PEF7071_WOLPW4_VAL                  0x00FF

//Wake-On-LAN SecureON Password Byte 5 register
#define PEF7071_WOLPW5_VAL                  0x00FF

//Legacy LPI Configuration 2 register
#define PEF7071_LEG_LPI_CFG2_IPG            0x00FF
#define PEF7071_LEG_LPI_CFG2_IPG_DEFAULT    0x000E

//Legacy LPI Configuration 3 register
#define PEF7071_LEG_LPI_CFG3_IDLE           0x00FF
#define PEF7071_LEG_LPI_CFG3_IDLE_DEFAULT   0x0040

//C++ guard
#ifdef __cplusplus
extern "C" {
#endif

//PEF7071 Ethernet PHY driver
extern const PhyDriver pef7071PhyDriver;

//PEF7071 related functions
error_t pef7071Init(NetInterface *interface);

void pef7071Tick(NetInterface *interface);

void pef7071EnableIrq(NetInterface *interface);
void pef7071DisableIrq(NetInterface *interface);

void pef7071EventHandler(NetInterface *interface);

void pef7071WritePhyReg(NetInterface *interface, uint8_t address,
   uint16_t data);

uint16_t pef7071ReadPhyReg(NetInterface *interface, uint8_t address);

void pef7071DumpPhyReg(NetInterface *interface);

//C++ guard
#ifdef __cplusplus
}
#endif

#endif
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   value |= TJA1100_CONFIG1_MII_MODE_RMII_25MHZ_XTAL;
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
#define TJA1100_BASIC_CTRL                            0x00
#define TJA1100_BASIC_STAT                            0x01
#define TJA1100_PHY_ID1                               0x02
#define TJA1100_PHY_ID2                               0x03
#define TJA1100_EXTENDED_STAT                         0x0F
#define TJA1100_PHY_ID3                               0x10
#define TJA1100_EXTENDED_CTRL                         0x11
#define TJA1100_CONFIG1                               0x12
#define TJA1100_CONFIG2                               0x13
#define TJA1100_SYM_ERR_COUNTER                       0x14
#define TJA1100_INT_SRC                               0x15
#define TJA1100_INT_EN                                0x16
#define TJA1100_COMM_STAT                             0x17
#define TJA1100_GENERAL_STAT                          0x18
#define TJA1100_EXTERNAL_STAT                         0x19
#define TJA1100_LINK_FAIL_COUNTER                     0x1A
#define TJA1100_BASIC_CTRL_RESET                      0x8000
#define TJA1100_BASIC_CTRL_LOOPBACK                   0x4000
#define TJA1100_BASIC_CTRL_SPEED_SEL_LSB              0x2000
#define TJA1100_BASIC_CTRL_AUTONEG_EN                 0x1000
#define TJA1100_BASIC_CTRL_POWER_DOWN                 0x0800
#define TJA1100_BASIC_CTRL_ISOLATE                    0x0400
#define TJA1100_BASIC_CTRL_RE_AUTONEG                 0x0200
#define TJA1100_BASIC_CTRL_DUPLEX_MODE                0x0100
#define TJA1100_BASIC_CTRL_COL_TEST                   0x0080
#define TJA1100_BASIC_CTRL_SPEED_SEL_MSB              0x0040
#define TJA1100_BASIC_CTRL_UNIDIRECT_EN               0x0020
#define TJA1100_BASIC_STAT_100BT4                     0x8000
#define TJA1100_BASIC_STAT_100BTX_FD                  0x4000
#define TJA1100_BASIC_STAT_100BTX_HD                  0x2000
#define TJA1100_BASIC_STAT_10BT_FD                    0x1000
#define TJA1100_BASIC_STAT_10BT_HD                    0x0800
#define TJA1100_BASIC_STAT_100BT2_FD                  0x0400
#define TJA1100_BASIC_STAT_100BT2_HD                  0x0200
#define TJA1100_BASIC_STAT_EXTENDED_STATUS            0x0100
#define TJA1100_BASIC_STAT_UNIDIRECT_ABILITY          0x0080
#define TJA1100_BASIC_STAT_MF_PREAMBLE_SUPPR          0x0040
#define TJA1100_BASIC_STAT_AUTONEG_COMPLETE           0x0020
#define TJA1100_BASIC_STAT_REMOTE_FAULT               0x0010
#define TJA1100_BASIC_STAT_AUTONEG_ABILITY            0x0008
#define TJA1100_BASIC_STAT_LINK_STATUS                0x0004
#define TJA1100_BASIC_STAT_JABBER_DETECT              0x0002
#define TJA1100_BASIC_STAT_EXTENDED_CAPABILITY        0x0001
#define TJA1100_PHY_ID1_OUI_MSB                       0xFFFF
#define TJA1100_PHY_ID1_OUI_MSB_DEFAULT               0x0180
#define TJA1100_PHY_ID2_OUI_LSB                       0xFC00
#define TJA1100_PHY_ID2_OUI_LSB_DEFAULT               0xDC00
#define TJA1100_PHY_ID2_TYPE_NO                       0x03F0
#define TJA1100_PHY_ID2_TYPE_NO_DEFAULT               0x0040
#define TJA1100_PHY_ID2_REVISION_NO                   0x000F
#define TJA1100_EXTENDED_STAT_1000BX_FD               0x8000
#define TJA1100_EXTENDED_STAT_1000BX_HD               0x4000
#define TJA1100_EXTENDED_STAT_1000BT_FD               0x2000
#define TJA1100_EXTENDED_STAT_1000BT_HD               0x1000
#define TJA1100_EXTENDED_STAT_100BT1                  0x0080
#define TJA1100_EXTENDED_STAT_1000BT1                 0x0040
#define TJA1100_PHY_ID3_VERSION_NO                    0x00FF
#define TJA1100_EXTENDED_CTRL_LINK_CONTROL            0x8000
#define TJA1100_EXTENDED_CTRL_POWER_MODE              0x7800
#define TJA1100_EXTENDED_CTRL_POWER_MODE_NO_CHANGE    0x0000
#define TJA1100_EXTENDED_CTRL_POWER_MODE_NORMAL       0x1800
#define TJA1100_EXTENDED_CTRL_POWER_MODE_SLEEP_REQ    0x5800
#define TJA1100_EXTENDED_CTRL_POWER_MODE_STANDBY      0x6000
#define TJA1100_EXTENDED_CTRL_SLAVE_JITTER_TEST       0x0400
#define TJA1100_EXTENDED_CTRL_TRAINING_RESTART        0x0200
#define TJA1100_EXTENDED_CTRL_TEST_MODE               0x01C0
#define TJA1100_EXTENDED_CTRL_TEST_MODE_0             0x0000
#define TJA1100_EXTENDED_CTRL_TEST_MODE_1             0x0040
#define TJA1100_EXTENDED_CTRL_TEST_MODE_2             0x0080
#define TJA1100_EXTENDED_CTRL_TEST_MODE_3             0x00C0
#define TJA1100_EXTENDED_CTRL_TEST_MODE_4             0x0100
#define TJA1100_EXTENDED_CTRL_TEST_MODE_5             0x0140
#define TJA1100_EXTENDED_CTRL_TEST_MODE_6             0x0180
#define TJA1100_EXTENDED_CTRL_CABLE_TEST              0x0020
#define TJA1100_EXTENDED_CTRL_LOOPBACK_MODE           0x0018
#define TJA1100_EXTENDED_CTRL_LOOPBACK_MODE_INTERNAL  0x0000
#define TJA1100_EXTENDED_CTRL_LOOPBACK_MODE_EXTERNAL  0x0008
#define TJA1100_EXTENDED_CTRL_LOOPBACK_MODE_REMOTE    0x0018
#define TJA1100_EXTENDED_CTRL_CONFIG_EN               0x0004
#define TJA1100_EXTENDED_CTRL_CONFIG_INH              0x0002
#define TJA1100_EXTENDED_CTRL_WAKE_REQUEST            0x0001
#define TJA1100_CONFIG1_MASTER_SLAVE                  0x8000
#define TJA1100_CONFIG1_AUTO_OP                       0x4000
#define TJA1100_CONFIG1_LINK_LENGTH                   0x2000
#define TJA1100_CONFIG1_TX_AMPLITUDE                  0x0C00
#define TJA1100_CONFIG1_TX_AMPLITUDE_500MV            0x0000
#define TJA1100_CONFIG1_TX_AMPLITUDE_750MV            0x0400
#define TJA1100_CONFIG1_TX_AMPLITUDE_1000MV           0x0800
#define TJA1100_CONFIG1_TX_AMPLITUDE_1250MV           0x0C00
#define TJA1100_CONFIG1_MII_MODE                      0x0300
#define TJA1100_CONFIG1_MII_MODE_MII                  0x0000
#define TJA1100_CONFIG1_MII_MODE_RMII_50MHZ_REFCLK_IN 0x0100
#define TJA1100_CONFIG1_MII_MODE_RMII_25MHZ_XTAL      0x0200
#define TJA1100_CONFIG1_MII_MODE_REV_MII              0x0300
#define TJA1100_CONFIG1_MII_DRIVER                    0x0080
#define TJA1100_CONFIG1_MII_DRIVER_STANDARD           0x0000
#define TJA1100_CONFIG1_MII_DRIVER_REDUCED            0x0080
#define TJA1100_CONFIG1_LED_MODE                      0x0030
#define TJA1100_CONFIG1_LED_MODE_LINK_UP              0x0000
#define TJA1100_CONFIG1_LED_MODE_FRAME_RX             0x0010
#define TJA1100_CONFIG1_LED_MODE_SYM_ERR              0x0020
#define TJA1100_CONFIG1_LED_MODE_CRS                  0x0030
#define TJA1100_CONFIG1_LED_ENABLE                    0x0008
#define TJA1100_CONFIG1_CONFIG_WAKE                   0x0004
#define TJA1100_CONFIG1_AUTO_PWD                      0x0002
#define TJA1100_CONFIG2_PHYAD                         0xF800
#define TJA1100_CONFIG2_SQI_AVERAGING                 0x0600
#define TJA1100_CONFIG2_SQI_AVERAGING_32_SYMBOLS      0x0000
#define TJA1100_CONFIG2_SQI_AVERAGING_64_SYMBOLS      0x0200
#define TJA1100_CONFIG2_SQI_AVERAGING_128_SYMBOLS     0x0400
#define TJA1100_CONFIG2_SQI_AVERAGING_256_SYMBOLS     0x0600
#define TJA1100_CONFIG2_SQI_WLIMIT                    0x01C0
#define TJA1100_CONFIG2_SQI_WLIMIT_NONE               0x0000
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_A            0x0040
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_B            0x0080
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_C            0x00C0
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_D            0x0100
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_E            0x0140
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_F            0x0180
#define TJA1100_CONFIG2_SQI_WLIMIT_CLASS_G            0x01C0
#define TJA1100_CONFIG2_SQI_FAILLIMIT                 0x0038
#define TJA1100_CONFIG2_SQI_FAILLIMIT_NONE            0x0000
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_A         0x0008
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_B         0x0010
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_C         0x0018
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_D         0x0020
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_E         0x0028
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_F         0x0030
#define TJA1100_CONFIG2_SQI_FAILLIMIT_CLASS_G         0x0038
#define TJA1100_CONFIG2_JUMBO_ENABLE                  0x0004
#define TJA1100_CONFIG2_SLEEP_REQUEST_TO              0x0003
#define TJA1100_CONFIG2_SLEEP_REQUEST_TO_0_4MS        0x0000
#define TJA1100_CONFIG2_SLEEP_REQUEST_TO_1MS          0x0001
#define TJA1100_CONFIG2_SLEEP_REQUEST_TO_4MS          0x0002
#define TJA1100_CONFIG2_SLEEP_REQUEST_TO_16MS         0x0003
#define TJA1100_SYM_ERR_COUNTER_SYM_ERR_CNT           0xFFFF
#define TJA1100_INT_SRC_PWON                          0x8000
#define TJA1100_INT_SRC_WAKEUP                        0x4000
#define TJA1100_INT_SRC_PHY_INIT_FAIL                 0x0800
#define TJA1100_INT_SRC_LINK_STATUS_FAIL              0x0400
#define TJA1100_INT_SRC_LINK_STATUS_UP                0x0200
#define TJA1100_INT_SRC_SYM_ERR                       0x0100
#define TJA1100_INT_SRC_TRAINING_FAILED               0x0080
#define TJA1100_INT_SRC_SQI_WARNING                   0x0040
#define TJA1100_INT_SRC_CONTROL_ERR                   0x0020
#define TJA1100_INT_SRC_UV_ERR                        0x0008
#define TJA1100_INT_SRC_UV_RECOVERY                   0x0004
#define TJA1100_INT_SRC_TEMP_ERR                      0x0002
#define TJA1100_INT_SRC_SLEEP_ABORT                   0x0001
#define TJA1100_INT_EN_PWON                           0x8000
#define TJA1100_INT_EN_WAKEUP                         0x4000
#define TJA1100_INT_EN_PHY_INIT_FAIL                  0x0800
#define TJA1100_INT_EN_LINK_STATUS_FAIL               0x0400
#define TJA1100_INT_EN_LINK_STATUS_UP                 0x0200
#define TJA1100_INT_EN_SYM_ERR                        0x0100
#define TJA1100_INT_EN_TRAINING_FAILED                0x0080
#define TJA1100_INT_EN_SQI_WARNING                    0x0040
#define TJA1100_INT_EN_CONTROL_ERR                    0x0020
#define TJA1100_INT_EN_UV_ERR                         0x0008
#define TJA1100_INT_EN_UV_RECOVERY                    0x0004
#define TJA1100_INT_EN_TEMP_ERR                       0x0002
#define TJA1100_INT_EN_SLEEP_ABORT                    0x0001
#define TJA1100_COMM_STAT_LINK_UP                     0x8000
#define TJA1100_COMM_STAT_TX_MODE                     0x6000
#define TJA1100_COMM_STAT_TX_MODE_DISABLED            0x0000
#define TJA1100_COMM_STAT_TX_MODE_SEND_N              0x2000
#define TJA1100_COMM_STAT_TX_MODE_SEND_I              0x4000
#define TJA1100_COMM_STAT_TX_MODE_SEND_Z              0x6000
#define TJA1100_COMM_STAT_LOC_RCVR_STATUS             0x1000
#define TJA1100_COMM_STAT_REM_RCVR_STATUS             0x0800
#define TJA1100_COMM_STAT_SCR_LOCKED                  0x0400
#define TJA1100_COMM_STAT_SSD_ERR                     0x0200
#define TJA1100_COMM_STAT_ESD_ERR                     0x0100
#define TJA1100_COMM_STAT_SQI                         0x00E0
#define TJA1100_COMM_STAT_SQI_WORSE_THAN_CLASS_A      0x0000
#define TJA1100_COMM_STAT_SQI_CLASS_A                 0x0020
#define TJA1100_COMM_STAT_SQI_CLASS_B                 0x0040
#define TJA1100_COMM_STAT_SQI_CLASS_C                 0x0060
#define TJA1100_COMM_STAT_SQI_CLASS_D                 0x0080
#define TJA1100_COMM_STAT_SQI_CLASS_E                 0x00A0
#define TJA1100_COMM_STAT_SQI_CLASS_F                 0x00C0
#define TJA1100_COMM_STAT_SQI_CLASS_G                 0x00E0
#define TJA1100_COMM_STAT_RECEIVE_ERR                 0x0010
#define TJA1100_COMM_STAT_TRANSMIT_ERR                0x0008
#define TJA1100_COMM_STAT_PHY_STATE                   0x0007
#define TJA1100_COMM_STAT_PHY_STATE_IDLE              0x0000
#define TJA1100_COMM_STAT_PHY_STATE_INITIALIZING      0x0001
#define TJA1100_COMM_STAT_PHY_STATE_CONFIGURED        0x0002
#define TJA1100_COMM_STAT_PHY_STATE_OFFLINE           0x0003
#define TJA1100_COMM_STAT_PHY_STATE_ACTIVE            0x0004
#define TJA1100_COMM_STAT_PHY_STATE_ISOLATE           0x0005
#define TJA1100_COMM_STAT_PHY_STATE_CABLE_TEST        0x0006
#define TJA1100_COMM_STAT_PHY_STATE_TEST_MODE         0x0007
#define TJA1100_GENERAL_STAT_INT_STATUS               0x8000
#define TJA1100_GENERAL_STAT_PLL_LOCKED               0x4000
#define TJA1100_GENERAL_STAT_LOCAL_WU                 0x2000
#define TJA1100_GENERAL_STAT_REMOTE_WU                0x1000
#define TJA1100_GENERAL_STAT_DATA_DET_WU              0x0800
#define TJA1100_GENERAL_STAT_EN_STATUS                0x0400
#define TJA1100_GENERAL_STAT_RESET_STATUS             0x0200
#define TJA1100_GENERAL_STAT_LINKFAIL_CNT             0x00F8
#define TJA1100_EXTERNAL_STAT_UV_VDDA_3V3             0x4000
#define TJA1100_EXTERNAL_STAT_UV_VDDD_1V8             0x2000
#define TJA1100_EXTERNAL_STAT_UV_VDDA_1V8             0x1000
#define TJA1100_EXTERNAL_STAT_UV_VDDIO                0x0800
#define TJA1100_EXTERNAL_STAT_TEMP_HIGH               0x0400
#define TJA1100_EXTERNAL_STAT_TEMP_WARN               0x0200
#define TJA1100_EXTERNAL_STAT_SHORT_DETECT            0x0100
#define TJA1100_EXTERNAL_STAT_OPEN_DETECT             0x0080
#define TJA1100_EXTERNAL_STAT_POLARITY_DETECT         0x0040
#define TJA1100_EXTERNAL_STAT_INTERLEAVE_DETECT       0x0020
#define TJA1100_LINK_FAIL_COUNTER_LOC_RCVR_CNT        0xFF00
#define TJA1100_LINK_FAIL_COUNTER_REM_RCVR_CNT        0x00FF
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   //Select RMII mode (50MHz output on REF_CLK)
   value |= TJA1101_CONFIG1_MII_MODE_RMII_50MHZ_REF_CLK_OUT;
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
#define TJA1101_BASIC_CTRL                               0x00
#define TJA1101_BASIC_STAT                               0x01
#define TJA1101_PHY_ID1                                  0x02
#define TJA1101_PHY_ID2                                  0x03
#define TJA1101_EXTENDED_STAT                            0x0F
#define TJA1101_PHY_ID3                                  0x10
#define TJA1101_EXTENDED_CTRL                            0x11
#define TJA1101_CONFIG1                                  0x12
#define TJA1101_CONFIG2                                  0x13
#define TJA1101_SYM_ERR_COUNTER                          0x14
#define TJA1101_INT_SRC                                  0x15
#define TJA1101_INT_EN                                   0x16
#define TJA1101_COMM_STAT                                0x17
#define TJA1101_GENERAL_STAT                             0x18
#define TJA1101_EXTERNAL_STAT                            0x19
#define TJA1101_LINK_FAIL_COUNTER                        0x1A
#define TJA1101_COMM_CTRL                                0x1B
#define TJA1101_CONFIG3                                  0x1C
#define TJA1101_BASIC_CTRL_RESET                         0x8000
#define TJA1101_BASIC_CTRL_LOOPBACK                      0x4000
#define TJA1101_BASIC_CTRL_SPEED_SEL_LSB                 0x2000
#define TJA1101_BASIC_CTRL_AUTONEG_EN                    0x1000
#define TJA1101_BASIC_CTRL_POWER_DOWN                    0x0800
#define TJA1101_BASIC_CTRL_ISOLATE                       0x0400
#define TJA1101_BASIC_CTRL_RE_AUTONEG                    0x0200
#define TJA1101_BASIC_CTRL_DUPLEX_MODE                   0x0100
#define TJA1101_BASIC_CTRL_COL_TEST                      0x0080
#define TJA1101_BASIC_CTRL_SPEED_SEL_MSB                 0x0040
#define TJA1101_BASIC_CTRL_UNIDIRECT_EN                  0x0020
#define TJA1101_BASIC_STAT_100BT4                        0x8000
#define TJA1101_BASIC_STAT_100BTX_FD                     0x4000
#define TJA1101_BASIC_STAT_100BTX_HD                     0x2000
#define TJA1101_BASIC_STAT_10BT_FD                       0x1000
#define TJA1101_BASIC_STAT_10BT_HD                       0x0800
#define TJA1101_BASIC_STAT_100BT2_FD                     0x0400
#define TJA1101_BASIC_STAT_100BT2_HD                     0x0200
#define TJA1101_BASIC_STAT_EXTENDED_STATUS               0x0100
#define TJA1101_BASIC_STAT_UNIDIRECT_ABILITY             0x0080
#define TJA1101_BASIC_STAT_MF_PREAMBLE_SUPPR             0x0040
#define TJA1101_BASIC_STAT_AUTONEG_COMPLETE              0x0020
#define TJA1101_BASIC_STAT_REMOTE_FAULT                  0x0010
#define TJA1101_BASIC_STAT_AUTONEG_ABILITY               0x0008
#define TJA1101_BASIC_STAT_LINK_STATUS                   0x0004
#define TJA1101_BASIC_STAT_JABBER_DETECT                 0x0002
#define TJA1101_BASIC_STAT_EXTENDED_CAPABILITY           0x0001
#define TJA1101_PHY_ID1_OUI_MSB                          0xFFFF
#define TJA1101_PHY_ID1_OUI_MSB_DEFAULT                  0x0180
#define TJA1101_PHY_ID2_OUI_LSB                          0xFC00
#define TJA1101_PHY_ID2_OUI_LSB_DEFAULT                  0xDC00
#define TJA1101_PHY_ID2_TYPE_NO                          0x03F0
#define TJA1101_PHY_ID2_TYPE_NO_DEFAULT                  0x0100
#define TJA1101_PHY_ID2_REVISION_NO                      0x000F
#define TJA1101_EXTENDED_STAT_1000BX_FD                  0x8000
#define TJA1101_EXTENDED_STAT_1000BX_HD                  0x4000
#define TJA1101_EXTENDED_STAT_1000BT_FD                  0x2000
#define TJA1101_EXTENDED_STAT_1000BT_HD                  0x1000
#define TJA1101_EXTENDED_STAT_100BT1                     0x0080
#define TJA1101_EXTENDED_STAT_RTPGE                      0x0040
#define TJA1101_PHY_ID3_VERSION_NO                       0x00FF
#define TJA1101_EXTENDED_CTRL_LINK_CONTROL               0x8000
#define TJA1101_EXTENDED_CTRL_POWER_MODE                 0x7800
#define TJA1101_EXTENDED_CTRL_POWER_MODE_NO_CHANGE       0x0000
#define TJA1101_EXTENDED_CTRL_POWER_MODE_NORMAL          0x1800
#define TJA1101_EXTENDED_CTRL_POWER_MODE_SILENT          0x4800
#define TJA1101_EXTENDED_CTRL_POWER_MODE_SLEEP           0x5000
#define TJA1101_EXTENDED_CTRL_POWER_MODE_SLEEP_REQ       0x5800
#define TJA1101_EXTENDED_CTRL_POWER_MODE_STANDBY         0x6000
#define TJA1101_EXTENDED_CTRL_SLAVE_JITTER_TEST          0x0400
#define TJA1101_EXTENDED_CTRL_TRAINING_RESTART           0x0200
#define TJA1101_EXTENDED_CTRL_TEST_MODE                  0x01C0
#define TJA1101_EXTENDED_CTRL_TEST_MODE_0                0x0000
#define TJA1101_EXTENDED_CTRL_TEST_MODE_1                0x0040
#define TJA1101_EXTENDED_CTRL_TEST_MODE_2                0x0080
#define TJA1101_EXTENDED_CTRL_TEST_MODE_3                0x00C0
#define TJA1101_EXTENDED_CTRL_TEST_MODE_4                0x0100
#define TJA1101_EXTENDED_CTRL_TEST_MODE_5                0x0140
#define TJA1101_EXTENDED_CTRL_TEST_MODE_6                0x0180
#define TJA1101_EXTENDED_CTRL_CABLE_TEST                 0x0020
#define TJA1101_EXTENDED_CTRL_LOOPBACK_MODE              0x0018
#define TJA1101_EXTENDED_CTRL_LOOPBACK_MODE_INTERNAL     0x0000
#define TJA1101_EXTENDED_CTRL_LOOPBACK_MODE_EXTERNAL     0x0008
#define TJA1101_EXTENDED_CTRL_LOOPBACK_MODE_REMOTE       0x0018
#define TJA1101_EXTENDED_CTRL_CONFIG_EN                  0x0004
#define TJA1101_EXTENDED_CTRL_WAKE_REQUEST               0x0001
#define TJA1101_CONFIG1_MASTER_SLAVE                     0x8000
#define TJA1101_CONFIG1_FWDPHYLOC                        0x4000
#define TJA1101_CONFIG1_REMWUPHY                         0x0800
#define TJA1101_CONFIG1_LOCWUPHY                         0x0400
#define TJA1101_CONFIG1_MII_MODE                         0x0300
#define TJA1101_CONFIG1_MII_MODE_MII                     0x0000
#define TJA1101_CONFIG1_MII_MODE_RMII_50MHZ_REF_CLK_IN   0x0100
#define TJA1101_CONFIG1_MII_MODE_RMII_50MHZ_REF_CLK_OUT  0x0200
#define TJA1101_CONFIG1_MII_MODE_REV_MII                 0x0300
#define TJA1101_CONFIG1_MII_DRIVER                       0x0080
#define TJA1101_CONFIG1_MII_DRIVER_STANDARD              0x0000
#define TJA1101_CONFIG1_MII_DRIVER_REDUCED               0x0080
#define TJA1101_CONFIG1_SLEEP_CONFIRM                    0x0040
#define TJA1101_CONFIG1_LPS_WUR_DIS                      0x0020
#define TJA1101_CONFIG1_SLEEP_ACK                        0x0010
#define TJA1101_CONFIG1_FWDPHYREM                        0x0004
#define TJA1101_CONFIG1_AUTO_PWD                         0x0002
#define TJA1101_CONFIG1_LPS_ACTIVE                       0x0001
#define TJA1101_CONFIG2_PHYAD                            0xF800
#define TJA1101_CONFIG2_SQI_AVERAGING                    0x0600
#define TJA1101_CONFIG2_SQI_AVERAGING_32_SYMBOLS         0x0000
#define TJA1101_CONFIG2_SQI_AVERAGING_64_SYMBOLS         0x0200
#define TJA1101_CONFIG2_SQI_AVERAGING_128_SYMBOLS        0x0400
#define TJA1101_CONFIG2_SQI_AVERAGING_256_SYMBOLS        0x0600
#define TJA1101_CONFIG2_SQI_WLIMIT                       0x01C0
#define TJA1101_CONFIG2_SQI_WLIMIT_NONE                  0x0000
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_A               0x0040
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_B               0x0080
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_C               0x00C0
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_D               0x0100
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_E               0x0140
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_F               0x0180
#define TJA1101_CONFIG2_SQI_WLIMIT_CLASS_G               0x01C0
#define TJA1101_CONFIG2_SQI_FAILLIMIT                    0x0038
#define TJA1101_CONFIG2_SQI_FAILLIMIT_NONE               0x0000
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_A            0x0008
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_B            0x0010
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_C            0x0018
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_D            0x0020
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_E            0x0028
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_F            0x0030
#define TJA1101_CONFIG2_SQI_FAILLIMIT_CLASS_G            0x0038
#define TJA1101_CONFIG2_JUMBO_ENABLE                     0x0004
#define TJA1101_CONFIG2_SLEEP_REQUEST_TO                 0x0003
#define TJA1101_CONFIG2_SLEEP_REQUEST_TO_0_4MS           0x0000
#define TJA1101_CONFIG2_SLEEP_REQUEST_TO_1MS             0x0001
#define TJA1101_CONFIG2_SLEEP_REQUEST_TO_4MS             0x0002
#define TJA1101_CONFIG2_SLEEP_REQUEST_TO_16MS            0x0003
#define TJA1101_SYM_ERR_COUNTER_SYM_ERR_CNT              0xFFFF
#define TJA1101_INT_SRC_PWON                             0x8000
#define TJA1101_INT_SRC_WAKEUP                           0x4000
#define TJA1101_INT_SRC_WUR_RECEIVED                     0x2000
#define TJA1101_INT_SRC_LPS_RECEIVED                     0x1000
#define TJA1101_INT_SRC_PHY_INIT_FAIL                    0x0800
#define TJA1101_INT_SRC_LINK_STATUS_FAIL                 0x0400
#define TJA1101_INT_SRC_LINK_STATUS_UP                   0x0200
#define TJA1101_INT_SRC_SYM_ERR                          0x0100
#define TJA1101_INT_SRC_TRAINING_FAILED                  0x0080
#define TJA1101_INT_SRC_SQI_WARNING                      0x0040
#define TJA1101_INT_SRC_CONTROL_ERR                      0x0020
#define TJA1101_INT_SRC_UV_ERR                           0x0008
#define TJA1101_INT_SRC_UV_RECOVERY                      0x0004
#define TJA1101_INT_SRC_TEMP_ERR                         0x0002
#define TJA1101_INT_SRC_SLEEP_ABORT                      0x0001
#define TJA1101_INT_EN_PWON                              0x8000
#define TJA1101_INT_EN_WAKEUP                            0x4000
#define TJA1101_INT_EN_WUR_RECEIVED                      0x2000
#define TJA1101_INT_EN_LPS_RECEIVED                      0x1000
#define TJA1101_INT_EN_PHY_INIT_FAIL                     0x0800
#define TJA1101_INT_EN_LINK_STATUS_FAIL                  0x0400
#define TJA1101_INT_EN_LINK_STATUS_UP                    0x0200
#define TJA1101_INT_EN_SYM_ERR                           0x0100
#define TJA1101_INT_EN_TRAINING_FAILED                   0x0080
#define TJA1101_INT_EN_SQI_WARNING                       0x0040
#define TJA1101_INT_EN_CONTROL_ERR                       0x0020
#define TJA1101_INT_EN_TXEN_CLAMPED                      0x0010
#define TJA1101_INT_EN_UV_ERR                            0x0008
#define TJA1101_INT_EN_UV_RECOVERY                       0x0004
#define TJA1101_INT_EN_TEMP_ERR                          0x0002
#define TJA1101_INT_EN_SLEEP_ABORT                       0x0001
#define TJA1101_COMM_STAT_LINK_UP                        0x8000
#define TJA1101_COMM_STAT_TX_MODE                        0x6000
#define TJA1101_COMM_STAT_TX_MODE_DISABLED               0x0000
#define TJA1101_COMM_STAT_TX_MODE_SEND_N                 0x2000
#define TJA1101_COMM_STAT_TX_MODE_SEND_I                 0x4000
#define TJA1101_COMM_STAT_TX_MODE_SEND_Z                 0x6000
#define TJA1101_COMM_STAT_LOC_RCVR_STATUS                0x1000
#define TJA1101_COMM_STAT_REM_RCVR_STATUS                0x0800
#define TJA1101_COMM_STAT_SCR_LOCKED                     0x0400
#define TJA1101_COMM_STAT_SSD_ERR                        0x0200
#define TJA1101_COMM_STAT_ESD_ERR                        0x0100
#define TJA1101_COMM_STAT_SQI                            0x00E0
#define TJA1101_COMM_STAT_SQI_WORSE_THAN_CLASS_A         0x0000
#define TJA1101_COMM_STAT_SQI_CLASS_A                    0x0020
#define TJA1101_COMM_STAT_SQI_CLASS_B                    0x0040
#define TJA1101_COMM_STAT_SQI_CLASS_C                    0x0060
#define TJA1101_COMM_STAT_SQI_CLASS_D                    0x0080
#define TJA1101_COMM_STAT_SQI_CLASS_E                    0x00A0
#define TJA1101_COMM_STAT_SQI_CLASS_F                    0x00C0
#define TJA1101_COMM_STAT_SQI_CLASS_G                    0x00E0
#define TJA1101_COMM_STAT_RECEIVE_ERR                    0x0010
#define TJA1101_COMM_STAT_TRANSMIT_ERR                   0x0008
#define TJA1101_COMM_STAT_PHY_STATE                      0x0007
#define TJA1101_COMM_STAT_PHY_STATE_IDLE                 0x0000
#define TJA1101_COMM_STAT_PHY_STATE_INITIALIZING         0x0001
#define TJA1101_COMM_STAT_PHY_STATE_CONFIGURED           0x0002
#define TJA1101_COMM_STAT_PHY_STATE_OFFLINE              0x0003
#define TJA1101_COMM_STAT_PHY_STATE_ACTIVE               0x0004
#define TJA1101_COMM_STAT_PHY_STATE_ISOLATE              0x0005
#define TJA1101_COMM_STAT_PHY_STATE_CABLE_TEST           0x0006
#define TJA1101_COMM_STAT_PHY_STATE_TEST_MODE            0x0007
#define TJA1101_GENERAL_STAT_INT_STATUS                  0x8000
#define TJA1101_GENERAL_STAT_PLL_LOCKED                  0x4000
#define TJA1101_GENERAL_STAT_LOCAL_WU                    0x2000
#define TJA1101_GENERAL_STAT_REMOTE_WU                   0x1000
#define TJA1101_GENERAL_STAT_DATA_DET_WU                 0x0800
#define TJA1101_GENERAL_STAT_EN_STATUS                   0x0400
#define TJA1101_GENERAL_STAT_RESET_STATUS                0x0200
#define TJA1101_GENERAL_STAT_LINKFAIL_CNT                0x00F8
#define TJA1101_EXTERNAL_STAT_UV_VDDA_3V3                0x8000
#define TJA1101_EXTERNAL_STAT_UV_VDDD_1V8                0x4000
#define TJA1101_EXTERNAL_STAT_UV_VDDA_1V8                0x2000
#define TJA1101_EXTERNAL_STAT_UV_VDDIO                   0x0800
#define TJA1101_EXTERNAL_STAT_TEMP_HIGH                  0x0400
#define TJA1101_EXTERNAL_STAT_TEMP_WARN                  0x0200
#define TJA1101_EXTERNAL_STAT_SHORT_DETECT               0x0100
#define TJA1101_EXTERNAL_STAT_OPEN_DETECT                0x0080
#define TJA1101_EXTERNAL_STAT_POLARITY_DETECT            0x0040
#define TJA1101_EXTERNAL_STAT_INTERLEAVE_DETECT          0x0020
#define TJA1101_LINK_FAIL_COUNTER_LOC_RCVR_CNT           0xFF00
#define TJA1101_LINK_FAIL_COUNTER_REM_RCVR_CNT           0x00FF
#define TJA1101_COMM_CTRL_AUTO_OP                        0x8000
#define TJA1101_COMM_CTRL_CLK_MODE                       0x3000
#define TJA1101_COMM_CTRL_CLK_MODE_25MHZ_XTAL_NO_CLK_OUT 0x0000
#define TJA1101_COMM_CTRL_CLK_MODE_25MHZ_XTAL_CLK_OUT    0x1000
#define TJA1101_COMM_CTRL_CLK_MODE_25MHZ_EXT_CLK_IN      0x2000
#define TJA1101_COMM_CTRL_CLK_MODE_50MHZ_REF_CLK_IN      0x3000
#define TJA1101_COMM_CTRL_LDO_MODE                       0x0800
#define TJA1101_COMM_CTRL_CLK_DRIVER                     0x0400
#define TJA1101_COMM_CTRL_CLK_HOLD                       0x0200
#define TJA1101_COMM_CTRL_LOC_WU_TIM                     0x0180
#define TJA1101_COMM_CTRL_LOC_WU_TIM_LONGEST             0x0000
#define TJA1101_COMM_CTRL_LOC_WU_TIM_LONG                0x0080
#define TJA1101_COMM_CTRL_LOC_WU_TIM_SHORT               0x0100
#define TJA1101_COMM_CTRL_LOC_WU_TIM_SHORTEST            0x0180
#define TJA1101_COMM_CTRL_CONFIG_WAKE                    0x0040
#define TJA1101_COMM_CTRL_CONFIG_INH                     0x0020
#define TJA1101_CONFIG3_FORCE_SLEEP                      0x0002
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
#elif (RNDIS_TX_BUFFER_COUNT < 1)
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
         {
         }
         {
         }
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   p = osStrchr(context->buffer, '\"');
         if(osStrstr(token, "PM") != NULL)
         {
         }
      if(osStrchr(token, 'd') != NULL)
      {
      }

      if(osStrchr(token, 'w') == NULL)
      {
      }
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      {
      }

      {
      }
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   p = osStrchr(context->buffer, ' ');
   p = osStrchr(context->buffer, ' ');
   p = osStrchr(context->buffer, ' ');
      q = osStrchr(p + 1, ' ');
   p = osStrchr(context->buffer, ' ');
      p = osStrchr(p + 1, ' ');
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      q = osStrchr(context->buffer, ' ');
      q = osStrchr(uri, ' ');
         if(osStrchr(", \t", param->value[i + n]) != NULL)
         {
         }
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      separator = osStrchr(line, ':');
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      if(osStrchr("!#$%&'*+-.^_`|~", c))
         else if(isalnum(c) || osStrchr("!#$%&'*+-.^_`|~", c) || c >= 128)
         else if(isalnum(c) || osStrchr("!#$%&'*+-.^_`|~", c) || c >= 128)
         else if(isalnum(c) || osStrchr("!#$%&'*+-.^_`|~", c) || c >= 128)
         else if(isalnum(c) || osStrchr("!#$%&'*+-.^_`|~", c) || c >= 128)
            else if(isalnum(c) || osStrchr("!#$%&'*+-.^_`|~", c) || c >= 128)
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
            separator = osStrchr(token, ':');
         separator = osStrchr(token, '=');
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
         separator = osStrchr(connection->buffer, ':');
   s = osStrchr(token, '?');
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   separator = osStrchr(connection->buffer, '=');
   separator = osStrchr(connection->buffer, '=');
   separator = osStrchr(connection->buffer, '=');
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
         separator = osStrchr(context->buffer, ':');
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      //Successful processing
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      //Successful processing
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      //Jump to the next option
      //Jump to the next option
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
               if(osStrchr(topicName, '#') == NULL && osStrchr(topicName, '+') == NULL)
 * @param[in] duration Sleep duration, in milliseconds
error_t mqttSnClientDisconnect(MqttSnClientContext *context,
   systime_t duration)
         error = mqttSnClientSendDisconnect(context, duration / 1000);
            error = mqttSnClientSendDisconnect(context, duration / 1000);
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
error_t mqttSnClientDisconnect(MqttSnClientContext *context,
   systime_t duration);

 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      if(osStrlen(topicName) == 2 && osStrchr(topicName, '#') == NULL &&
         osStrchr(topicName, '+') == NULL)
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      if(osStrchr(topicName, '#') == NULL && osStrchr(topicName, '+') == NULL)
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
      separator = osStrchr(token, '=');
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
   s = osStrchr(token, '?');
   separator = osStrchr(line, ':');
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2
 * Copyright (C) 2010-2021 Oryx Embedded SARL. All rights reserved.
 * @version 2.0.2