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


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/qlxgb/qla_misc.c

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

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2011-2013 Qlogic Corporation
    5  * All rights reserved.
    6  *
    7  *  Redistribution and use in source and binary forms, with or without
    8  *  modification, are permitted provided that the following conditions
    9  *  are met:
   10  *
   11  *  1. Redistributions of source code must retain the above copyright
   12  *     notice, this list of conditions and the following disclaimer.
   13  *  2. Redistributions in binary form must reproduce the above copyright
   14  *     notice, this list of conditions and the following disclaimer in the
   15  *     documentation and/or other materials provided with the distribution.
   16  *
   17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   18  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   21  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27  *  POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 /*
   30  * File : qla_misc.c
   31  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 
   37 #include "qla_os.h"
   38 #include "qla_reg.h"
   39 #include "qla_hw.h"
   40 #include "qla_def.h"
   41 #include "qla_reg.h"
   42 #include "qla_inline.h"
   43 #include "qla_glbl.h"
   44 #include "qla_dbg.h"
   45 
   46 /*
   47  * structure encapsulating the value to read/write to offchip memory
   48  */
   49 typedef struct _offchip_mem_val {
   50         uint32_t data_lo;
   51         uint32_t data_hi;
   52         uint32_t data_ulo;
   53         uint32_t data_uhi;
   54 } offchip_mem_val_t;
   55 
   56 #define Q8_ADDR_UNDEFINED               0xFFFFFFFF
   57 
   58 /*
   59  * The index to this table is Bits 20-27 of the indirect register address
   60  */ 
   61 static uint32_t indirect_to_base_map[] =
   62         {
   63                 Q8_ADDR_UNDEFINED,      /* 0x00 */
   64                 0x77300000,             /* 0x01 */
   65                 0x29500000,             /* 0x02 */
   66                 0x2A500000,             /* 0x03 */
   67                 Q8_ADDR_UNDEFINED,      /* 0x04 */
   68                 0x0D000000,             /* 0x05 */
   69                 0x1B100000,             /* 0x06 */
   70                 0x0E600000,             /* 0x07 */
   71                 0x0E000000,             /* 0x08 */
   72                 0x0E100000,             /* 0x09 */
   73                 0x0E200000,             /* 0x0A */
   74                 0x0E300000,             /* 0x0B */
   75                 0x42000000,             /* 0x0C */
   76                 0x41700000,             /* 0x0D */
   77                 0x42100000,             /* 0x0E */
   78                 0x34B00000,             /* 0x0F */
   79                 0x40500000,             /* 0x10 */
   80                 0x34000000,             /* 0x11 */
   81                 0x34100000,             /* 0x12 */
   82                 0x34200000,             /* 0x13 */
   83                 0x34300000,             /* 0x14 */
   84                 0x34500000,             /* 0x15 */
   85                 0x34400000,             /* 0x16 */
   86                 0x3C000000,             /* 0x17 */
   87                 0x3C100000,             /* 0x18 */
   88                 0x3C200000,             /* 0x19 */
   89                 0x3C300000,             /* 0x1A */
   90                 Q8_ADDR_UNDEFINED,      /* 0x1B */
   91                 0x3C400000,             /* 0x1C */
   92                 0x41000000,             /* 0x1D */
   93                 Q8_ADDR_UNDEFINED,      /* 0x1E */
   94                 0x0D100000,             /* 0x1F */
   95                 Q8_ADDR_UNDEFINED,      /* 0x20 */
   96                 0x77300000,             /* 0x21 */
   97                 0x41600000,             /* 0x22 */
   98                 Q8_ADDR_UNDEFINED,      /* 0x23 */
   99                 Q8_ADDR_UNDEFINED,      /* 0x24 */
  100                 Q8_ADDR_UNDEFINED,      /* 0x25 */
  101                 Q8_ADDR_UNDEFINED,      /* 0x26 */
  102                 Q8_ADDR_UNDEFINED,      /* 0x27 */
  103                 0x41700000,             /* 0x28 */
  104                 Q8_ADDR_UNDEFINED,      /* 0x29 */
  105                 0x08900000,             /* 0x2A */
  106                 0x70A00000,             /* 0x2B */
  107                 0x70B00000,             /* 0x2C */
  108                 0x70C00000,             /* 0x2D */
  109                 0x08D00000,             /* 0x2E */
  110                 0x08E00000,             /* 0x2F */
  111                 0x70F00000,             /* 0x30 */
  112                 0x40500000,             /* 0x31 */
  113                 0x42000000,             /* 0x32 */
  114                 0x42100000,             /* 0x33 */
  115                 Q8_ADDR_UNDEFINED,      /* 0x34 */
  116                 0x08800000,             /* 0x35 */
  117                 0x09100000,             /* 0x36 */
  118                 0x71200000,             /* 0x37 */
  119                 0x40600000,             /* 0x38 */
  120                 Q8_ADDR_UNDEFINED,      /* 0x39 */
  121                 0x71800000,             /* 0x3A */
  122                 0x19900000,             /* 0x3B */
  123                 0x1A900000,             /* 0x3C */
  124                 Q8_ADDR_UNDEFINED,      /* 0x3D */
  125                 0x34600000,             /* 0x3E */
  126                 Q8_ADDR_UNDEFINED,      /* 0x3F */
  127         };
  128 
  129 /*
  130  * Address Translation Table for CRB to offsets from PCI BAR0
  131  */
  132 typedef struct _crb_to_pci {
  133         uint32_t crb_addr;
  134         uint32_t pci_addr;
  135 } crb_to_pci_t;
  136 
  137 static crb_to_pci_t crbinit_to_pciaddr[] = {
  138         {(0x088 << 20), (0x035 << 20)},
  139         {(0x089 << 20), (0x02A << 20)},
  140         {(0x08D << 20), (0x02E << 20)},
  141         {(0x08E << 20), (0x02F << 20)},
  142         {(0x0C6 << 20), (0x023 << 20)},
  143         {(0x0C7 << 20), (0x024 << 20)},
  144         {(0x0C8 << 20), (0x025 << 20)},
  145         {(0x0D0 << 20), (0x005 << 20)},
  146         {(0x0D1 << 20), (0x01F << 20)},
  147         {(0x0E0 << 20), (0x008 << 20)},
  148         {(0x0E1 << 20), (0x009 << 20)},
  149         {(0x0E2 << 20), (0x00A << 20)},
  150         {(0x0E3 << 20), (0x00B << 20)},
  151         {(0x0E6 << 20), (0x007 << 20)},
  152         {(0x199 << 20), (0x03B << 20)},
  153         {(0x1B1 << 20), (0x006 << 20)},
  154         {(0x295 << 20), (0x002 << 20)},
  155         {(0x29A << 20), (0x000 << 20)},
  156         {(0x2A5 << 20), (0x003 << 20)},
  157         {(0x340 << 20), (0x011 << 20)},
  158         {(0x341 << 20), (0x012 << 20)},
  159         {(0x342 << 20), (0x013 << 20)},
  160         {(0x343 << 20), (0x014 << 20)},
  161         {(0x344 << 20), (0x016 << 20)},
  162         {(0x345 << 20), (0x015 << 20)},
  163         {(0x3C0 << 20), (0x017 << 20)},
  164         {(0x3C1 << 20), (0x018 << 20)},
  165         {(0x3C2 << 20), (0x019 << 20)},
  166         {(0x3C3 << 20), (0x01A << 20)},
  167         {(0x3C4 << 20), (0x01C << 20)},
  168         {(0x3C5 << 20), (0x01B << 20)},
  169         {(0x405 << 20), (0x031 << 20)},
  170         {(0x406 << 20), (0x038 << 20)},
  171         {(0x410 << 20), (0x01D << 20)},
  172         {(0x416 << 20), (0x022 << 20)},
  173         {(0x417 << 20), (0x028 << 20)},
  174         {(0x420 << 20), (0x032 << 20)},
  175         {(0x421 << 20), (0x033 << 20)},
  176         {(0x700 << 20), (0x00C << 20)},
  177         {(0x701 << 20), (0x00D << 20)},
  178         {(0x702 << 20), (0x00E << 20)},
  179         {(0x703 << 20), (0x00F << 20)},
  180         {(0x704 << 20), (0x010 << 20)},
  181         {(0x70A << 20), (0x02B << 20)},
  182         {(0x70B << 20), (0x02C << 20)},
  183         {(0x70C << 20), (0x02D << 20)},
  184         {(0x70F << 20), (0x030 << 20)},
  185         {(0x718 << 20), (0x03A << 20)},
  186         {(0x758 << 20), (0x026 << 20)},
  187         {(0x759 << 20), (0x027 << 20)},
  188         {(0x773 << 20), (0x001 << 20)}
  189 };
  190 
  191 #define Q8_INVALID_ADDRESS      (-1)
  192 #define Q8_ADDR_MASK            (0xFFF << 20)
  193 
  194 typedef struct _addr_val {
  195         uint32_t addr;
  196         uint32_t value;
  197         uint32_t pci_addr;
  198         uint32_t ind_addr;
  199 } addr_val_t;
  200 
  201 /*
  202  * Name: qla_rdwr_indreg32
  203  * Function: Read/Write an Indirect Register
  204  */
  205 int
  206 qla_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd)
  207 {
  208         uint32_t offset;
  209         int count = 100;
  210 
  211         offset = (addr & 0xFFF00000) >> 20;
  212 
  213         if (offset > 0x3F) {
  214                 device_printf(ha->pci_dev, "%s: invalid addr 0x%08x\n",
  215                         __func__, addr);
  216                 return -1;
  217         }
  218 
  219         offset = indirect_to_base_map[offset];
  220         if (offset == Q8_ADDR_UNDEFINED) {
  221                 device_printf(ha->pci_dev, "%s: undefined map 0x%08x\n",
  222                         __func__, addr);
  223                 return -1;
  224         }
  225 
  226         offset = offset | (addr & 0x000F0000);
  227 
  228         if (qla_sem_lock(ha, Q8_SEM7_LOCK, 0, 0)) {
  229                 device_printf(ha->pci_dev, "%s: SEM7_LOCK failed\n", __func__);
  230                 return (-1);
  231         }
  232 
  233         WRITE_OFFSET32(ha, Q8_CRB_WINDOW_2M, offset);
  234 
  235         while (offset != (READ_OFFSET32(ha, Q8_CRB_WINDOW_2M))) {
  236                 count--;
  237                 if (!count) {
  238                         qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
  239                         return -1;
  240                 }
  241 
  242                 qla_mdelay(__func__, 1);
  243         }
  244 
  245         if (rd) {
  246                 *val = READ_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000));
  247         } else {
  248                 WRITE_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000), *val);
  249         } 
  250 
  251         qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
  252         return 0;
  253 }
  254 
  255 /*
  256  * Name: qla_rdwr_offchip_mem
  257  * Function: Read/Write OffChip Memory
  258  */
  259 static int
  260 qla_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, offchip_mem_val_t *val,
  261         uint32_t rd)
  262 {
  263         uint32_t count = 100;
  264         uint32_t data;
  265 
  266         WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_LO, (uint32_t)addr);
  267         WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_HI, (uint32_t)(addr >> 32));
  268 
  269         if (!rd) {
  270                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_LO, val->data_lo);
  271                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_HI, val->data_hi);
  272                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_ULO, val->data_ulo);
  273                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_UHI, val->data_uhi);
  274                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x07); /* Write */
  275         } else {
  276                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x03); /* Read */
  277         }
  278 
  279         while (count--) {
  280                 data = READ_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL);
  281                 if (!(data & BIT_3)) {
  282                         if (rd) {
  283                                 val->data_lo = READ_OFFSET32(ha, \
  284                                                 Q8_MIU_TEST_AGT_RDDATA_LO);
  285                                 val->data_hi = READ_OFFSET32(ha, \
  286                                                 Q8_MIU_TEST_AGT_RDDATA_HI);
  287                                 val->data_ulo = READ_OFFSET32(ha, \
  288                                                 Q8_MIU_TEST_AGT_RDDATA_ULO);
  289                                 val->data_uhi = READ_OFFSET32(ha, \
  290                                                 Q8_MIU_TEST_AGT_RDDATA_UHI);
  291                         }
  292                         return 0;
  293                 } else 
  294                         qla_mdelay(__func__, 1);
  295         }
  296 
  297         device_printf(ha->pci_dev, "%s: failed[0x%08x]\n", __func__, data);
  298         return (-1);
  299 }
  300 
  301 /*
  302  * Name: qla_rd_flash32
  303  * Function: Read Flash Memory
  304  */
  305 int
  306 qla_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
  307 {
  308         uint32_t val;
  309         uint32_t count = 100;
  310 
  311         if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
  312                 device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
  313                 return (-1);
  314         }
  315         WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
  316 
  317         val = addr;
  318         qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
  319         val = 0;
  320         qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
  321         val = 3;
  322         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
  323 
  324         QLA_USEC_DELAY(100);
  325 
  326         val = ROM_OPCODE_FAST_RD;
  327         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
  328 
  329         while (!((val = READ_OFFSET32(ha, Q8_ROM_STATUS)) & BIT_1)) {
  330                 count--;
  331                 if (!count) {
  332                         qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
  333                         return -1;
  334                 }
  335         }
  336 
  337         val = 0;
  338         qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
  339         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
  340 
  341         QLA_USEC_DELAY(100);
  342 
  343         qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, data, 1);
  344 
  345         qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
  346         return 0;
  347 }
  348 
  349 static int
  350 qla_p3p_sem_lock2(qla_host_t *ha)
  351 {
  352         if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
  353                 device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
  354                 return (-1);
  355         }
  356         WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
  357         return (0);
  358 }
  359 
  360 /*
  361  * Name: qla_int_to_pci_addr_map
  362  * Function: Convert's Internal(CRB) Address to Indirect Address
  363  */
  364 static uint32_t
  365 qla_int_to_pci_addr_map(qla_host_t *ha, uint32_t int_addr)
  366 {
  367         uint32_t crb_to_pci_table_size, i;
  368         uint32_t addr;
  369 
  370         crb_to_pci_table_size = sizeof(crbinit_to_pciaddr)/sizeof(crb_to_pci_t);
  371         addr = int_addr & Q8_ADDR_MASK;
  372 
  373         for (i = 0; i < crb_to_pci_table_size; i++) {
  374                 if (crbinit_to_pciaddr[i].crb_addr == addr) {
  375                         addr = (int_addr & ~Q8_ADDR_MASK) |
  376                                         crbinit_to_pciaddr[i].pci_addr;
  377                         return (addr);
  378                 }
  379         }
  380         return (Q8_INVALID_ADDRESS);
  381 }
  382 
  383 /*
  384  * Name: qla_filter_pci_addr
  385  * Function: Filter's out Indirect Addresses which are not writeable
  386  */
  387 static uint32_t
  388 qla_filter_pci_addr(qla_host_t *ha, uint32_t addr)
  389 {
  390         if ((addr == Q8_INVALID_ADDRESS) ||
  391                 (addr == 0x00112040) ||
  392                 (addr == 0x00112048) ||
  393                 ((addr & 0xFFFF0FFF) == 0x001100C4) ||
  394                 ((addr & 0xFFFF0FFF) == 0x001100C8) ||
  395                 ((addr & 0x0FF00000) == 0x00200000) ||
  396                 (addr == 0x022021FC) ||
  397                 (addr == 0x0330001C) ||
  398                 (addr == 0x03300024) ||
  399                 (addr == 0x033000A8) ||
  400                 (addr == 0x033000C8) ||
  401                 (addr == 0x033000BC) ||
  402                 ((addr & 0x0FF00000) == 0x03A00000) ||
  403                 (addr == 0x03B0001C))
  404                 return (Q8_INVALID_ADDRESS);
  405         else
  406                 return (addr); 
  407 }
  408 
  409 /*
  410  * Name: qla_crb_init
  411  * Function: CRB Initialization - first step in the initialization after reset
  412  *      Essentially reads the address/value pairs from address = 0x00 and
  413  *      writes the value into address in the addr/value pair.
  414  */
  415 static int
  416 qla_crb_init(qla_host_t *ha)
  417 {
  418         uint32_t val = 0, sig = 0;
  419         uint32_t offset, count, i;
  420         addr_val_t *addr_val_map, *avmap;
  421 
  422         qla_rd_flash32(ha, 0, &sig);
  423         QL_DPRINT2((ha->pci_dev, "%s: val[0] = 0x%08x\n", __func__, sig));
  424 
  425         qla_rd_flash32(ha, 4, &val);
  426         QL_DPRINT2((ha->pci_dev, "%s: val[4] = 0x%08x\n", __func__, val));
  427 
  428         count = val >> 16;
  429         offset = val & 0xFFFF;
  430         offset = offset << 2;
  431 
  432         QL_DPRINT2((ha->pci_dev, "%s: [sig,val]=[0x%08x, 0x%08x] %d pairs\n",
  433                 __func__, sig, val, count));
  434 
  435         addr_val_map = avmap = malloc((sizeof(addr_val_t) * count),
  436                                         M_QLA8XXXBUF, M_NOWAIT);
  437 
  438         if (addr_val_map == NULL) {
  439                 device_printf(ha->pci_dev, "%s: malloc failed\n", __func__);
  440                 return (-1);
  441         }
  442         memset(avmap, 0, (sizeof(addr_val_t) * count));
  443 
  444         count = count << 1;
  445         for (i = 0; i < count; ) {
  446                 qla_rd_flash32(ha, (offset + (i * 4)), &avmap->value);
  447                 i++;
  448                 qla_rd_flash32(ha, (offset + (i * 4)), &avmap->addr);
  449                 i++;
  450 
  451                 avmap->pci_addr = qla_int_to_pci_addr_map(ha, avmap->addr);
  452                 avmap->ind_addr = qla_filter_pci_addr(ha, avmap->pci_addr);
  453 
  454                 QL_DPRINT2((ha->pci_dev,
  455                         "%s: [0x%02x][0x%08x:0x%08x:0x%08x] 0x%08x\n",
  456                         __func__, (i >> 1), avmap->addr, avmap->pci_addr,
  457                         avmap->ind_addr, avmap->value));
  458 
  459                 if (avmap->ind_addr != Q8_INVALID_ADDRESS) {
  460                         qla_rdwr_indreg32(ha, avmap->ind_addr, &avmap->value,0);
  461                         qla_mdelay(__func__, 1);
  462                 }
  463                 avmap++;
  464         }
  465 
  466         free (addr_val_map, M_QLA8XXXBUF);
  467         return (0);
  468 }
  469 
  470 /*
  471  * Name: qla_init_peg_regs
  472  * Function: Protocol Engine Register Initialization
  473  */
  474 static void
  475 qla_init_peg_regs(qla_host_t *ha)
  476 {
  477         WRITE_OFFSET32(ha, Q8_PEG_D_RESET1, 0x001E);
  478         WRITE_OFFSET32(ha, Q8_PEG_D_RESET2, 0x0008);
  479         WRITE_OFFSET32(ha, Q8_PEG_I_RESET, 0x0008);
  480         WRITE_OFFSET32(ha, Q8_PEG_0_CLR1, 0x0000);
  481         WRITE_OFFSET32(ha, Q8_PEG_0_CLR2, 0x0000);
  482         WRITE_OFFSET32(ha, Q8_PEG_1_CLR1, 0x0000);
  483         WRITE_OFFSET32(ha, Q8_PEG_1_CLR2, 0x0000);
  484         WRITE_OFFSET32(ha, Q8_PEG_2_CLR1, 0x0000);
  485         WRITE_OFFSET32(ha, Q8_PEG_2_CLR2, 0x0000);
  486         WRITE_OFFSET32(ha, Q8_PEG_3_CLR1, 0x0000);
  487         WRITE_OFFSET32(ha, Q8_PEG_3_CLR2, 0x0000);
  488         WRITE_OFFSET32(ha, Q8_PEG_4_CLR1, 0x0000);
  489         WRITE_OFFSET32(ha, Q8_PEG_4_CLR2, 0x0000);
  490 }
  491 
  492 /*
  493  * Name: qla_load_fw_from_flash
  494  * Function: Reads the Bootloader from Flash and Loads into Offchip Memory
  495  */
  496 static void
  497 qla_load_fw_from_flash(qla_host_t *ha)
  498 {
  499         uint64_t mem_off        = 0x10000;
  500         uint32_t flash_off      = 0x10000;
  501         uint32_t count;
  502         offchip_mem_val_t val;
  503 
  504         /* only bootloader needs to be loaded into memory */
  505         for (count = 0; count < 0x20000 ; ) {
  506                 qla_rd_flash32(ha, flash_off, &val.data_lo);
  507                 count = count + 4;
  508                 flash_off = flash_off + 4;
  509 
  510                 qla_rd_flash32(ha, flash_off, &val.data_hi);
  511                 count = count + 4;
  512                 flash_off = flash_off + 4;
  513 
  514                 qla_rd_flash32(ha, flash_off, &val.data_ulo);
  515                 count = count + 4;
  516                 flash_off = flash_off + 4;
  517 
  518                 qla_rd_flash32(ha, flash_off, &val.data_uhi);
  519                 count = count + 4;
  520                 flash_off = flash_off + 4;
  521 
  522                 qla_rdwr_offchip_mem(ha, mem_off, &val, 0);
  523 
  524                 mem_off = mem_off + 16;
  525         }
  526         return;
  527 }
  528 
  529 /*
  530  * Name: qla_init_from_flash
  531  * Function: Performs Initialization which consists of the following sequence
  532  *      - reset
  533  *      - CRB Init
  534  *      - Peg Init
  535  *      - Read the Bootloader from Flash and Load into Offchip Memory
  536  *      - Kick start the bootloader which loads the rest of the firmware
  537  *              and performs the remaining steps in the initialization process.
  538  */
  539 static int
  540 qla_init_from_flash(qla_host_t *ha)
  541 {
  542         uint32_t delay = 300;
  543         uint32_t data;
  544 
  545         qla_hw_reset(ha);
  546         qla_mdelay(__func__, 100);
  547 
  548         qla_crb_init(ha);
  549         qla_mdelay(__func__, 10);
  550 
  551         qla_init_peg_regs(ha);
  552         qla_mdelay(__func__, 10);
  553 
  554         qla_load_fw_from_flash(ha);
  555 
  556         WRITE_OFFSET32(ha, Q8_CMDPEG_STATE, 0x00000000);
  557         WRITE_OFFSET32(ha, Q8_PEG_0_RESET, 0x00001020);
  558         WRITE_OFFSET32(ha, Q8_ASIC_RESET, 0x0080001E);
  559         qla_mdelay(__func__, 100);
  560 
  561         do {
  562                 data = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
  563 
  564                 QL_DPRINT2((ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
  565                                 __func__, ha->pci_func, data));
  566                 if (data == CMDPEG_PHAN_INIT_COMPLETE) {
  567                         QL_DPRINT2((ha->pci_dev,
  568                                 "%s: func[%d] init complete\n",
  569                                 __func__, ha->pci_func));
  570                         return(0);
  571                 }
  572                 qla_mdelay(__func__, 100);
  573         } while (delay--);
  574 
  575         device_printf(ha->pci_dev,
  576                 "%s: func[%d] Q8_PEG_HALT_STATUS1[0x%08x] STATUS2[0x%08x]"
  577                 " HEARTBEAT[0x%08x] RCVPEG_STATE[0x%08x]"
  578                 " CMDPEG_STATE[0x%08x]\n",
  579                 __func__, ha->pci_func,
  580                 (READ_OFFSET32(ha, Q8_PEG_HALT_STATUS1)),
  581                 (READ_OFFSET32(ha, Q8_PEG_HALT_STATUS2)),
  582                 (READ_OFFSET32(ha, Q8_FIRMWARE_HEARTBEAT)),
  583                 (READ_OFFSET32(ha, Q8_RCVPEG_STATE)), data);
  584 
  585         return (-1);
  586 }
  587 
  588 /*
  589  * Name: qla_init_hw
  590  * Function: Initializes P3+ hardware.
  591  */
  592 int
  593 qla_init_hw(qla_host_t *ha)
  594 {
  595         device_t dev;
  596         int ret = 0;
  597         uint32_t val, delay = 300;
  598 
  599         dev = ha->pci_dev;
  600 
  601         QL_DPRINT1((dev, "%s: enter\n", __func__));
  602 
  603         qla_mdelay(__func__, 100);
  604 
  605         if (ha->pci_func & 0x1) {
  606                 while ((ha->pci_func & 0x1) && delay--) {
  607                         val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
  608 
  609                         if (val == CMDPEG_PHAN_INIT_COMPLETE) {
  610                                 QL_DPRINT2((dev,
  611                                         "%s: func = %d init complete\n",
  612                                         __func__, ha->pci_func));
  613                                 qla_mdelay(__func__, 100);
  614                                 goto qla_init_exit;
  615                         }
  616                         qla_mdelay(__func__, 100);
  617                 }
  618                 return (-1);
  619         }
  620 
  621         val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
  622 
  623         if (val != CMDPEG_PHAN_INIT_COMPLETE) {
  624                 ret = qla_init_from_flash(ha);
  625                 qla_mdelay(__func__, 100);
  626         } else {
  627                 ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
  628                 ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
  629                 ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
  630 
  631                 if (qla_rd_flash32(ha, 0x100004, &val) == 0) {
  632                         if (((val & 0xFF) != ha->fw_ver_major) ||
  633                                 (((val >> 8) & 0xFF) != ha->fw_ver_minor) ||
  634                                 (((val >> 16) & 0xFF) != ha->fw_ver_sub)) {
  635                                 ret = qla_init_from_flash(ha);
  636                                 qla_mdelay(__func__, 100);
  637                         }
  638                 }
  639         }
  640 
  641 qla_init_exit:
  642         ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
  643         ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
  644         ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
  645         ha->fw_ver_build = READ_OFFSET32(ha, Q8_FW_VER_BUILD);
  646 
  647         return (ret);
  648 }
  649 
  650 static int
  651 qla_wait_for_flash_busy(qla_host_t *ha)
  652 {
  653         uint32_t count = 100;
  654         uint32_t val;
  655 
  656         QLA_USEC_DELAY(100);
  657 
  658         while (count--) {
  659                 val = READ_OFFSET32(ha, Q8_ROM_STATUS);
  660 
  661                 if (val & BIT_1)
  662                         return 0;
  663                 qla_mdelay(__func__, 1);
  664         }
  665         return -1;
  666 }
  667 
  668 static int
  669 qla_flash_write_enable(qla_host_t *ha)
  670 {
  671         uint32_t val, rval;
  672 
  673         val = 0;
  674         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
  675 
  676         val = ROM_OPCODE_WR_ENABLE;
  677         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
  678 
  679         rval = qla_wait_for_flash_busy(ha);
  680 
  681         if (rval)
  682                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
  683 
  684         return (rval);
  685 }
  686 
  687 static int
  688 qla_flash_unprotect(qla_host_t *ha)
  689 {
  690         uint32_t val, rval;
  691 
  692         if (qla_flash_write_enable(ha) != 0) 
  693                 return(-1);
  694 
  695         val = 0;
  696         qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
  697 
  698         val = ROM_OPCODE_WR_STATUS_REG;
  699         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
  700 
  701         rval = qla_wait_for_flash_busy(ha);
  702 
  703         if (rval) {
  704                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
  705                 return rval;
  706         }
  707 
  708         if (qla_flash_write_enable(ha) != 0) 
  709                 return(-1);
  710 
  711         val = 0;
  712         qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
  713 
  714         val = ROM_OPCODE_WR_STATUS_REG;
  715         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
  716 
  717         rval = qla_wait_for_flash_busy(ha);
  718 
  719         if (rval)
  720                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
  721 
  722         return rval;
  723 }
  724 
  725 static int
  726 qla_flash_protect(qla_host_t *ha)
  727 {
  728         uint32_t val, rval;
  729 
  730         if (qla_flash_write_enable(ha) != 0) 
  731                 return(-1);
  732 
  733         val = 0x9C;
  734         qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
  735 
  736         val = ROM_OPCODE_WR_STATUS_REG;
  737         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
  738 
  739         rval = qla_wait_for_flash_busy(ha);
  740 
  741         if (rval)
  742                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
  743 
  744         return rval;
  745 }
  746 
  747 static uint32_t
  748 qla_flash_get_status(qla_host_t *ha)
  749 {
  750         uint32_t count = 1000;
  751         uint32_t val, rval;
  752 
  753         while (count--) {
  754                 val = 0;
  755                 qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
  756                         
  757                 val = ROM_OPCODE_RD_STATUS_REG;
  758                 qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
  759 
  760                 rval = qla_wait_for_flash_busy(ha);
  761 
  762                 if (rval == 0) {
  763                         qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
  764 
  765                         if ((val & BIT_0) == 0)
  766                                 return (val);
  767                 }
  768                 qla_mdelay(__func__, 1);
  769         }
  770         return -1;
  771 }
  772 
  773 static int
  774 qla_wait_for_flash_unprotect(qla_host_t *ha)
  775 {
  776         uint32_t delay = 1000;
  777 
  778         while (delay--) {
  779                 if (qla_flash_get_status(ha) == 0)
  780                         return 0;
  781 
  782                 qla_mdelay(__func__, 1);
  783         }
  784 
  785         return -1;
  786 }
  787 
  788 static int
  789 qla_wait_for_flash_protect(qla_host_t *ha)
  790 {
  791         uint32_t delay = 1000;
  792 
  793         while (delay--) {
  794                 if (qla_flash_get_status(ha) == 0x9C)
  795                         return 0;
  796 
  797                 qla_mdelay(__func__, 1);
  798         }
  799 
  800         return -1;
  801 }
  802 
  803 static int
  804 qla_erase_flash_sector(qla_host_t *ha, uint32_t start)
  805 {
  806         uint32_t val;
  807         int rval;
  808 
  809         if (qla_flash_write_enable(ha) != 0) 
  810                 return(-1);
  811 
  812         val = start;
  813         qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
  814 
  815         val = 3;
  816         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
  817 
  818         val = ROM_OPCODE_SECTOR_ERASE;
  819         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
  820 
  821         rval = qla_wait_for_flash_busy(ha);
  822 
  823         if (rval)
  824                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
  825         return rval;
  826 }
  827 
  828 #define Q8_FLASH_SECTOR_SIZE 0x10000
  829 int
  830 qla_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size)
  831 {
  832         int rval = 0;
  833         uint32_t start;
  834 
  835         if (off & (Q8_FLASH_SECTOR_SIZE -1))
  836                 return -1;
  837 
  838         if ((rval = qla_p3p_sem_lock2(ha)))
  839                 goto qla_erase_flash_exit;
  840 
  841         if ((rval = qla_flash_unprotect(ha)))
  842                 goto qla_erase_flash_unlock_exit;
  843 
  844         if ((rval = qla_wait_for_flash_unprotect(ha)))
  845                 goto qla_erase_flash_unlock_exit;
  846 
  847         for (start = off; start < (off + size); start = start + 0x10000) {
  848                 if (qla_erase_flash_sector(ha, start)) {
  849                         rval = -1;
  850                         break;
  851                 }
  852         }
  853 
  854         rval = qla_flash_protect(ha);
  855 
  856 qla_erase_flash_unlock_exit:
  857         qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
  858 
  859 qla_erase_flash_exit:
  860         return (rval);
  861 }
  862 
  863 static int
  864 qla_flash_write32(qla_host_t *ha, uint32_t off, uint32_t data)
  865 {
  866         uint32_t val;
  867         int rval = 0;
  868 
  869         val = data;
  870         qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
  871 
  872         val = off;
  873         qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
  874 
  875         val = 3;
  876         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
  877 
  878         val = ROM_OPCODE_PROG_PAGE;
  879         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
  880 
  881         rval = qla_wait_for_flash_busy(ha);
  882 
  883         if (rval)
  884                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
  885 
  886         return rval;
  887 }
  888 
  889 static int
  890 qla_flash_wait_for_write_complete(qla_host_t *ha)
  891 {
  892         uint32_t val, count = 1000;
  893         int rval = 0;
  894 
  895         while (count--) {
  896                 val = 0;
  897                 qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
  898 
  899                 val = ROM_OPCODE_RD_STATUS_REG;
  900                 qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
  901 
  902                 
  903                 rval = qla_wait_for_flash_busy(ha);
  904 
  905                 if (rval == 0) {
  906                         qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
  907 
  908                         if ((val & BIT_0) == 0)
  909                                 return (0);
  910                 }
  911                 qla_mdelay(__func__, 1);
  912         }
  913         return -1;
  914 }
  915 
  916 static int
  917 qla_flash_write(qla_host_t *ha, uint32_t off, uint32_t data)
  918 {
  919         if (qla_flash_write_enable(ha) != 0) 
  920                 return(-1);
  921 
  922         if (qla_flash_write32(ha, off, data) != 0)
  923                 return -1;
  924 
  925         if (qla_flash_wait_for_write_complete(ha))
  926                 return -1;
  927 
  928         return 0;
  929 }
  930 
  931 static int
  932 qla_flash_write_pattern(qla_host_t *ha, uint32_t off, uint32_t size,
  933         uint32_t pattern)
  934 {
  935         int rval = 0;
  936         uint32_t start;
  937 
  938         if ((rval = qla_p3p_sem_lock2(ha)))
  939                 goto qla_wr_pattern_exit;
  940 
  941         if ((rval = qla_flash_unprotect(ha)))
  942                 goto qla_wr_pattern_unlock_exit;
  943 
  944         if ((rval = qla_wait_for_flash_unprotect(ha)))
  945                 goto qla_wr_pattern_unlock_exit;
  946 
  947         for (start = off; start < (off + size); start = start + 4) {
  948                 if (qla_flash_write(ha, start, pattern)) {
  949                         rval = -1;
  950                         break;
  951                 }
  952         }
  953 
  954         rval = qla_flash_protect(ha);
  955 
  956         if (rval == 0)
  957                 rval = qla_wait_for_flash_protect(ha);
  958 
  959 qla_wr_pattern_unlock_exit:
  960         qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
  961 
  962 qla_wr_pattern_exit:
  963         return (rval);
  964 }
  965 
  966 static int
  967 qla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size,
  968         void *data)
  969 {
  970         int rval = 0;
  971         uint32_t start;
  972         uint32_t *data32 = data;
  973 
  974         if ((rval = qla_p3p_sem_lock2(ha)))
  975                 goto qla_wr_pattern_exit;
  976 
  977         if ((rval = qla_flash_unprotect(ha)))
  978                 goto qla_wr_pattern_unlock_exit;
  979 
  980         if ((rval = qla_wait_for_flash_unprotect(ha)))
  981                 goto qla_wr_pattern_unlock_exit;
  982 
  983         for (start = off; start < (off + size); start = start + 4) {
  984                 
  985                 if (*data32 != 0xFFFFFFFF) {
  986                         if (qla_flash_write(ha, start, *data32)) {
  987                                 rval = -1;
  988                                 break;
  989                         }
  990                 }
  991                 data32++;
  992         }
  993 
  994         rval = qla_flash_protect(ha);
  995 
  996         if (rval == 0)
  997                 rval = qla_wait_for_flash_protect(ha);
  998 
  999 qla_wr_pattern_unlock_exit:
 1000         qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
 1001 
 1002 qla_wr_pattern_exit:
 1003         return (rval);
 1004 }
 1005 
 1006 int
 1007 qla_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf,
 1008         uint32_t pattern)
 1009 {
 1010         int rval = 0;
 1011         void *data;
 1012 
 1013         if (size == 0)
 1014                 return 0;
 1015 
 1016         size = size << 2;
 1017 
 1018         if (buf == NULL) {
 1019                 rval = qla_flash_write_pattern(ha, off, size, pattern);
 1020                 return (rval);
 1021         }
 1022 
 1023         if ((data = malloc(size, M_QLA8XXXBUF, M_NOWAIT)) == NULL) {
 1024                 device_printf(ha->pci_dev, "%s: malloc failed \n", __func__);
 1025                 rval = -1;
 1026                 goto qla_wr_flash_buffer_exit;
 1027         }
 1028 
 1029         if ((rval = copyin(buf, data, size))) {
 1030                 device_printf(ha->pci_dev, "%s copyin failed\n", __func__);
 1031                 goto qla_wr_flash_buffer_free_exit;
 1032         }
 1033 
 1034         rval = qla_flash_write_data(ha, off, size, data);
 1035 
 1036 qla_wr_flash_buffer_free_exit:
 1037         free(data, M_QLA8XXXBUF);
 1038 
 1039 qla_wr_flash_buffer_exit:
 1040         return (rval);
 1041 }

Cache object: 63d2ad565e1c05f86128e80d8cc82770


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


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