1 /*
   2  * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  * 1. Redistributions of source code must retain the above copyright
   8  *    notice, this list of conditions and the following disclaimer.
   9  * 2. Redistributions in binary form must reproduce the above copyright
  10  *    notice, this list of conditions and the following disclaimer in the
  11  *    documentation and/or other materials provided with the distribution.
  12  *
  13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
  14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23  * SUCH DAMAGE.
  24  */
  25 
  26 #include "efsys.h"
  27 #include "efx.h"
  28 #include "efx_types.h"
  29 #include "efx_regs.h"
  30 #include "efx_impl.h"
  31 
  32         __checkReturn   int
  33 efx_family(
  34         __in            uint16_t venid,
  35         __in            uint16_t devid,
  36         __out           efx_family_t *efp)
  37 {
  38 #if EFSYS_OPT_FALCON
  39         if (venid == EFX_PCI_VENID_SFC && devid == EFX_PCI_DEVID_FALCON) {
  40                 *efp = EFX_FAMILY_FALCON;
  41                 return (0);
  42         }
  43 #endif
  44 #if EFSYS_OPT_SIENA
  45         if (venid == EFX_PCI_VENID_SFC && devid == EFX_PCI_DEVID_BETHPAGE) {
  46                 *efp = EFX_FAMILY_SIENA;
  47                 return (0);
  48         }
  49         if (venid == EFX_PCI_VENID_SFC && devid == EFX_PCI_DEVID_SIENA) {
  50                 *efp = EFX_FAMILY_SIENA;
  51                 return (0);
  52         }
  53         if (venid == EFX_PCI_VENID_SFC &&
  54             devid == EFX_PCI_DEVID_SIENA_F1_UNINIT) {
  55                 *efp = EFX_FAMILY_SIENA;
  56                 return (0);
  57         }
  58 #endif
  59         return (ENOTSUP);
  60 }
  61 
  62 /*
  63  * To support clients which aren't provided with any PCI context infer
  64  * the hardware family by inspecting the hardware. Obviously the caller
  65  * must be damn sure they're really talking to a supported device.
  66  */
  67         __checkReturn   int
  68 efx_infer_family(
  69         __in            efsys_bar_t *esbp,
  70         __out           efx_family_t *efp)
  71 {
  72         efx_family_t family;
  73         efx_oword_t oword;
  74         unsigned int portnum;
  75         int rc;
  76 
  77         EFSYS_BAR_READO(esbp, FR_AZ_CS_DEBUG_REG_OFST, &oword, B_TRUE);
  78         portnum = EFX_OWORD_FIELD(oword, FRF_CZ_CS_PORT_NUM);
  79         switch (portnum) {
  80 #if EFSYS_OPT_FALCON
  81         case 0:
  82                 family = EFX_FAMILY_FALCON;
  83                 break;
  84 #endif
  85 #if EFSYS_OPT_SIENA
  86         case 1:
  87         case 2:
  88                 family = EFX_FAMILY_SIENA;
  89                 break;
  90 #endif
  91         default:
  92                 rc = ENOTSUP;
  93                 goto fail1;
  94         }
  95 
  96         if (efp != NULL)
  97                 *efp = family;
  98         return (0);
  99 
 100 fail1:
 101         EFSYS_PROBE1(fail1, int, rc);
 102 
 103         return (rc);
 104 }
 105 
 106 /*
 107  * The built-in default value device id for port 1 of Siena is 0x0810.
 108  * manftest needs to be able to cope with that.
 109  */
 110 
 111 #define EFX_BIU_MAGIC0  0x01234567
 112 #define EFX_BIU_MAGIC1  0xfedcba98
 113 
 114 static  __checkReturn   int
 115 efx_nic_biu_test(
 116         __in            efx_nic_t *enp)
 117 {
 118         efx_oword_t oword;
 119         int rc;
 120 
 121         /*
 122          * Write magic values to scratch registers 0 and 1, then
 123          * verify that the values were written correctly.  Interleave
 124          * the accesses to ensure that the BIU is not just reading
 125          * back the cached value that was last written.
 126          */
 127         EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0);
 128         EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword);
 129 
 130         EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1);
 131         EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword);
 132 
 133         EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword);
 134         if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) {
 135                 rc = EIO;
 136                 goto fail1;
 137         }
 138 
 139         EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword);
 140         if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) {
 141                 rc = EIO;
 142                 goto fail2;
 143         }
 144 
 145         /*
 146          * Perform the same test, with the values swapped.  This
 147          * ensures that subsequent tests don't start with the correct
 148          * values already written into the scratch registers.
 149          */
 150         EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1);
 151         EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword);
 152 
 153         EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0);
 154         EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword);
 155 
 156         EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword);
 157         if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) {
 158                 rc = EIO;
 159                 goto fail3;
 160         }
 161 
 162         EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword);
 163         if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) {
 164                 rc = EIO;
 165                 goto fail4;
 166         }
 167 
 168         return (0);
 169 
 170 fail4:
 171         EFSYS_PROBE(fail4);
 172 fail3:
 173         EFSYS_PROBE(fail3);
 174 fail2:
 175         EFSYS_PROBE(fail2);
 176 fail1:
 177         EFSYS_PROBE1(fail1, int, rc);
 178 
 179         return (rc);
 180 }
 181 
 182 #if EFSYS_OPT_FALCON
 183 
 184 static efx_nic_ops_t    __cs __efx_nic_falcon_ops = {
 185         falcon_nic_probe,               /* eno_probe */
 186         falcon_nic_reset,               /* eno_reset */
 187         falcon_nic_init,                /* eno_init */
 188 #if EFSYS_OPT_DIAG
 189         falcon_sram_test,               /* eno_sram_test */
 190         falcon_nic_register_test,       /* eno_register_test */
 191 #endif  /* EFSYS_OPT_DIAG */
 192         falcon_nic_fini,                /* eno_fini */
 193         falcon_nic_unprobe,             /* eno_unprobe */
 194 };
 195 
 196 #endif  /* EFSYS_OPT_FALCON */
 197 
 198 #if EFSYS_OPT_SIENA
 199 
 200 static efx_nic_ops_t    __cs __efx_nic_siena_ops = {
 201         siena_nic_probe,                /* eno_probe */
 202         siena_nic_reset,                /* eno_reset */
 203         siena_nic_init,                 /* eno_init */
 204 #if EFSYS_OPT_DIAG
 205         siena_sram_test,                /* eno_sram_test */
 206         siena_nic_register_test,        /* eno_register_test */
 207 #endif  /* EFSYS_OPT_DIAG */
 208         siena_nic_fini,                 /* eno_fini */
 209         siena_nic_unprobe,              /* eno_unprobe */
 210 };
 211 
 212 #endif  /* EFSYS_OPT_SIENA */
 213 
 214         __checkReturn   int
 215 efx_nic_create(
 216         __in            efx_family_t family,
 217         __in            efsys_identifier_t *esip,
 218         __in            efsys_bar_t *esbp,
 219         __in            efsys_lock_t *eslp,
 220         __deref_out     efx_nic_t **enpp)
 221 {
 222         efx_nic_t *enp;
 223         int rc;
 224 
 225         EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID);
 226         EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES);
 227 
 228         /* Allocate a NIC object */
 229         EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp);
 230 
 231         if (enp == NULL) {
 232                 rc = ENOMEM;
 233                 goto fail1;
 234         }
 235 
 236         enp->en_magic = EFX_NIC_MAGIC;
 237 
 238         switch (family) {
 239 #if EFSYS_OPT_FALCON
 240         case EFX_FAMILY_FALCON:
 241                 enp->en_enop = (efx_nic_ops_t *)&__efx_nic_falcon_ops;
 242                 enp->en_features = 0;
 243                 break;
 244 #endif  /* EFSYS_OPT_FALCON */
 245 
 246 #if EFSYS_OPT_SIENA
 247         case EFX_FAMILY_SIENA:
 248                 enp->en_enop = (efx_nic_ops_t *)&__efx_nic_siena_ops;
 249                 enp->en_features =
 250                     EFX_FEATURE_IPV6 |
 251                     EFX_FEATURE_LFSR_HASH_INSERT |
 252                     EFX_FEATURE_LINK_EVENTS |
 253                     EFX_FEATURE_PERIODIC_MAC_STATS |
 254                     EFX_FEATURE_WOL |
 255                     EFX_FEATURE_MCDI |
 256                     EFX_FEATURE_LOOKAHEAD_SPLIT |
 257                     EFX_FEATURE_MAC_HEADER_FILTERS;
 258                 break;
 259 #endif  /* EFSYS_OPT_SIENA */
 260 
 261         default:
 262                 rc = ENOTSUP;
 263                 goto fail2;
 264         }
 265 
 266         enp->en_family = family;
 267         enp->en_esip = esip;
 268         enp->en_esbp = esbp;
 269         enp->en_eslp = eslp;
 270 
 271         *enpp = enp;
 272 
 273         return (0);
 274 
 275 fail2:
 276         EFSYS_PROBE(fail3);
 277 
 278         enp->en_magic = 0;
 279 
 280         /* Free the NIC object */
 281         EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
 282 
 283 fail1:
 284         EFSYS_PROBE1(fail1, int, rc);
 285 
 286         return (rc);
 287 }
 288 
 289         __checkReturn   int
 290 efx_nic_probe(
 291         __in            efx_nic_t *enp)
 292 {
 293         efx_nic_ops_t *enop;
 294         efx_oword_t oword;
 295         int rc;
 296 
 297         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 298 #if EFSYS_OPT_MCDI
 299         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
 300 #endif  /* EFSYS_OPT_MCDI */
 301         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
 302 
 303         /* Test BIU */
 304         if ((rc = efx_nic_biu_test(enp)) != 0)
 305                 goto fail1;
 306 
 307         /* Clear the region register */
 308         EFX_POPULATE_OWORD_4(oword,
 309             FRF_AZ_ADR_REGION0, 0,
 310             FRF_AZ_ADR_REGION1, (1 << 16),
 311             FRF_AZ_ADR_REGION2, (2 << 16),
 312             FRF_AZ_ADR_REGION3, (3 << 16));
 313         EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
 314 
 315         enop = enp->en_enop;
 316         if ((rc = enop->eno_probe(enp)) != 0)
 317                 goto fail2;
 318 
 319         if ((rc = efx_phy_probe(enp)) != 0)
 320                 goto fail3;
 321 
 322         enp->en_mod_flags |= EFX_MOD_PROBE;
 323 
 324         return (0);
 325 
 326 fail3:
 327         EFSYS_PROBE(fail3);
 328 
 329         enop->eno_unprobe(enp);
 330 
 331 fail2:
 332         EFSYS_PROBE(fail2);
 333 fail1:
 334         EFSYS_PROBE1(fail1, int, rc);
 335 
 336         return (rc);
 337 }
 338 
 339 #if EFSYS_OPT_PCIE_TUNE
 340 
 341         __checkReturn   int
 342 efx_nic_pcie_tune(
 343         __in            efx_nic_t *enp,
 344         unsigned int    nlanes)
 345 {
 346         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 347         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
 348         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
 349 
 350 #if EFSYS_OPT_FALCON
 351         if (enp->en_family == EFX_FAMILY_FALCON)
 352                 return (falcon_nic_pcie_tune(enp, nlanes));
 353 #endif
 354         return (ENOTSUP);
 355 }
 356 
 357         __checkReturn   int
 358 efx_nic_pcie_extended_sync(
 359         __in            efx_nic_t *enp)
 360 {
 361         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 362         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
 363         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
 364 
 365 #if EFSYS_OPT_SIENA
 366         if (enp->en_family == EFX_FAMILY_SIENA)
 367                 return (siena_nic_pcie_extended_sync(enp));
 368 #endif
 369 
 370         return (ENOTSUP);
 371 }
 372 
 373 #endif  /* EFSYS_OPT_PCIE_TUNE */
 374 
 375         __checkReturn   int
 376 efx_nic_init(
 377         __in            efx_nic_t *enp)
 378 {
 379         efx_nic_ops_t *enop = enp->en_enop;
 380         int rc;
 381 
 382         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 383         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
 384 
 385         if (enp->en_mod_flags & EFX_MOD_NIC) {
 386                 rc = EINVAL;
 387                 goto fail1;
 388         }
 389 
 390         if ((rc = enop->eno_init(enp)) != 0)
 391                 goto fail2;
 392 
 393         enp->en_mod_flags |= EFX_MOD_NIC;
 394 
 395         return (0);
 396 
 397 fail2:
 398         EFSYS_PROBE(fail2);
 399 fail1:
 400         EFSYS_PROBE1(fail1, int, rc);
 401 
 402         return (rc);
 403 }
 404 
 405                         void
 406 efx_nic_fini(
 407         __in            efx_nic_t *enp)
 408 {
 409         efx_nic_ops_t *enop = enp->en_enop;
 410 
 411         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 412         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
 413         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC);
 414         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
 415         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
 416         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
 417         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
 418 
 419         enop->eno_fini(enp);
 420 
 421         enp->en_mod_flags &= ~EFX_MOD_NIC;
 422 }
 423 
 424                         void
 425 efx_nic_unprobe(
 426         __in            efx_nic_t *enp)
 427 {
 428         efx_nic_ops_t *enop = enp->en_enop;
 429 
 430         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 431 #if EFSYS_OPT_MCDI
 432         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
 433 #endif  /* EFSYS_OPT_MCDI */
 434         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
 435         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
 436         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
 437         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
 438         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
 439         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
 440 
 441         efx_phy_unprobe(enp);
 442 
 443         enop->eno_unprobe(enp);
 444 
 445         enp->en_mod_flags &= ~EFX_MOD_PROBE;
 446 }
 447 
 448                         void
 449 efx_nic_destroy(
 450         __in    efx_nic_t *enp)
 451 {
 452         efsys_identifier_t *esip = enp->en_esip;
 453 
 454         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 455         EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0);
 456 
 457         enp->en_family = 0;
 458         enp->en_esip = NULL;
 459         enp->en_esbp = NULL;
 460         enp->en_eslp = NULL;
 461 
 462         enp->en_enop = NULL;
 463 
 464         enp->en_magic = 0;
 465 
 466         /* Free the NIC object */
 467         EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
 468 }
 469 
 470         __checkReturn   int
 471 efx_nic_reset(
 472         __in            efx_nic_t *enp)
 473 {
 474         efx_nic_ops_t *enop = enp->en_enop;
 475         unsigned int mod_flags;
 476         int rc;
 477 
 478         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 479         EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
 480         /*
 481          * All modules except the MCDI, PROBE, NVRAM, VPD, MON (which we
 482          * do not reset here) must have been shut down or never initialized.
 483          *
 484          * A rule of thumb here is: If the controller or MC reboots, is *any*
 485          * state lost. If it's lost and needs reapplying, then the module
 486          * *must* not be initialised during the reset.
 487          */
 488         mod_flags = enp->en_mod_flags;
 489         mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
 490                     EFX_MOD_VPD | EFX_MOD_MON);
 491         EFSYS_ASSERT3U(mod_flags, ==, 0);
 492         if (mod_flags != 0) {
 493                 rc = EINVAL;
 494                 goto fail1;
 495         }
 496 
 497         if ((rc = enop->eno_reset(enp)) != 0)
 498                 goto fail2;
 499 
 500         enp->en_reset_flags |= EFX_RESET_MAC;
 501 
 502         return (0);
 503 
 504 fail2:
 505         EFSYS_PROBE(fail2);
 506 fail1:
 507         EFSYS_PROBE1(fail1, int, rc);
 508 
 509         return (rc);
 510 }
 511 
 512                         const efx_nic_cfg_t *
 513 efx_nic_cfg_get(
 514         __in            efx_nic_t *enp)
 515 {
 516         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 517 
 518         return (&(enp->en_nic_cfg));
 519 }
 520 
 521 #if EFSYS_OPT_DIAG
 522 
 523         __checkReturn   int
 524 efx_nic_register_test(
 525         __in            efx_nic_t *enp)
 526 {
 527         efx_nic_ops_t *enop = enp->en_enop;
 528         int rc;
 529 
 530         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
 531         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
 532         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
 533 
 534         if ((rc = enop->eno_register_test(enp)) != 0)
 535                 goto fail1;
 536 
 537         return (0);
 538 
 539 fail1:
 540         EFSYS_PROBE1(fail1, int, rc);
 541 
 542         return (rc);
 543 }
 544 
 545         __checkReturn   int
 546 efx_nic_test_registers(
 547         __in            efx_nic_t *enp,
 548         __in            efx_register_set_t *rsp,
 549         __in            size_t count)
 550 {
 551         unsigned int bit;
 552         efx_oword_t original;
 553         efx_oword_t reg;
 554         efx_oword_t buf;
 555         int rc;
 556 
 557         while (count > 0) {
 558                 /* This function is only suitable for registers */
 559                 EFSYS_ASSERT(rsp->rows == 1);
 560 
 561                 /* bit sweep on and off */
 562                 EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original,
 563                             B_TRUE);
 564                 for (bit = 0; bit < 128; bit++) {
 565                         /* Is this bit in the mask? */
 566                         if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit))
 567                                 continue;
 568 
 569                         /* Test this bit can be set in isolation */
 570                         reg = original;
 571                         EFX_AND_OWORD(reg, rsp->mask);
 572                         EFX_SET_OWORD_BIT(reg, bit);
 573 
 574                         EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &reg,
 575                                     B_TRUE);
 576                         EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
 577                                     B_TRUE);
 578 
 579                         EFX_AND_OWORD(buf, rsp->mask);
 580                         if (memcmp(&reg, &buf, sizeof (reg))) {
 581                                 rc = EIO;
 582                                 goto fail1;
 583                         }
 584 
 585                         /* Test this bit can be cleared in isolation */
 586                         EFX_OR_OWORD(reg, rsp->mask);
 587                         EFX_CLEAR_OWORD_BIT(reg, bit);
 588 
 589                         EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &reg,
 590                                     B_TRUE);
 591                         EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
 592                                     B_TRUE);
 593 
 594                         EFX_AND_OWORD(buf, rsp->mask);
 595                         if (memcmp(&reg, &buf, sizeof (reg))) {
 596                                 rc = EIO;
 597                                 goto fail2;
 598                         }
 599                 }
 600 
 601                 /* Restore the old value */
 602                 EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original,
 603                             B_TRUE);
 604 
 605                 --count;
 606                 ++rsp;
 607         }
 608 
 609         return (0);
 610 
 611 fail2:
 612         EFSYS_PROBE(fail2);
 613 fail1:
 614         EFSYS_PROBE1(fail1, int, rc);
 615 
 616         /* Restore the old value */
 617         EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE);
 618 
 619         return (rc);
 620 }
 621 
 622         __checkReturn   int
 623 efx_nic_test_tables(
 624         __in            efx_nic_t *enp,
 625         __in            efx_register_set_t *rsp,
 626         __in            efx_pattern_type_t pattern,
 627         __in            size_t count)
 628 {
 629         efx_sram_pattern_fn_t func;
 630         unsigned int index;
 631         unsigned int address;
 632         efx_oword_t reg;
 633         efx_oword_t buf;
 634         int rc;
 635 
 636         EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES);
 637         func = __efx_sram_pattern_fns[pattern];
 638 
 639         while (count > 0) {
 640                 /* Write */
 641                 address = rsp->address;
 642                 for (index = 0; index < rsp->rows; ++index) {
 643                         func(2 * index + 0, B_FALSE, &reg.eo_qword[0]);
 644                         func(2 * index + 1, B_FALSE, &reg.eo_qword[1]);
 645                         EFX_AND_OWORD(reg, rsp->mask);
 646                         EFSYS_BAR_WRITEO(enp->en_esbp, address, &reg, B_TRUE);
 647 
 648                         address += rsp->step;
 649                 }
 650 
 651                 /* Read */
 652                 address = rsp->address;
 653                 for (index = 0; index < rsp->rows; ++index) {
 654                         func(2 * index + 0, B_FALSE, &reg.eo_qword[0]);
 655                         func(2 * index + 1, B_FALSE, &reg.eo_qword[1]);
 656                         EFX_AND_OWORD(reg, rsp->mask);
 657                         EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE);
 658                         if (memcmp(&reg, &buf, sizeof (reg))) {
 659                                 rc = EIO;
 660                                 goto fail1;
 661                         }
 662 
 663                         address += rsp->step;
 664                 }
 665 
 666                 ++rsp;
 667                 --count;
 668         }
 669 
 670         return (0);
 671 
 672 fail1:
 673         EFSYS_PROBE1(fail1, int, rc);
 674 
 675         return (rc);
 676 }
 677 
 678 #endif  /* EFSYS_OPT_DIAG */