patched lwip-eth with https://github.com/mbedmicro/mbed/commit/8222bde1af2e328e4c58d0f438827f3091e5e0eb

Dependents:   EthernetInterface

Fork of lwip-eth by mbed official

Committer:
emilmont
Date:
Mon Jul 23 11:52:41 2012 +0000
Revision:
3:dd8b8f5b449a
Parent:
1:0c9d93e2f51c
Child:
4:d827a085afd9
tidyup

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emilmont 3:dd8b8f5b449a 1 /**********************************************************************
emilmont 3:dd8b8f5b449a 2 * $Id$ lpc_phy_dp83848.c 2011-11-20
emilmont 3:dd8b8f5b449a 3 *//**
emilmont 3:dd8b8f5b449a 4 * @file lpc_phy_dp83848.c
emilmont 3:dd8b8f5b449a 5 * @brief DP83848C PHY status and control.
emilmont 3:dd8b8f5b449a 6 * @version 1.0
emilmont 3:dd8b8f5b449a 7 * @date 20 Nov. 2011
emilmont 3:dd8b8f5b449a 8 * @author NXP MCU SW Application Team
emilmont 3:dd8b8f5b449a 9 *
emilmont 3:dd8b8f5b449a 10 * Copyright(C) 2011, NXP Semiconductor
emilmont 3:dd8b8f5b449a 11 * All rights reserved.
emilmont 3:dd8b8f5b449a 12 *
emilmont 3:dd8b8f5b449a 13 ***********************************************************************
emilmont 3:dd8b8f5b449a 14 * Software that is described herein is for illustrative purposes only
emilmont 3:dd8b8f5b449a 15 * which provides customers with programming information regarding the
emilmont 3:dd8b8f5b449a 16 * products. This software is supplied "AS IS" without any warranties.
emilmont 3:dd8b8f5b449a 17 * NXP Semiconductors assumes no responsibility or liability for the
emilmont 3:dd8b8f5b449a 18 * use of the software, conveys no license or title under any patent,
emilmont 3:dd8b8f5b449a 19 * copyright, or mask work right to the product. NXP Semiconductors
emilmont 3:dd8b8f5b449a 20 * reserves the right to make changes in the software without
emilmont 3:dd8b8f5b449a 21 * notification. NXP Semiconductors also make no representation or
emilmont 3:dd8b8f5b449a 22 * warranty that such application will be suitable for the specified
emilmont 3:dd8b8f5b449a 23 * use without further testing or modification.
emilmont 3:dd8b8f5b449a 24 **********************************************************************/
emilmont 3:dd8b8f5b449a 25
emilmont 3:dd8b8f5b449a 26 #include "lwip/opt.h"
emilmont 3:dd8b8f5b449a 27 #include "lwip/err.h"
emilmont 3:dd8b8f5b449a 28 #include "lwip/tcpip.h"
emilmont 3:dd8b8f5b449a 29 #include "lwip/snmp.h"
emilmont 3:dd8b8f5b449a 30 #include "lpc_emac_config.h"
emilmont 3:dd8b8f5b449a 31 #include "lpc_phy.h"
emilmont 3:dd8b8f5b449a 32
emilmont 3:dd8b8f5b449a 33 /** @defgroup dp83848_phy PHY status and control for the DP83848.
emilmont 3:dd8b8f5b449a 34 * @ingroup lwip_phy
emilmont 3:dd8b8f5b449a 35 *
emilmont 3:dd8b8f5b449a 36 * Various functions for controlling and monitoring the status of the
emilmont 3:dd8b8f5b449a 37 * DP83848 PHY. In polled (standalone) systems, the PHY state must be
emilmont 3:dd8b8f5b449a 38 * monitored as part of the application. In a threaded (RTOS) system,
emilmont 3:dd8b8f5b449a 39 * the PHY state is monitored by the PHY handler thread. The MAC
emilmont 3:dd8b8f5b449a 40 * driver will not transmit unless the PHY link is active.
emilmont 3:dd8b8f5b449a 41 * @{
emilmont 3:dd8b8f5b449a 42 */
emilmont 3:dd8b8f5b449a 43
emilmont 3:dd8b8f5b449a 44 /** \brief DP83848 PHY register offsets */
emilmont 3:dd8b8f5b449a 45 #define DP8_BMCR_REG 0x0 /**< Basic Mode Control Register */
emilmont 3:dd8b8f5b449a 46 #define DP8_BMSR_REG 0x1 /**< Basic Mode Status Reg */
emilmont 3:dd8b8f5b449a 47 #define DP8_ANADV_REG 0x4 /**< Auto_Neg Advt Reg */
emilmont 3:dd8b8f5b449a 48 #define DP8_ANLPA_REG 0x5 /**< Auto_neg Link Partner Ability Reg */
emilmont 3:dd8b8f5b449a 49 #define DP8_ANEEXP_REG 0x6 /**< Auto-neg Expansion Reg */
emilmont 3:dd8b8f5b449a 50 #define DP8_PHY_STAT_REG 0x10 /**< PHY Status Register */
emilmont 3:dd8b8f5b449a 51 #define DP8_PHY_INT_CTL_REG 0x11 /**< PHY Interrupt Control Register */
emilmont 3:dd8b8f5b449a 52 #define DP8_PHY_RBR_REG 0x17 /**< PHY RMII and Bypass Register */
emilmont 3:dd8b8f5b449a 53 #define DP8_PHY_STS_REG 0x19 /**< PHY Status Register */
emilmont 3:dd8b8f5b449a 54
emilmont 3:dd8b8f5b449a 55 /** \brief DP83848 Control register definitions */
emilmont 3:dd8b8f5b449a 56 #define DP8_RESET (1 << 15) /**< 1= S/W Reset */
emilmont 3:dd8b8f5b449a 57 #define DP8_LOOPBACK (1 << 14) /**< 1=loopback Enabled */
emilmont 3:dd8b8f5b449a 58 #define DP8_SPEED_SELECT (1 << 13) /**< 1=Select 100MBps */
emilmont 3:dd8b8f5b449a 59 #define DP8_AUTONEG (1 << 12) /**< 1=Enable auto-negotiation */
emilmont 3:dd8b8f5b449a 60 #define DP8_POWER_DOWN (1 << 11) /**< 1=Power down PHY */
emilmont 3:dd8b8f5b449a 61 #define DP8_ISOLATE (1 << 10) /**< 1=Isolate PHY */
emilmont 3:dd8b8f5b449a 62 #define DP8_RESTART_AUTONEG (1 << 9) /**< 1=Restart auto-negoatiation */
emilmont 3:dd8b8f5b449a 63 #define DP8_DUPLEX_MODE (1 << 8) /**< 1=Full duplex mode */
emilmont 3:dd8b8f5b449a 64 #define DP8_COLLISION_TEST (1 << 7) /**< 1=Perform collsion test */
emilmont 3:dd8b8f5b449a 65
emilmont 3:dd8b8f5b449a 66 /** \brief DP83848 Status register definitions */
emilmont 3:dd8b8f5b449a 67 #define DP8_100BASE_T4 (1 << 15) /**< T4 mode */
emilmont 3:dd8b8f5b449a 68 #define DP8_100BASE_TX_FD (1 << 14) /**< 100MBps full duplex */
emilmont 3:dd8b8f5b449a 69 #define DP8_100BASE_TX_HD (1 << 13) /**< 100MBps half duplex */
emilmont 3:dd8b8f5b449a 70 #define DP8_10BASE_T_FD (1 << 12) /**< 100Bps full duplex */
emilmont 3:dd8b8f5b449a 71 #define DP8_10BASE_T_HD (1 << 11) /**< 10MBps half duplex */
emilmont 3:dd8b8f5b449a 72 #define DP8_MF_PREAMB_SUPPR (1 << 6) /**< Preamble suppress */
emilmont 3:dd8b8f5b449a 73 #define DP8_AUTONEG_COMP (1 << 5) /**< Auto-negotation complete */
emilmont 3:dd8b8f5b449a 74 #define DP8_RMT_FAULT (1 << 4) /**< Fault */
emilmont 3:dd8b8f5b449a 75 #define DP8_AUTONEG_ABILITY (1 << 3) /**< Auto-negotation supported */
emilmont 3:dd8b8f5b449a 76 #define DP8_LINK_STATUS (1 << 2) /**< 1=Link active */
emilmont 3:dd8b8f5b449a 77 #define DP8_JABBER_DETECT (1 << 1) /**< Jabber detect */
emilmont 3:dd8b8f5b449a 78 #define DP8_EXTEND_CAPAB (1 << 0) /**< Supports extended capabilities */
emilmont 3:dd8b8f5b449a 79
emilmont 3:dd8b8f5b449a 80 /** \brief DP83848 PHY RBR MII dode definitions */
emilmont 3:dd8b8f5b449a 81 #define DP8_RBR_RMII_MODE (1 << 5) /**< Use RMII mode */
emilmont 3:dd8b8f5b449a 82
emilmont 3:dd8b8f5b449a 83 /** \brief DP83848 PHY status definitions */
emilmont 3:dd8b8f5b449a 84 #define DP8_REMOTEFAULT (1 << 6) /**< Remote fault */
emilmont 3:dd8b8f5b449a 85 #define DP8_FULLDUPLEX (1 << 2) /**< 1=full duplex */
emilmont 3:dd8b8f5b449a 86 #define DP8_SPEED10MBPS (1 << 1) /**< 1=10MBps speed */
emilmont 3:dd8b8f5b449a 87 #define DP8_VALID_LINK (1 << 0) /**< 1=Link active */
emilmont 3:dd8b8f5b449a 88
emilmont 3:dd8b8f5b449a 89 /** \brief DP83848 PHY ID register definitions */
emilmont 3:dd8b8f5b449a 90 #define DP8_PHYID1_OUI 0x2000 /**< Expected PHY ID1 */
emilmont 3:dd8b8f5b449a 91 #define DP8_PHYID2_OUI 0x5c90 /**< Expected PHY ID2 */
emilmont 3:dd8b8f5b449a 92
emilmont 3:dd8b8f5b449a 93 /** \brief PHY status structure used to indicate current status of PHY.
emilmont 3:dd8b8f5b449a 94 */
emilmont 3:dd8b8f5b449a 95 typedef struct {
emilmont 3:dd8b8f5b449a 96 u32_t phy_speed_100mbs:1; /**< 10/100 MBS connection speed flag. */
emilmont 3:dd8b8f5b449a 97 u32_t phy_full_duplex:1; /**< Half/full duplex connection speed flag. */
emilmont 3:dd8b8f5b449a 98 u32_t phy_link_active:1; /**< Phy link active flag. */
emilmont 3:dd8b8f5b449a 99 } PHY_STATUS_TYPE;
emilmont 3:dd8b8f5b449a 100
emilmont 3:dd8b8f5b449a 101 /** \brief PHY update flags */
emilmont 3:dd8b8f5b449a 102 static PHY_STATUS_TYPE physts;
emilmont 3:dd8b8f5b449a 103
emilmont 3:dd8b8f5b449a 104 /** \brief Last PHY update flags, used for determing if something has changed */
emilmont 3:dd8b8f5b449a 105 static PHY_STATUS_TYPE olddphysts;
emilmont 3:dd8b8f5b449a 106
emilmont 3:dd8b8f5b449a 107 /** \brief PHY update counter for state machine */
emilmont 3:dd8b8f5b449a 108 static s32_t phyustate;
emilmont 3:dd8b8f5b449a 109
emilmont 3:dd8b8f5b449a 110 /** \brief Update PHY status from passed value
emilmont 3:dd8b8f5b449a 111 *
emilmont 3:dd8b8f5b449a 112 * This function updates the current PHY status based on the
emilmont 3:dd8b8f5b449a 113 * passed PHY status word. The PHY status indicate if the link
emilmont 3:dd8b8f5b449a 114 * is active, the connection speed, and duplex.
emilmont 3:dd8b8f5b449a 115 *
emilmont 3:dd8b8f5b449a 116 * \param[in] netif NETIF structure
emilmont 3:dd8b8f5b449a 117 * \param[in] linksts Status word from PHY
emilmont 3:dd8b8f5b449a 118 * \return 1 if the status has changed, otherwise 0
emilmont 3:dd8b8f5b449a 119 */
emilmont 3:dd8b8f5b449a 120 static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts)
emilmont 3:dd8b8f5b449a 121 {
emilmont 3:dd8b8f5b449a 122 s32_t changed = 0;
emilmont 3:dd8b8f5b449a 123
emilmont 3:dd8b8f5b449a 124 /* Update link active status */
emilmont 3:dd8b8f5b449a 125 if (linksts & DP8_VALID_LINK)
emilmont 3:dd8b8f5b449a 126 physts.phy_link_active = 1;
emilmont 3:dd8b8f5b449a 127 else
emilmont 3:dd8b8f5b449a 128 physts.phy_link_active = 0;
emilmont 3:dd8b8f5b449a 129
emilmont 3:dd8b8f5b449a 130 /* Full or half duplex */
emilmont 3:dd8b8f5b449a 131 if (linksts & DP8_FULLDUPLEX)
emilmont 3:dd8b8f5b449a 132 physts.phy_full_duplex = 1;
emilmont 3:dd8b8f5b449a 133 else
emilmont 3:dd8b8f5b449a 134 physts.phy_full_duplex = 0;
emilmont 3:dd8b8f5b449a 135
emilmont 3:dd8b8f5b449a 136 /* Configure 100MBit/10MBit mode. */
emilmont 3:dd8b8f5b449a 137 if (linksts & DP8_SPEED10MBPS)
emilmont 3:dd8b8f5b449a 138 physts.phy_speed_100mbs = 0;
emilmont 3:dd8b8f5b449a 139 else
emilmont 3:dd8b8f5b449a 140 physts.phy_speed_100mbs = 1;
emilmont 3:dd8b8f5b449a 141
emilmont 3:dd8b8f5b449a 142 if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) {
emilmont 3:dd8b8f5b449a 143 changed = 1;
emilmont 3:dd8b8f5b449a 144 if (physts.phy_speed_100mbs) {
emilmont 3:dd8b8f5b449a 145 /* 100MBit mode. */
emilmont 3:dd8b8f5b449a 146 lpc_emac_set_speed(1);
emilmont 3:dd8b8f5b449a 147
emilmont 3:dd8b8f5b449a 148 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);
emilmont 3:dd8b8f5b449a 149 }
emilmont 3:dd8b8f5b449a 150 else {
emilmont 3:dd8b8f5b449a 151 /* 10MBit mode. */
emilmont 3:dd8b8f5b449a 152 lpc_emac_set_speed(0);
emilmont 3:dd8b8f5b449a 153
emilmont 3:dd8b8f5b449a 154 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
emilmont 3:dd8b8f5b449a 155 }
emilmont 3:dd8b8f5b449a 156
emilmont 3:dd8b8f5b449a 157 olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs;
emilmont 3:dd8b8f5b449a 158 }
emilmont 3:dd8b8f5b449a 159
emilmont 3:dd8b8f5b449a 160 if (physts.phy_full_duplex != olddphysts.phy_full_duplex) {
emilmont 3:dd8b8f5b449a 161 changed = 1;
emilmont 3:dd8b8f5b449a 162 if (physts.phy_full_duplex)
emilmont 3:dd8b8f5b449a 163 lpc_emac_set_duplex(1);
emilmont 3:dd8b8f5b449a 164 else
emilmont 3:dd8b8f5b449a 165 lpc_emac_set_duplex(0);
emilmont 3:dd8b8f5b449a 166
emilmont 3:dd8b8f5b449a 167 olddphysts.phy_full_duplex = physts.phy_full_duplex;
emilmont 3:dd8b8f5b449a 168 }
emilmont 3:dd8b8f5b449a 169
emilmont 3:dd8b8f5b449a 170 if (physts.phy_link_active != olddphysts.phy_link_active) {
emilmont 3:dd8b8f5b449a 171 changed = 1;
emilmont 3:dd8b8f5b449a 172 #if NO_SYS == 1
emilmont 3:dd8b8f5b449a 173 if (physts.phy_link_active)
emilmont 3:dd8b8f5b449a 174 netif_set_link_up(netif);
emilmont 3:dd8b8f5b449a 175 else
emilmont 3:dd8b8f5b449a 176 netif_set_link_down(netif);
emilmont 3:dd8b8f5b449a 177 #else
emilmont 3:dd8b8f5b449a 178 if (physts.phy_link_active)
emilmont 3:dd8b8f5b449a 179 tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up,
emilmont 3:dd8b8f5b449a 180 (void*) netif, 1);
emilmont 3:dd8b8f5b449a 181 else
emilmont 3:dd8b8f5b449a 182 tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down,
emilmont 3:dd8b8f5b449a 183 (void*) netif, 1);
emilmont 3:dd8b8f5b449a 184 #endif
emilmont 3:dd8b8f5b449a 185
emilmont 3:dd8b8f5b449a 186 olddphysts.phy_link_active = physts.phy_link_active;
emilmont 3:dd8b8f5b449a 187 }
emilmont 3:dd8b8f5b449a 188
emilmont 3:dd8b8f5b449a 189 return changed;
emilmont 3:dd8b8f5b449a 190 }
emilmont 3:dd8b8f5b449a 191
emilmont 3:dd8b8f5b449a 192 /** \brief Initialize the DP83848 PHY.
emilmont 3:dd8b8f5b449a 193 *
emilmont 3:dd8b8f5b449a 194 * This function initializes the DP83848 PHY. It will block until
emilmont 3:dd8b8f5b449a 195 * complete. This function is called as part of the EMAC driver
emilmont 3:dd8b8f5b449a 196 * initialization. Configuration of the PHY at startup is
emilmont 3:dd8b8f5b449a 197 * controlled by setting up configuration defines in lpc_phy.h.
emilmont 3:dd8b8f5b449a 198 *
emilmont 3:dd8b8f5b449a 199 * \param[in] netif NETIF structure
emilmont 3:dd8b8f5b449a 200 * \param[in] rmii If set, configures the PHY for RMII mode
emilmont 3:dd8b8f5b449a 201 * \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
emilmont 3:dd8b8f5b449a 202 */
emilmont 3:dd8b8f5b449a 203 err_t lpc_phy_init(struct netif *netif, int rmii)
emilmont 3:dd8b8f5b449a 204 {
emilmont 3:dd8b8f5b449a 205 u32_t tmp;
emilmont 3:dd8b8f5b449a 206 s32_t i;
emilmont 3:dd8b8f5b449a 207
emilmont 3:dd8b8f5b449a 208 physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 2;
emilmont 3:dd8b8f5b449a 209 physts.phy_full_duplex = olddphysts.phy_full_duplex = 2;
emilmont 3:dd8b8f5b449a 210 physts.phy_link_active = olddphysts.phy_link_active = 2;
emilmont 3:dd8b8f5b449a 211 phyustate = 0;
emilmont 3:dd8b8f5b449a 212
emilmont 3:dd8b8f5b449a 213 /* Only first read and write are checked for failure */
emilmont 3:dd8b8f5b449a 214 /* Put the DP83848C in reset mode and wait for completion */
emilmont 3:dd8b8f5b449a 215 if (lpc_mii_write(DP8_BMCR_REG, DP8_RESET) != 0)
emilmont 3:dd8b8f5b449a 216 return ERR_TIMEOUT;
emilmont 3:dd8b8f5b449a 217 i = 400;
emilmont 3:dd8b8f5b449a 218 while (i > 0) {
emilmont 3:dd8b8f5b449a 219 osDelay(1); /* 1 ms */
emilmont 3:dd8b8f5b449a 220 if (lpc_mii_read(DP8_BMCR_REG, &tmp) != 0)
emilmont 3:dd8b8f5b449a 221 return ERR_TIMEOUT;
emilmont 3:dd8b8f5b449a 222
emilmont 3:dd8b8f5b449a 223 if (!(tmp & (DP8_RESET | DP8_POWER_DOWN)))
emilmont 3:dd8b8f5b449a 224 i = -1;
emilmont 3:dd8b8f5b449a 225 else
emilmont 3:dd8b8f5b449a 226 i--;
emilmont 3:dd8b8f5b449a 227 }
emilmont 3:dd8b8f5b449a 228 /* Timeout? */
emilmont 3:dd8b8f5b449a 229 if (i == 0)
emilmont 3:dd8b8f5b449a 230 return ERR_TIMEOUT;
emilmont 3:dd8b8f5b449a 231
emilmont 3:dd8b8f5b449a 232 /* Setup link based on configuration options */
emilmont 3:dd8b8f5b449a 233 #if PHY_USE_AUTONEG==1
emilmont 3:dd8b8f5b449a 234 tmp = DP8_AUTONEG;
emilmont 3:dd8b8f5b449a 235 #else
emilmont 3:dd8b8f5b449a 236 tmp = 0;
emilmont 3:dd8b8f5b449a 237 #endif
emilmont 3:dd8b8f5b449a 238 #if PHY_USE_100MBS==1
emilmont 3:dd8b8f5b449a 239 tmp |= DP8_SPEED_SELECT;
emilmont 3:dd8b8f5b449a 240 #endif
emilmont 3:dd8b8f5b449a 241 #if PHY_USE_FULL_DUPLEX==1
emilmont 3:dd8b8f5b449a 242 tmp |= DP8_DUPLEX_MODE;
emilmont 3:dd8b8f5b449a 243 #endif
emilmont 3:dd8b8f5b449a 244 lpc_mii_write(DP8_BMCR_REG, tmp);
emilmont 3:dd8b8f5b449a 245
emilmont 3:dd8b8f5b449a 246 /* Enable RMII mode for PHY */
emilmont 3:dd8b8f5b449a 247 if (rmii)
emilmont 3:dd8b8f5b449a 248 lpc_mii_write(DP8_PHY_RBR_REG, DP8_RBR_RMII_MODE);
emilmont 3:dd8b8f5b449a 249
emilmont 3:dd8b8f5b449a 250 /* The link is not set active at this point, but will be detected
emilmont 3:dd8b8f5b449a 251 later */
emilmont 3:dd8b8f5b449a 252
emilmont 3:dd8b8f5b449a 253 return ERR_OK;
emilmont 3:dd8b8f5b449a 254 }
emilmont 3:dd8b8f5b449a 255
emilmont 3:dd8b8f5b449a 256 /* Phy status update state machine */
emilmont 3:dd8b8f5b449a 257 s32_t lpc_phy_sts_sm(struct netif *netif)
emilmont 3:dd8b8f5b449a 258 {
emilmont 3:dd8b8f5b449a 259 s32_t changed = 0;
emilmont 3:dd8b8f5b449a 260
emilmont 3:dd8b8f5b449a 261 switch (phyustate) {
emilmont 3:dd8b8f5b449a 262 default:
emilmont 3:dd8b8f5b449a 263 case 0:
emilmont 3:dd8b8f5b449a 264 /* Read BMSR to clear faults */
emilmont 3:dd8b8f5b449a 265 lpc_mii_read_noblock(DP8_PHY_STAT_REG);
emilmont 3:dd8b8f5b449a 266 phyustate = 1;
emilmont 3:dd8b8f5b449a 267 break;
emilmont 3:dd8b8f5b449a 268
emilmont 3:dd8b8f5b449a 269 case 1:
emilmont 3:dd8b8f5b449a 270 /* Wait for read status state */
emilmont 3:dd8b8f5b449a 271 if (!lpc_mii_is_busy()) {
emilmont 3:dd8b8f5b449a 272 /* Update PHY status */
emilmont 3:dd8b8f5b449a 273 changed = lpc_update_phy_sts(netif, lpc_mii_read_data());
emilmont 3:dd8b8f5b449a 274 phyustate = 0;
emilmont 3:dd8b8f5b449a 275 }
emilmont 3:dd8b8f5b449a 276 break;
emilmont 3:dd8b8f5b449a 277 }
emilmont 3:dd8b8f5b449a 278
emilmont 3:dd8b8f5b449a 279 return changed;
emilmont 3:dd8b8f5b449a 280 }
emilmont 3:dd8b8f5b449a 281
emilmont 3:dd8b8f5b449a 282 /**
emilmont 3:dd8b8f5b449a 283 * @}
emilmont 3:dd8b8f5b449a 284 */
emilmont 3:dd8b8f5b449a 285
emilmont 3:dd8b8f5b449a 286 /* --------------------------------- End Of File ------------------------------ */