The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/utopia/idtphy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2003
    3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
    4  *      All rights reserved.
    5  *
    6  * Author: Hartmut Brandt <harti@freebsd.org>
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: releng/9.0/sys/dev/utopia/idtphy.c 142384 2005-02-24 16:56:36Z harti $");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/unistd.h>
   36 #include <sys/kernel.h>
   37 #include <sys/kthread.h>
   38 #include <sys/proc.h>
   39 #include <sys/bus.h>
   40 #include <sys/malloc.h>
   41 #include <sys/module.h>
   42 #include <sys/sysctl.h>
   43 #include <sys/lock.h>
   44 #include <sys/mutex.h>
   45 #include <sys/socket.h>
   46 
   47 #include <net/if.h>
   48 #include <net/if_var.h>
   49 #include <net/if_media.h>
   50 #include <net/if_atm.h>
   51 
   52 #include <dev/utopia/idtphy.h>
   53 #include <dev/utopia/utopia.h>
   54 #include <dev/utopia/utopia_priv.h>
   55 
   56 /*
   57  * Reset IDT77105. There is really no way to reset this thing by acessing
   58  * the registers. Load the registers with default values.
   59  */
   60 static int
   61 idt77105_reset(struct utopia *utp)
   62 {
   63         int err = 0;
   64         u_int n;
   65         uint8_t val[2];
   66 
   67         err |= UTP_WRITEREG(utp, IDTPHY_REGO_MCR, 0xff,
   68             IDTPHY_REGM_MCR_DRIC | IDTPHY_REGM_MCR_EI);
   69         n = 1;
   70         err |= UTP_READREGS(utp, IDTPHY_REGO_ISTAT, val, &n);
   71         err |= UTP_WRITEREG(utp, IDTPHY_REGO_DIAG, 0xff, 0);
   72         err |= UTP_WRITEREG(utp, IDTPHY_REGO_LHEC, 0xff, 0);
   73 
   74         err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_SEC);
   75         n = 2;
   76         err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
   77 
   78         err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_TX);
   79         n = 2;
   80         err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
   81 
   82         err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_RX);
   83         n = 2;
   84         err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
   85 
   86         err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_HECE);
   87         n = 2;
   88         err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
   89 
   90         err |= UTP_WRITEREG(utp, IDTPHY_REGO_MCR, IDTPHY_REGM_MCR_DREC,
   91             IDTPHY_REGM_MCR_DREC);
   92         err |= UTP_WRITEREG(utp, IDTPHY_REGO_DIAG, IDTPHY_REGM_DIAG_RFLUSH,
   93             IDTPHY_REGM_DIAG_RFLUSH);
   94 
   95         /* loopback */
   96         err |= utopia_set_loopback(utp, utp->loopback);
   97 
   98         /* update carrier state */
   99         err |= utopia_update_carrier(utp);
  100 
  101         return (err ? EIO : 0);
  102 }
  103 
  104 static int
  105 idt77105_inval(struct utopia *utp, int what __unused)
  106 {
  107 
  108         return (EINVAL);
  109 }
  110 
  111 static int
  112 idt77105_update_carrier(struct utopia *utp)
  113 {
  114         int err;
  115         uint8_t reg;
  116         u_int n = 1;
  117 
  118         if ((err = UTP_READREGS(utp, IDTPHY_REGO_ISTAT, &reg, &n)) != 0) {
  119                 utp->carrier = UTP_CARR_UNKNOWN;
  120                 return (err);
  121         }
  122         utopia_check_carrier(utp, reg & IDTPHY_REGM_ISTAT_GOOD);
  123         return (0);
  124 }
  125 
  126 static int
  127 idt77105_set_loopback(struct utopia *utp, u_int mode)
  128 {
  129         int err;
  130 
  131         switch (mode) {
  132           case UTP_LOOP_NONE:
  133                 err = UTP_WRITEREG(utp, IDTPHY_REGO_DIAG,
  134                     IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_NONE);
  135                 break;
  136 
  137           case UTP_LOOP_DIAG:
  138                 err = UTP_WRITEREG(utp, IDTPHY_REGO_DIAG,
  139                     IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_PHY);
  140                 break;
  141 
  142           case UTP_LOOP_LINE:
  143                 err = UTP_WRITEREG(utp, IDTPHY_REGO_DIAG,
  144                     IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_LINE);
  145                 break;
  146 
  147           default:
  148                 return (EINVAL);
  149         }
  150         if (err)
  151                 return (err);
  152         utp->loopback = mode;
  153         return (0);
  154 }
  155 
  156 /*
  157  * Handle interrupt on IDT77105 chip
  158  */
  159 static void
  160 idt77105_intr(struct utopia *utp)
  161 {
  162         uint8_t reg;
  163         u_int n = 1;
  164         int err;
  165 
  166         /* Interrupt status and ack the interrupt */
  167         if ((err = UTP_READREGS(utp, IDTPHY_REGO_ISTAT, &reg, &n)) != 0) {
  168                 printf("IDT77105 read error %d\n", err);
  169                 return;
  170         }
  171         /* check for signal condition */
  172         utopia_check_carrier(utp, reg & IDTPHY_REGM_ISTAT_GOOD);
  173 }
  174 
  175 static void
  176 idt77105_update_stats(struct utopia *utp)
  177 {
  178         int err = 0;
  179         uint8_t regs[2];
  180         u_int n;
  181 
  182 #ifdef DIAGNOSTIC
  183 #define UDIAG(F,A,B)    printf(F, A, B)
  184 #else
  185 #define UDIAG(F,A,B)    do { } while (0)
  186 #endif
  187 
  188 #define UPD(FIELD, CODE, N, MASK)                                       \
  189         err = UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, CODE);          \
  190         if (err != 0) {                                                 \
  191                 UDIAG("%s: cannot write CNTS: %d\n", __func__, err);    \
  192                 return;                                                 \
  193         }                                                               \
  194         n = N;                                                          \
  195         err = UTP_READREGS(utp, IDTPHY_REGO_CNT, regs, &n);             \
  196         if (err != 0) {                                                 \
  197                 UDIAG("%s: cannot read CNT: %d\n", __func__, err);      \
  198                 return;                                                 \
  199         }                                                               \
  200         if (n != N) {                                                   \
  201                 UDIAG("%s: got only %u registers\n", __func__, n);      \
  202                 return;                                                 \
  203         }                                                               \
  204         if (N == 1)                                                     \
  205                 utp->stats.FIELD += (regs[0] & MASK);                   \
  206         else                                                            \
  207                 utp->stats.FIELD += (regs[0] | (regs[1] << 8)) & MASK;
  208 
  209         UPD(rx_symerr, IDTPHY_REGM_CNTS_SEC, 1, 0xff);
  210         UPD(tx_cells, IDTPHY_REGM_CNTS_TX, 2, 0xffff);
  211         UPD(rx_cells, IDTPHY_REGM_CNTS_RX, 2, 0xffff);
  212         UPD(rx_uncorr, IDTPHY_REGM_CNTS_HECE, 1, 0x1f);
  213 
  214 #undef  UDIAG
  215 #undef  UPD
  216 }
  217 
  218 struct utopia_chip utopia_chip_idt77105 = {
  219         UTP_TYPE_IDT77105,
  220         "IDT77105",
  221         7,
  222         idt77105_reset,
  223         idt77105_inval,
  224         idt77105_inval,
  225         idt77105_inval,
  226         idt77105_update_carrier,
  227         idt77105_set_loopback,
  228         idt77105_intr,
  229         idt77105_update_stats,
  230 };
  231 
  232 /*
  233  * Update the carrier status
  234  */
  235 static int
  236 idt77155_update_carrier(struct utopia *utp)
  237 {
  238         int err;
  239         uint8_t reg;
  240         u_int n = 1;
  241 
  242         if ((err = UTP_READREGS(utp, IDTPHY_REGO_RSOS, &reg, &n)) != 0) {
  243                 utp->carrier = UTP_CARR_UNKNOWN;
  244                 return (err);
  245         }
  246         utopia_check_carrier(utp, !(reg & IDTPHY_REGM_RSOS_LOS));
  247         return (0);
  248 }
  249 
  250 /*
  251  * Handle interrupt on IDT77155 chip
  252  */
  253 static void
  254 idt77155_intr(struct utopia *utp)
  255 {
  256         uint8_t reg;
  257         u_int n = 1;
  258         int err;
  259 
  260         if ((err = UTP_READREGS(utp, IDTPHY_REGO_RSOS, &reg, &n)) != 0) {
  261                 printf("IDT77105 read error %d\n", err);
  262                 return;
  263         }
  264         utopia_check_carrier(utp, !(reg & IDTPHY_REGM_RSOS_LOS));
  265 }
  266 
  267 /*
  268  * set SONET/SDH mode
  269  */
  270 static int
  271 idt77155_set_sdh(struct utopia *utp, int sdh)
  272 {
  273         int err;
  274 
  275         if (sdh)
  276                 err = UTP_WRITEREG(utp, IDTPHY_REGO_PTRM,
  277                     IDTPHY_REGM_PTRM_SS, IDTPHY_REGM_PTRM_SDH);
  278         else
  279                 err = UTP_WRITEREG(utp, IDTPHY_REGO_PTRM,
  280                     IDTPHY_REGM_PTRM_SS, IDTPHY_REGM_PTRM_SONET);
  281         if (err != 0)
  282                 return (err);
  283 
  284         utp->state &= ~UTP_ST_SDH;
  285         if (sdh)
  286                 utp->state |= UTP_ST_SDH;
  287 
  288         return (0);
  289 }
  290 
  291 /*
  292  * set idle/unassigned cells
  293  */
  294 static int
  295 idt77155_set_unass(struct utopia *utp, int unass)
  296 {
  297         int err;
  298 
  299         if (unass)
  300                 err = UTP_WRITEREG(utp, IDTPHY_REGO_TCHP, 0xff, 0);
  301         else
  302                 err = UTP_WRITEREG(utp, IDTPHY_REGO_TCHP, 0xff, 1);
  303         if (err != 0)
  304                 return (err);
  305 
  306         utp->state &= ~UTP_ST_UNASS;
  307         if (unass)
  308                 utp->state |= UTP_ST_UNASS;
  309 
  310         return (0);
  311 }
  312 
  313 /*
  314  * enable/disable scrambling
  315  */
  316 static int
  317 idt77155_set_noscramb(struct utopia *utp, int noscramb)
  318 {
  319         int err;
  320 
  321         if (noscramb) {
  322                 err = UTP_WRITEREG(utp, IDTPHY_REGO_TCC,
  323                     IDTPHY_REGM_TCC_DSCR, IDTPHY_REGM_TCC_DSCR);
  324                 if (err)
  325                         return (err);
  326                 err = UTP_WRITEREG(utp, IDTPHY_REGO_RCC,
  327                     IDTPHY_REGM_RCC_DSCR, IDTPHY_REGM_RCC_DSCR);
  328                 if (err)
  329                         return (err);
  330                 utp->state |= UTP_ST_NOSCRAMB;
  331         } else {
  332                 err = UTP_WRITEREG(utp, IDTPHY_REGO_TCC,
  333                     IDTPHY_REGM_TCC_DSCR, 0);
  334                 if (err)
  335                         return (err);
  336                 err = UTP_WRITEREG(utp, IDTPHY_REGO_RCC,
  337                     IDTPHY_REGM_RCC_DSCR, 0);
  338                 if (err)
  339                         return (err);
  340                 utp->state &= ~UTP_ST_NOSCRAMB;
  341         }
  342         return (0);
  343 }
  344 
  345 /*
  346  * Set loopback mode for the 77155
  347  */
  348 static int
  349 idt77155_set_loopback(struct utopia *utp, u_int mode)
  350 {
  351         int err;
  352         uint32_t val;
  353         u_int nmode;
  354 
  355         val = 0;
  356         nmode = mode;
  357         if (mode & UTP_LOOP_TIME) {
  358                 nmode &= ~UTP_LOOP_TIME;
  359                 val |= IDTPHY_REGM_MCTL_TLOOP;
  360         }
  361         if (mode & UTP_LOOP_DIAG) {
  362                 nmode &= ~UTP_LOOP_DIAG;
  363                 val |= IDTPHY_REGM_MCTL_DLOOP;
  364         }
  365         if (mode & UTP_LOOP_LINE) {
  366                 nmode &= ~UTP_LOOP_LINE;
  367                 val |= IDTPHY_REGM_MCTL_LLOOP;
  368         }
  369         if (nmode != 0)
  370                 return (EINVAL);
  371 
  372         err = UTP_WRITEREG(utp, IDTPHY_REGO_MCTL, IDTPHY_REGM_MCTL_TLOOP |
  373             IDTPHY_REGM_MCTL_DLOOP | IDTPHY_REGM_MCTL_LLOOP, val);
  374         if (err)
  375                 return (err);
  376         utp->loopback = mode;
  377 
  378         return (0);
  379 }
  380 
  381 /*
  382  * Set the chip to reflect the current state in utopia.
  383  * Assume, that the chip has been reset.
  384  */
  385 static int
  386 idt77155_set_chip(struct utopia *utp)
  387 {
  388         int err = 0;
  389 
  390         /* set sonet/sdh */
  391         err |= idt77155_set_sdh(utp, utp->state & UTP_ST_SDH);
  392 
  393         /* unassigned or idle cells */
  394         err |= idt77155_set_unass(utp, utp->state & UTP_ST_UNASS);
  395 
  396         /* loopback */
  397         err |= idt77155_set_loopback(utp, utp->loopback);
  398 
  399         /* update carrier state */
  400         err |= idt77155_update_carrier(utp);
  401 
  402         /* enable interrupts on LOS */
  403         err |= UTP_WRITEREG(utp, IDTPHY_REGO_INT,
  404             IDTPHY_REGM_INT_RXSOHI, IDTPHY_REGM_INT_RXSOHI);
  405         err |= UTP_WRITEREG(utp, IDTPHY_REGO_RSOC,
  406             IDTPHY_REGM_RSOC_LOSI, IDTPHY_REGM_RSOC_LOSI);
  407 
  408         return (err ? EIO : 0);
  409 }
  410 
  411 /*
  412  * Reset the chip to reflect the current state of utopia.
  413  */
  414 static int
  415 idt77155_reset(struct utopia *utp)
  416 {
  417         int err = 0;
  418 
  419         if (!(utp->flags & UTP_FL_NORESET)) {
  420                 err |= UTP_WRITEREG(utp, IDTPHY_REGO_MRID,
  421                     IDTPHY_REGM_MRID_RESET, IDTPHY_REGM_MRID_RESET);
  422                 err |= UTP_WRITEREG(utp, IDTPHY_REGO_MRID,
  423                     IDTPHY_REGM_MRID_RESET, 0);
  424         }
  425 
  426         err |= idt77155_set_chip(utp);
  427 
  428         return (err ? EIO : 0);
  429 }
  430 
  431 /*
  432  * Update statistics from a IDT77155
  433  * This appears to be the same as for the Suni/Lite and Ultra. IDT however
  434  * makes no assessment about the transfer time. Assume 7us.
  435  */
  436 static void
  437 idt77155_update_stats(struct utopia *utp)
  438 {
  439         int err;
  440 
  441         /* write to the master if we can */
  442         if (!(utp->flags & UTP_FL_NORESET)) {
  443                 err = UTP_WRITEREG(utp, IDTPHY_REGO_MRID, 0, 0);
  444         } else {
  445                 err = UTP_WRITEREG(utp, IDTPHY_REGO_BIPC, 0, 0);
  446                 err |= UTP_WRITEREG(utp, IDTPHY_REGO_B2EC, 0, 0);
  447                 err |= UTP_WRITEREG(utp, IDTPHY_REGO_B3EC, 0, 0);
  448                 err |= UTP_WRITEREG(utp, IDTPHY_REGO_CEC, 0, 0);
  449                 err |= UTP_WRITEREG(utp, IDTPHY_REGO_TXCNT, 0, 0);
  450 
  451         }
  452         if (err) {
  453 #ifdef DIAGNOSTIC
  454                 printf("%s: register write error %s: %d\n", __func__,
  455                     utp->chip->name, err);
  456 #endif
  457                 return;
  458         }
  459 
  460         DELAY(8);
  461 
  462         utp->stats.rx_sbip += utopia_update(utp,
  463             IDTPHY_REGO_BIPC, 2, 0xffff);
  464         utp->stats.rx_lbip += utopia_update(utp,
  465             IDTPHY_REGO_B2EC, 3, 0xfffff);
  466         utp->stats.rx_lfebe += utopia_update(utp,
  467             IDTPHY_REGO_FEBEC, 3, 0xfffff);
  468         utp->stats.rx_pbip += utopia_update(utp,
  469             IDTPHY_REGO_B3EC, 2, 0xffff);
  470         utp->stats.rx_pfebe += utopia_update(utp,
  471             IDTPHY_REGO_PFEBEC, 2, 0xffff);
  472         utp->stats.rx_corr += utopia_update(utp,
  473             IDTPHY_REGO_CEC, 1, 0xff);
  474         utp->stats.rx_uncorr += utopia_update(utp,
  475             IDTPHY_REGO_UEC, 1, 0xff);
  476         utp->stats.rx_cells += utopia_update(utp,
  477             IDTPHY_REGO_RCCNT, 3, 0x7ffff);
  478         utp->stats.tx_cells += utopia_update(utp,
  479             IDTPHY_REGO_TXCNT, 3, 0x7ffff);
  480 }
  481 
  482 const struct utopia_chip utopia_chip_idt77155 = {
  483         UTP_TYPE_IDT77155,
  484         "IDT77155",
  485         0x80,
  486         idt77155_reset,
  487         idt77155_set_sdh,
  488         idt77155_set_unass,
  489         idt77155_set_noscramb,
  490         idt77155_update_carrier,
  491         idt77155_set_loopback,
  492         idt77155_intr,
  493         idt77155_update_stats,
  494 };

Cache object: 2330826cc02fc47cbd12c3f2f10580a7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.