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/cxgb/common/cxgb_vsc7323.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 /**************************************************************************
    3 
    4 Copyright (c) 2007, Chelsio Inc.
    5 All rights reserved.
    6 
    7 Redistribution and use in source and binary forms, with or without
    8 modification, are permitted provided that the following conditions are met:
    9 
   10  1. Redistributions of source code must retain the above copyright notice,
   11     this list of conditions and the following disclaimer.
   12 
   13  2. Neither the name of the Chelsio Corporation nor the names of its
   14     contributors may be used to endorse or promote products derived from
   15     this software without specific prior written permission.
   16 
   17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   18 AND 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
   21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27 POSSIBILITY OF SUCH DAMAGE.
   28 
   29 ***************************************************************************/
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/6.4/sys/dev/cxgb/common/cxgb_vsc7323.c 174319 2007-12-05 22:05:49Z kmacy $");
   33 
   34 #ifdef CONFIG_DEFINED
   35 #include <common/cxgb_common.h>
   36 #else
   37 #include <dev/cxgb/common/cxgb_common.h>
   38 #endif
   39 
   40 enum {
   41         ELMR_ADDR    = 0,
   42         ELMR_STAT    = 1,
   43         ELMR_DATA_LO = 2,
   44         ELMR_DATA_HI = 3,
   45 
   46         ELMR_THRES0  = 0xe000,
   47         ELMR_BW      = 0xe00c,
   48         ELMR_FIFO_SZ = 0xe00d,
   49         ELMR_STATS   = 0xf000,
   50 
   51         ELMR_MDIO_ADDR = 10
   52 };
   53 
   54 #define VSC_REG(block, subblock, reg) \
   55         ((reg) | ((subblock) << 8) | ((block) << 12))
   56 
   57 int t3_elmr_blk_write(adapter_t *adap, int start, const u32 *vals, int n)
   58 {
   59         int ret;
   60         const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
   61 
   62         ELMR_LOCK(adap);
   63         ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
   64         for ( ; !ret && n; n--, vals++) {
   65                 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO,
   66                                 *vals & 0xffff);
   67                 if (!ret)
   68                         ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
   69                                         *vals >> 16);
   70         }
   71         ELMR_UNLOCK(adap);
   72         return ret;
   73 }
   74 
   75 static int elmr_write(adapter_t *adap, int addr, u32 val)
   76 {
   77         return t3_elmr_blk_write(adap, addr, &val, 1);
   78 }
   79 
   80 int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n)
   81 {
   82         int i, ret;
   83         unsigned int v;
   84         const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
   85 
   86         ELMR_LOCK(adap);
   87 
   88         ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
   89         if (ret)
   90                 goto out;
   91 
   92         for (i = 0; i < 5; i++) {
   93                 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v);
   94                 if (ret)
   95                         goto out;
   96                 if (v == 1)
   97                         break;
   98                 udelay(5);
   99         }
  100         if (v != 1) {
  101                 ret = -ETIMEDOUT;
  102                 goto out;
  103         }
  104 
  105         for ( ; !ret && n; n--, vals++) {
  106                 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO, vals);
  107                 if (!ret) {
  108                         ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
  109                                        &v);
  110                         *vals |= v << 16;
  111                 }
  112         }
  113 out:    ELMR_UNLOCK(adap);
  114         return ret;
  115 }
  116 
  117 int t3_vsc7323_init(adapter_t *adap, int nports)
  118 {
  119         static struct addr_val_pair sys_avp[] = {
  120                 { VSC_REG(7, 15, 0xf),  2 },
  121                 { VSC_REG(7, 15, 0x19), 0xd6 },
  122                 { VSC_REG(7, 15, 7),    0xc },
  123                 { VSC_REG(7, 1, 0),     0x220 },
  124         };
  125         static struct addr_val_pair fifo_avp[] = {
  126                 { VSC_REG(2, 0, 0x2f), 0 },
  127                 { VSC_REG(2, 0, 0xf),  0xa0010291 },
  128                 { VSC_REG(2, 1, 0x2f), 1 },
  129                 { VSC_REG(2, 1, 0xf),  0xa026301 }
  130         };
  131         static struct addr_val_pair xg_avp[] = {
  132                 { VSC_REG(1, 10, 0),    0x600b },
  133                 { VSC_REG(1, 10, 1),    0x70600 }, //QUANTA = 96*1024*8/512
  134                 { VSC_REG(1, 10, 2),    0x2710 },
  135                 { VSC_REG(1, 10, 5),    0x65 },
  136                 { VSC_REG(1, 10, 7),    0x23 },
  137                 { VSC_REG(1, 10, 0x23), 0x800007bf },
  138                 { VSC_REG(1, 10, 0x23), 0x000007bf },
  139                 { VSC_REG(1, 10, 0x23), 0x800007bf },
  140                 { VSC_REG(1, 10, 0x24), 4 }
  141         };
  142 
  143         int i, ret, ing_step, egr_step, ing_bot, egr_bot;
  144 
  145         for (i = 0; i < ARRAY_SIZE(sys_avp); i++)
  146                 if ((ret = t3_elmr_blk_write(adap, sys_avp[i].reg_addr,
  147                                              &sys_avp[i].val, 1)))
  148                         return ret;
  149 
  150         ing_step = 0xc0 / nports;
  151         egr_step = 0x40 / nports;
  152         ing_bot = egr_bot = 0;
  153 //      ing_wm = ing_step * 64;
  154 //      egr_wm = egr_step * 64;
  155 
  156         /* {ING,EGR}_CONTROL.CLR = 1 here */
  157         for (i = 0; i < nports; i++) {
  158                 if (
  159                     (ret = elmr_write(adap, VSC_REG(2, 0, 0x10 + i),
  160                                 ((ing_bot + ing_step) << 16) | ing_bot)) ||
  161                     (ret = elmr_write(adap, VSC_REG(2, 0, 0x40 + i),
  162                                 0x6000bc0)) ||
  163                     (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 1)) ||
  164                     (ret = elmr_write(adap, VSC_REG(2, 1, 0x10 + i),
  165                                 ((egr_bot + egr_step) << 16) | egr_bot)) ||
  166                     (ret = elmr_write(adap, VSC_REG(2, 1, 0x40 + i),
  167                                 0x2000280)) ||
  168                     (ret = elmr_write(adap, VSC_REG(2, 1, 0x50 + i), 0)))
  169                         return ret;
  170                 ing_bot += ing_step;
  171                 egr_bot += egr_step;
  172         }
  173 
  174         for (i = 0; i < ARRAY_SIZE(fifo_avp); i++)
  175                 if ((ret = t3_elmr_blk_write(adap, fifo_avp[i].reg_addr,
  176                                              &fifo_avp[i].val, 1)))
  177                         return ret;
  178 
  179         for (i = 0; i < ARRAY_SIZE(xg_avp); i++)
  180                 if ((ret = t3_elmr_blk_write(adap, xg_avp[i].reg_addr,
  181                                              &xg_avp[i].val, 1)))
  182                         return ret;
  183 
  184         for (i = 0; i < nports; i++)
  185                 if ((ret = elmr_write(adap, VSC_REG(1, i, 0), 0xa59c)) ||
  186                     (ret = elmr_write(adap, VSC_REG(1, i, 5),
  187                                  (i << 12) | 0x63)) ||
  188                     (ret = elmr_write(adap, VSC_REG(1, i, 0xb), 0x96)) ||
  189                     (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21)) ||
  190                     (ret = elmr_write(adap, ELMR_THRES0 + i, 768)))
  191                         return ret;
  192 
  193         if ((ret = elmr_write(adap, ELMR_BW, 7)))
  194                 return ret;
  195 
  196         return ret;
  197 }
  198 
  199 int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port)
  200 {
  201         int mode, clk, r;
  202 
  203         if (speed >= 0) {
  204                 if (speed == SPEED_10)
  205                         mode = clk = 1;
  206                 else if (speed == SPEED_100)
  207                         mode = 1, clk = 2;
  208                 else if (speed == SPEED_1000)
  209                         mode = clk = 3;
  210                 else
  211                         return -EINVAL;
  212 
  213                 if ((r = elmr_write(adap, VSC_REG(1, port, 0),
  214                                     0xa590 | (mode << 2))) ||
  215                     (r = elmr_write(adap, VSC_REG(1, port, 0xb),
  216                                     0x91 | (clk << 1))) ||
  217                     (r = elmr_write(adap, VSC_REG(1, port, 0xb),
  218                                     0x90 | (clk << 1))) ||
  219                     (r = elmr_write(adap, VSC_REG(1, port, 0),
  220                                     0xa593 | (mode << 2))))
  221                         return r;
  222         }
  223 
  224         r = (fc & PAUSE_RX) ? 0x60200 : 0x20200; //QUANTA = 32*1024*8/512
  225         if (fc & PAUSE_TX)
  226                 r |= (1 << 19);
  227         return elmr_write(adap, VSC_REG(1, port, 1), r);
  228 }
  229 
  230 int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port)
  231 {
  232         return elmr_write(adap, VSC_REG(1, port, 2), mtu);
  233 }
  234 
  235 int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port)
  236 {
  237         int ret;
  238 
  239         ret = elmr_write(adap, VSC_REG(1, port, 3),
  240                          (addr[0] << 16) | (addr[1] << 8) | addr[2]);
  241         if (!ret)
  242                 ret = elmr_write(adap, VSC_REG(1, port, 4),
  243                                  (addr[3] << 16) | (addr[4] << 8) | addr[5]);
  244         return ret;
  245 }
  246 
  247 int t3_vsc7323_enable(adapter_t *adap, int port, int which)
  248 {
  249         int ret;
  250         unsigned int v, orig;
  251 
  252         ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
  253         if (!ret) {
  254                 orig = v;
  255                 if (which & MAC_DIRECTION_TX)
  256                         v |= 1;
  257                 if (which & MAC_DIRECTION_RX)
  258                         v |= 2;
  259                 if (v != orig)
  260                         ret = elmr_write(adap, VSC_REG(1, port, 0), v);
  261         }
  262         return ret;
  263 }
  264 
  265 int t3_vsc7323_disable(adapter_t *adap, int port, int which)
  266 {
  267         int ret;
  268         unsigned int v, orig;
  269 
  270         ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
  271         if (!ret) {
  272                 orig = v;
  273                 if (which & MAC_DIRECTION_TX)
  274                         v &= ~1;
  275                 if (which & MAC_DIRECTION_RX)
  276                         v &= ~2;
  277                 if (v != orig)
  278                         ret = elmr_write(adap, VSC_REG(1, port, 0), v);
  279         }
  280         return ret;
  281 }
  282 
  283 #define STATS0_START 1
  284 #define STATS1_START 0x24
  285 #define NSTATS0 (0x1d - STATS0_START + 1)
  286 #define NSTATS1 (0x2a - STATS1_START + 1)
  287 
  288 #define ELMR_STAT(port, reg) (ELMR_STATS + port * 0x40 + reg)
  289 
  290 const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac)
  291 {
  292         int ret;
  293         u64 rx_ucast, tx_ucast;
  294         u32 stats0[NSTATS0], stats1[NSTATS1];
  295 
  296         ret = t3_elmr_blk_read(mac->adapter,
  297                                ELMR_STAT(mac->ext_port, STATS0_START),
  298                                stats0, NSTATS0);
  299         if (!ret)
  300                 ret = t3_elmr_blk_read(mac->adapter,
  301                                        ELMR_STAT(mac->ext_port, STATS1_START),
  302                                        stats1, NSTATS1);
  303         if (ret)
  304                 goto out;
  305 
  306         /*
  307          * HW counts Rx/Tx unicast frames but we want all the frames.
  308          */
  309         rx_ucast = mac->stats.rx_frames - mac->stats.rx_mcast_frames -
  310                    mac->stats.rx_bcast_frames;
  311         rx_ucast += (u64)(stats0[6 - STATS0_START] - (u32)rx_ucast);
  312         tx_ucast = mac->stats.tx_frames - mac->stats.tx_mcast_frames -
  313                    mac->stats.tx_bcast_frames;
  314         tx_ucast += (u64)(stats0[27 - STATS0_START] - (u32)tx_ucast);
  315 
  316 #define RMON_UPDATE(mac, name, hw_stat) \
  317         mac->stats.name += (u64)((hw_stat) - (u32)(mac->stats.name))
  318 
  319         RMON_UPDATE(mac, rx_octets, stats0[4 - STATS0_START]);
  320         RMON_UPDATE(mac, rx_frames, stats0[6 - STATS0_START]);
  321         RMON_UPDATE(mac, rx_frames, stats0[7 - STATS0_START]);
  322         RMON_UPDATE(mac, rx_frames, stats0[8 - STATS0_START]);
  323         RMON_UPDATE(mac, rx_mcast_frames, stats0[7 - STATS0_START]);
  324         RMON_UPDATE(mac, rx_bcast_frames, stats0[8 - STATS0_START]);
  325         RMON_UPDATE(mac, rx_fcs_errs, stats0[9 - STATS0_START]);
  326         RMON_UPDATE(mac, rx_pause, stats0[2 - STATS0_START]);
  327         RMON_UPDATE(mac, rx_jabber, stats0[16 - STATS0_START]);
  328         RMON_UPDATE(mac, rx_short, stats0[11 - STATS0_START]);
  329         RMON_UPDATE(mac, rx_symbol_errs, stats0[1 - STATS0_START]);
  330         RMON_UPDATE(mac, rx_too_long, stats0[15 - STATS0_START]);
  331 
  332         RMON_UPDATE(mac, rx_frames_64,        stats0[17 - STATS0_START]);
  333         RMON_UPDATE(mac, rx_frames_65_127,    stats0[18 - STATS0_START]);
  334         RMON_UPDATE(mac, rx_frames_128_255,   stats0[19 - STATS0_START]);
  335         RMON_UPDATE(mac, rx_frames_256_511,   stats0[20 - STATS0_START]);
  336         RMON_UPDATE(mac, rx_frames_512_1023,  stats0[21 - STATS0_START]);
  337         RMON_UPDATE(mac, rx_frames_1024_1518, stats0[22 - STATS0_START]);
  338         RMON_UPDATE(mac, rx_frames_1519_max,  stats0[23 - STATS0_START]);
  339 
  340         RMON_UPDATE(mac, tx_octets, stats0[26 - STATS0_START]);
  341         RMON_UPDATE(mac, tx_frames, stats0[27 - STATS0_START]);
  342         RMON_UPDATE(mac, tx_frames, stats0[28 - STATS0_START]);
  343         RMON_UPDATE(mac, tx_frames, stats0[29 - STATS0_START]);
  344         RMON_UPDATE(mac, tx_mcast_frames, stats0[28 - STATS0_START]);
  345         RMON_UPDATE(mac, tx_bcast_frames, stats0[29 - STATS0_START]);
  346         RMON_UPDATE(mac, tx_pause, stats0[25 - STATS0_START]);
  347 
  348         RMON_UPDATE(mac, tx_underrun, 0);
  349 
  350         RMON_UPDATE(mac, tx_frames_64,        stats1[36 - STATS1_START]);
  351         RMON_UPDATE(mac, tx_frames_65_127,    stats1[37 - STATS1_START]);
  352         RMON_UPDATE(mac, tx_frames_128_255,   stats1[38 - STATS1_START]);
  353         RMON_UPDATE(mac, tx_frames_256_511,   stats1[39 - STATS1_START]);
  354         RMON_UPDATE(mac, tx_frames_512_1023,  stats1[40 - STATS1_START]);
  355         RMON_UPDATE(mac, tx_frames_1024_1518, stats1[41 - STATS1_START]);
  356         RMON_UPDATE(mac, tx_frames_1519_max,  stats1[42 - STATS1_START]);
  357 
  358 #undef RMON_UPDATE
  359 
  360         mac->stats.rx_frames = rx_ucast + mac->stats.rx_mcast_frames +
  361                                mac->stats.rx_bcast_frames;
  362         mac->stats.tx_frames = tx_ucast + mac->stats.tx_mcast_frames +
  363                                mac->stats.tx_bcast_frames;
  364 out:    return &mac->stats;
  365 }

Cache object: 1571f621c9df6b34bb0da8e8feadb346


[ 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.