root/drivers/net/phy/phy-c45.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. genphy_c45_pma_setup_forced
  2. genphy_c45_an_config_aneg
  3. genphy_c45_an_disable_aneg
  4. genphy_c45_restart_aneg
  5. genphy_c45_check_and_restart_aneg
  6. genphy_c45_aneg_done
  7. genphy_c45_read_link
  8. genphy_c45_read_lpa
  9. genphy_c45_read_pma
  10. genphy_c45_read_mdix
  11. genphy_c45_pma_read_abilities
  12. genphy_c45_read_status
  13. genphy_c45_config_aneg
  14. gen10g_config_aneg

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Clause 45 PHY support
   4  */
   5 #include <linux/ethtool.h>
   6 #include <linux/export.h>
   7 #include <linux/mdio.h>
   8 #include <linux/mii.h>
   9 #include <linux/phy.h>
  10 
  11 /**
  12  * genphy_c45_setup_forced - configures a forced speed
  13  * @phydev: target phy_device struct
  14  */
  15 int genphy_c45_pma_setup_forced(struct phy_device *phydev)
  16 {
  17         int ctrl1, ctrl2, ret;
  18 
  19         /* Half duplex is not supported */
  20         if (phydev->duplex != DUPLEX_FULL)
  21                 return -EINVAL;
  22 
  23         ctrl1 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
  24         if (ctrl1 < 0)
  25                 return ctrl1;
  26 
  27         ctrl2 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2);
  28         if (ctrl2 < 0)
  29                 return ctrl2;
  30 
  31         ctrl1 &= ~MDIO_CTRL1_SPEEDSEL;
  32         /*
  33          * PMA/PMD type selection is 1.7.5:0 not 1.7.3:0.  See 45.2.1.6.1
  34          * in 802.3-2012 and 802.3-2015.
  35          */
  36         ctrl2 &= ~(MDIO_PMA_CTRL2_TYPE | 0x30);
  37 
  38         switch (phydev->speed) {
  39         case SPEED_10:
  40                 ctrl2 |= MDIO_PMA_CTRL2_10BT;
  41                 break;
  42         case SPEED_100:
  43                 ctrl1 |= MDIO_PMA_CTRL1_SPEED100;
  44                 ctrl2 |= MDIO_PMA_CTRL2_100BTX;
  45                 break;
  46         case SPEED_1000:
  47                 ctrl1 |= MDIO_PMA_CTRL1_SPEED1000;
  48                 /* Assume 1000base-T */
  49                 ctrl2 |= MDIO_PMA_CTRL2_1000BT;
  50                 break;
  51         case SPEED_2500:
  52                 ctrl1 |= MDIO_CTRL1_SPEED2_5G;
  53                 /* Assume 2.5Gbase-T */
  54                 ctrl2 |= MDIO_PMA_CTRL2_2_5GBT;
  55                 break;
  56         case SPEED_5000:
  57                 ctrl1 |= MDIO_CTRL1_SPEED5G;
  58                 /* Assume 5Gbase-T */
  59                 ctrl2 |= MDIO_PMA_CTRL2_5GBT;
  60                 break;
  61         case SPEED_10000:
  62                 ctrl1 |= MDIO_CTRL1_SPEED10G;
  63                 /* Assume 10Gbase-T */
  64                 ctrl2 |= MDIO_PMA_CTRL2_10GBT;
  65                 break;
  66         default:
  67                 return -EINVAL;
  68         }
  69 
  70         ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, ctrl1);
  71         if (ret < 0)
  72                 return ret;
  73 
  74         ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2);
  75         if (ret < 0)
  76                 return ret;
  77 
  78         return genphy_c45_an_disable_aneg(phydev);
  79 }
  80 EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced);
  81 
  82 /**
  83  * genphy_c45_an_config_aneg - configure advertisement registers
  84  * @phydev: target phy_device struct
  85  *
  86  * Configure advertisement registers based on modes set in phydev->advertising
  87  *
  88  * Returns negative errno code on failure, 0 if advertisement didn't change,
  89  * or 1 if advertised modes changed.
  90  */
  91 int genphy_c45_an_config_aneg(struct phy_device *phydev)
  92 {
  93         int changed, ret;
  94         u32 adv;
  95 
  96         linkmode_and(phydev->advertising, phydev->advertising,
  97                      phydev->supported);
  98 
  99         changed = genphy_config_eee_advert(phydev);
 100 
 101         adv = linkmode_adv_to_mii_adv_t(phydev->advertising);
 102 
 103         ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
 104                                      ADVERTISE_ALL | ADVERTISE_100BASE4 |
 105                                      ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
 106                                      adv);
 107         if (ret < 0)
 108                 return ret;
 109         if (ret > 0)
 110                 changed = 1;
 111 
 112         adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising);
 113 
 114         ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
 115                                      MDIO_AN_10GBT_CTRL_ADV10G |
 116                                      MDIO_AN_10GBT_CTRL_ADV5G |
 117                                      MDIO_AN_10GBT_CTRL_ADV2_5G, adv);
 118         if (ret < 0)
 119                 return ret;
 120         if (ret > 0)
 121                 changed = 1;
 122 
 123         return changed;
 124 }
 125 EXPORT_SYMBOL_GPL(genphy_c45_an_config_aneg);
 126 
 127 /**
 128  * genphy_c45_an_disable_aneg - disable auto-negotiation
 129  * @phydev: target phy_device struct
 130  *
 131  * Disable auto-negotiation in the Clause 45 PHY. The link parameters
 132  * parameters are controlled through the PMA/PMD MMD registers.
 133  *
 134  * Returns zero on success, negative errno code on failure.
 135  */
 136 int genphy_c45_an_disable_aneg(struct phy_device *phydev)
 137 {
 138 
 139         return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1,
 140                                   MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
 141 }
 142 EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg);
 143 
 144 /**
 145  * genphy_c45_restart_aneg - Enable and restart auto-negotiation
 146  * @phydev: target phy_device struct
 147  *
 148  * This assumes that the auto-negotiation MMD is present.
 149  *
 150  * Enable and restart auto-negotiation.
 151  */
 152 int genphy_c45_restart_aneg(struct phy_device *phydev)
 153 {
 154         return phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1,
 155                                 MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
 156 }
 157 EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
 158 
 159 /**
 160  * genphy_c45_check_and_restart_aneg - Enable and restart auto-negotiation
 161  * @phydev: target phy_device struct
 162  * @restart: whether aneg restart is requested
 163  *
 164  * This assumes that the auto-negotiation MMD is present.
 165  *
 166  * Check, and restart auto-negotiation if needed.
 167  */
 168 int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart)
 169 {
 170         int ret = 0;
 171 
 172         if (!restart) {
 173                 /* Configure and restart aneg if it wasn't set before */
 174                 ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
 175                 if (ret < 0)
 176                         return ret;
 177 
 178                 if (!(ret & MDIO_AN_CTRL1_ENABLE))
 179                         restart = true;
 180         }
 181 
 182         if (restart)
 183                 ret = genphy_c45_restart_aneg(phydev);
 184 
 185         return ret;
 186 }
 187 EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg);
 188 
 189 /**
 190  * genphy_c45_aneg_done - return auto-negotiation complete status
 191  * @phydev: target phy_device struct
 192  *
 193  * This assumes that the auto-negotiation MMD is present.
 194  *
 195  * Reads the status register from the auto-negotiation MMD, returning:
 196  * - positive if auto-negotiation is complete
 197  * - negative errno code on error
 198  * - zero otherwise
 199  */
 200 int genphy_c45_aneg_done(struct phy_device *phydev)
 201 {
 202         int val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
 203 
 204         return val < 0 ? val : val & MDIO_AN_STAT1_COMPLETE ? 1 : 0;
 205 }
 206 EXPORT_SYMBOL_GPL(genphy_c45_aneg_done);
 207 
 208 /**
 209  * genphy_c45_read_link - read the overall link status from the MMDs
 210  * @phydev: target phy_device struct
 211  *
 212  * Read the link status from the specified MMDs, and if they all indicate
 213  * that the link is up, set phydev->link to 1.  If an error is encountered,
 214  * a negative errno will be returned, otherwise zero.
 215  */
 216 int genphy_c45_read_link(struct phy_device *phydev)
 217 {
 218         u32 mmd_mask = MDIO_DEVS_PMAPMD;
 219         int val, devad;
 220         bool link = true;
 221 
 222         if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
 223                 val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
 224                 if (val < 0)
 225                         return val;
 226 
 227                 /* Autoneg is being started, therefore disregard current
 228                  * link status and report link as down.
 229                  */
 230                 if (val & MDIO_AN_CTRL1_RESTART) {
 231                         phydev->link = 0;
 232                         return 0;
 233                 }
 234         }
 235 
 236         while (mmd_mask && link) {
 237                 devad = __ffs(mmd_mask);
 238                 mmd_mask &= ~BIT(devad);
 239 
 240                 /* The link state is latched low so that momentary link
 241                  * drops can be detected. Do not double-read the status
 242                  * in polling mode to detect such short link drops.
 243                  */
 244                 if (!phy_polling_mode(phydev)) {
 245                         val = phy_read_mmd(phydev, devad, MDIO_STAT1);
 246                         if (val < 0)
 247                                 return val;
 248                         else if (val & MDIO_STAT1_LSTATUS)
 249                                 continue;
 250                 }
 251 
 252                 val = phy_read_mmd(phydev, devad, MDIO_STAT1);
 253                 if (val < 0)
 254                         return val;
 255 
 256                 if (!(val & MDIO_STAT1_LSTATUS))
 257                         link = false;
 258         }
 259 
 260         phydev->link = link;
 261 
 262         return 0;
 263 }
 264 EXPORT_SYMBOL_GPL(genphy_c45_read_link);
 265 
 266 /**
 267  * genphy_c45_read_lpa - read the link partner advertisement and pause
 268  * @phydev: target phy_device struct
 269  *
 270  * Read the Clause 45 defined base (7.19) and 10G (7.33) status registers,
 271  * filling in the link partner advertisement, pause and asym_pause members
 272  * in @phydev.  This assumes that the auto-negotiation MMD is present, and
 273  * the backplane bit (7.48.0) is clear.  Clause 45 PHY drivers are expected
 274  * to fill in the remainder of the link partner advert from vendor registers.
 275  */
 276 int genphy_c45_read_lpa(struct phy_device *phydev)
 277 {
 278         int val;
 279 
 280         val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
 281         if (val < 0)
 282                 return val;
 283 
 284         if (!(val & MDIO_AN_STAT1_COMPLETE)) {
 285                 linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 286                                    phydev->lp_advertising);
 287                 mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0);
 288                 mii_adv_mod_linkmode_adv_t(phydev->lp_advertising, 0);
 289                 phydev->pause = 0;
 290                 phydev->asym_pause = 0;
 291 
 292                 return 0;
 293         }
 294 
 295         linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->lp_advertising,
 296                          val & MDIO_AN_STAT1_LPABLE);
 297 
 298         /* Read the link partner's base page advertisement */
 299         val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA);
 300         if (val < 0)
 301                 return val;
 302 
 303         mii_adv_mod_linkmode_adv_t(phydev->lp_advertising, val);
 304         phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0;
 305         phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0;
 306 
 307         /* Read the link partner's 10G advertisement */
 308         val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
 309         if (val < 0)
 310                 return val;
 311 
 312         mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, val);
 313 
 314         return 0;
 315 }
 316 EXPORT_SYMBOL_GPL(genphy_c45_read_lpa);
 317 
 318 /**
 319  * genphy_c45_read_pma - read link speed etc from PMA
 320  * @phydev: target phy_device struct
 321  */
 322 int genphy_c45_read_pma(struct phy_device *phydev)
 323 {
 324         int val;
 325 
 326         linkmode_zero(phydev->lp_advertising);
 327 
 328         val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
 329         if (val < 0)
 330                 return val;
 331 
 332         switch (val & MDIO_CTRL1_SPEEDSEL) {
 333         case 0:
 334                 phydev->speed = SPEED_10;
 335                 break;
 336         case MDIO_PMA_CTRL1_SPEED100:
 337                 phydev->speed = SPEED_100;
 338                 break;
 339         case MDIO_PMA_CTRL1_SPEED1000:
 340                 phydev->speed = SPEED_1000;
 341                 break;
 342         case MDIO_CTRL1_SPEED2_5G:
 343                 phydev->speed = SPEED_2500;
 344                 break;
 345         case MDIO_CTRL1_SPEED5G:
 346                 phydev->speed = SPEED_5000;
 347                 break;
 348         case MDIO_CTRL1_SPEED10G:
 349                 phydev->speed = SPEED_10000;
 350                 break;
 351         default:
 352                 phydev->speed = SPEED_UNKNOWN;
 353                 break;
 354         }
 355 
 356         phydev->duplex = DUPLEX_FULL;
 357 
 358         return 0;
 359 }
 360 EXPORT_SYMBOL_GPL(genphy_c45_read_pma);
 361 
 362 /**
 363  * genphy_c45_read_mdix - read mdix status from PMA
 364  * @phydev: target phy_device struct
 365  */
 366 int genphy_c45_read_mdix(struct phy_device *phydev)
 367 {
 368         int val;
 369 
 370         if (phydev->speed == SPEED_10000) {
 371                 val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
 372                                    MDIO_PMA_10GBT_SWAPPOL);
 373                 if (val < 0)
 374                         return val;
 375 
 376                 switch (val) {
 377                 case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
 378                         phydev->mdix = ETH_TP_MDI;
 379                         break;
 380 
 381                 case 0:
 382                         phydev->mdix = ETH_TP_MDI_X;
 383                         break;
 384 
 385                 default:
 386                         phydev->mdix = ETH_TP_MDI_INVALID;
 387                         break;
 388                 }
 389         }
 390 
 391         return 0;
 392 }
 393 EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
 394 
 395 /**
 396  * genphy_c45_pma_read_abilities - read supported link modes from PMA
 397  * @phydev: target phy_device struct
 398  *
 399  * Read the supported link modes from the PMA Status 2 (1.8) register. If bit
 400  * 1.8.9 is set, the list of supported modes is build using the values in the
 401  * PMA Extended Abilities (1.11) register, indicating 1000BASET an 10G related
 402  * modes. If bit 1.11.14 is set, then the list is also extended with the modes
 403  * in the 2.5G/5G PMA Extended register (1.21), indicating if 2.5GBASET and
 404  * 5GBASET are supported.
 405  */
 406 int genphy_c45_pma_read_abilities(struct phy_device *phydev)
 407 {
 408         int val;
 409 
 410         linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
 411         if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
 412                 val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
 413                 if (val < 0)
 414                         return val;
 415 
 416                 if (val & MDIO_AN_STAT1_ABLE)
 417                         linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 418                                          phydev->supported);
 419         }
 420 
 421         val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
 422         if (val < 0)
 423                 return val;
 424 
 425         linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
 426                          phydev->supported,
 427                          val & MDIO_PMA_STAT2_10GBSR);
 428 
 429         linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
 430                          phydev->supported,
 431                          val & MDIO_PMA_STAT2_10GBLR);
 432 
 433         linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
 434                          phydev->supported,
 435                          val & MDIO_PMA_STAT2_10GBER);
 436 
 437         if (val & MDIO_PMA_STAT2_EXTABLE) {
 438                 val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
 439                 if (val < 0)
 440                         return val;
 441 
 442                 linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
 443                                  phydev->supported,
 444                                  val & MDIO_PMA_EXTABLE_10GBLRM);
 445                 linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
 446                                  phydev->supported,
 447                                  val & MDIO_PMA_EXTABLE_10GBT);
 448                 linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
 449                                  phydev->supported,
 450                                  val & MDIO_PMA_EXTABLE_10GBKX4);
 451                 linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
 452                                  phydev->supported,
 453                                  val & MDIO_PMA_EXTABLE_10GBKR);
 454                 linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
 455                                  phydev->supported,
 456                                  val & MDIO_PMA_EXTABLE_1000BT);
 457                 linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
 458                                  phydev->supported,
 459                                  val & MDIO_PMA_EXTABLE_1000BKX);
 460 
 461                 linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
 462                                  phydev->supported,
 463                                  val & MDIO_PMA_EXTABLE_100BTX);
 464                 linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
 465                                  phydev->supported,
 466                                  val & MDIO_PMA_EXTABLE_100BTX);
 467 
 468                 linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
 469                                  phydev->supported,
 470                                  val & MDIO_PMA_EXTABLE_10BT);
 471                 linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
 472                                  phydev->supported,
 473                                  val & MDIO_PMA_EXTABLE_10BT);
 474 
 475                 if (val & MDIO_PMA_EXTABLE_NBT) {
 476                         val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
 477                                            MDIO_PMA_NG_EXTABLE);
 478                         if (val < 0)
 479                                 return val;
 480 
 481                         linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
 482                                          phydev->supported,
 483                                          val & MDIO_PMA_NG_EXTABLE_2_5GBT);
 484 
 485                         linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
 486                                          phydev->supported,
 487                                          val & MDIO_PMA_NG_EXTABLE_5GBT);
 488                 }
 489         }
 490 
 491         return 0;
 492 }
 493 EXPORT_SYMBOL_GPL(genphy_c45_pma_read_abilities);
 494 
 495 /**
 496  * genphy_c45_read_status - read PHY status
 497  * @phydev: target phy_device struct
 498  *
 499  * Reads status from PHY and sets phy_device members accordingly.
 500  */
 501 int genphy_c45_read_status(struct phy_device *phydev)
 502 {
 503         int ret;
 504 
 505         ret = genphy_c45_read_link(phydev);
 506         if (ret)
 507                 return ret;
 508 
 509         phydev->speed = SPEED_UNKNOWN;
 510         phydev->duplex = DUPLEX_UNKNOWN;
 511         phydev->pause = 0;
 512         phydev->asym_pause = 0;
 513 
 514         if (phydev->autoneg == AUTONEG_ENABLE) {
 515                 ret = genphy_c45_read_lpa(phydev);
 516                 if (ret)
 517                         return ret;
 518 
 519                 phy_resolve_aneg_linkmode(phydev);
 520         } else {
 521                 ret = genphy_c45_read_pma(phydev);
 522         }
 523 
 524         return ret;
 525 }
 526 EXPORT_SYMBOL_GPL(genphy_c45_read_status);
 527 
 528 /**
 529  * genphy_c45_config_aneg - restart auto-negotiation or forced setup
 530  * @phydev: target phy_device struct
 531  *
 532  * Description: If auto-negotiation is enabled, we configure the
 533  *   advertising, and then restart auto-negotiation.  If it is not
 534  *   enabled, then we force a configuration.
 535  */
 536 int genphy_c45_config_aneg(struct phy_device *phydev)
 537 {
 538         bool changed = false;
 539         int ret;
 540 
 541         if (phydev->autoneg == AUTONEG_DISABLE)
 542                 return genphy_c45_pma_setup_forced(phydev);
 543 
 544         ret = genphy_c45_an_config_aneg(phydev);
 545         if (ret < 0)
 546                 return ret;
 547         if (ret > 0)
 548                 changed = true;
 549 
 550         return genphy_c45_check_and_restart_aneg(phydev, changed);
 551 }
 552 EXPORT_SYMBOL_GPL(genphy_c45_config_aneg);
 553 
 554 /* The gen10g_* functions are the old Clause 45 stub */
 555 
 556 int gen10g_config_aneg(struct phy_device *phydev)
 557 {
 558         return 0;
 559 }
 560 EXPORT_SYMBOL_GPL(gen10g_config_aneg);
 561 
 562 struct phy_driver genphy_c45_driver = {
 563         .phy_id         = 0xffffffff,
 564         .phy_id_mask    = 0xffffffff,
 565         .name           = "Generic Clause 45 PHY",
 566         .soft_reset     = genphy_no_soft_reset,
 567         .read_status    = genphy_c45_read_status,
 568 };

/* [<][>][^][v][top][bottom][index][help] */