Print this page
NEX-5717 import QLogic 16G FC drivers
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_nx.c
          +++ new/usr/src/uts/common/io/fibre-channel/fca/qlc/ql_nx.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23      - * Copyright 2010 QLogic Corporation.  All rights reserved.
       23 + * Copyright 2015 QLogic Corporation.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27      -#pragma ident   "Copyright 2010 QLogic Corporation; ql_nx.c"
       27 +#pragma ident   "Copyright 2015 QLogic Corporation; ql_nx.c"
  28   28  
  29   29  /*
  30   30   * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
  31   31   *
  32   32   * ***********************************************************************
  33   33   * *                                                                    **
  34   34   * *                            NOTICE                                  **
  35      - * *            COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION              **
       35 + * *            COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION              **
  36   36   * *                    ALL RIGHTS RESERVED                             **
  37   37   * *                                                                    **
  38   38   * ***********************************************************************
  39   39   *
  40   40   */
  41   41  
  42   42  #include <ql_apps.h>
  43   43  #include <ql_api.h>
  44   44  #include <ql_debug.h>
       45 +#include <ql_init.h>
  45   46  #include <ql_mbx.h>
  46   47  #include <ql_nx.h>
  47   48  
  48   49  /*
  49   50   *  Local Function Prototypes.
  50   51   */
  51      -static void *ql_8021_pci_base_offsetfset(ql_adapter_state_t *, uint64_t);
  52   52  static void ql_crb_addr_transform_setup(ql_adapter_state_t *);
  53   53  static void ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t *, uint64_t *);
  54      -static void ql_8021_wr_32(ql_adapter_state_t *, uint64_t, uint32_t);
  55      -static void ql_8021_rd_32(ql_adapter_state_t *, uint64_t, uint32_t *);
  56   54  static int ql_8021_crb_win_lock(ql_adapter_state_t *);
  57   55  static void ql_8021_crb_win_unlock(ql_adapter_state_t *);
  58   56  static int ql_8021_pci_get_crb_addr_2M(ql_adapter_state_t *, uint64_t *);
  59   57  static uint32_t ql_8021_pci_mem_bound_check(ql_adapter_state_t *, uint64_t,
  60   58      uint32_t);
  61   59  static uint64_t ql_8021_pci_set_window(ql_adapter_state_t *, uint64_t);
  62   60  static int ql_8021_pci_is_same_window(ql_adapter_state_t *, uint64_t);
  63   61  static int ql_8021_pci_mem_read_direct(ql_adapter_state_t *, uint64_t, void *,
  64   62      uint32_t);
  65   63  static int ql_8021_pci_mem_write_direct(ql_adapter_state_t *, uint64_t, void *,
↓ open down ↓ 13 lines elided ↑ open up ↑
  79   77  static int ql_8021_do_rom_erase(ql_adapter_state_t *, uint32_t);
  80   78  static int ql_8021_phantom_init(ql_adapter_state_t *);
  81   79  static int ql_8021_pinit_from_rom(ql_adapter_state_t *);
  82   80  static int ql_8021_load_from_flash(ql_adapter_state_t *);
  83   81  static int ql_8021_load_firmware(ql_adapter_state_t *);
  84   82  static int ql_8021_reset_hw(ql_adapter_state_t *, int);
  85   83  static int ql_8021_init_p3p(ql_adapter_state_t *);
  86   84  static int ql_8021_hw_lock(ql_adapter_state_t *, uint32_t);
  87   85  static void ql_8021_hw_unlock(ql_adapter_state_t *);
  88   86  static void ql_8021_need_reset_handler(ql_adapter_state_t *);
       87 +static int ql_8021_load_fw(ql_adapter_state_t *);
       88 +static uint32_t ql_8021_check_fw_alive(ql_adapter_state_t *);
       89 +static int ql_8021_get_fw_dump(ql_adapter_state_t *);
       90 +static void ql_8021_md_parse_template(ql_adapter_state_t *, caddr_t, caddr_t,
       91 +    uint32_t, uint32_t);
       92 +static int ql_8021_md_rdcrb(ql_adapter_state_t *, md_entry_rdcrb_t *,
       93 +    uint32_t *);
       94 +static int ql_8021_md_L2Cache(ql_adapter_state_t *, md_entry_cache_t *,
       95 +    uint32_t *);
       96 +static int ql_8021_md_L1Cache(ql_adapter_state_t *, md_entry_cache_t *,
       97 +    uint32_t *);
       98 +static int ql_8021_md_rdocm(ql_adapter_state_t *, md_entry_rdocm_t *,
       99 +    uint32_t *);
      100 +static int ql_8021_md_rdmem(ql_adapter_state_t *, md_entry_rdmem_t *,
      101 +    uint32_t *);
      102 +static int ql_8021_md_rdrom(ql_adapter_state_t *, md_entry_rdrom_t *,
      103 +    uint32_t *);
      104 +static int ql_8021_md_rdmux(ql_adapter_state_t *, md_entry_mux_t *,
      105 +    uint32_t *);
      106 +static int ql_8021_md_rdqueue(ql_adapter_state_t *, md_entry_queue_t *,
      107 +    uint32_t *);
      108 +static int ql_8021_md_cntrl(ql_adapter_state_t *, md_template_hdr_t *,
      109 +    md_entry_cntrl_t *);
      110 +static void ql_8021_md_entry_err_chk(ql_adapter_state_t *, md_entry_t *,
      111 +    uint32_t, int);
      112 +static uint32_t ql_8021_md_template_checksum(ql_adapter_state_t *);
      113 +static uint32_t ql_8021_read_reg(ql_adapter_state_t *, uint32_t);
      114 +static void ql_8021_write_reg(ql_adapter_state_t *, uint32_t, uint32_t);
      115 +static uint32_t ql_8021_read_ocm(ql_adapter_state_t *, uint32_t);
  89  116  
  90  117  /*
  91  118   * Local Data.
  92  119   */
  93  120  static uint32_t crb_addr_xform[MAX_CRB_XFORM];
  94  121  static int      crb_table_initialized = 0;
  95  122  static int      pci_set_window_warning_count = 0;
  96  123  
  97  124  static struct legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
  98  125  
↓ open down ↓ 14 lines elided ↑ open up ↑
 113  140              {0, 0x0000000, 0x0000000, 0x000000},
 114  141              {0, 0x0000000, 0x0000000, 0x000000},
 115  142              {1, 0x01e0000, 0x01e0800, 0x122000},
 116  143              {0, 0x0000000, 0x0000000, 0x000000}}},
 117  144          {{{1, 0x0200000, 0x0210000, 0x180000}}},        /* 2: MN */
 118  145          {{{0, 0,         0,      0}}},                  /* 3: */
 119  146          {{{1, 0x0400000, 0x0401000, 0x169000}}},        /* 4: P2NR1 */
 120  147          {{{1, 0x0500000, 0x0510000, 0x140000}}},        /* 5: SRE   */
 121  148          {{{1, 0x0600000, 0x0610000, 0x1c0000}}},        /* 6: NIU   */
 122  149          {{{1, 0x0700000, 0x0704000, 0x1b8000}}},        /* 7: QM    */
 123      -        {{{1, 0x0800000, 0x0802000, 0x170000},          /* 8: SQM0  */
      150 +        {{{1, 0x0800000, 0x0802000, 0x170000},          /* 8: SQM0  */
 124  151              {0, 0x0000000, 0x0000000, 0x000000},
 125  152              {0, 0x0000000, 0x0000000, 0x000000},
 126  153              {0, 0x0000000, 0x0000000, 0x000000},
 127  154              {0, 0x0000000, 0x0000000, 0x000000},
 128  155              {0, 0x0000000, 0x0000000, 0x000000},
 129  156              {0, 0x0000000, 0x0000000, 0x000000},
 130  157              {0, 0x0000000, 0x0000000, 0x000000},
 131  158              {0, 0x0000000, 0x0000000, 0x000000},
 132  159              {0, 0x0000000, 0x0000000, 0x000000},
 133  160              {0, 0x0000000, 0x0000000, 0x000000},
↓ open down ↓ 182 lines elided ↑ open up ↑
 316  343          UNM_HW_CRB_HUB_AGT_ADR_OCM0,
 317  344          0,
 318  345          UNM_HW_CRB_HUB_AGT_ADR_SMB,
 319  346          UNM_HW_CRB_HUB_AGT_ADR_I2C0,
 320  347          UNM_HW_CRB_HUB_AGT_ADR_I2C1,
 321  348          0,
 322  349          UNM_HW_CRB_HUB_AGT_ADR_PGNC,
 323  350          0,
 324  351  };
 325  352  
 326      -static void *
 327      -ql_8021_pci_base_offsetfset(ql_adapter_state_t *ha, uint64_t off)
 328      -{
 329      -        if ((off < ha->first_page_group_end) &&
 330      -            (off >= ha->first_page_group_start)) {
 331      -                return ((void *)(ha->nx_pcibase + off));
 332      -        }
 333      -
 334      -        return (NULL);
 335      -}
 336      -
 337  353  /* ARGSUSED */
 338  354  static void
 339  355  ql_crb_addr_transform_setup(ql_adapter_state_t *ha)
 340  356  {
 341  357          crb_addr_transform(XDMA);
 342  358          crb_addr_transform(TIMR);
 343  359          crb_addr_transform(SRE);
 344  360          crb_addr_transform(SQN3);
 345  361          crb_addr_transform(SQN2);
 346  362          crb_addr_transform(SQN1);
↓ open down ↓ 50 lines elided ↑ open up ↑
 397  413  }
 398  414  
 399  415  /*
 400  416   * In: 'off' is offset from CRB space in 128M pci map
 401  417   * Out: 'off' is 2M pci map addr
 402  418   * side effect: lock crb window
 403  419   */
 404  420  static void
 405  421  ql_8021_pci_set_crbwindow_2M(ql_adapter_state_t *ha, uint64_t *off)
 406  422  {
 407      -        uint32_t        win_read;
      423 +        uint32_t        win_read, crb_win;
 408  424  
 409      -        ha->crb_win = (uint32_t)CRB_HI(*off);
 410      -        WRT_REG_DWORD(ha, CRB_WINDOW_2M + ha->nx_pcibase, ha->crb_win);
      425 +        crb_win = (uint32_t)CRB_HI(*off);
      426 +        WRT_REG_DWORD(ha, CRB_WINDOW_2M + ha->nx_pcibase, crb_win);
 411  427  
 412  428          /*
 413  429           * Read back value to make sure write has gone through before trying
 414  430           * to use it.
 415  431           */
 416  432          win_read = RD_REG_DWORD(ha, CRB_WINDOW_2M + ha->nx_pcibase);
 417      -        if (win_read != ha->crb_win) {
      433 +        if (win_read != crb_win) {
 418  434                  EL(ha, "Written crbwin (0x%x) != Read crbwin (0x%x), "
 419      -                    "off=0x%llx\n", ha->crb_win, win_read, *off);
      435 +                    "off=0x%llx\n", crb_win, win_read, *off);
 420  436          }
 421  437          *off = (*off & MASK(16)) + CRB_INDIRECT_2M + (uintptr_t)ha->nx_pcibase;
 422  438  }
 423  439  
 424      -static void
      440 +void
 425  441  ql_8021_wr_32(ql_adapter_state_t *ha, uint64_t off, uint32_t data)
 426  442  {
 427  443          int     rv;
 428  444  
 429  445          rv = ql_8021_pci_get_crb_addr_2M(ha, &off);
 430  446          if (rv == -1) {
 431  447                  cmn_err(CE_PANIC, "ql_8021_wr_32, ql_8021_pci_get_crb_addr_"
 432  448                      "2M=-1\n");
 433  449          }
 434  450          if (rv == 1) {
↓ open down ↓ 1 lines elided ↑ open up ↑
 436  452                  ql_8021_pci_set_crbwindow_2M(ha, &off);
 437  453          }
 438  454  
 439  455          WRT_REG_DWORD(ha, (uintptr_t)off, data);
 440  456  
 441  457          if (rv == 1) {
 442  458                  ql_8021_crb_win_unlock(ha);
 443  459          }
 444  460  }
 445  461  
 446      -static void
      462 +void
 447  463  ql_8021_rd_32(ql_adapter_state_t *ha, uint64_t off, uint32_t *data)
 448  464  {
 449  465          int             rv;
 450  466          uint32_t        n;
 451  467  
 452  468          rv = ql_8021_pci_get_crb_addr_2M(ha, &off);
 453  469          if (rv == -1) {
 454  470                  cmn_err(CE_PANIC, "ql_8021_rd_32, ql_8021_pci_get_crb_addr_"
 455  471                      "2M=-1\n");
 456  472          }
↓ open down ↓ 26 lines elided ↑ open up ↑
 483  499                  }
 484  500                  if (timeout >= CRB_WIN_LOCK_TIMEOUT) {
 485  501                          EL(ha, "timeout\n");
 486  502                          return (-1);
 487  503                  }
 488  504                  timeout++;
 489  505  
 490  506                  /* Yield CPU */
 491  507                  delay(1);
 492  508          }
 493      -        ql_8021_wr_32(ha, UNM_CRB_WIN_LOCK_ID, ha->function_number);
      509 +        ql_8021_wr_32(ha, UNM_CRB_WIN_LOCK_ID, ha->pci_function_number);
 494  510  
 495  511          return (0);
 496  512  }
 497  513  
 498  514  static void
 499  515  ql_8021_crb_win_unlock(ql_adapter_state_t *ha)
 500  516  {
 501  517          ql_8021_rd_32(ha, UNM_PCIE_REG(PCIE_SEM7_UNLOCK), NULL);
 502  518  }
 503  519  
↓ open down ↓ 63 lines elided ↑ open up ↑
 567  583  static uint64_t
 568  584  ql_8021_pci_set_window(ql_adapter_state_t *ha, uint64_t addr)
 569  585  {
 570  586          uint32_t        window, win_read;
 571  587  
 572  588          /*LINTED suspicious 0 comparison*/
 573  589          if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_DDR_NET,
 574  590              UNM_ADDR_DDR_NET_MAX)) {
 575  591                  /* DDR network side */
 576  592                  window = (uint32_t)MN_WIN(addr);
 577      -                ha->ddr_mn_window = window;
 578      -                ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window);
 579      -                ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE,
 580      -                    &win_read);
      593 +                ql_8021_wr_32(ha, UNM_PCI_CRBSPACE, window);
      594 +                ql_8021_rd_32(ha, UNM_PCI_CRBSPACE, &win_read);
 581  595                  if ((win_read << 17) != window) {
 582  596                          EL(ha, "Warning, Written MNwin (0x%x) != Read MNwin "
 583  597                              "(0x%x)\n", window, win_read);
 584  598                  }
 585  599                  addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_DDR_NET;
 586  600          } else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_OCM0,
 587  601              UNM_ADDR_OCM0_MAX)) {
 588  602                  uint32_t        temp1;
 589  603  
 590  604                  if ((addr & 0x00ff800) == 0xff800) {
 591  605                          /* if bits 19:18&17:11 are on */
 592  606                          EL(ha, "QM access not handled\n");
 593  607                          addr = -1UL;
 594  608                  }
 595  609  
 596  610                  window = (uint32_t)OCM_WIN(addr);
 597      -                ha->ddr_mn_window = window;
 598      -                ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window);
 599      -                ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE,
 600      -                    &win_read);
      611 +                ql_8021_wr_32(ha, UNM_PCI_CRBSPACE, window);
      612 +                ql_8021_rd_32(ha, UNM_PCI_CRBSPACE, &win_read);
 601  613                  temp1 = ((window & 0x1FF) << 7) |
 602  614                      ((window & 0x0FFFE0000) >> 17);
 603  615                  if (win_read != temp1) {
 604  616                          EL(ha, "Written OCMwin (0x%x) != Read OCMwin (0x%x)\n",
 605  617                              temp1, win_read);
 606  618                  }
 607  619                  addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_OCM0_2M;
 608  620          } else if (QL_8021_ADDR_IN_RANGE(addr, UNM_ADDR_QDR_NET,
 609  621              NX_P3_ADDR_QDR_NET_MAX)) {
 610  622                  /* QDR network side */
 611  623                  window = (uint32_t)MS_WIN(addr);
 612  624                  ha->qdr_sn_window = window;
 613      -                ql_8021_wr_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE, window);
 614      -                ql_8021_rd_32(ha, ha->mn_win_crb | UNM_PCI_CRBSPACE,
 615      -                    &win_read);
      625 +                ql_8021_wr_32(ha, UNM_PCI_CRBSPACE, window);
      626 +                ql_8021_rd_32(ha, UNM_PCI_CRBSPACE, &win_read);
 616  627                  if (win_read != window) {
 617  628                          EL(ha, "Written MSwin (0x%x) != Read MSwin (0x%x)\n",
 618  629                              window, win_read);
 619  630                  }
 620  631                  addr = GET_MEM_OFFS_2M(addr) + UNM_PCI_QDR_NET;
 621  632          } else {
 622  633                  /*
 623  634                   * peg gdb frequently accesses memory that doesn't exist,
 624  635                   * this limits the chit chat so debugging isn't slowed down.
 625  636                   */
↓ open down ↓ 51 lines elided ↑ open up ↑
 677  688           * If attempting to access unknown address or straddle hw windows,
 678  689           * do not access.
 679  690           */
 680  691          if (((start = ql_8021_pci_set_window(ha, off)) == -1UL) ||
 681  692              (ql_8021_pci_is_same_window(ha, off + size - 1) == 0)) {
 682  693                  EL(ha, "out of bound pci memory access. offset is 0x%llx\n",
 683  694                      off);
 684  695                  return (-1);
 685  696          }
 686  697  
 687      -        addr = ql_8021_pci_base_offsetfset(ha, start);
 688      -        if (!addr) {
 689      -                addr = (void *)((uint8_t *)ha->nx_pcibase + start);
 690      -        }
      698 +        addr = (void *)((uint8_t *)ha->nx_pcibase + start);
 691  699  
 692  700          switch (size) {
 693  701          case 1:
 694      -                *(uint8_t  *)data = RD_REG_BYTE(ha, addr);
      702 +                *(uint8_t *)data = RD_REG_BYTE(ha, addr);
 695  703                  break;
 696  704          case 2:
 697      -                *(uint16_t  *)data = RD_REG_WORD(ha, addr);
      705 +                *(uint16_t *)data = RD_REG_WORD(ha, addr);
 698  706                  break;
 699  707          case 4:
 700      -                *(uint32_t  *)data = RD_REG_DWORD(ha, addr);
      708 +                *(uint32_t *)data = RD_REG_DWORD(ha, addr);
 701  709                  break;
 702  710          case 8:
 703      -                *(uint64_t  *)data = RD_REG_DDWORD(ha, addr);
      711 +                *(uint64_t *)data = RD_REG_DDWORD(ha, addr);
 704  712                  break;
 705  713          default:
 706  714                  EL(ha, "invalid size=%x\n", size);
 707  715                  ret = -1;
 708  716                  break;
 709  717          }
 710  718  
 711  719          return (ret);
 712  720  }
 713  721  
↓ open down ↓ 9 lines elided ↑ open up ↑
 723  731           * If attempting to access unknown address or straddle hw windows,
 724  732           * do not access.
 725  733           */
 726  734          if (((start = ql_8021_pci_set_window(ha, off)) == -1UL) ||
 727  735              (ql_8021_pci_is_same_window(ha, off + size -1) == 0)) {
 728  736                  EL(ha, "out of bound pci memory access. offset is 0x%llx\n",
 729  737                      off);
 730  738                  return (-1);
 731  739          }
 732  740  
 733      -        addr = ql_8021_pci_base_offsetfset(ha, start);
 734      -        if (!addr) {
 735      -                addr = (void *)((uint8_t *)ha->nx_pcibase + start);
 736      -        }
      741 +        addr = (void *)((uint8_t *)ha->nx_pcibase + start);
 737  742  
 738  743          switch (size) {
 739  744          case 1:
 740  745                  WRT_REG_BYTE(ha, addr, *(uint8_t *)data);
 741  746                  break;
 742  747          case 2:
 743  748                  WRT_REG_WORD(ha, addr, *(uint16_t *)data);
 744  749                  break;
 745  750          case 4:
 746  751                  WRT_REG_DWORD(ha, addr, *(uint32_t *)data);
↓ open down ↓ 191 lines elided ↑ open up ↑
 938  943  
 939  944          if (p3p) {
 940  945                  if (sz[0] == 8) {
 941  946                          word[startword] = tmpw;
 942  947                  } else {
 943  948                          word[startword] &= ~((~(~0ULL << (sz[0] * 8))) <<
 944  949                              (off0 * 8));
 945  950                          word[startword] |= tmpw << (off0 * 8);
 946  951                  }
 947  952                  if (sz[1] != 0) {
 948      -                        word[startword+1] &= ~(~0ULL << (sz[1] * 8));
 949      -                        word[startword+1] |= tmpw >> (sz[0] * 8);
      953 +                        word[startword + 1] &= ~(~0ULL << (sz[1] * 8));
      954 +                        word[startword + 1] |= tmpw >> (sz[0] * 8);
 950  955                  }
 951  956          } else {
 952  957                  word[startword] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
 953  958                  word[startword] |= tmpw << (off0 * 8);
 954  959  
 955  960                  if (loop == 2) {
 956  961                          word[1] &= ~(~0ULL << (sz[1] * 8));
 957  962                          word[1] |= tmpw >> (sz[0] * 8);
 958  963                  }
 959  964          }
↓ open down ↓ 152 lines elided ↑ open up ↑
1112 1117  
1113 1118          return (0);
1114 1119  }
1115 1120  
1116 1121  static int
1117 1122  ql_8021_wait_flash_done(ql_adapter_state_t *ha)
1118 1123  {
1119 1124          clock_t         timer;
1120 1125          uint32_t        status;
1121 1126  
1122      -        for (timer = 30 * drv_usectohz(1000000); timer; timer--) {
     1127 +        for (timer = 500000; timer; timer--) {
1123 1128                  ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1124 1129                  ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1125 1130                      UNM_ROMUSB_ROM_RDSR_INSTR);
1126 1131                  if (ql_8021_wait_rom_done(ha)) {
1127 1132                          EL(ha, "Error waiting for rom done2\n");
1128 1133                          return (-1);
1129 1134                  }
1130 1135  
1131 1136                  /* Get status. */
1132 1137                  ql_8021_rd_32(ha, UNM_ROMUSB_ROM_RDATA, &status);
1133 1138                  if (!(status & BIT_0)) {
1134 1139                          return (0);
1135 1140                  }
1136      -                delay(1);
     1141 +                drv_usecwait(10);
1137 1142          }
1138 1143  
1139 1144          EL(ha, "timeout status=%x\n", status);
1140 1145          return (-1);
1141 1146  }
1142 1147  
1143 1148  static int
1144 1149  ql_8021_do_rom_fast_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *valp)
1145 1150  {
1146 1151          ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ADDRESS, addr);
↓ open down ↓ 13 lines elided ↑ open up ↑
1160 1165          ql_8021_rd_32(ha, UNM_ROMUSB_ROM_RDATA, valp);
1161 1166  
1162 1167          return (0);
1163 1168  }
1164 1169  
1165 1170  int
1166 1171  ql_8021_rom_fast_read(ql_adapter_state_t *ha, uint32_t addr, uint32_t *valp)
1167 1172  {
1168 1173          int     ret, loops = 0;
1169 1174  
1170      -        while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
1171      -                drv_usecwait(100);
     1175 +        while ((ql_8021_rom_lock(ha) != 0) && (loops < 500000)) {
     1176 +                drv_usecwait(10);
1172 1177                  loops++;
1173 1178          }
1174 1179          if (loops >= 50000) {
1175 1180                  EL(ha, "rom_lock failed\n");
1176 1181                  return (-1);
1177 1182          }
1178 1183          ret = ql_8021_do_rom_fast_read(ha, addr, valp);
1179 1184          ql_8021_rom_unlock(ha);
1180 1185  
1181 1186          return (ret);
↓ open down ↓ 65 lines elided ↑ open up ↑
1247 1252              QL_FUNCTION_FAILED;
1248 1253  
1249 1254          return (ret);
1250 1255  }
1251 1256  
1252 1257  int
1253 1258  ql_8021_rom_write(ql_adapter_state_t *ha, uint32_t addr, uint32_t data)
1254 1259  {
1255 1260          int     ret, loops = 0;
1256 1261  
1257      -        while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
1258      -                drv_usecwait(100);
     1262 +        while ((ql_8021_rom_lock(ha) != 0) && (loops < 500000)) {
     1263 +                drv_usecwait(10);
1259 1264                  loops++;
1260 1265          }
1261 1266          if (loops >= 50000) {
1262 1267                  EL(ha, "rom_lock failed\n");
1263 1268                  ret = QL_FUNCTION_TIMEOUT;
1264 1269          } else {
1265 1270                  ret = ql_8021_do_rom_write(ha, addr << 2, data) == 0 ?
1266 1271                      QL_SUCCESS : QL_FUNCTION_FAILED;
1267 1272                  ql_8021_rom_unlock(ha);
1268 1273          }
1269 1274  
1270 1275          return (ret);
1271 1276  }
1272 1277  
1273 1278  int
1274 1279  ql_8021_rom_erase(ql_adapter_state_t *ha, uint32_t addr)
1275 1280  {
1276 1281          int     ret, loops = 0;
1277 1282  
1278      -        while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
1279      -                drv_usecwait(100);
     1283 +        while ((ql_8021_rom_lock(ha) != 0) && (loops < 500000)) {
     1284 +                drv_usecwait(10);
1280 1285                  loops++;
1281 1286          }
1282 1287          if (loops >= 50000) {
1283 1288                  EL(ha, "rom_lock failed\n");
1284 1289                  ret = QL_FUNCTION_TIMEOUT;
1285 1290          } else {
1286 1291                  ret = ql_8021_do_rom_erase(ha, addr << 2) == 0 ? QL_SUCCESS :
1287 1292                      QL_FUNCTION_FAILED;
1288 1293                  ql_8021_rom_unlock(ha);
1289 1294          }
1290 1295  
1291 1296          return (ret);
1292 1297  }
1293 1298  
1294 1299  int
1295 1300  ql_8021_rom_wrsr(ql_adapter_state_t *ha, uint32_t data)
1296 1301  {
1297 1302          int     ret = QL_SUCCESS, loops = 0;
1298 1303  
1299      -        while ((ql_8021_rom_lock(ha) != 0) && (loops < 50000)) {
1300      -                drv_usecwait(100);
     1304 +        while ((ql_8021_rom_lock(ha) != 0) && (loops < 500000)) {
     1305 +                drv_usecwait(10);
1301 1306                  loops++;
1302 1307          }
1303 1308          if (loops >= 50000) {
1304 1309                  EL(ha, "rom_lock failed\n");
1305 1310                  ret = QL_FUNCTION_TIMEOUT;
1306 1311          } else {
1307 1312                  ql_8021_wr_32(ha, UNM_ROMUSB_ROM_ABYTE_CNT, 0);
1308 1313                  ql_8021_wr_32(ha, UNM_ROMUSB_ROM_INSTR_OPCODE,
1309 1314                      UNM_ROMUSB_ROM_WREN_INSTR);
1310 1315                  if (ql_8021_wait_rom_done(ha)) {
↓ open down ↓ 61 lines elided ↑ open up ↑
1372 1377  {
1373 1378          int                     init_delay = 0;
1374 1379          struct crb_addr_pair    *buf;
1375 1380          uint32_t                offset, off, i, n, addr, val;
1376 1381  
1377 1382          /* Grab the lock so that no one can read flash when we reset the chip */
1378 1383          (void) ql_8021_rom_lock(ha);
1379 1384          ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, 0xffffffff);
1380 1385          /* Just in case it was held when we reset the chip */
1381 1386          ql_8021_rom_unlock(ha);
     1387 +        delay(100);
1382 1388  
1383 1389          if (ql_8021_rom_fast_read(ha, 0, &n) != 0 || n != 0xcafecafe ||
1384 1390              ql_8021_rom_fast_read(ha, 4, &n) != 0) {
1385 1391                  EL(ha, "ERROR Reading crb_init area: n: %08x\n", n);
1386 1392                  return (-1);
1387 1393          }
1388 1394          offset = n & 0xffff;
1389 1395          n = (n >> 16) & 0xffff;
1390 1396          if (n >= 1024) {
1391 1397                  EL(ha, "n=0x%x Error! NetXen card flash not initialized\n", n);
↓ open down ↓ 113 lines elided ↑ open up ↑
1505 1511  
1506 1512  static int
1507 1513  ql_8021_load_from_flash(ql_adapter_state_t *ha)
1508 1514  {
1509 1515          int             i;
1510 1516          uint32_t        flashaddr, memaddr;
1511 1517          uint32_t        high, low, size;
1512 1518          uint64_t        data;
1513 1519  
1514 1520          size = ha->bootloader_size / 2;
1515      -        flashaddr = ha->bootloader_addr << 2;
1516      -        memaddr = BOOTLD_START;
     1521 +        memaddr = flashaddr = ha->bootloader_addr << 2;
1517 1522  
1518 1523          for (i = 0; i < size; i++) {
1519 1524                  if ((ql_8021_rom_fast_read(ha, flashaddr, &low)) ||
1520 1525                      (ql_8021_rom_fast_read(ha, flashaddr + 4, &high))) {
1521 1526                          EL(ha, "ql_8021_rom_fast_read != 0\n");
1522 1527                          return (-1);
1523 1528                  }
1524 1529                  data = ((uint64_t)high << 32) | low;
1525      -                (void) ql_8021_pci_mem_write_2M(ha, memaddr, &data, 8);
     1530 +                if (ql_8021_pci_mem_write_2M(ha, memaddr, &data, 8)) {
     1531 +                        EL(ha, "qla_fc_8021_pci_mem_write_2M != 0\n");
     1532 +                        return (-1);
     1533 +                }
1526 1534                  flashaddr += 8;
1527 1535                  memaddr += 8;
     1536 +
     1537 +                /* Allow other system activity. */
     1538 +                if (i % 0x1000 == 0) {
     1539 +                        /* Delay for 1 tick (10ms). */
     1540 +                        delay(1);
     1541 +                }
1528 1542          }
1529 1543  
     1544 +#if 0
     1545 +        /* Allow other system activity, delay for 1 tick (10ms). */
     1546 +        delay(1);
     1547 +
1530 1548          size = ha->flash_fw_size / 2;
1531      -        flashaddr = ha->flash_fw_addr << 2;
1532      -        memaddr = IMAGE_START;
     1549 +        memaddr = flashaddr = ha->flash_fw_addr << 2;
1533 1550  
1534 1551          for (i = 0; i < size; i++) {
1535 1552                  if ((ql_8021_rom_fast_read(ha, flashaddr, &low)) ||
1536 1553                      (ql_8021_rom_fast_read(ha, flashaddr + 4, &high))) {
1537 1554                          EL(ha, "ql_8021_rom_fast_read3 != 0\n");
1538 1555                          return (-1);
1539 1556                  }
1540 1557                  data = ((uint64_t)high << 32) | low;
1541 1558                  (void) ql_8021_pci_mem_write_2M(ha, memaddr, &data, 8);
1542 1559                  flashaddr += 8;
1543 1560                  memaddr += 8;
1544      -        }
1545 1561  
     1562 +                /* Allow other system activity. */
     1563 +                if (i % 0x1000 == 0) {
     1564 +                        /* Delay for 1 tick (10ms). */
     1565 +                        delay(1);
     1566 +                }
     1567 +        }
     1568 +#endif
1546 1569          return (0);
1547 1570  }
1548 1571  
1549 1572  static int
1550 1573  ql_8021_load_firmware(ql_adapter_state_t *ha)
1551 1574  {
1552 1575          uint64_t        data;
1553 1576          uint32_t        i, flashaddr, size;
1554 1577          uint8_t         *bp, n, *dp;
1555 1578  
1556 1579          bp = (uint8_t *)(ha->risc_fw[0].code);
1557 1580          dp = (uint8_t *)&size;
1558 1581          for (n = 0; n < 4; n++) {
1559 1582                  dp[n] = *bp++;
1560 1583          }
1561 1584          LITTLE_ENDIAN_32(&size);
1562 1585          EL(ha, "signature=%x\n", size);
1563 1586  
1564      -        size = (IMAGE_START - BOOTLD_START) / 8;
     1587 +        size = ha->bootloader_size / 2;
     1588 +        flashaddr = ha->bootloader_addr << 2;
1565 1589  
1566      -        bp = (uint8_t *)(ha->risc_fw[0].code + BOOTLD_START);
1567      -        flashaddr = BOOTLD_START;
1568      -
     1590 +        bp = (uint8_t *)(ha->risc_fw[0].code + flashaddr);
1569 1591          dp = (uint8_t *)&data;
1570 1592          for (i = 0; i < size; i++) {
1571 1593                  for (n = 0; n < 8; n++) {
1572 1594                          dp[n] = *bp++;
1573 1595                  }
1574 1596                  LITTLE_ENDIAN_64(&data);
1575      -                (void) ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8);
     1597 +                if (ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8)) {
     1598 +                        EL(ha, "qla_fc_8021_pci_mem_write_2M != 0\n");
     1599 +                        return (-1);
     1600 +                }
1576 1601                  flashaddr += 8;
1577 1602          }
1578 1603  
1579 1604          bp = (uint8_t *)(ha->risc_fw[0].code + FW_SIZE_OFFSET);
1580 1605          dp = (uint8_t *)&size;
1581 1606          for (n = 0; n < 4; n++) {
1582 1607                  dp[n] = *bp++;
1583 1608          }
1584 1609          LITTLE_ENDIAN_32(&size);
1585 1610          EL(ha, "IMAGE_START size=%llx\n", size);
1586 1611          size = (size + 7) / 8;
1587 1612  
1588      -        bp = (uint8_t *)(ha->risc_fw[0].code + IMAGE_START);
1589      -        flashaddr = IMAGE_START;
     1613 +        flashaddr = ha->flash_fw_addr << 2;
     1614 +        bp = (uint8_t *)(ha->risc_fw[0].code + flashaddr);
1590 1615  
1591 1616          dp = (uint8_t *)&data;
1592 1617          for (i = 0; i < size; i++) {
1593 1618                  for (n = 0; n < 8; n++) {
1594 1619                          dp[n] = *bp++;
1595 1620                  }
1596 1621                  LITTLE_ENDIAN_64(&data);
1597      -                (void) ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8);
     1622 +                if (ql_8021_pci_mem_write_2M(ha, flashaddr, &data, 8)) {
     1623 +                        EL(ha, "qla_fc_8021_pci_mem_write_2M != 0\n");
     1624 +                        return (-1);
     1625 +                }
1598 1626                  flashaddr += 8;
1599 1627          }
1600 1628  
1601 1629          return (0);
1602 1630  }
1603 1631  
1604 1632  static int
1605 1633  ql_8021_init_p3p(ql_adapter_state_t *ha)
1606 1634  {
1607 1635          uint32_t        data;
↓ open down ↓ 31 lines elided ↑ open up ↑
1639 1667  {
1640 1668          /*
1641 1669           * Disable interrupts does not work on a per function bases
1642 1670           * leave them enabled
1643 1671           */
1644 1672          ql_8021_enable_intrs(ha);
1645 1673  
1646 1674          ADAPTER_STATE_LOCK(ha);
1647 1675          ha->flags |= INTERRUPTS_ENABLED;
1648 1676          ADAPTER_STATE_UNLOCK(ha);
1649      -
1650      -        (void) ql_stop_firmware(ha);
     1677 +        if (!(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
     1678 +                (void) ql_stop_firmware(ha);
     1679 +        }
1651 1680  }
1652 1681  
1653 1682  static int
1654 1683  ql_8021_reset_hw(ql_adapter_state_t *ha, int type)
1655 1684  {
1656 1685          int             ret;
1657 1686          uint32_t        rst;
1658 1687  
1659 1688          /* scrub dma mask expansion register */
1660 1689          ql_8021_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
1661 1690  
1662 1691          /* Overwrite stale initialization register values */
1663 1692          ql_8021_wr_32(ha, CRB_CMDPEG_STATE, 0);
1664 1693          ql_8021_wr_32(ha, CRB_RCVPEG_STATE, 0);
1665 1694          ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS1, 0);
1666 1695          ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS2, 0);
1667 1696  
1668      -        (void) ql_8021_pinit_from_rom(ha);
     1697 +        /*
     1698 +         * This reset sequence is to provide a graceful shutdown of the
     1699 +         * different hardware blocks prior to performing an ASIC Reset,
     1700 +         * has to be done before writing 0xffffffff to ASIC_RESET.
     1701 +         */
     1702 +        ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x10, 0);
     1703 +        ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x14, 0);
     1704 +        ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x18, 0);
     1705 +        ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x1c, 0);
     1706 +        ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x20, 0);
     1707 +        ql_8021_wr_32(ha, UNM_CRB_I2Q + 0x24, 0);
     1708 +        ql_8021_wr_32(ha, UNM_CRB_NIU + 0x40, 0xff);
     1709 +        ql_8021_wr_32(ha, UNM_CRB_NIU + 0x70000, 0x0);
     1710 +        ql_8021_wr_32(ha, UNM_CRB_NIU + 0x80000, 0x0);
     1711 +        ql_8021_wr_32(ha, UNM_CRB_NIU + 0x90000, 0x0);
     1712 +        ql_8021_wr_32(ha, UNM_CRB_NIU + 0xa0000, 0x0);
     1713 +        ql_8021_wr_32(ha, UNM_CRB_NIU + 0xb0000, 0x0);
     1714 +        ql_8021_wr_32(ha, UNM_CRB_SRE + 0x1000, 0x28ff000c);
     1715 +        ql_8021_wr_32(ha, UNM_CRB_EPG + 0x1300, 0x1);
     1716 +        ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x0, 0x0);
     1717 +        ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x8, 0x0);
     1718 +        ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x10, 0x0);
     1719 +        ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x18, 0x0);
     1720 +        ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x100, 0x0);
     1721 +        ql_8021_wr_32(ha, UNM_CRB_TIMER + 0x200, 0x0);
     1722 +        ql_8021_wr_32(ha, UNM_CRB_PEG_NET_0 + 0x3C, 0x1);
     1723 +        ql_8021_wr_32(ha, UNM_CRB_PEG_NET_1 + 0x3C, 0x1);
     1724 +        ql_8021_wr_32(ha, UNM_CRB_PEG_NET_2 + 0x3C, 0x1);
     1725 +        ql_8021_wr_32(ha, UNM_CRB_PEG_NET_3 + 0x3C, 0x1);
     1726 +        ql_8021_wr_32(ha, UNM_CRB_PEG_NET_4 + 0x3C, 0x1);
1669 1727          delay(1);
1670 1728  
     1729 +        ret = ql_8021_pinit_from_rom(ha);
     1730 +        if (ret) {
     1731 +                EL(ha, "pinit_from_rom ret=%d\n", ret);
     1732 +                return (ret);
     1733 +        }
     1734 +        delay(1);
     1735 +
1671 1736          /* Bring QM and CAMRAM out of reset */
1672 1737          ql_8021_rd_32(ha, UNM_ROMUSB_GLB_SW_RESET, &rst);
1673 1738          rst &= ~((1 << 28) | (1 << 24));
1674 1739          ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, rst);
1675 1740  
1676 1741          switch (type) {
1677 1742          case 0:
1678 1743                  ret = ql_8021_init_p3p(ha);
1679 1744                  break;
1680 1745          case 1:
↓ open down ↓ 9 lines elided ↑ open up ↑
1690 1755          ql_8021_wr_32(ha, UNM_ROMUSB_GLB_SW_RESET, 0x80001e);
1691 1756  
1692 1757          if (ret) {
1693 1758                  EL(ha, "type=%d, ret=%d\n", type, ret);
1694 1759          } else {
1695 1760                  ret = ql_8021_phantom_init(ha);
1696 1761          }
1697 1762          return (ret);
1698 1763  }
1699 1764  
1700      -int
1701      -ql_8021_load_risc(ql_adapter_state_t *ha)
     1765 +static int
     1766 +ql_8021_load_fw(ql_adapter_state_t *ha)
1702 1767  {
1703      -        int             rv = 0;
1704      -        static int      ql_8021_fw_loaded = 0;
     1768 +        int     rv = 0;
1705 1769  
1706 1770          GLOBAL_HW_LOCK();
1707      -        if (!ql_8021_fw_loaded) {
1708      -                if (ha->risc_fw[0].code) {
1709      -                        EL(ha, "from driver\n");
1710      -                        rv = ql_8021_reset_hw(ha, 2);
1711      -                } else {
1712      -                        /*
1713      -                         * BIOS method
1714      -                         * ql_8021_reset_hw(ha, 0)
1715      -                         */
1716      -                        EL(ha, "from flash\n");
1717      -                        rv = ql_8021_reset_hw(ha, 1);
1718      -                }
1719      -                if (rv == 0) {
1720      -                        ql_8021_fw_loaded = 1;
     1771 +        if (ha->risc_fw[0].code) {
     1772 +                EL(ha, "from driver\n");
     1773 +                rv = ql_8021_reset_hw(ha, 2);
     1774 +        } else {
     1775 +                /*
     1776 +                 * BIOS method
     1777 +                 * ql_8021_reset_hw(ha, 0)
     1778 +                 */
     1779 +                EL(ha, "from flash\n");
     1780 +                rv = ql_8021_reset_hw(ha, 1);
     1781 +        }
     1782 +        if (rv == 0) {
     1783 +                ql_8021_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
     1784 +                ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS1, 0x0);
     1785 +                ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS2, 0x0);
1721 1786  
1722      -                        ql_8021_wr_32(ha, CRB_DMA_SHIFT, 0x55555555);
1723      -                        ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS1, 0x0);
1724      -                        ql_8021_wr_32(ha, UNM_PEG_HALT_STATUS2, 0x0);
     1787 +                GLOBAL_HW_UNLOCK();
1725 1788  
1726      -                        GLOBAL_HW_UNLOCK();
     1789 +                ADAPTER_STATE_LOCK(ha);
     1790 +                ha->flags &= ~INTERRUPTS_ENABLED;
     1791 +                ADAPTER_STATE_UNLOCK(ha);
1727 1792  
1728      -                        ADAPTER_STATE_LOCK(ha);
1729      -                        ha->flags &= ~INTERRUPTS_ENABLED;
1730      -                        ADAPTER_STATE_UNLOCK(ha);
     1793 +                /* clear the mailbox command pointer. */
     1794 +                INTR_LOCK(ha);
     1795 +                ha->mcp = NULL;
     1796 +                INTR_UNLOCK(ha);
1731 1797  
1732      -                        (void) ql_8021_enable_intrs(ha);
     1798 +                MBX_REGISTER_LOCK(ha);
     1799 +                ha->mailbox_flags = (uint8_t)(ha->mailbox_flags &
     1800 +                    ~(MBX_BUSY_FLG | MBX_WANT_FLG | MBX_ABORT | MBX_INTERRUPT));
     1801 +                MBX_REGISTER_UNLOCK(ha);
1733 1802  
1734      -                        ADAPTER_STATE_LOCK(ha);
1735      -                        ha->flags |= INTERRUPTS_ENABLED;
1736      -                        ADAPTER_STATE_UNLOCK(ha);
1737      -                } else {
1738      -                        GLOBAL_HW_UNLOCK();
1739      -                }
     1803 +                (void) ql_8021_enable_intrs(ha);
     1804 +
     1805 +                ADAPTER_STATE_LOCK(ha);
     1806 +                ha->flags |= INTERRUPTS_ENABLED;
     1807 +                ADAPTER_STATE_UNLOCK(ha);
1740 1808          } else {
1741 1809                  GLOBAL_HW_UNLOCK();
1742      -                EL(ha, "Firmware loaded by other function\n");
1743 1810          }
1744 1811  
1745 1812          if (rv == 0) {
1746 1813                  ql_8021_rd_32(ha, UNM_FW_VERSION_MAJOR, &ha->fw_major_version);
1747 1814                  ql_8021_rd_32(ha, UNM_FW_VERSION_MINOR, &ha->fw_minor_version);
1748 1815                  ql_8021_rd_32(ha, UNM_FW_VERSION_SUB, &ha->fw_subminor_version);
1749 1816                  EL(ha, "fw v%d.%02d.%02d\n", ha->fw_major_version,
1750 1817                      ha->fw_minor_version, ha->fw_subminor_version);
1751 1818          } else {
1752 1819                  EL(ha, "status = -1\n");
1753      -                return (QL_FUNCTION_FAILED);
1754 1820          }
1755 1821  
1756      -        return (QL_SUCCESS);
     1822 +        return (rv);
1757 1823  }
1758 1824  
1759 1825  void
1760 1826  ql_8021_clr_hw_intr(ql_adapter_state_t *ha)
1761 1827  {
1762 1828          ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xffffffff);
1763 1829          ql_8021_rd_32(ha, ISR_INT_VECTOR, NULL);
1764 1830          ql_8021_rd_32(ha, ISR_INT_VECTOR, NULL);
1765 1831  }
1766 1832  
↓ open down ↓ 3 lines elided ↑ open up ↑
1770 1836          WRT32_IO_REG(ha, nx_risc_int, 0);
1771 1837          ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_status_reg, 0xfbff);
1772 1838  }
1773 1839  
1774 1840  void
1775 1841  ql_8021_enable_intrs(ql_adapter_state_t *ha)
1776 1842  {
1777 1843          GLOBAL_HW_LOCK();
1778 1844          ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0xfbff);
1779 1845          GLOBAL_HW_UNLOCK();
1780      -        (void) ql_toggle_interrupt(ha, 1);
     1846 +        if (!(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
     1847 +                (void) ql_toggle_interrupt(ha, 1);
     1848 +        }
1781 1849  }
1782 1850  
1783 1851  void
1784 1852  ql_8021_disable_intrs(ql_adapter_state_t *ha)
1785 1853  {
1786 1854          (void) ql_toggle_interrupt(ha, 0);
1787 1855          GLOBAL_HW_LOCK();
1788 1856          ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400);
1789 1857          GLOBAL_HW_UNLOCK();
1790 1858  }
1791 1859  
1792 1860  void
1793 1861  ql_8021_update_crb_int_ptr(ql_adapter_state_t *ha)
1794 1862  {
1795 1863          struct legacy_intr_set  *nx_legacy_intr;
1796 1864  
1797 1865          ha->qdr_sn_window = (uint32_t)-1;
1798      -        ha->ddr_mn_window = (uint32_t)-1;
1799      -        nx_legacy_intr = &legacy_intr[ha->function_number];
     1866 +        nx_legacy_intr = &legacy_intr[ha->pci_function_number];
1800 1867  
1801 1868          ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit;
1802 1869          ha->nx_legacy_intr.tgt_status_reg = nx_legacy_intr->tgt_status_reg;
1803 1870          ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg;
1804 1871          ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
1805 1872  }
1806 1873  
1807 1874  void
1808 1875  ql_8021_set_drv_active(ql_adapter_state_t *ha)
1809 1876  {
1810 1877          uint32_t        val;
1811 1878  
1812 1879          if (ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT)) {
1813 1880                  return;
1814 1881          }
1815 1882  
1816 1883          ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &val);
1817 1884          if (val == 0xffffffff) {
1818      -                val = (1 << (ha->function_number * 4));
     1885 +                val = (1 << (ha->pci_function_number * 4));
1819 1886          } else {
1820      -                val |= (1 << (ha->function_number * 4));
     1887 +                val |= (1 << (ha->pci_function_number * 4));
1821 1888          }
1822 1889          ql_8021_wr_32(ha, CRB_DRV_ACTIVE, val);
1823 1890  
1824 1891          ql_8021_hw_unlock(ha);
1825 1892  }
1826 1893  
1827 1894  void
1828 1895  ql_8021_clr_drv_active(ql_adapter_state_t *ha)
1829 1896  {
1830 1897          uint32_t        val;
1831 1898  
1832 1899          if (ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT)) {
1833 1900                  return;
1834 1901          }
1835 1902  
1836 1903          ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &val);
1837      -        val &= ~(1 << (ha->function_number * 4));
     1904 +        val &= ~(1 << (ha->pci_function_number * 4));
1838 1905          ql_8021_wr_32(ha, CRB_DRV_ACTIVE, val);
1839 1906  
1840 1907          ql_8021_hw_unlock(ha);
1841 1908  }
1842 1909  
1843 1910  static void
1844 1911  ql_8021_need_reset_handler(ql_adapter_state_t *ha)
1845 1912  {
1846      -        uint32_t        drv_state, drv_active;
1847      -        clock_t         timer;
     1913 +        uint32_t        drv_state, drv_active, cnt;
1848 1914  
1849      -        (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1850      -
1851 1915          ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
1852      -        drv_state |= (1 << (ha->function_number * 4));
     1916 +        if (drv_state == 0xffffffff) {
     1917 +                drv_state = 0;
     1918 +        }
     1919 +        if (!(ha->ql_dump_state & QL_DUMPING)) {
     1920 +                drv_state |= (1 << (ha->pci_function_number * 4));
     1921 +        }
1853 1922          ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
1854 1923  
1855      -        ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &drv_active);
1856      -
1857      -        ql_8021_hw_unlock(ha);
1858      -
1859      -        for (timer = 30; timer && drv_state != drv_active; timer--) {
     1924 +        for (cnt = 60; cnt; cnt--) {
     1925 +                ql_8021_hw_unlock(ha);
1860 1926                  delay(100);
1861      -
1862 1927                  (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
     1928 +
1863 1929                  ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
1864 1930                  ql_8021_rd_32(ha, CRB_DRV_ACTIVE, &drv_active);
1865      -                ql_8021_hw_unlock(ha);
     1931 +                if (ha->ql_dump_state & QL_DUMPING) {
     1932 +                        drv_state |= (1 << (ha->pci_function_number * 4));
     1933 +                }
     1934 +                if (drv_state == drv_active) {
     1935 +                        if (ha->ql_dump_state & QL_DUMPING) {
     1936 +                                ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
     1937 +                        }
     1938 +                        break;
     1939 +                }
1866 1940          }
1867 1941  }
1868 1942  
1869      -uint32_t
1870      -ql_8021_idc_handler(ql_adapter_state_t *ha)
     1943 +int
     1944 +ql_8021_fw_reload(ql_adapter_state_t *ha)
1871 1945  {
1872      -        uint32_t        dev_state, drv_state, rval;
1873      -        clock_t         timer;
     1946 +        int     rval;
     1947 +
     1948 +        (void) ql_stall_driver(ha, BIT_0);
     1949 +
     1950 +        (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
     1951 +        ql_8021_wr_32(ha, CRB_DEV_STATE, NX_DEV_INITIALIZING);
     1952 +        ql_8021_hw_unlock(ha);
     1953 +
     1954 +        rval = ql_8021_load_fw(ha) == 0 ? NX_DEV_READY : NX_DEV_FAILED;
     1955 +
     1956 +        (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
     1957 +        ql_8021_wr_32(ha, CRB_DEV_STATE, rval);
     1958 +        ql_8021_hw_unlock(ha);
     1959 +
     1960 +        TASK_DAEMON_LOCK(ha);
     1961 +        ha->task_daemon_flags &= ~(TASK_DAEMON_STALLED_FLG | DRIVER_STALL);
     1962 +        TASK_DAEMON_UNLOCK(ha);
     1963 +
     1964 +        if (rval != NX_DEV_READY) {
     1965 +                EL(ha, "status=%xh\n", QL_FUNCTION_FAILED);
     1966 +                return (QL_FUNCTION_FAILED);
     1967 +        }
     1968 +        return (QL_SUCCESS);
     1969 +}
     1970 +
     1971 +void
     1972 +ql_8021_idc_poll(ql_adapter_state_t *ha)
     1973 +{
     1974 +        uint32_t        new_state;
     1975 +
     1976 +        if (ha->ql_dump_state & QL_DUMPING) {
     1977 +                return;
     1978 +        }
     1979 +        new_state = ql_8021_check_fw_alive(ha);
     1980 +
     1981 +        if (new_state == NX_DEV_NEED_RESET &&
     1982 +            !(ha->ql_dump_state & QL_DUMPING ||
     1983 +            (ha->ql_dump_state & QL_DUMP_VALID &&
     1984 +            !(ha->ql_dump_state & QL_DUMP_UPLOADED)))) {
     1985 +                (void) ql_dump_firmware(ha);
     1986 +        } else {
     1987 +                (void) ql_8021_idc_handler(ha, new_state);
     1988 +        }
     1989 +}
     1990 +
     1991 +int
     1992 +ql_8021_idc_handler(ql_adapter_state_t *ha, uint32_t new_state)
     1993 +{
     1994 +        int             rval;
     1995 +        uint32_t        dev_state, drv_state, loop;
1874 1996          ql_mbx_data_t   mr;
1875      -        boolean_t       stalled = B_FALSE, lock = B_FALSE;
     1997 +        boolean_t       stalled = B_FALSE, reset_needed = B_FALSE;
     1998 +        boolean_t       force_load = B_FALSE;
1876 1999  
1877      -        /* wait for 30 seconds for device to go ready */
1878      -        timer = 30;
1879      -        while (timer) {
1880      -                if (lock == B_FALSE) {
1881      -                        (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1882      -                        lock = B_TRUE;
     2000 +        (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
     2001 +
     2002 +        /* wait for 180 seconds for device to go ready */
     2003 +        for (loop = 180; loop; loop--) {
     2004 +                if (new_state != NX_DEV_POLL) {
     2005 +                        ql_8021_wr_32(ha, CRB_DEV_STATE, new_state);
     2006 +                        dev_state = new_state;
     2007 +                        new_state = NX_DEV_POLL;
     2008 +                } else {
     2009 +                        ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state);
1883 2010                  }
1884      -                ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state);
1885 2011  
1886 2012                  switch (dev_state) {
1887 2013                  case 0xffffffff:
1888 2014                  case NX_DEV_COLD:
1889      -                        EL(ha, "dev_state=NX_DEV_COLD\n");
     2015 +                        if (ha->dev_state != dev_state) {
     2016 +                                EL(ha, "dev_state=NX_DEV_COLD\n");
     2017 +                        }
1890 2018                          rval = NX_DEV_COLD;
1891 2019                          ql_8021_wr_32(ha, CRB_DEV_STATE, NX_DEV_INITIALIZING);
1892 2020                          ql_8021_wr_32(ha, CRB_DRV_IDC_VERSION, NX_IDC_VERSION);
1893      -                        (void) ql_8021_hw_unlock(ha);
1894      -                        if (ql_get_fw_version(ha, &mr, 2) == QL_SUCCESS &&
     2021 +                        ql_8021_hw_unlock(ha);
     2022 +                        if (!force_load &&
     2023 +                            ql_get_fw_version(ha, &mr, 2) == QL_SUCCESS &&
1895 2024                              (mr.mb[1] | mr.mb[2] | mr.mb[3])) {
1896 2025                                  ql_8021_rd_32(ha, UNM_FW_VERSION_MAJOR,
1897 2026                                      &ha->fw_major_version);
1898 2027                                  ql_8021_rd_32(ha, UNM_FW_VERSION_MINOR,
1899 2028                                      &ha->fw_minor_version);
1900 2029                                  ql_8021_rd_32(ha, UNM_FW_VERSION_SUB,
1901 2030                                      &ha->fw_subminor_version);
1902 2031                                  rval = NX_DEV_READY;
1903      -                        } else if (ql_8021_load_risc(ha) == QL_SUCCESS) {
1904      -                                rval = NX_DEV_READY;
     2032 +                        } else {
     2033 +                                if (!stalled) {
     2034 +                                        TASK_DAEMON_LOCK(ha);
     2035 +                                        ha->task_daemon_flags |=
     2036 +                                            TASK_DAEMON_STALLED_FLG;
     2037 +                                        TASK_DAEMON_UNLOCK(ha);
     2038 +                                        ql_abort_queues(ha);
     2039 +                                        stalled = B_TRUE;
     2040 +                                }
     2041 +                                if (ha->ql_dump_state & QL_DUMPING) {
     2042 +                                        (void) ql_8021_get_fw_dump(ha);
     2043 +                                }
     2044 +                                rval = ql_8021_load_fw(ha) == 0 ?
     2045 +                                    NX_DEV_READY : NX_DEV_FAILED;
1905 2046                          }
1906 2047                          (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1907 2048                          ql_8021_wr_32(ha, CRB_DEV_STATE, rval);
1908 2049                          break;
1909 2050                  case NX_DEV_READY:
     2051 +                        if (ha->dev_state != dev_state) {
     2052 +                                EL(ha, "dev_state=NX_DEV_READY\n");
     2053 +                        }
1910 2054                          rval = NX_DEV_READY;
1911      -                        timer = 0;
     2055 +                        loop = 1;
1912 2056                          break;
1913 2057                  case NX_DEV_FAILED:
1914      -                        EL(ha, "dev_state=NX_DEV_FAILED\n");
     2058 +                        if (ha->dev_state != dev_state) {
     2059 +                                EL(ha, "dev_state=NX_DEV_FAILED\n");
     2060 +                        }
1915 2061                          rval = NX_DEV_FAILED;
1916      -                        timer = 0;
     2062 +                        loop = 1;
1917 2063                          break;
1918      -
1919 2064                  case NX_DEV_NEED_RESET:
1920      -                        EL(ha, "dev_state=NX_DEV_NEED_RESET\n");
     2065 +                        if (ha->dev_state != dev_state) {
     2066 +                                EL(ha, "dev_state=NX_DEV_NEED_RESET\n");
     2067 +                        }
1921 2068                          rval = NX_DEV_NEED_RESET;
1922      -                        (void) ql_8021_hw_unlock(ha);
1923      -                        lock = B_FALSE;
1924      -                        if (ql_stall_driver(ha, 0) == QL_SUCCESS) {
1925      -                                stalled = B_TRUE;
1926      -                                ql_8021_need_reset_handler(ha);
     2069 +                        ql_8021_need_reset_handler(ha);
     2070 +                        /*
     2071 +                         * Force to DEV_COLD unless someone else is starting
     2072 +                         * a reset
     2073 +                         */
     2074 +                        ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state);
     2075 +                        if (dev_state == NX_DEV_NEED_RESET) {
     2076 +                                EL(ha, "HW State: COLD/RE-INIT\n");
     2077 +                                ql_8021_wr_32(ha, CRB_DEV_STATE, NX_DEV_COLD);
     2078 +                                force_load = B_TRUE;
1927 2079                          }
     2080 +                        reset_needed = B_TRUE;
1928 2081                          break;
1929      -
1930 2082                  case NX_DEV_NEED_QUIESCENT:
1931      -                        EL(ha, "dev_state=NX_DEV_NEED_QUIESCENT\n");
1932      -                        (void) ql_8021_hw_unlock(ha);
1933      -                        lock = B_FALSE;
1934      -                        rval = ql_stall_driver(ha, 0);
1935      -                        if (rval == QL_SUCCESS) {
     2083 +                        if (ha->dev_state != dev_state) {
     2084 +                                EL(ha, "dev_state=NX_DEV_NEED_QUIESCENT\n");
     2085 +                        }
     2086 +                        ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
     2087 +                        drv_state |= (2 << (ha->pci_function_number * 4));
     2088 +                        ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
     2089 +                        ql_8021_hw_unlock(ha);
     2090 +                        if (!stalled) {
     2091 +                                TASK_DAEMON_LOCK(ha);
     2092 +                                ha->task_daemon_flags |=
     2093 +                                    TASK_DAEMON_STALLED_FLG;
     2094 +                                TASK_DAEMON_UNLOCK(ha);
     2095 +                                (void) ql_stall_driver(ha, BIT_0);
1936 2096                                  stalled = B_TRUE;
1937      -                                (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1938      -                                lock = B_TRUE;
1939      -                                ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
1940      -                                drv_state |=
1941      -                                    (2 << (ha->function_number * 4));
1942      -                                ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
1943 2097                          }
     2098 +                        (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1944 2099                          break;
1945      -
1946 2100                  case NX_DEV_INITIALIZING:
1947      -                        EL(ha, "dev_state=NX_DEV_INITIALIZING\n");
     2101 +                        if (ha->dev_state != dev_state) {
     2102 +                                EL(ha, "dev_state=NX_DEV_INITIALIZING\n");
     2103 +                        }
     2104 +                        ql_8021_hw_unlock(ha);
     2105 +                        if (!stalled) {
     2106 +                                TASK_DAEMON_LOCK(ha);
     2107 +                                ha->task_daemon_flags |=
     2108 +                                    TASK_DAEMON_STALLED_FLG;
     2109 +                                TASK_DAEMON_UNLOCK(ha);
     2110 +                                ql_awaken_task_daemon(ha, NULL,
     2111 +                                    DRIVER_STALL, 0);
     2112 +                                stalled = B_TRUE;
     2113 +                                ql_requeue_all_cmds(ha);
     2114 +                                ADAPTER_STATE_LOCK(ha);
     2115 +                                ha->flags &= ~INTERRUPTS_ENABLED;
     2116 +                                ADAPTER_STATE_UNLOCK(ha);
     2117 +                        }
     2118 +                        delay(100);
     2119 +                        (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
     2120 +                        reset_needed = B_TRUE;
1948 2121                          break;
1949 2122                  case NX_DEV_QUIESCENT:
1950      -                        EL(ha, "dev_state=NX_DEV_QUIESCENT\n");
     2123 +                        if (ha->dev_state != dev_state) {
     2124 +                                EL(ha, "dev_state=NX_DEV_QUIESCENT\n");
     2125 +                        }
     2126 +                        ql_8021_hw_unlock(ha);
     2127 +                        delay(100);
     2128 +                        (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1951 2129                          break;
1952 2130                  default:
1953      -                        EL(ha, "dev_state=%x, default\n", dev_state);
     2131 +                        if (ha->dev_state != dev_state) {
     2132 +                                EL(ha, "dev_state=%x, default\n", dev_state);
     2133 +                        }
     2134 +                        ql_8021_hw_unlock(ha);
     2135 +                        delay(100);
     2136 +                        (void) ql_8021_hw_lock(ha, IDC_LOCK_TIMEOUT);
1954 2137                          break;
1955 2138                  }
1956      -                if (lock == B_TRUE) {
1957      -                        (void) ql_8021_hw_unlock(ha);
1958      -                        lock = B_FALSE;
     2139 +                ha->dev_state = dev_state;
     2140 +        }
     2141 +
     2142 +        /* Clear reset ready and quiescent flags. */
     2143 +        ql_8021_rd_32(ha, CRB_DRV_STATE, &drv_state);
     2144 +        drv_state &= ~(1 << (ha->pci_function_number * 4));
     2145 +        drv_state &= ~(2 << (ha->pci_function_number * 4));
     2146 +        ql_8021_wr_32(ha, CRB_DRV_STATE, drv_state);
     2147 +
     2148 +        ql_8021_hw_unlock(ha);
     2149 +        if (reset_needed && ha->flags & ONLINE &&
     2150 +            !(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
     2151 +                delay(100);
     2152 +                ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0);
     2153 +        }
     2154 +        if (stalled) {
     2155 +                TASK_DAEMON_LOCK(ha);
     2156 +                ha->task_daemon_flags &= ~TASK_DAEMON_STALLED_FLG;
     2157 +                TASK_DAEMON_UNLOCK(ha);
     2158 +                ql_restart_driver(ha);
     2159 +        }
     2160 +        return (rval);
     2161 +}
     2162 +
     2163 +void
     2164 +ql_8021_wr_req_in(ql_adapter_state_t *ha, uint32_t index)
     2165 +{
     2166 +        index = index << 16 | ha->pci_function_number << 5 | 4;
     2167 +
     2168 +        if (NX_IS_REVISION_P3PLUS_B0(ha->rev_id)) {
     2169 +                uint64_t        addr;
     2170 +
     2171 +                addr = ha->function_number ? (uint64_t)CRB_PORT_1_REQIN :
     2172 +                    (uint64_t)CRB_PORT_0_REQIN;
     2173 +                ql_8021_wr_32(ha, addr, index);
     2174 +        } else {
     2175 +                do {
     2176 +                        ddi_put32(ha->db_dev_handle, ha->nx_req_in, index);
     2177 +                } while (RD_REG_DWORD(ha, ha->db_read) != index);
     2178 +        }
     2179 +}
     2180 +
     2181 +/* Called every 2 seconds */
     2182 +static uint32_t
     2183 +ql_8021_check_fw_alive(ql_adapter_state_t *ha)
     2184 +{
     2185 +        uint32_t        dev_state, fw_heartbeat_counter, cnt, data[7];
     2186 +        uint32_t        new_state = NX_DEV_POLL;
     2187 +
     2188 +        ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state);
     2189 +        if (dev_state != NX_DEV_READY) {
     2190 +                return (new_state);
     2191 +        }
     2192 +
     2193 +        ql_8021_rd_32(ha, UNM_PEG_ALIVE_COUNTER, &fw_heartbeat_counter);
     2194 +
     2195 +        if (ha->fw_heartbeat_counter == fw_heartbeat_counter) {
     2196 +                ha->seconds_since_last_heartbeat++;
     2197 +                /* FW not alive after 6 seconds */
     2198 +                if (ha->seconds_since_last_heartbeat == 3) {
     2199 +                        ha->seconds_since_last_heartbeat = 0;
     2200 +                        /* FW not alive after 5 milliseconds */
     2201 +                        for (cnt = 5; cnt; cnt--) {
     2202 +                                ql_8021_rd_32(ha, UNM_PEG_ALIVE_COUNTER,
     2203 +                                    &fw_heartbeat_counter);
     2204 +                                if (ha->fw_heartbeat_counter !=
     2205 +                                    fw_heartbeat_counter) {
     2206 +                                        break;
     2207 +                                }
     2208 +                                drv_usecwait(1000);
     2209 +                        }
     2210 +                        if (ha->fw_heartbeat_counter == fw_heartbeat_counter) {
     2211 +                                EL(ha, "nx_dev_need_reset\n");
     2212 +                                ql_8021_rd_32(ha, UNM_PEG_HALT_STATUS1,
     2213 +                                    &data[0]);
     2214 +                                ql_8021_rd_32(ha, UNM_PEG_HALT_STATUS2,
     2215 +                                    &data[1]);
     2216 +                                ql_8021_rd_32(ha, UNM_CRB_PEG_NET_0 + 0x3C,
     2217 +                                    &data[2]);
     2218 +                                ql_8021_rd_32(ha, UNM_CRB_PEG_NET_1 + 0x3C,
     2219 +                                    &data[3]);
     2220 +                                ql_8021_rd_32(ha, UNM_CRB_PEG_NET_2 + 0x3C,
     2221 +                                    &data[4]);
     2222 +                                ql_8021_rd_32(ha, UNM_CRB_PEG_NET_3 + 0x3C,
     2223 +                                    &data[5]);
     2224 +                                ql_8021_rd_32(ha, UNM_CRB_PEG_NET_4 + 0x3C,
     2225 +                                    &data[6]);
     2226 +                                EL(ha, "halt_status1=%xh, halt_status2=%xh,\n"
     2227 +                                    "peg_pc0=%xh, peg_pc1=%xh, peg_pc2=%xh, "
     2228 +                                    "peg_pc3=%xh, peg_pc4=%xh\n", data[0],
     2229 +                                    data[1], data[2], data[3], data[4],
     2230 +                                    data[5], data[6]);
     2231 +                                new_state = NX_DEV_NEED_RESET;
     2232 +                        }
1959 2233                  }
     2234 +        } else {
     2235 +                ha->seconds_since_last_heartbeat = 0;
     2236 +        }
1960 2237  
1961      -                if (timer) {
1962      -                        delay(100);
1963      -                        timer--;
     2238 +        ha->fw_heartbeat_counter = fw_heartbeat_counter;
     2239 +        return (new_state);
     2240 +}
     2241 +
     2242 +int
     2243 +ql_8021_reset_fw(ql_adapter_state_t *ha)
     2244 +{
     2245 +        return (ql_8021_idc_handler(ha, NX_DEV_NEED_RESET));
     2246 +}
     2247 +
     2248 +int
     2249 +ql_8021_fw_chk(ql_adapter_state_t *ha)
     2250 +{
     2251 +        uint32_t        dev_state, new_state = NX_DEV_POLL;
     2252 +        int             rval;
     2253 +        ql_mbx_data_t   mr;
     2254 +
     2255 +        ql_8021_rd_32(ha, CRB_DEV_STATE, &dev_state);
     2256 +        switch (dev_state) {
     2257 +        case 0xffffffff:
     2258 +        case NX_DEV_COLD:
     2259 +        case NX_DEV_NEED_RESET:
     2260 +        case NX_DEV_NEED_QUIESCENT:
     2261 +        case NX_DEV_INITIALIZING:
     2262 +        case NX_DEV_QUIESCENT:
     2263 +        case NX_DEV_BADOBADO:
     2264 +                break;
     2265 +        case NX_DEV_READY:
     2266 +                if (ql_get_fw_version(ha, &mr, 2) != QL_SUCCESS ||
     2267 +                    (mr.mb[1] | mr.mb[2] | mr.mb[3]) == 0) {
     2268 +                        EL(ha, "version check needs reset\n", dev_state);
     2269 +                        new_state = NX_DEV_NEED_RESET;
1964 2270                  }
     2271 +                break;
     2272 +        case NX_DEV_FAILED:
     2273 +                EL(ha, "device needs reset\n");
     2274 +                new_state = NX_DEV_NEED_RESET;
     2275 +                break;
     2276 +        default:
     2277 +                EL(ha, "state=%xh needs reset\n", dev_state);
     2278 +                new_state = NX_DEV_COLD;
     2279 +                break;
1965 2280          }
1966 2281  
1967      -        if (stalled) {
1968      -                ql_restart_driver(ha);
     2282 +        /* Test for firmware running. */
     2283 +        rval = ql_8021_idc_handler(ha, new_state) == NX_DEV_READY ?
     2284 +            QL_SUCCESS : QL_FUNCTION_FAILED;
     2285 +
     2286 +        return (rval);
     2287 +}
     2288 +
     2289 +/* ****************************************************************** */
     2290 +/* ***************** NetXen MiniDump Functions ********************** */
     2291 +/* ****************************************************************** */
     2292 +
     2293 +/*
     2294 + * ql_8021_get_fw_dump
     2295 + *
     2296 + * Input:
     2297 + *      pi:     FC port info pointer.
     2298 + *
     2299 + * Returns:
     2300 + *      qla driver local function return status codes
     2301 + *
     2302 + * Context:
     2303 + *      Interrupt or Kernel context, no mailbox commands allowed.
     2304 + */
     2305 +static int
     2306 +ql_8021_get_fw_dump(ql_adapter_state_t *ha)
     2307 +{
     2308 +        uint32_t        tsize, cnt, *dp, *bp;
     2309 +
     2310 +        QL_PRINT_10(ha, "started\n");
     2311 +
     2312 +        tsize = ha->dmp_template.size;
     2313 +        cnt = (uint32_t)(tsize / sizeof (uint32_t));
     2314 +        dp = (uint32_t *)ha->ql_dump_ptr;
     2315 +        bp = (uint32_t *)ha->dmp_template.bp;
     2316 +        while (cnt--) {
     2317 +                *dp++ = ddi_get32(ha->dmp_template.acc_handle, bp++);
1969 2318          }
     2319 +        ql_8021_md_parse_template(ha, ha->ql_dump_ptr, (caddr_t)dp,
     2320 +            ha->md_capture_size - tsize, ha->md_capture_mask);
     2321 +
     2322 +#ifdef _BIG_ENDIAN
     2323 +        cnt = (uint32_t)(ha->ql_dump_size / sizeof (uint32_t));
     2324 +        dp = (uint32_t *)ha->ql_dump_ptr;
     2325 +        while (cnt--) {
     2326 +                ql_chg_endian((uint8_t *)dp, 4);
     2327 +                dp++;
     2328 +        }
     2329 +#endif
     2330 +        QL_PRINT_10(ha, "done\n");
     2331 +        return (QL_SUCCESS);
     2332 +}
     2333 +
     2334 +/*
     2335 + * ql_8021_get_md_template
     2336 + *      Get mini-dump template
     2337 + *
     2338 + * Input:
     2339 + *      ha:     adapter state pointer.
     2340 + *
     2341 + * Returns:
     2342 + *      ql local function return status code.
     2343 + *
     2344 + * Context:
     2345 + *      Kernel context.
     2346 + */
     2347 +int
     2348 +ql_8021_get_md_template(ql_adapter_state_t *ha)
     2349 +{
     2350 +        ql_mbx_data_t   mr;
     2351 +        uint32_t        tsize, chksum;
     2352 +        int             rval;
     2353 +
     2354 +        rval = ql_get_md_template(ha, NULL, &mr, 0, GTO_TEMPLATE_SIZE);
     2355 +        if (rval != QL_SUCCESS ||
     2356 +            (tsize = SHORT_TO_LONG(mr.mb[2], mr.mb[3])) == 0) {
     2357 +                EL(ha, "size=%xh status=%xh\n", tsize, rval);
     2358 +                ha->md_capture_size = 0;
     2359 +                ql_free_phys(ha, &ha->dmp_template);
     2360 +                return (rval);
     2361 +        }
     2362 +        if (ha->dmp_template.dma_handle && ha->dmp_template.size != tsize) {
     2363 +                ql_free_phys(ha, &ha->dmp_template);
     2364 +        }
     2365 +        ha->md_capture_mask = 0x1f;
     2366 +        ha->md_capture_size = SHORT_TO_LONG(mr.mb[4], mr.mb[5]) +
     2367 +            SHORT_TO_LONG(mr.mb[6], mr.mb[7]) +
     2368 +            SHORT_TO_LONG(mr.mb[8], mr.mb[9]) +
     2369 +            SHORT_TO_LONG(mr.mb[10], mr.mb[11]) + tsize;
     2370 +        /*
     2371 +         * Determine ascii dump file size
     2372 +         * 2 ascii bytes per binary byte + a space and
     2373 +         * a newline every 16 binary bytes
     2374 +         */
     2375 +        ha->risc_dump_size = ha->md_capture_size << 1;
     2376 +        ha->risc_dump_size += ha->md_capture_size;
     2377 +        ha->risc_dump_size += ha->md_capture_size / 16 + 1;
     2378 +
     2379 +        /* Allocate template buffer. */
     2380 +        if (ha->dmp_template.dma_handle == NULL) {
     2381 +                rval = ql_get_dma_mem(ha, &ha->dmp_template, tsize,
     2382 +                    LITTLE_ENDIAN_DMA, QL_DMA_RING_ALIGN);
     2383 +                if (rval != QL_SUCCESS) {
     2384 +                        EL(ha, "unable to allocate template buffer, "
     2385 +                            "status=%xh\n", rval);
     2386 +                        ha->md_capture_size = 0;
     2387 +                        ql_free_phys(ha, &ha->dmp_template);
     2388 +                        return (rval);
     2389 +                }
     2390 +        }
     2391 +        rval = ql_get_md_template(ha, &ha->dmp_template, &mr, 0, GTO_TEMPLATE);
     2392 +        if (rval != QL_SUCCESS ||
     2393 +            (chksum = ql_8021_md_template_checksum(ha))) {
     2394 +                EL(ha, "status=%xh, chksum=%xh\n", rval, chksum);
     2395 +                if (rval == QL_SUCCESS) {
     2396 +                        rval = QL_FUNCTION_FAILED;
     2397 +                }
     2398 +                ql_free_phys(ha, &ha->dmp_template);
     2399 +                ha->md_capture_size = 0;
     2400 +        }
     2401 +
1970 2402          return (rval);
     2403 +}
     2404 +
     2405 +static void
     2406 +ql_8021_md_parse_template(ql_adapter_state_t *ha, caddr_t template_buff,
     2407 +    caddr_t dump_buff, uint32_t buff_size, uint32_t capture_mask)
     2408 +{
     2409 +        int                     e_cnt, buff_level, esize;
     2410 +        uint32_t                num_of_entries;
     2411 +        time_t                  time;
     2412 +        caddr_t                 dbuff;
     2413 +        int                     sane_start = 0, sane_end = 0;
     2414 +        md_template_hdr_t       *template_hdr;
     2415 +        md_entry_t              *entry;
     2416 +
     2417 +        if ((capture_mask & 0x3) != 0x3) {
     2418 +                EL(ha, "capture mask %02xh below minimum needed for valid "
     2419 +                    "dump\n", capture_mask);
     2420 +                return;
     2421 +        }
     2422 +        /* Setup parameters */
     2423 +        template_hdr = (md_template_hdr_t *)template_buff;
     2424 +        if (template_hdr->entry_type == TLHDR) {
     2425 +                sane_start = 1;
     2426 +        }
     2427 +        (void) drv_getparm(TIME, &time);
     2428 +        template_hdr->driver_timestamp = LSD(time);
     2429 +        template_hdr->driver_capture_mask = capture_mask;
     2430 +        num_of_entries = template_hdr->num_of_entries;
     2431 +        entry = (md_entry_t *)((caddr_t)template_buff +
     2432 +            template_hdr->first_entry_offset);
     2433 +        for (buff_level = 0, e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
     2434 +                /*
     2435 +                 * If the capture_mask of the entry does not match capture mask
     2436 +                 * skip the entry after marking the driver_flags indicator.
     2437 +                 */
     2438 +                if (!(entry->h.a.ecw.entry_capture_mask & capture_mask)) {
     2439 +                        entry->h.a.ecw.driver_flags = (uint8_t)
     2440 +                            (entry->h.a.ecw.driver_flags |
     2441 +                            QL_DBG_SKIPPED_FLAG);
     2442 +                        entry = (md_entry_t *)((char *)entry +
     2443 +                            entry->h.entry_size);
     2444 +                        continue;
     2445 +                }
     2446 +                /*
     2447 +                 * This is ONLY needed in implementations where
     2448 +                 * the capture buffer allocated is too small to capture
     2449 +                 * all of the required entries for a given capture mask.
     2450 +                 * We need to empty the buffer contents to a file
     2451 +                 * if possible, before processing the next entry
     2452 +                 * If the buff_full_flag is set, no further capture will
     2453 +                 * happen and all remaining non-control entries will be
     2454 +                 * skipped.
     2455 +                 */
     2456 +                if (entry->h.entry_capture_size != 0) {
     2457 +                        if ((buff_level + entry->h.entry_capture_size) >
     2458 +                            buff_size) {
     2459 +                                entry = (md_entry_t *)((char *)entry +
     2460 +                                    entry->h.entry_size);
     2461 +                                continue;
     2462 +                        }
     2463 +                }
     2464 +                /*
     2465 +                 * Decode the entry type and process it accordingly
     2466 +                 */
     2467 +                switch (entry->h.entry_type) {
     2468 +                case RDNOP:
     2469 +                        break;
     2470 +                case RDEND:
     2471 +                        sane_end += 1;
     2472 +                        break;
     2473 +                case RDCRB:
     2474 +                        dbuff = dump_buff + buff_level;
     2475 +                        esize = ql_8021_md_rdcrb(ha, (void *)entry,
     2476 +                            (void *)dbuff);
     2477 +                        ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
     2478 +                        buff_level += esize;
     2479 +                        break;
     2480 +                case L2ITG:
     2481 +                case L2DTG:
     2482 +                case L2DAT:
     2483 +                case L2INS:
     2484 +                        dbuff = dump_buff + buff_level;
     2485 +                        esize = ql_8021_md_L2Cache(ha, (void *)entry,
     2486 +                            (void *)dbuff);
     2487 +                        if (esize == -1) {
     2488 +                                entry->h.a.ecw.driver_flags = (uint8_t)
     2489 +                                    (entry->h.a.ecw.driver_flags |
     2490 +                                    QL_DBG_SKIPPED_FLAG);
     2491 +                        } else {
     2492 +                                ql_8021_md_entry_err_chk(ha, entry, esize,
     2493 +                                    e_cnt);
     2494 +                                buff_level += esize;
     2495 +                        }
     2496 +                        break;
     2497 +                case L1DAT:
     2498 +                case L1INS:
     2499 +                        dbuff = dump_buff + buff_level;
     2500 +                        esize = ql_8021_md_L1Cache(ha, (void *)entry,
     2501 +                            (void *)dbuff);
     2502 +                        ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
     2503 +                        buff_level += esize;
     2504 +                        break;
     2505 +                case RDOCM:
     2506 +                        dbuff = dump_buff + buff_level;
     2507 +                        esize = ql_8021_md_rdocm(ha, (void *)entry,
     2508 +                            (void *)dbuff);
     2509 +                        ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
     2510 +                        buff_level += esize;
     2511 +                        break;
     2512 +                case RDMEM:
     2513 +                        dbuff = dump_buff + buff_level;
     2514 +                        esize = ql_8021_md_rdmem(ha, (void *)entry,
     2515 +                            (void *)dbuff);
     2516 +                        ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
     2517 +                        buff_level += esize;
     2518 +                        break;
     2519 +                case BOARD:
     2520 +                case RDROM:
     2521 +                        dbuff = dump_buff + buff_level;
     2522 +                        esize = ql_8021_md_rdrom(ha, (void *)entry,
     2523 +                            (void *)dbuff);
     2524 +                        ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
     2525 +                        buff_level += esize;
     2526 +                        break;
     2527 +                case RDMUX:
     2528 +                        dbuff = dump_buff + buff_level;
     2529 +                        esize = ql_8021_md_rdmux(ha, (void *)entry,
     2530 +                            (void *)dbuff);
     2531 +                        ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
     2532 +                        buff_level += esize;
     2533 +                        break;
     2534 +                case QUEUE:
     2535 +                        dbuff = dump_buff + buff_level;
     2536 +                        esize = ql_8021_md_rdqueue(ha, (void *)entry,
     2537 +                            (void *)dbuff);
     2538 +                        ql_8021_md_entry_err_chk(ha, entry, esize, e_cnt);
     2539 +                        buff_level += esize;
     2540 +                        break;
     2541 +                case CNTRL:
     2542 +                        if (ql_8021_md_cntrl(ha, template_hdr,
     2543 +                            (void *)entry)) {
     2544 +                                entry->h.a.ecw.driver_flags = (uint8_t)
     2545 +                                    (entry->h.a.ecw.driver_flags |
     2546 +                                    QL_DBG_SKIPPED_FLAG);
     2547 +                                EL(ha, "Entry ID=%d, entry_type=%d non zero "
     2548 +                                    "status\n", e_cnt, entry->h.entry_type);
     2549 +                        }
     2550 +                        break;
     2551 +                default:
     2552 +                        entry->h.a.ecw.driver_flags = (uint8_t)
     2553 +                            (entry->h.a.ecw.driver_flags |
     2554 +                            QL_DBG_SKIPPED_FLAG);
     2555 +                        EL(ha, "Entry ID=%d, entry_type=%d unknown\n", e_cnt,
     2556 +                            entry->h.entry_type);
     2557 +                        break;
     2558 +                }
     2559 +                /* next entry in the template */
     2560 +                entry = (md_entry_t *)((caddr_t)entry + entry->h.entry_size);
     2561 +        }
     2562 +        if (!sane_start || (sane_end > 1)) {
     2563 +                EL(ha, "Template configuration error. Check Template\n");
     2564 +        }
     2565 +        QL_PRINT_10(ha, "Minidump num of entries=%d\n",
     2566 +            template_hdr->num_of_entries);
     2567 +}
     2568 +
     2569 +/*
     2570 + * Read CRB operation.
     2571 + */
     2572 +static int
     2573 +ql_8021_md_rdcrb(ql_adapter_state_t *ha, md_entry_rdcrb_t *crbEntry,
     2574 +    uint32_t *data_buff)
     2575 +{
     2576 +        uint32_t        loop_cnt, op_count, addr, stride, value;
     2577 +        int             i;
     2578 +
     2579 +        addr = crbEntry->addr;
     2580 +        op_count = crbEntry->op_count;
     2581 +        stride = crbEntry->a.ac.addr_stride;
     2582 +
     2583 +        for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) {
     2584 +                value = ql_8021_read_reg(ha, addr);
     2585 +                *data_buff++ = addr;
     2586 +                *data_buff++ = value;
     2587 +                addr = addr + stride;
     2588 +        }
     2589 +
     2590 +        /*
     2591 +         * for testing purpose we return amount of data written
     2592 +         */
     2593 +        i = (int)(loop_cnt * (2 * sizeof (uint32_t)));
     2594 +
     2595 +        return (i);
     2596 +}
     2597 +
     2598 +/*
     2599 + * Handle L2 Cache.
     2600 + */
     2601 +static int
     2602 +ql_8021_md_L2Cache(ql_adapter_state_t *ha, md_entry_cache_t *cacheEntry,
     2603 +    uint32_t *data_buff)
     2604 +{
     2605 +        int                     i, k, tflag;
     2606 +        uint32_t                read_value, loop_cnt, read_cnt;
     2607 +        uint32_t                addr, read_addr, cntrl_addr, tag_reg_addr;
     2608 +        uint32_t                cntl_value_w, tag_value, tag_value_stride;
     2609 +        volatile uint8_t        cntl_value_r;
     2610 +        clock_t                 timeout, elapsed;
     2611 +
     2612 +        read_addr = cacheEntry->read_addr;
     2613 +        loop_cnt = cacheEntry->op_count;
     2614 +        cntrl_addr = cacheEntry->control_addr;
     2615 +        cntl_value_w = CHAR_TO_SHORT(cacheEntry->b.cv.write_value[0],
     2616 +            cacheEntry->b.cv.write_value[1]);
     2617 +        tag_reg_addr = cacheEntry->tag_reg_addr;
     2618 +        tag_value = CHAR_TO_SHORT(cacheEntry->a.sac.init_tag_value[0],
     2619 +            cacheEntry->a.sac.init_tag_value[1]);
     2620 +        tag_value_stride = CHAR_TO_SHORT(cacheEntry->a.sac.tag_value_stride[0],
     2621 +            cacheEntry->a.sac.tag_value_stride[1]);
     2622 +        read_cnt = cacheEntry->c.rac.read_addr_cnt;
     2623 +
     2624 +        for (i = 0; i < loop_cnt; i++) {
     2625 +                ql_8021_write_reg(ha, tag_value, tag_reg_addr);
     2626 +                if (cntl_value_w) {
     2627 +                        ql_8021_write_reg(ha, cntl_value_w, cntrl_addr);
     2628 +                }
     2629 +                if (cacheEntry->b.cv.poll_wait) {
     2630 +                        (void) drv_getparm(LBOLT, &timeout);
     2631 +                        timeout += drv_usectohz(cacheEntry->b.cv.poll_wait *
     2632 +                            1000) + 1;
     2633 +                        cntl_value_r = (uint8_t)ql_8021_read_reg(ha,
     2634 +                            cntrl_addr);
     2635 +                        tflag = 0;
     2636 +                        while (!tflag && ((cntl_value_r &
     2637 +                            cacheEntry->b.cv.poll_mask) != 0)) {
     2638 +                                (void) drv_getparm(LBOLT, &elapsed);
     2639 +                                if (elapsed > timeout) {
     2640 +                                        tflag = 1;
     2641 +                                }
     2642 +                                cntl_value_r = (uint8_t)ql_8021_read_reg(ha,
     2643 +                                    cntrl_addr);
     2644 +                        }
     2645 +                        if (tflag) {
     2646 +                                /*
     2647 +                                 *  Report timeout error.  core dump capture
     2648 +                                 *  failed
     2649 +                                 *  Skip remaining entries. Write buffer out
     2650 +                                 *  to file
     2651 +                                 *  Use driver specific fields in template
     2652 +                                 *  header
     2653 +                                 *  to report this error.
     2654 +                                 */
     2655 +                                EL(ha, "timeout\n");
     2656 +                                return (-1);
     2657 +                        }
     2658 +                }
     2659 +                addr = read_addr;
     2660 +                for (k = 0; k < read_cnt; k++) {
     2661 +                        read_value = ql_8021_read_reg(ha, addr);
     2662 +                        *data_buff++ = read_value;
     2663 +                        addr += cacheEntry->c.rac.read_addr_stride;
     2664 +                }
     2665 +                tag_value += tag_value_stride;
     2666 +        }
     2667 +        i = (int)(read_cnt * loop_cnt * sizeof (uint32_t));
     2668 +
     2669 +        return (i);
     2670 +}
     2671 +
     2672 +/*
     2673 + * Handle L1 Cache.
     2674 + */
     2675 +static int
     2676 +ql_8021_md_L1Cache(ql_adapter_state_t *ha, md_entry_cache_t *cacheEntry,
     2677 +    uint32_t *data_buff)
     2678 +{
     2679 +        int                     i, k;
     2680 +        uint32_t                read_value, tag_value, tag_value_stride;
     2681 +        uint32_t                read_cnt, loop_cnt;
     2682 +        uint32_t                addr, read_addr, cntrl_addr, tag_reg_addr;
     2683 +        volatile uint32_t       cntl_value_w;
     2684 +
     2685 +        read_addr = cacheEntry->read_addr;
     2686 +        loop_cnt = cacheEntry->op_count;
     2687 +        cntrl_addr = cacheEntry->control_addr;
     2688 +        cntl_value_w = CHAR_TO_SHORT(cacheEntry->b.cv.write_value[0],
     2689 +            cacheEntry->b.cv.write_value[1]);
     2690 +        tag_reg_addr = cacheEntry->tag_reg_addr;
     2691 +        tag_value = CHAR_TO_SHORT(cacheEntry->a.sac.init_tag_value[0],
     2692 +            cacheEntry->a.sac.init_tag_value[1]);
     2693 +        tag_value_stride = CHAR_TO_SHORT(cacheEntry->a.sac.tag_value_stride[0],
     2694 +            cacheEntry->a.sac.tag_value_stride[1]);
     2695 +        read_cnt = cacheEntry->c.rac.read_addr_cnt;
     2696 +
     2697 +        for (i = 0; i < loop_cnt; i++) {
     2698 +                ql_8021_write_reg(ha, tag_value, tag_reg_addr);
     2699 +                ql_8021_write_reg(ha, cntl_value_w, cntrl_addr);
     2700 +                addr = read_addr;
     2701 +                for (k = 0; k < read_cnt; k++) {
     2702 +                        read_value = ql_8021_read_reg(ha, addr);
     2703 +                        *data_buff++ = read_value;
     2704 +                        addr += cacheEntry->c.rac.read_addr_stride;
     2705 +                }
     2706 +                tag_value += tag_value_stride;
     2707 +        }
     2708 +        i = (int)(read_cnt * loop_cnt * sizeof (uint32_t));
     2709 +
     2710 +        return (i);
     2711 +}
     2712 +
     2713 +/*
     2714 + * Reading OCM memory
     2715 + */
     2716 +static int
     2717 +ql_8021_md_rdocm(ql_adapter_state_t *ha, md_entry_rdocm_t *ocmEntry,
     2718 +    uint32_t *data_buff)
     2719 +{
     2720 +        int             i;
     2721 +        uint32_t        addr, value, loop_cnt;
     2722 +
     2723 +        addr = ocmEntry->read_addr;
     2724 +        loop_cnt = ocmEntry->op_count;
     2725 +
     2726 +        for (i = 0; i < loop_cnt; i++) {
     2727 +                value = ql_8021_read_ocm(ha, addr);
     2728 +                *data_buff++ = value;
     2729 +                addr += ocmEntry->read_addr_stride;
     2730 +        }
     2731 +        i = (int)(loop_cnt * sizeof (value));
     2732 +
     2733 +        return (i);
     2734 +}
     2735 +
     2736 +/*
     2737 + * Read memory
     2738 + */
     2739 +static int
     2740 +ql_8021_md_rdmem(ql_adapter_state_t *ha, md_entry_rdmem_t *memEntry,
     2741 +    uint32_t *data_buff)
     2742 +{
     2743 +        int             i, k;
     2744 +        uint32_t        addr, value, loop_cnt;
     2745 +
     2746 +        addr = memEntry->read_addr;
     2747 +        loop_cnt = (uint32_t)(memEntry->read_data_size /
     2748 +            (sizeof (uint32_t) * 4));           /* size in bytes / 16 */
     2749 +
     2750 +        ql_8021_write_reg(ha, 0, MD_MIU_TEST_AGT_ADDR_HI);
     2751 +        for (i = 0; i < loop_cnt; i++) {
     2752 +                /*
     2753 +                 * Write address
     2754 +                 */
     2755 +                ql_8021_write_reg(ha, addr, MD_MIU_TEST_AGT_ADDR_LO);
     2756 +                ql_8021_write_reg(ha, MD_TA_CTL_ENABLE,
     2757 +                    MD_MIU_TEST_AGT_CTRL);
     2758 +                ql_8021_write_reg(ha, (MD_TA_CTL_START | MD_TA_CTL_ENABLE),
     2759 +                    MD_MIU_TEST_AGT_CTRL);
     2760 +                /*
     2761 +                 * Check busy bit.
     2762 +                 */
     2763 +                for (k = 0; k < MD_TA_CTL_CHECK; k++) {
     2764 +                        value = ql_8021_read_reg(ha, MD_MIU_TEST_AGT_CTRL);
     2765 +                        if ((value & MD_TA_CTL_BUSY) == 0) {
     2766 +                                break;
     2767 +                        }
     2768 +                }
     2769 +                if (k == MD_TA_CTL_CHECK) {
     2770 +                        i = (int)((uint_t)i * (sizeof (uint32_t) * 4));
     2771 +                        EL(ha, "failed to read=xh\n", i);
     2772 +                        return (i);
     2773 +                }
     2774 +                /*
     2775 +                 * Read data
     2776 +                 */
     2777 +                value = ql_8021_read_reg(ha, MD_MIU_TEST_AGT_RDDATA_0_31);
     2778 +                *data_buff++ = value;
     2779 +                value = ql_8021_read_reg(ha, MD_MIU_TEST_AGT_RDDATA_32_63);
     2780 +                *data_buff++ = value;
     2781 +                value = ql_8021_read_reg(ha, MD_MIU_TEST_AGT_RDDATA_64_95);
     2782 +                *data_buff++ = value;
     2783 +                value = ql_8021_read_reg(ha, MD_MIU_TEST_AGT_RDDATA_96_127);
     2784 +                *data_buff++ = value;
     2785 +                /*
     2786 +                 *  next address to read
     2787 +                 */
     2788 +                addr = (uint32_t)(addr + (sizeof (uint32_t) * 4));
     2789 +        }
     2790 +        i = (int)(loop_cnt * (sizeof (uint32_t) * 4));
     2791 +
     2792 +        return (i);
     2793 +}
     2794 +
     2795 +/*
     2796 + * Read Rom
     2797 + */
     2798 +static int
     2799 +ql_8021_md_rdrom(ql_adapter_state_t *ha, md_entry_rdrom_t *romEntry,
     2800 +    uint32_t *data_buff)
     2801 +{
     2802 +        int             i;
     2803 +        uint32_t        addr, waddr, raddr, value, loop_cnt;
     2804 +
     2805 +        addr = romEntry->read_addr;
     2806 +        loop_cnt = romEntry->read_data_size;    /* This is size in bytes */
     2807 +        loop_cnt = (uint32_t)(loop_cnt / sizeof (value));
     2808 +
     2809 +        for (i = 0; i < loop_cnt; i++) {
     2810 +                waddr = addr & 0xFFFF0000;
     2811 +                (void) ql_8021_rom_lock(ha);
     2812 +                ql_8021_write_reg(ha, waddr, MD_DIRECT_ROM_WINDOW);
     2813 +                raddr = MD_DIRECT_ROM_READ_BASE + (addr & 0x0000FFFF);
     2814 +                value = ql_8021_read_reg(ha, raddr);
     2815 +                ql_8021_rom_unlock(ha);
     2816 +                *data_buff++ = value;
     2817 +                addr = (uint32_t)(addr + sizeof (value));
     2818 +        }
     2819 +        i = (int)(loop_cnt * sizeof (value));
     2820 +
     2821 +        return (i);
     2822 +}
     2823 +
     2824 +/*
     2825 + * Read MUX data
     2826 + */
     2827 +static int
     2828 +ql_8021_md_rdmux(ql_adapter_state_t *ha, md_entry_mux_t *muxEntry,
     2829 +    uint32_t *data_buff)
     2830 +{
     2831 +        uint32_t        read_value, sel_value, loop_cnt;
     2832 +        uint32_t        read_addr, select_addr;
     2833 +        int             i;
     2834 +
     2835 +        select_addr = muxEntry->select_addr;
     2836 +        sel_value = muxEntry->select_value;
     2837 +        read_addr = muxEntry->read_addr;
     2838 +
     2839 +        for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) {
     2840 +                ql_8021_write_reg(ha, sel_value, select_addr);
     2841 +                read_value = ql_8021_read_reg(ha, read_addr);
     2842 +                *data_buff++ = sel_value;
     2843 +                *data_buff++ = read_value;
     2844 +                sel_value += muxEntry->select_value_stride;
     2845 +        }
     2846 +        i = (int)(loop_cnt * (2 * sizeof (uint32_t)));
     2847 +
     2848 +        return (i);
     2849 +}
     2850 +
     2851 +/*
     2852 + * Handling Queue State Reads.
     2853 + */
     2854 +static int
     2855 +ql_8021_md_rdqueue(ql_adapter_state_t *ha, md_entry_queue_t *queueEntry,
     2856 +    uint32_t *data_buff)
     2857 +{
     2858 +        int             k;
     2859 +        uint32_t        read_value, read_addr, read_stride, select_addr;
     2860 +        uint32_t        queue_id, loop_cnt, read_cnt;
     2861 +
     2862 +        read_cnt = queueEntry->b.rac.read_addr_cnt;
     2863 +        read_stride = queueEntry->b.rac.read_addr_stride;
     2864 +        select_addr = queueEntry->select_addr;
     2865 +
     2866 +        for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count;
     2867 +            loop_cnt++) {
     2868 +                ql_8021_write_reg(ha, queue_id, select_addr);
     2869 +                read_addr = queueEntry->read_addr;
     2870 +                for (k = 0; k < read_cnt; k++) {
     2871 +                        read_value = ql_8021_read_reg(ha, read_addr);
     2872 +                        *data_buff++ = read_value;
     2873 +                        read_addr += read_stride;
     2874 +                }
     2875 +                queue_id += CHAR_TO_SHORT(queueEntry->a.sac.queue_id_stride[0],
     2876 +                    queueEntry->a.sac.queue_id_stride[1]);
     2877 +        }
     2878 +        k = (int)(loop_cnt * (read_cnt * sizeof (uint32_t)));
     2879 +
     2880 +        return (k);
     2881 +}
     2882 +
     2883 +/*
     2884 + * Handling control entries.
     2885 + */
     2886 +static int
     2887 +ql_8021_md_cntrl(ql_adapter_state_t *ha, md_template_hdr_t *template_hdr,
     2888 +    md_entry_cntrl_t *crbEntry)
     2889 +{
     2890 +        int             tflag;
     2891 +        uint32_t        opcode, read_value, addr, entry_addr, loop_cnt;
     2892 +        clock_t         timeout, elapsed;
     2893 +
     2894 +        entry_addr = crbEntry->addr;
     2895 +
     2896 +        for (loop_cnt = 0; loop_cnt < crbEntry->op_count; loop_cnt++) {
     2897 +                opcode = crbEntry->b.cv.opcode;
     2898 +                if (opcode & QL_DBG_OPCODE_WR) {
     2899 +                        ql_8021_write_reg(ha, crbEntry->value_1, entry_addr);
     2900 +                        opcode &= ~QL_DBG_OPCODE_WR;
     2901 +                }
     2902 +                if (opcode & QL_DBG_OPCODE_RW) {
     2903 +                        read_value = ql_8021_read_reg(ha, entry_addr);
     2904 +                        ql_8021_write_reg(ha, read_value, entry_addr);
     2905 +                        opcode &= ~QL_DBG_OPCODE_RW;
     2906 +                }
     2907 +                if (opcode & QL_DBG_OPCODE_AND) {
     2908 +                        read_value = ql_8021_read_reg(ha, entry_addr);
     2909 +                        read_value &= crbEntry->value_2;
     2910 +                        opcode &= ~QL_DBG_OPCODE_AND;
     2911 +
     2912 +                        /* Checking for OR here to avoid extra register write */
     2913 +                        if (opcode & QL_DBG_OPCODE_OR) {
     2914 +                                read_value |= crbEntry->value_3;
     2915 +                                opcode &= ~QL_DBG_OPCODE_OR;
     2916 +                        }
     2917 +                        ql_8021_write_reg(ha, read_value, entry_addr);
     2918 +                }
     2919 +                if (opcode & QL_DBG_OPCODE_OR) {
     2920 +                        read_value = ql_8021_read_reg(ha, entry_addr);
     2921 +                        read_value |= crbEntry->value_3;
     2922 +                        ql_8021_write_reg(ha, read_value, entry_addr);
     2923 +                        opcode &= ~QL_DBG_OPCODE_OR;
     2924 +                }
     2925 +                if (opcode & QL_DBG_OPCODE_POLL) {
     2926 +                        opcode &= ~QL_DBG_OPCODE_POLL;
     2927 +                        (void) drv_getparm(LBOLT, &timeout);
     2928 +                        timeout += drv_usectohz(
     2929 +                            CHAR_TO_SHORT(crbEntry->a.ac.poll_timeout[0],
     2930 +                            crbEntry->a.ac.poll_timeout[1]) * 1000) + 1;
     2931 +                        addr = entry_addr;
     2932 +                        read_value = ql_8021_read_reg(ha, addr);
     2933 +                        tflag = 0;
     2934 +                        while (!tflag && ((read_value & crbEntry->value_2) !=
     2935 +                            crbEntry->value_1)) {
     2936 +                                (void) drv_getparm(LBOLT, &elapsed);
     2937 +                                if (elapsed > timeout) {
     2938 +                                        tflag = 1;
     2939 +                                }
     2940 +                                read_value = ql_8021_read_reg(ha, addr);
     2941 +                        }
     2942 +                        if (tflag) {
     2943 +                                /*
     2944 +                                 *  Report timeout error.  core dump capture
     2945 +                                 *  failed Skip remaining entries. Write buffer
     2946 +                                 *  out to file Use driver specific fields in
     2947 +                                 *  template header to report this error.
     2948 +                                 */
     2949 +                                EL(ha, "timeout\n");
     2950 +                                return (-1);
     2951 +                        }
     2952 +                }
     2953 +                if (opcode & QL_DBG_OPCODE_RDSTATE) {
     2954 +                        /*
     2955 +                         * decide which address to use.
     2956 +                         */
     2957 +                        if (crbEntry->a.ac.state_index_a) {
     2958 +                                addr = template_hdr->saved_state_array[
     2959 +                                    crbEntry->a.ac.state_index_a];
     2960 +                        } else {
     2961 +                                addr = entry_addr;
     2962 +                        }
     2963 +                        read_value = ql_8021_read_reg(ha, addr);
     2964 +                        template_hdr->saved_state_array[
     2965 +                            crbEntry->b.cv.state_index_v] = read_value;
     2966 +                        opcode &= ~QL_DBG_OPCODE_RDSTATE;
     2967 +                }
     2968 +                if (opcode & QL_DBG_OPCODE_WRSTATE) {
     2969 +                        /*
     2970 +                         * decide which value to use.
     2971 +                         */
     2972 +                        if (crbEntry->b.cv.state_index_v) {
     2973 +                                read_value = template_hdr->saved_state_array[
     2974 +                                    crbEntry->b.cv.state_index_v];
     2975 +                        } else {
     2976 +                                read_value = crbEntry->value_1;
     2977 +                        }
     2978 +                        /*
     2979 +                         * decide which address to use.
     2980 +                         */
     2981 +                        if (crbEntry->a.ac.state_index_a) {
     2982 +                                addr = template_hdr->saved_state_array[
     2983 +                                    crbEntry->a.ac.state_index_a];
     2984 +                        } else {
     2985 +                                addr = entry_addr;
     2986 +                        }
     2987 +                        ql_8021_write_reg(ha, read_value, addr);
     2988 +                        opcode &= ~QL_DBG_OPCODE_WRSTATE;
     2989 +                }
     2990 +                if (opcode & QL_DBG_OPCODE_MDSTATE) {
     2991 +                        /* Read value from saved state using index */
     2992 +                        read_value = template_hdr->saved_state_array[
     2993 +                            crbEntry->b.cv.state_index_v];
     2994 +                        /* Shift left operation */
     2995 +                        read_value <<= crbEntry->b.cv.shl;
     2996 +                        /* Shift right operation */
     2997 +                        read_value >>= crbEntry->b.cv.shr;
     2998 +                        /* check if AND mask is provided */
     2999 +                        if (crbEntry->value_2) {
     3000 +                                read_value &= crbEntry->value_2;
     3001 +                        }
     3002 +                        read_value |= crbEntry->value_3; /* OR operation */
     3003 +                        read_value += crbEntry->value_1; /* inc operation */
     3004 +                        /* Write value back to state area. */
     3005 +                        template_hdr->saved_state_array[
     3006 +                            crbEntry->b.cv.state_index_v] = read_value;
     3007 +                        opcode &= ~QL_DBG_OPCODE_MDSTATE;
     3008 +                }
     3009 +                entry_addr += crbEntry->a.ac.addr_stride;
     3010 +        }
     3011 +
     3012 +        return (0);
     3013 +}
     3014 +
     3015 +/*
     3016 + * Error Checking routines for template consistency.
     3017 + *
     3018 + * We catch an error where driver does not read
     3019 + * as much data as we expect from the entry.
     3020 + */
     3021 +static void
     3022 +ql_8021_md_entry_err_chk(ql_adapter_state_t *ha, md_entry_t *entry,
     3023 +    uint32_t esize, int e_cnt)
     3024 +{
     3025 +        if (esize != entry->h.entry_capture_size) {
     3026 +                EL(ha, "%d %04x Dump write count = %d did not match entry "
     3027 +                    "capture size = %d entry_count = %d\n", entry->h.entry_type,
     3028 +                    entry->h.a.ecw.entry_capture_mask, esize,
     3029 +                    entry->h.entry_capture_size, e_cnt);
     3030 +                entry->h.entry_capture_size = esize;
     3031 +                entry->h.a.ecw.driver_flags = (uint8_t)
     3032 +                    (entry->h.a.ecw.driver_flags | QL_DBG_SKIPPED_FLAG);
     3033 +        }
     3034 +}
     3035 +
     3036 +static uint32_t
     3037 +ql_8021_md_template_checksum(ql_adapter_state_t *ha)
     3038 +{
     3039 +        uint64_t        sum = 0;
     3040 +        uint32_t        cnt, *bp;
     3041 +
     3042 +        cnt = (uint32_t)(ha->dmp_template.size / sizeof (uint32_t));
     3043 +        bp = ha->dmp_template.bp;
     3044 +        while (cnt-- > 0) {
     3045 +                sum += ddi_get32(ha->dmp_template.acc_handle, bp++);
     3046 +        }
     3047 +        while (sum >> 32) {
     3048 +                sum = (sum & 0xFFFFFFFF) + (sum >> 32);
     3049 +        }
     3050 +        cnt = (uint32_t)~sum;
     3051 +
     3052 +        return (cnt);
     3053 +}
     3054 +
     3055 +static uint32_t
     3056 +ql_8021_read_reg(ql_adapter_state_t *ha, uint32_t addr)
     3057 +{
     3058 +        uint32_t        addr0, addr1, value;
     3059 +
     3060 +        (void) ql_8021_crb_win_lock(ha);
     3061 +
     3062 +        addr0 = addr & 0xFFFF0000;
     3063 +        WRT_REG_DWORD(ha, (ha->nx_pcibase + 0x00130060), addr0);
     3064 +        /* PCI posting read */
     3065 +        (void) RD_REG_DWORD(ha, (ha->nx_pcibase + 0x00130060));
     3066 +        addr1 = addr & 0x0000FFFF;
     3067 +        value = RD_REG_DWORD(ha, (ha->nx_pcibase + 0x001E0000 + addr1));
     3068 +
     3069 +        ql_8021_crb_win_unlock(ha);
     3070 +
     3071 +        return (value);
     3072 +}
     3073 +
     3074 +static void
     3075 +ql_8021_write_reg(ql_adapter_state_t *ha, uint32_t value, uint32_t addr)
     3076 +{
     3077 +        uint32_t        addr0, addr1;
     3078 +
     3079 +        (void) ql_8021_crb_win_lock(ha);
     3080 +
     3081 +        addr0 = addr & 0xFFFF0000;
     3082 +        WRT_REG_DWORD(ha, (ha->nx_pcibase + 0x00130060), addr0);
     3083 +        /* PCI posting read */
     3084 +        (void) RD_REG_DWORD(ha, (ha->nx_pcibase + 0x00130060));
     3085 +        addr1 = addr & 0x0000FFFF;
     3086 +        WRT_REG_DWORD(ha, (ha->nx_pcibase + 0x001E0000 + addr1), value);
     3087 +        /* PCI posting read */
     3088 +        (void) RD_REG_DWORD(ha, (ha->nx_pcibase + 0x001E0000 + addr1));
     3089 +
     3090 +        ql_8021_crb_win_unlock(ha);
     3091 +}
     3092 +
     3093 +static uint32_t
     3094 +ql_8021_read_ocm(ql_adapter_state_t *ha, uint32_t addr)
     3095 +{
     3096 +        uint32_t        value;
     3097 +
     3098 +        value = RD_REG_DWORD(ha, (ha->nx_pcibase + addr));
     3099 +
     3100 +        return (value);
1971 3101  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX