Ethernet test for ECE 4180 and others to find your IP address and do a simple HTTP GET request over port 80.

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Committer:
mkersh3
Date:
Thu Apr 04 05:26:09 2013 +0000
Revision:
0:e7ca326e76ee
Ethernet Test for ECE4180 and others to find their IP Address and do a simple HTTP GET request over port 80.

Who changed what in which revision?

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