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  * Copyright (c) 2010-2011 Qlogic Corporation
    3  * All rights reserved.
    4  *
    5  *  Redistribution and use in source and binary forms, with or without
    6  *  modification, are permitted provided that the following conditions
    7  *  are met:
    8  *
    9  *  1. Redistributions of source code must retain the above copyright
   10  *     notice, this list of conditions and the following disclaimer.
   11  *  2. Redistributions in binary form must reproduce the above copyright
   12  *     notice, this list of conditions and the following disclaimer in the
   13  *     documentation and/or other materials provided with the distribution.
   14  *
   15  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   16  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   19  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   20  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   21  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   22  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   23  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   24  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   25  *  POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 /*
   28  * File : qla_misc.c
   29  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include "qla_os.h"
   36 #include "qla_reg.h"
   37 #include "qla_hw.h"
   38 #include "qla_def.h"
   39 #include "qla_reg.h"
   40 #include "qla_inline.h"
   41 #include "qla_glbl.h"
   42 #include "qla_dbg.h"
   43 
   44 /*
   45  * structure encapsulating the value to read/write to offchip memory
   46  */
   47 typedef struct _offchip_mem_val {
   48         uint32_t data_lo;
   49         uint32_t data_hi;
   50         uint32_t data_ulo;
   51         uint32_t data_uhi;
   52 } offchip_mem_val_t;
   53 
   54 #define Q8_ADDR_UNDEFINED               0xFFFFFFFF
   55 
   56 /*
   57  * The index to this table is Bits 20-27 of the indirect register address
   58  */ 
   59 static uint32_t indirect_to_base_map[] =
   60         {
   61                 Q8_ADDR_UNDEFINED,      /* 0x00 */
   62                 0x77300000,             /* 0x01 */
   63                 0x29500000,             /* 0x02 */
   64                 0x2A500000,             /* 0x03 */
   65                 Q8_ADDR_UNDEFINED,      /* 0x04 */
   66                 0x0D000000,             /* 0x05 */
   67                 0x1B100000,             /* 0x06 */
   68                 0x0E600000,             /* 0x07 */
   69                 0x0E000000,             /* 0x08 */
   70                 0x0E100000,             /* 0x09 */
   71                 0x0E200000,             /* 0x0A */
   72                 0x0E300000,             /* 0x0B */
   73                 0x42000000,             /* 0x0C */
   74                 0x41700000,             /* 0x0D */
   75                 0x42100000,             /* 0x0E */
   76                 0x34B00000,             /* 0x0F */
   77                 0x40500000,             /* 0x10 */
   78                 0x34000000,             /* 0x11 */
   79                 0x34100000,             /* 0x12 */
   80                 0x34200000,             /* 0x13 */
   81                 0x34300000,             /* 0x14 */
   82                 0x34500000,             /* 0x15 */
   83                 0x34400000,             /* 0x16 */
   84                 0x3C000000,             /* 0x17 */
   85                 0x3C100000,             /* 0x18 */
   86                 0x3C200000,             /* 0x19 */
   87                 0x3C300000,             /* 0x1A */
   88                 Q8_ADDR_UNDEFINED,      /* 0x1B */
   89                 0x3C400000,             /* 0x1C */
   90                 0x41000000,             /* 0x1D */
   91                 Q8_ADDR_UNDEFINED,      /* 0x1E */
   92                 0x0D100000,             /* 0x1F */
   93                 Q8_ADDR_UNDEFINED,      /* 0x20 */
   94                 0x77300000,             /* 0x21 */
   95                 0x41600000,             /* 0x22 */
   96                 Q8_ADDR_UNDEFINED,      /* 0x23 */
   97                 Q8_ADDR_UNDEFINED,      /* 0x24 */
   98                 Q8_ADDR_UNDEFINED,      /* 0x25 */
   99                 Q8_ADDR_UNDEFINED,      /* 0x26 */
  100                 Q8_ADDR_UNDEFINED,      /* 0x27 */
  101                 0x41700000,             /* 0x28 */
  102                 Q8_ADDR_UNDEFINED,      /* 0x29 */
  103                 0x08900000,             /* 0x2A */
  104                 0x70A00000,             /* 0x2B */
  105                 0x70B00000,             /* 0x2C */
  106                 0x70C00000,             /* 0x2D */
  107                 0x08D00000,             /* 0x2E */
  108                 0x08E00000,             /* 0x2F */
  109                 0x70F00000,             /* 0x30 */
  110                 0x40500000,             /* 0x31 */
  111                 0x42000000,             /* 0x32 */
  112                 0x42100000,             /* 0x33 */
  113                 Q8_ADDR_UNDEFINED,      /* 0x34 */
  114                 0x08800000,             /* 0x35 */
  115                 0x09100000,             /* 0x36 */
  116                 0x71200000,             /* 0x37 */
  117                 0x40600000,             /* 0x38 */
  118                 Q8_ADDR_UNDEFINED,      /* 0x39 */
  119                 0x71800000,             /* 0x3A */
  120                 0x19900000,             /* 0x3B */
  121                 0x1A900000,             /* 0x3C */
  122                 Q8_ADDR_UNDEFINED,      /* 0x3D */
  123                 0x34600000,             /* 0x3E */
  124                 Q8_ADDR_UNDEFINED,      /* 0x3F */
  125         };
  126 
  127 /*
  128  * Address Translation Table for CRB to offsets from PCI BAR0
  129  */
  130 typedef struct _crb_to_pci {
  131         uint32_t crb_addr;
  132         uint32_t pci_addr;
  133 } crb_to_pci_t;
  134 
  135 static crb_to_pci_t crbinit_to_pciaddr[] = {
  136         {(0x088 << 20), (0x035 << 20)},
  137         {(0x089 << 20), (0x02A << 20)},
  138         {(0x08D << 20), (0x02E << 20)},
  139         {(0x08E << 20), (0x02F << 20)},
  140         {(0x0C6 << 20), (0x023 << 20)},
  141         {(0x0C7 << 20), (0x024 << 20)},
  142         {(0x0C8 << 20), (0x025 << 20)},
  143         {(0x0D0 << 20), (0x005 << 20)},
  144         {(0x0D1 << 20), (0x01F << 20)},
  145         {(0x0E0 << 20), (0x008 << 20)},
  146         {(0x0E1 << 20), (0x009 << 20)},
  147         {(0x0E2 << 20), (0x00A << 20)},
  148         {(0x0E3 << 20), (0x00B << 20)},
  149         {(0x0E6 << 20), (0x007 << 20)},
  150         {(0x199 << 20), (0x03B << 20)},
  151         {(0x1B1 << 20), (0x006 << 20)},
  152         {(0x295 << 20), (0x002 << 20)},
  153         {(0x29A << 20), (0x000 << 20)},
  154         {(0x2A5 << 20), (0x003 << 20)},
  155         {(0x340 << 20), (0x011 << 20)},
  156         {(0x341 << 20), (0x012 << 20)},
  157         {(0x342 << 20), (0x013 << 20)},
  158         {(0x343 << 20), (0x014 << 20)},
  159         {(0x344 << 20), (0x016 << 20)},
  160         {(0x345 << 20), (0x015 << 20)},
  161         {(0x3C0 << 20), (0x017 << 20)},
  162         {(0x3C1 << 20), (0x018 << 20)},
  163         {(0x3C2 << 20), (0x019 << 20)},
  164         {(0x3C3 << 20), (0x01A << 20)},
  165         {(0x3C4 << 20), (0x01C << 20)},
  166         {(0x3C5 << 20), (0x01B << 20)},
  167         {(0x405 << 20), (0x031 << 20)},
  168         {(0x406 << 20), (0x038 << 20)},
  169         {(0x410 << 20), (0x01D << 20)},
  170         {(0x416 << 20), (0x022 << 20)},
  171         {(0x417 << 20), (0x028 << 20)},
  172         {(0x420 << 20), (0x032 << 20)},
  173         {(0x421 << 20), (0x033 << 20)},
  174         {(0x700 << 20), (0x00C << 20)},
  175         {(0x701 << 20), (0x00D << 20)},
  176         {(0x702 << 20), (0x00E << 20)},
  177         {(0x703 << 20), (0x00F << 20)},
  178         {(0x704 << 20), (0x010 << 20)},
  179         {(0x70A << 20), (0x02B << 20)},
  180         {(0x70B << 20), (0x02C << 20)},
  181         {(0x70C << 20), (0x02D << 20)},
  182         {(0x70F << 20), (0x030 << 20)},
  183         {(0x718 << 20), (0x03A << 20)},
  184         {(0x758 << 20), (0x026 << 20)},
  185         {(0x759 << 20), (0x027 << 20)},
  186         {(0x773 << 20), (0x001 << 20)}
  187 };
  188  
  189 #define Q8_INVALID_ADDRESS      (-1)
  190 #define Q8_ADDR_MASK            (0xFFF << 20)
  191 
  192 typedef struct _addr_val {
  193         uint32_t addr;
  194         uint32_t value;
  195         uint32_t pci_addr;
  196         uint32_t ind_addr;
  197 } addr_val_t;
  198 
  199 /*
  200  * Name: qla_rdwr_indreg32
  201  * Function: Read/Write an Indirect Register
  202  */
  203 int
  204 qla_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd)
  205 {
  206         uint32_t offset;
  207         int count = 100;
  208 
  209         offset = (addr & 0xFFF00000) >> 20;
  210 
  211         if (offset > 0x3F) {
  212                 device_printf(ha->pci_dev, "%s: invalid addr 0x%08x\n",
  213                         __func__, addr);
  214                 return -1;
  215         }
  216 
  217         offset = indirect_to_base_map[offset];
  218         if (offset == Q8_ADDR_UNDEFINED) {
  219                 device_printf(ha->pci_dev, "%s: undefined map 0x%08x\n",
  220                         __func__, addr);
  221                 return -1;
  222         }
  223 
  224         offset = offset | (addr & 0x000F0000);
  225 
  226         if (qla_sem_lock(ha, Q8_SEM7_LOCK, 0, 0)) {
  227                 device_printf(ha->pci_dev, "%s: SEM7_LOCK failed\n", __func__);
  228                 return (-1);
  229         }
  230 
  231         WRITE_OFFSET32(ha, Q8_CRB_WINDOW_2M, offset);
  232 
  233         while (offset != (READ_OFFSET32(ha, Q8_CRB_WINDOW_2M))) {
  234                 count--;
  235                 if (!count) {
  236                         qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
  237                         return -1;
  238                 }
  239 
  240                 qla_mdelay(__func__, 1);
  241         }
  242 
  243         if (rd) {
  244                 *val = READ_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000));
  245         } else {
  246                 WRITE_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000), *val);
  247         } 
  248 
  249         qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
  250         return 0;
  251 }
  252 
  253 /*
  254  * Name: qla_rdwr_offchip_mem
  255  * Function: Read/Write OffChip Memory
  256  */
  257 static int
  258 qla_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, offchip_mem_val_t *val,
  259         uint32_t rd)
  260 {
  261         uint32_t count = 100;
  262         uint32_t data;
  263 
  264         WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_LO, (uint32_t)addr);
  265         WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_HI, (uint32_t)(addr >> 32));
  266 
  267         if (!rd) {
  268                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_LO, val->data_lo);
  269                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_HI, val->data_hi);
  270                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_ULO, val->data_ulo);
  271                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_UHI, val->data_uhi);
  272                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x07); /* Write */
  273         } else {
  274                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x03); /* Read */
  275         }
  276 
  277         while (count--) {
  278                 data = READ_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL);
  279                 if (!(data & BIT_3)) {
  280                         if (rd) {
  281                                 val->data_lo = READ_OFFSET32(ha, \
  282                                                 Q8_MIU_TEST_AGT_RDDATA_LO);
  283                                 val->data_hi = READ_OFFSET32(ha, \
  284                                                 Q8_MIU_TEST_AGT_RDDATA_HI);
  285                                 val->data_ulo = READ_OFFSET32(ha, \
  286                                                 Q8_MIU_TEST_AGT_RDDATA_ULO);
  287                                 val->data_uhi = READ_OFFSET32(ha, \
  288                                                 Q8_MIU_TEST_AGT_RDDATA_UHI);
  289                         }
  290                         return 0;
  291                 } else 
  292                         qla_mdelay(__func__, 1);
  293         }
  294         
  295         device_printf(ha->pci_dev, "%s: failed[0x%08x]\n", __func__, data);
  296         return (-1);
  297 }
  298 
  299 /*
  300  * Name: qla_rd_flash32
  301  * Function: Read Flash Memory
  302  */
  303 int
  304 qla_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
  305 {
  306         uint32_t val;
  307         uint32_t count = 100;
  308 
  309         if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
  310                 device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
  311                 return (-1);
  312         }
  313         WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
  314 
  315         val = addr;
  316         qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
  317         val = 0;
  318         qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
  319         val = 3;
  320         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
  321 
  322         QLA_USEC_DELAY(100);
  323 
  324         val = ROM_OPCODE_FAST_RD;
  325         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
  326 
  327         while (!((val = READ_OFFSET32(ha, Q8_ROM_STATUS)) & BIT_1)) {
  328                 count--;
  329                 if (!count) {
  330                         qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
  331                         return -1;
  332                 }
  333         }
  334 
  335         val = 0;
  336         qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
  337         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
  338 
  339         QLA_USEC_DELAY(100);
  340 
  341         qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, data, 1);
  342 
  343         qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
  344         return 0;
  345 }
  346 
  347 /*
  348  * Name: qla_int_to_pci_addr_map
  349  * Function: Convert's Internal(CRB) Address to Indirect Address
  350  */
  351 static uint32_t
  352 qla_int_to_pci_addr_map(qla_host_t *ha, uint32_t int_addr)
  353 {
  354         uint32_t crb_to_pci_table_size, i;
  355         uint32_t addr;
  356 
  357         crb_to_pci_table_size = sizeof(crbinit_to_pciaddr)/sizeof(crb_to_pci_t);
  358         addr = int_addr & Q8_ADDR_MASK;
  359 
  360         for (i = 0; i < crb_to_pci_table_size; i++) {
  361                 if (crbinit_to_pciaddr[i].crb_addr == addr) {
  362                         addr = (int_addr & ~Q8_ADDR_MASK) |
  363                                         crbinit_to_pciaddr[i].pci_addr;
  364                         return (addr);
  365                 }
  366         }
  367         return (Q8_INVALID_ADDRESS);
  368 }
  369 
  370 /*
  371  * Name: qla_filter_pci_addr
  372  * Function: Filter's out Indirect Addresses which are not writeable
  373  */
  374 static uint32_t
  375 qla_filter_pci_addr(qla_host_t *ha, uint32_t addr)
  376 {
  377         if ((addr == Q8_INVALID_ADDRESS) ||
  378                 (addr == 0x00112040) ||
  379                 (addr == 0x00112048) ||
  380                 ((addr & 0xFFFF0FFF) == 0x001100C4) ||
  381                 ((addr & 0xFFFF0FFF) == 0x001100C8) ||
  382                 ((addr & 0x0FF00000) == 0x00200000) ||
  383                 (addr == 0x022021FC) ||
  384                 (addr == 0x0330001C) ||
  385                 (addr == 0x03300024) ||
  386                 (addr == 0x033000A8) ||
  387                 (addr == 0x033000C8) ||
  388                 (addr == 0x033000BC) ||
  389                 ((addr & 0x0FF00000) == 0x03A00000) ||
  390                 (addr == 0x03B0001C))
  391                 return (Q8_INVALID_ADDRESS);
  392         else
  393                 return (addr); 
  394 }
  395 
  396 /*
  397  * Name: qla_crb_init
  398  * Function: CRB Initialization - first step in the initialization after reset
  399  *      Essentially reads the address/value pairs from address = 0x00 and
  400  *      writes the value into address in the addr/value pair.
  401  */
  402 static int
  403 qla_crb_init(qla_host_t *ha)
  404 {
  405         uint32_t val, sig;
  406         uint32_t offset, count, i;
  407         addr_val_t *addr_val_map, *avmap;
  408 
  409         qla_rd_flash32(ha, 0, &sig);
  410         QL_DPRINT2((ha->pci_dev, "%s: val[0] = 0x%08x\n", __func__, sig));
  411 
  412         qla_rd_flash32(ha, 4, &val);
  413         QL_DPRINT2((ha->pci_dev, "%s: val[4] = 0x%08x\n", __func__, val));
  414 
  415         count = val >> 16;
  416         offset = val & 0xFFFF;
  417         offset = offset << 2;
  418 
  419         QL_DPRINT2((ha->pci_dev, "%s: [sig,val]=[0x%08x, 0x%08x] %d pairs\n",
  420                 __func__, sig, val, count));
  421 
  422         addr_val_map = avmap = malloc((sizeof(addr_val_t) * count),
  423                                         M_QLA8XXXBUF, M_NOWAIT);
  424 
  425         if (addr_val_map == NULL) {
  426                 device_printf(ha->pci_dev, "%s: malloc failed\n", __func__);
  427                 return (-1);
  428         }
  429         memset(avmap, 0, (sizeof(addr_val_t) * count));
  430 
  431         count = count << 1;
  432         for (i = 0; i < count; ) {
  433                 qla_rd_flash32(ha, (offset + (i * 4)), &avmap->value);
  434                 i++;
  435                 qla_rd_flash32(ha, (offset + (i * 4)), &avmap->addr);
  436                 i++;
  437 
  438                 avmap->pci_addr = qla_int_to_pci_addr_map(ha, avmap->addr);
  439                 avmap->ind_addr = qla_filter_pci_addr(ha, avmap->pci_addr);
  440 
  441                 QL_DPRINT2((ha->pci_dev,
  442                         "%s: [0x%02x][0x%08x:0x%08x:0x%08x] 0x%08x\n",
  443                         __func__, (i >> 1), avmap->addr, avmap->pci_addr,
  444                         avmap->ind_addr, avmap->value));
  445 
  446                 if (avmap->ind_addr != Q8_INVALID_ADDRESS) {
  447                         qla_rdwr_indreg32(ha, avmap->ind_addr, &avmap->value,0);
  448                         qla_mdelay(__func__, 1);
  449                 }
  450                 avmap++;
  451         }
  452 
  453         free (addr_val_map, M_QLA8XXXBUF);
  454         return (0);
  455 }
  456 
  457 /*
  458  * Name: qla_init_peg_regs
  459  * Function: Protocol Engine Register Initialization
  460  */
  461 static void
  462 qla_init_peg_regs(qla_host_t *ha)
  463 {
  464         WRITE_OFFSET32(ha, Q8_PEG_D_RESET1, 0x001E);
  465         WRITE_OFFSET32(ha, Q8_PEG_D_RESET2, 0x0008);
  466         WRITE_OFFSET32(ha, Q8_PEG_I_RESET, 0x0008);
  467         WRITE_OFFSET32(ha, Q8_PEG_0_CLR1, 0x0000);
  468         WRITE_OFFSET32(ha, Q8_PEG_0_CLR2, 0x0000);
  469         WRITE_OFFSET32(ha, Q8_PEG_1_CLR1, 0x0000);
  470         WRITE_OFFSET32(ha, Q8_PEG_1_CLR2, 0x0000);
  471         WRITE_OFFSET32(ha, Q8_PEG_2_CLR1, 0x0000);
  472         WRITE_OFFSET32(ha, Q8_PEG_2_CLR2, 0x0000);
  473         WRITE_OFFSET32(ha, Q8_PEG_3_CLR1, 0x0000);
  474         WRITE_OFFSET32(ha, Q8_PEG_3_CLR2, 0x0000);
  475         WRITE_OFFSET32(ha, Q8_PEG_4_CLR1, 0x0000);
  476         WRITE_OFFSET32(ha, Q8_PEG_4_CLR2, 0x0000);
  477 }
  478 
  479 /*
  480  * Name: qla_load_fw_from_flash
  481  * Function: Reads the Bootloader from Flash and Loads into Offchip Memory
  482  */
  483 static void
  484 qla_load_fw_from_flash(qla_host_t *ha)
  485 {
  486         uint64_t mem_off        = 0x10000;
  487         uint32_t flash_off      = 0x10000;
  488         uint32_t count;
  489         offchip_mem_val_t val;
  490 
  491 
  492         /* only bootloader needs to be loaded into memory */
  493         for (count = 0; count < 0x20000 ; ) {
  494                 qla_rd_flash32(ha, flash_off, &val.data_lo);
  495                 count = count + 4;
  496                 flash_off = flash_off + 4;
  497 
  498                 qla_rd_flash32(ha, flash_off, &val.data_hi);
  499                 count = count + 4;
  500                 flash_off = flash_off + 4;
  501 
  502                 qla_rd_flash32(ha, flash_off, &val.data_ulo);
  503                 count = count + 4;
  504                 flash_off = flash_off + 4;
  505 
  506                 qla_rd_flash32(ha, flash_off, &val.data_uhi);
  507                 count = count + 4;
  508                 flash_off = flash_off + 4;
  509 
  510                 qla_rdwr_offchip_mem(ha, mem_off, &val, 0);
  511 
  512                 mem_off = mem_off + 16;
  513         }
  514         return;
  515 }
  516 
  517 /*
  518  * Name: qla_init_from_flash
  519  * Function: Performs Initialization which consists of the following sequence
  520  *      - reset
  521  *      - CRB Init
  522  *      - Peg Init
  523  *      - Read the Bootloader from Flash and Load into Offchip Memory
  524  *      - Kick start the bootloader which loads the rest of the firmware
  525  *              and performs the remaining steps in the initialization process.
  526  */
  527 static int
  528 qla_init_from_flash(qla_host_t *ha)
  529 {
  530         uint32_t delay = 300;
  531         uint32_t data;
  532 
  533         qla_hw_reset(ha);
  534         qla_mdelay(__func__, 100);
  535 
  536         qla_crb_init(ha);
  537         qla_mdelay(__func__, 10);
  538 
  539         qla_init_peg_regs(ha);
  540         qla_mdelay(__func__, 10);
  541 
  542         qla_load_fw_from_flash(ha);
  543         
  544         WRITE_OFFSET32(ha, Q8_CMDPEG_STATE, 0x00000000);
  545         WRITE_OFFSET32(ha, Q8_PEG_0_RESET, 0x00001020);
  546         WRITE_OFFSET32(ha, Q8_ASIC_RESET, 0x0080001E);
  547         qla_mdelay(__func__, 100);
  548 
  549         do {
  550                 data = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
  551 
  552                 QL_DPRINT2((ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
  553                                 __func__, ha->pci_func, data));
  554                 if (data == CMDPEG_PHAN_INIT_COMPLETE) {
  555                         QL_DPRINT2((ha->pci_dev,
  556                                 "%s: func[%d] init complete\n",
  557                                 __func__, ha->pci_func));
  558                         return(0);
  559                 }
  560                 qla_mdelay(__func__, 100);
  561         } while (delay--);
  562 
  563         device_printf(ha->pci_dev,
  564                 "%s: func[%d] Q8_PEG_HALT_STATUS1[0x%08x] STATUS2[0x%08x]"
  565                 " HEARTBEAT[0x%08x] RCVPEG_STATE[0x%08x]"
  566                 " CMDPEG_STATE[0x%08x]\n",
  567                 __func__, ha->pci_func,
  568                 (READ_OFFSET32(ha, Q8_PEG_HALT_STATUS1)),
  569                 (READ_OFFSET32(ha, Q8_PEG_HALT_STATUS2)),
  570                 (READ_OFFSET32(ha, Q8_FIRMWARE_HEARTBEAT)),
  571                 (READ_OFFSET32(ha, Q8_RCVPEG_STATE)), data);
  572         
  573         return (-1);
  574 }
  575 
  576 /*
  577  * Name: qla_init_hw
  578  * Function: Initializes P3+ hardware.
  579  */
  580 int
  581 qla_init_hw(qla_host_t *ha)
  582 {
  583         device_t dev;
  584         int ret = 0;
  585         uint32_t val, delay = 300;
  586 
  587         dev = ha->pci_dev;
  588 
  589         QL_DPRINT1((dev, "%s: enter\n", __func__));
  590 
  591         qla_mdelay(__func__, 100);
  592 
  593         if (ha->pci_func & 0x1) {
  594                 while ((ha->pci_func & 0x1) && delay--) {
  595                         val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
  596 
  597                         if (val == CMDPEG_PHAN_INIT_COMPLETE) {
  598                                 QL_DPRINT2((dev,
  599                                         "%s: func = %d init complete\n",
  600                                         __func__, ha->pci_func));
  601                                 qla_mdelay(__func__, 100);
  602                                 goto qla_init_exit;
  603                         }
  604                         qla_mdelay(__func__, 100);
  605                 }
  606                 return (-1);
  607         }
  608 
  609         val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
  610 
  611         if (val != CMDPEG_PHAN_INIT_COMPLETE) {
  612                 ret = qla_init_from_flash(ha);
  613                 qla_mdelay(__func__, 100);
  614         }
  615 
  616 qla_init_exit:
  617         ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
  618         ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
  619         ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
  620         ha->fw_ver_build = READ_OFFSET32(ha, Q8_FW_VER_BUILD);
  621 
  622         return (ret);
  623 }
  624 

Cache object: 3217b173450c86c7eeb424fb619a8f25


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