1331722Seadler/* 2284741Sdavidcs * Copyright (c) 2013-2016 Qlogic Corporation 3250661Sdavidcs * All rights reserved. 4250661Sdavidcs * 5250661Sdavidcs * Redistribution and use in source and binary forms, with or without 6250661Sdavidcs * modification, are permitted provided that the following conditions 7250661Sdavidcs * are met: 8250661Sdavidcs * 9250661Sdavidcs * 1. Redistributions of source code must retain the above copyright 10250661Sdavidcs * notice, this list of conditions and the following disclaimer. 11250661Sdavidcs * 2. Redistributions in binary form must reproduce the above copyright 12250661Sdavidcs * notice, this list of conditions and the following disclaimer in the 13250661Sdavidcs * documentation and/or other materials provided with the distribution. 14250661Sdavidcs * 15250661Sdavidcs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16250661Sdavidcs * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17250661Sdavidcs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18250661Sdavidcs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19250661Sdavidcs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20250661Sdavidcs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21250661Sdavidcs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22250661Sdavidcs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23250661Sdavidcs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24250661Sdavidcs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25250661Sdavidcs * POSSIBILITY OF SUCH DAMAGE. 26250661Sdavidcs */ 27250661Sdavidcs/* 28250661Sdavidcs * File : ql_misc.c 29250661Sdavidcs * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656. 30250661Sdavidcs */ 31250661Sdavidcs 32250661Sdavidcs#include <sys/cdefs.h> 33250661Sdavidcs__FBSDID("$FreeBSD: stable/11/sys/dev/qlxgbe/ql_misc.c 331722 2018-03-29 02:50:57Z eadler $"); 34250661Sdavidcs 35250661Sdavidcs#include "ql_os.h" 36250661Sdavidcs#include "ql_hw.h" 37250661Sdavidcs#include "ql_def.h" 38250661Sdavidcs#include "ql_inline.h" 39250661Sdavidcs#include "ql_glbl.h" 40250661Sdavidcs#include "ql_dbg.h" 41250661Sdavidcs#include "ql_tmplt.h" 42250661Sdavidcs 43250661Sdavidcs#define QL_FDT_OFFSET 0x3F0000 44250661Sdavidcs#define Q8_FLASH_SECTOR_SIZE 0x10000 45250661Sdavidcs 46250661Sdavidcsstatic int qla_ld_fw_init(qla_host_t *ha); 47250661Sdavidcs 48250661Sdavidcs/* 49250661Sdavidcs * structure encapsulating the value to read/write to offchip memory 50250661Sdavidcs */ 51250661Sdavidcstypedef struct _offchip_mem_val { 52250661Sdavidcs uint32_t data_lo; 53250661Sdavidcs uint32_t data_hi; 54250661Sdavidcs uint32_t data_ulo; 55250661Sdavidcs uint32_t data_uhi; 56250661Sdavidcs} offchip_mem_val_t; 57250661Sdavidcs 58250661Sdavidcs/* 59250661Sdavidcs * Name: ql_rdwr_indreg32 60250661Sdavidcs * Function: Read/Write an Indirect Register 61250661Sdavidcs */ 62250661Sdavidcsint 63250661Sdavidcsql_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd) 64250661Sdavidcs{ 65250661Sdavidcs uint32_t wnd_reg; 66250661Sdavidcs uint32_t count = 100; 67250661Sdavidcs 68250661Sdavidcs wnd_reg = (Q8_CRB_WINDOW_PF0 | (ha->pci_func << 2)); 69250661Sdavidcs 70250661Sdavidcs WRITE_REG32(ha, wnd_reg, addr); 71250661Sdavidcs 72250661Sdavidcs while (count--) { 73250661Sdavidcs if (READ_REG32(ha, wnd_reg) == addr) 74250661Sdavidcs break; 75250661Sdavidcs qla_mdelay(__func__, 1); 76250661Sdavidcs } 77250661Sdavidcs if (!count || QL_ERR_INJECT(ha, INJCT_RDWR_INDREG_FAILURE)) { 78250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x, 0x%08x, %d] failed\n", 79250661Sdavidcs __func__, addr, *val, rd); 80330555Sdavidcs QL_INITIATE_RECOVERY(ha); 81250661Sdavidcs return -1; 82250661Sdavidcs } 83250661Sdavidcs 84250661Sdavidcs if (rd) { 85250661Sdavidcs *val = READ_REG32(ha, Q8_WILD_CARD); 86250661Sdavidcs } else { 87250661Sdavidcs WRITE_REG32(ha, Q8_WILD_CARD, *val); 88250661Sdavidcs } 89250661Sdavidcs 90250661Sdavidcs return 0; 91250661Sdavidcs} 92250661Sdavidcs 93250661Sdavidcs/* 94250661Sdavidcs * Name: ql_rdwr_offchip_mem 95250661Sdavidcs * Function: Read/Write OffChip Memory 96250661Sdavidcs */ 97250661Sdavidcsint 98250661Sdavidcsql_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, q80_offchip_mem_val_t *val, 99250661Sdavidcs uint32_t rd) 100250661Sdavidcs{ 101250661Sdavidcs uint32_t count = 100; 102250661Sdavidcs uint32_t data, step = 0; 103250661Sdavidcs 104250661Sdavidcs 105250661Sdavidcs if (QL_ERR_INJECT(ha, INJCT_RDWR_OFFCHIPMEM_FAILURE)) 106250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 107250661Sdavidcs 108250661Sdavidcs data = (uint32_t)addr; 109250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_ADDR_LO, &data, 0)) { 110250661Sdavidcs step = 1; 111250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 112250661Sdavidcs } 113250661Sdavidcs 114250661Sdavidcs data = (uint32_t)(addr >> 32); 115250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_ADDR_HI, &data, 0)) { 116250661Sdavidcs step = 2; 117250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 118250661Sdavidcs } 119250661Sdavidcs 120250661Sdavidcs data = BIT_1; 121250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) { 122250661Sdavidcs step = 3; 123250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 124250661Sdavidcs } 125250661Sdavidcs 126250661Sdavidcs if (!rd) { 127250661Sdavidcs data = val->data_lo; 128250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_0_31, &data, 0)) { 129250661Sdavidcs step = 4; 130250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 131250661Sdavidcs } 132250661Sdavidcs 133250661Sdavidcs data = val->data_hi; 134250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_32_63, &data, 0)) { 135250661Sdavidcs step = 5; 136250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 137250661Sdavidcs } 138250661Sdavidcs 139250661Sdavidcs data = val->data_ulo; 140250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_64_95, &data, 0)) { 141250661Sdavidcs step = 6; 142250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 143250661Sdavidcs } 144250661Sdavidcs 145250661Sdavidcs data = val->data_uhi; 146250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_96_127, &data, 0)) { 147250661Sdavidcs step = 7; 148250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 149250661Sdavidcs } 150250661Sdavidcs 151250661Sdavidcs data = (BIT_2|BIT_1|BIT_0); 152250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) { 153250661Sdavidcs step = 7; 154250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 155250661Sdavidcs } 156250661Sdavidcs } else { 157250661Sdavidcs data = (BIT_1|BIT_0); 158250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) { 159250661Sdavidcs step = 8; 160250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 161250661Sdavidcs } 162250661Sdavidcs } 163250661Sdavidcs 164250661Sdavidcs while (count--) { 165250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 1)) { 166250661Sdavidcs step = 9; 167250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 168250661Sdavidcs } 169250661Sdavidcs 170250661Sdavidcs if (!(data & BIT_3)) { 171250661Sdavidcs if (rd) { 172250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_0_31, 173250661Sdavidcs &data, 1)) { 174250661Sdavidcs step = 10; 175250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 176250661Sdavidcs } 177250661Sdavidcs val->data_lo = data; 178250661Sdavidcs 179250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_32_63, 180250661Sdavidcs &data, 1)) { 181250661Sdavidcs step = 11; 182250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 183250661Sdavidcs } 184250661Sdavidcs val->data_hi = data; 185250661Sdavidcs 186250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_64_95, 187250661Sdavidcs &data, 1)) { 188250661Sdavidcs step = 12; 189250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 190250661Sdavidcs } 191250661Sdavidcs val->data_ulo = data; 192250661Sdavidcs 193250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_96_127, 194250661Sdavidcs &data, 1)) { 195250661Sdavidcs step = 13; 196250661Sdavidcs goto exit_ql_rdwr_offchip_mem; 197250661Sdavidcs } 198250661Sdavidcs val->data_uhi = data; 199250661Sdavidcs } 200250661Sdavidcs return 0; 201250661Sdavidcs } else 202250661Sdavidcs qla_mdelay(__func__, 1); 203250661Sdavidcs } 204250661Sdavidcs 205250661Sdavidcsexit_ql_rdwr_offchip_mem: 206250661Sdavidcs 207250661Sdavidcs device_printf(ha->pci_dev, 208250661Sdavidcs "%s: [0x%08x 0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x]" 209250661Sdavidcs " [%d] [%d] failed\n", __func__, (uint32_t)(addr >> 32), 210250661Sdavidcs (uint32_t)(addr), val->data_lo, val->data_hi, val->data_ulo, 211250661Sdavidcs val->data_uhi, rd, step); 212250661Sdavidcs 213330555Sdavidcs QL_INITIATE_RECOVERY(ha); 214250661Sdavidcs 215250661Sdavidcs return (-1); 216250661Sdavidcs} 217250661Sdavidcs 218250661Sdavidcs/* 219250661Sdavidcs * Name: ql_rd_flash32 220250661Sdavidcs * Function: Read Flash Memory 221250661Sdavidcs */ 222250661Sdavidcsint 223250661Sdavidcsql_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data) 224250661Sdavidcs{ 225250661Sdavidcs uint32_t data32; 226250661Sdavidcs 227250661Sdavidcs if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID, 0xABCDABCD)) { 228250661Sdavidcs device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n", 229250661Sdavidcs __func__); 230250661Sdavidcs return (-1); 231250661Sdavidcs } 232250661Sdavidcs 233250661Sdavidcs data32 = addr; 234250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_DIRECT_WINDOW, &data32, 0)) { 235250661Sdavidcs qla_sem_unlock(ha, Q8_FLASH_UNLOCK); 236250661Sdavidcs device_printf(ha->pci_dev, 237250661Sdavidcs "%s: Q8_FLASH_DIRECT_WINDOW[0x%08x] failed\n", 238250661Sdavidcs __func__, data32); 239250661Sdavidcs return (-1); 240250661Sdavidcs } 241250661Sdavidcs 242250661Sdavidcs data32 = Q8_FLASH_DIRECT_DATA | (addr & 0xFFFF); 243250661Sdavidcs if (ql_rdwr_indreg32(ha, data32, data, 1)) { 244250661Sdavidcs qla_sem_unlock(ha, Q8_FLASH_UNLOCK); 245250661Sdavidcs device_printf(ha->pci_dev, 246250661Sdavidcs "%s: data32:data [0x%08x] failed\n", 247250661Sdavidcs __func__, data32); 248250661Sdavidcs return (-1); 249250661Sdavidcs } 250250661Sdavidcs 251250661Sdavidcs qla_sem_unlock(ha, Q8_FLASH_UNLOCK); 252250661Sdavidcs return 0; 253250661Sdavidcs} 254250661Sdavidcs 255250661Sdavidcsstatic int 256250661Sdavidcsqla_get_fdt(qla_host_t *ha) 257250661Sdavidcs{ 258250661Sdavidcs uint32_t data32; 259250661Sdavidcs int count; 260250661Sdavidcs qla_hw_t *hw; 261250661Sdavidcs 262250661Sdavidcs hw = &ha->hw; 263250661Sdavidcs 264250661Sdavidcs for (count = 0; count < sizeof(qla_flash_desc_table_t); count+=4) { 265250661Sdavidcs if (ql_rd_flash32(ha, QL_FDT_OFFSET + count, 266250661Sdavidcs (uint32_t *)&hw->fdt + (count >> 2))) { 267250661Sdavidcs device_printf(ha->pci_dev, 268250661Sdavidcs "%s: Read QL_FDT_OFFSET + %d failed\n", 269250661Sdavidcs __func__, count); 270250661Sdavidcs return (-1); 271250661Sdavidcs } 272250661Sdavidcs } 273250661Sdavidcs 274250661Sdavidcs if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID, 275250661Sdavidcs Q8_FDT_LOCK_MAGIC_ID)) { 276250661Sdavidcs device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n", 277250661Sdavidcs __func__); 278250661Sdavidcs return (-1); 279250661Sdavidcs } 280250661Sdavidcs 281250661Sdavidcs data32 = Q8_FDT_FLASH_ADDR_VAL; 282250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) { 283250661Sdavidcs qla_sem_unlock(ha, Q8_FLASH_UNLOCK); 284250661Sdavidcs device_printf(ha->pci_dev, 285250661Sdavidcs "%s: Write to Q8_FLASH_ADDRESS failed\n", 286250661Sdavidcs __func__); 287250661Sdavidcs return (-1); 288250661Sdavidcs } 289250661Sdavidcs 290250661Sdavidcs data32 = Q8_FDT_FLASH_CTRL_VAL; 291250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) { 292250661Sdavidcs qla_sem_unlock(ha, Q8_FLASH_UNLOCK); 293250661Sdavidcs device_printf(ha->pci_dev, 294250661Sdavidcs "%s: Write to Q8_FLASH_CONTROL failed\n", 295250661Sdavidcs __func__); 296250661Sdavidcs return (-1); 297250661Sdavidcs } 298250661Sdavidcs 299250661Sdavidcs count = 0; 300250661Sdavidcs 301250661Sdavidcs do { 302250661Sdavidcs if (count < 1000) { 303250661Sdavidcs QLA_USEC_DELAY(10); 304250661Sdavidcs count += 10; 305250661Sdavidcs } else { 306250661Sdavidcs qla_mdelay(__func__, 1); 307250661Sdavidcs count += 1000; 308250661Sdavidcs } 309250661Sdavidcs 310250661Sdavidcs data32 = 0; 311250661Sdavidcs 312250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) { 313250661Sdavidcs qla_sem_unlock(ha, Q8_FLASH_UNLOCK); 314250661Sdavidcs device_printf(ha->pci_dev, 315250661Sdavidcs "%s: Read Q8_FLASH_STATUS failed\n", 316250661Sdavidcs __func__); 317250661Sdavidcs return (-1); 318250661Sdavidcs } 319250661Sdavidcs 320250661Sdavidcs data32 &= 0x6; 321250661Sdavidcs 322250661Sdavidcs } while ((count < 10000) && (data32 != 0x6)); 323250661Sdavidcs 324254976Sdavidcs if (data32 != 0x6) { 325250661Sdavidcs qla_sem_unlock(ha, Q8_FLASH_UNLOCK); 326250661Sdavidcs device_printf(ha->pci_dev, 327250661Sdavidcs "%s: Poll Q8_FLASH_STATUS failed\n", 328250661Sdavidcs __func__); 329250661Sdavidcs return (-1); 330250661Sdavidcs } 331250661Sdavidcs 332250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_RD_DATA, &data32, 1)) { 333250661Sdavidcs qla_sem_unlock(ha, Q8_FLASH_UNLOCK); 334250661Sdavidcs device_printf(ha->pci_dev, 335250661Sdavidcs "%s: Read Q8_FLASH_RD_DATA failed\n", 336250661Sdavidcs __func__); 337250661Sdavidcs return (-1); 338250661Sdavidcs } 339250661Sdavidcs 340250661Sdavidcs qla_sem_unlock(ha, Q8_FLASH_UNLOCK); 341250661Sdavidcs 342250661Sdavidcs data32 &= Q8_FDT_MASK_VAL; 343250661Sdavidcs if (hw->fdt.flash_manuf == data32) 344250661Sdavidcs return (0); 345250661Sdavidcs else 346250661Sdavidcs return (-1); 347250661Sdavidcs} 348250661Sdavidcs 349250661Sdavidcsstatic int 350250661Sdavidcsqla_flash_write_enable(qla_host_t *ha, int enable) 351250661Sdavidcs{ 352250661Sdavidcs uint32_t data32; 353250661Sdavidcs int count = 0; 354250661Sdavidcs 355250661Sdavidcs data32 = Q8_WR_ENABLE_FL_ADDR | ha->hw.fdt.write_statusreg_cmd; 356250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) { 357250661Sdavidcs device_printf(ha->pci_dev, 358250661Sdavidcs "%s: Write to Q8_FLASH_ADDRESS failed\n", 359250661Sdavidcs __func__); 360250661Sdavidcs return (-1); 361250661Sdavidcs } 362250661Sdavidcs 363250661Sdavidcs if (enable) 364250661Sdavidcs data32 = ha->hw.fdt.write_enable_bits; 365250661Sdavidcs else 366250661Sdavidcs data32 = ha->hw.fdt.write_disable_bits; 367250661Sdavidcs 368250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, &data32, 0)) { 369250661Sdavidcs device_printf(ha->pci_dev, 370250661Sdavidcs "%s: Write to Q8_FLASH_WR_DATA failed\n", 371250661Sdavidcs __func__); 372250661Sdavidcs return (-1); 373250661Sdavidcs } 374250661Sdavidcs 375250661Sdavidcs data32 = Q8_WR_ENABLE_FL_CTRL; 376250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) { 377250661Sdavidcs device_printf(ha->pci_dev, 378250661Sdavidcs "%s: Write to Q8_FLASH_CONTROL failed\n", 379250661Sdavidcs __func__); 380250661Sdavidcs return (-1); 381250661Sdavidcs } 382250661Sdavidcs 383250661Sdavidcs do { 384250661Sdavidcs if (count < 1000) { 385250661Sdavidcs QLA_USEC_DELAY(10); 386250661Sdavidcs count += 10; 387250661Sdavidcs } else { 388250661Sdavidcs qla_mdelay(__func__, 1); 389250661Sdavidcs count += 1000; 390250661Sdavidcs } 391250661Sdavidcs 392250661Sdavidcs data32 = 0; 393250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) { 394250661Sdavidcs device_printf(ha->pci_dev, 395250661Sdavidcs "%s: Read Q8_FLASH_STATUS failed\n", 396250661Sdavidcs __func__); 397250661Sdavidcs return (-1); 398250661Sdavidcs } 399250661Sdavidcs 400250661Sdavidcs data32 &= 0x6; 401250661Sdavidcs 402250661Sdavidcs } while ((count < 10000) && (data32 != 0x6)); 403250661Sdavidcs 404254976Sdavidcs if (data32 != 0x6) { 405250661Sdavidcs device_printf(ha->pci_dev, 406250661Sdavidcs "%s: Poll Q8_FLASH_STATUS failed\n", 407250661Sdavidcs __func__); 408250661Sdavidcs return (-1); 409250661Sdavidcs } 410250661Sdavidcs 411250661Sdavidcs return 0; 412250661Sdavidcs} 413250661Sdavidcs 414250661Sdavidcsstatic int 415250661Sdavidcsqla_erase_flash_sector(qla_host_t *ha, uint32_t start) 416250661Sdavidcs{ 417250661Sdavidcs uint32_t data32; 418250661Sdavidcs int count = 0; 419250661Sdavidcs 420250661Sdavidcs do { 421250661Sdavidcs qla_mdelay(__func__, 1); 422250661Sdavidcs 423250661Sdavidcs data32 = 0; 424250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) { 425250661Sdavidcs device_printf(ha->pci_dev, 426250661Sdavidcs "%s: Read Q8_FLASH_STATUS failed\n", 427250661Sdavidcs __func__); 428250661Sdavidcs return (-1); 429250661Sdavidcs } 430250661Sdavidcs 431250661Sdavidcs data32 &= 0x6; 432250661Sdavidcs 433250661Sdavidcs } while (((count++) < 1000) && (data32 != 0x6)); 434250661Sdavidcs 435254976Sdavidcs if (data32 != 0x6) { 436250661Sdavidcs device_printf(ha->pci_dev, 437250661Sdavidcs "%s: Poll Q8_FLASH_STATUS failed\n", 438250661Sdavidcs __func__); 439250661Sdavidcs return (-1); 440250661Sdavidcs } 441250661Sdavidcs 442250661Sdavidcs data32 = (start >> 16) & 0xFF; 443250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, &data32, 0)) { 444250661Sdavidcs device_printf(ha->pci_dev, 445250661Sdavidcs "%s: Write to Q8_FLASH_WR_DATA failed\n", 446250661Sdavidcs __func__); 447250661Sdavidcs return (-1); 448250661Sdavidcs } 449250661Sdavidcs 450250661Sdavidcs data32 = Q8_ERASE_FL_ADDR_MASK | ha->hw.fdt.erase_cmd; 451250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) { 452250661Sdavidcs device_printf(ha->pci_dev, 453250661Sdavidcs "%s: Write to Q8_FLASH_ADDRESS failed\n", 454250661Sdavidcs __func__); 455250661Sdavidcs return (-1); 456250661Sdavidcs } 457250661Sdavidcs 458250661Sdavidcs data32 = Q8_ERASE_FL_CTRL_MASK; 459250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) { 460250661Sdavidcs device_printf(ha->pci_dev, 461250661Sdavidcs "%s: Write to Q8_FLASH_CONTROL failed\n", 462250661Sdavidcs __func__); 463250661Sdavidcs return (-1); 464250661Sdavidcs } 465250661Sdavidcs 466250661Sdavidcs count = 0; 467250661Sdavidcs do { 468250661Sdavidcs qla_mdelay(__func__, 1); 469250661Sdavidcs 470250661Sdavidcs data32 = 0; 471250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) { 472250661Sdavidcs device_printf(ha->pci_dev, 473250661Sdavidcs "%s: Read Q8_FLASH_STATUS failed\n", 474250661Sdavidcs __func__); 475250661Sdavidcs return (-1); 476250661Sdavidcs } 477250661Sdavidcs 478250661Sdavidcs data32 &= 0x6; 479250661Sdavidcs 480250661Sdavidcs } while (((count++) < 1000) && (data32 != 0x6)); 481250661Sdavidcs 482254976Sdavidcs if (data32 != 0x6) { 483250661Sdavidcs device_printf(ha->pci_dev, 484250661Sdavidcs "%s: Poll Q8_FLASH_STATUS failed\n", 485250661Sdavidcs __func__); 486250661Sdavidcs return (-1); 487250661Sdavidcs } 488250661Sdavidcs 489250661Sdavidcs return 0; 490250661Sdavidcs} 491250661Sdavidcs 492250661Sdavidcsint 493250661Sdavidcsql_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size) 494250661Sdavidcs{ 495250661Sdavidcs int rval = 0; 496250661Sdavidcs uint32_t start; 497250661Sdavidcs 498250661Sdavidcs if (off & (Q8_FLASH_SECTOR_SIZE -1)) 499250661Sdavidcs return (-1); 500250661Sdavidcs 501250661Sdavidcs if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID, 502250661Sdavidcs Q8_ERASE_LOCK_MAGIC_ID)) { 503250661Sdavidcs device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n", 504250661Sdavidcs __func__); 505250661Sdavidcs return (-1); 506250661Sdavidcs } 507250661Sdavidcs 508250661Sdavidcs if (qla_flash_write_enable(ha, 1) != 0) { 509250661Sdavidcs rval = -1; 510250661Sdavidcs goto ql_erase_flash_exit; 511250661Sdavidcs } 512250661Sdavidcs 513250661Sdavidcs for (start = off; start < (off + size); start = start + 514250661Sdavidcs Q8_FLASH_SECTOR_SIZE) { 515250661Sdavidcs if (qla_erase_flash_sector(ha, start)) { 516250661Sdavidcs rval = -1; 517250661Sdavidcs break; 518250661Sdavidcs } 519250661Sdavidcs } 520250661Sdavidcs 521250661Sdavidcs rval = qla_flash_write_enable(ha, 0); 522250661Sdavidcs 523250661Sdavidcsql_erase_flash_exit: 524250661Sdavidcs qla_sem_unlock(ha, Q8_FLASH_UNLOCK); 525250661Sdavidcs return (rval); 526250661Sdavidcs} 527250661Sdavidcs 528250661Sdavidcsstatic int 529250661Sdavidcsqla_wr_flash32(qla_host_t *ha, uint32_t off, uint32_t *data) 530250661Sdavidcs{ 531250661Sdavidcs uint32_t data32; 532250661Sdavidcs int count = 0; 533250661Sdavidcs 534250661Sdavidcs data32 = Q8_WR_FL_ADDR_MASK | (off >> 2); 535250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) { 536250661Sdavidcs device_printf(ha->pci_dev, 537250661Sdavidcs "%s: Write to Q8_FLASH_ADDRESS failed\n", 538250661Sdavidcs __func__); 539250661Sdavidcs return (-1); 540250661Sdavidcs } 541250661Sdavidcs 542250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, data, 0)) { 543250661Sdavidcs device_printf(ha->pci_dev, 544250661Sdavidcs "%s: Write to Q8_FLASH_WR_DATA failed\n", 545250661Sdavidcs __func__); 546250661Sdavidcs return (-1); 547250661Sdavidcs } 548250661Sdavidcs 549250661Sdavidcs data32 = Q8_WR_FL_CTRL_MASK; 550250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) { 551250661Sdavidcs device_printf(ha->pci_dev, 552250661Sdavidcs "%s: Write to Q8_FLASH_CONTROL failed\n", 553250661Sdavidcs __func__); 554250661Sdavidcs return (-1); 555250661Sdavidcs } 556250661Sdavidcs 557250661Sdavidcs do { 558250661Sdavidcs if (count < 1000) { 559250661Sdavidcs QLA_USEC_DELAY(10); 560250661Sdavidcs count += 10; 561250661Sdavidcs } else { 562250661Sdavidcs qla_mdelay(__func__, 1); 563250661Sdavidcs count += 1000; 564250661Sdavidcs } 565250661Sdavidcs 566250661Sdavidcs data32 = 0; 567250661Sdavidcs if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) { 568250661Sdavidcs device_printf(ha->pci_dev, 569250661Sdavidcs "%s: Read Q8_FLASH_STATUS failed\n", 570250661Sdavidcs __func__); 571250661Sdavidcs return (-1); 572250661Sdavidcs } 573250661Sdavidcs 574250661Sdavidcs data32 &= 0x6; 575250661Sdavidcs 576250661Sdavidcs } while ((count < 10000) && (data32 != 0x6)); 577250661Sdavidcs 578254976Sdavidcs if (data32 != 0x6) { 579250661Sdavidcs device_printf(ha->pci_dev, 580250661Sdavidcs "%s: Poll Q8_FLASH_STATUS failed\n", 581250661Sdavidcs __func__); 582250661Sdavidcs return (-1); 583250661Sdavidcs } 584250661Sdavidcs 585250661Sdavidcs return 0; 586250661Sdavidcs} 587250661Sdavidcs 588250661Sdavidcsstatic int 589250661Sdavidcsqla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size, 590250661Sdavidcs void *data) 591250661Sdavidcs{ 592250661Sdavidcs int rval = 0; 593250661Sdavidcs uint32_t start; 594250661Sdavidcs uint32_t *data32 = data; 595250661Sdavidcs 596250661Sdavidcs if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID, 597250661Sdavidcs Q8_WR_FL_LOCK_MAGIC_ID)) { 598250661Sdavidcs device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n", 599250661Sdavidcs __func__); 600250661Sdavidcs rval = -1; 601250661Sdavidcs goto qla_flash_write_data_exit; 602250661Sdavidcs } 603250661Sdavidcs 604250661Sdavidcs if ((qla_flash_write_enable(ha, 1) != 0)) { 605250661Sdavidcs device_printf(ha->pci_dev, "%s: failed\n", 606250661Sdavidcs __func__); 607250661Sdavidcs rval = -1; 608250661Sdavidcs goto qla_flash_write_data_unlock_exit; 609250661Sdavidcs } 610250661Sdavidcs 611250661Sdavidcs for (start = off; start < (off + size); start = start + 4) { 612250661Sdavidcs if (*data32 != 0xFFFFFFFF) { 613250661Sdavidcs if (qla_wr_flash32(ha, start, data32)) { 614250661Sdavidcs rval = -1; 615250661Sdavidcs break; 616250661Sdavidcs } 617250661Sdavidcs } 618250661Sdavidcs data32++; 619250661Sdavidcs } 620250661Sdavidcs 621250661Sdavidcs rval = qla_flash_write_enable(ha, 0); 622250661Sdavidcs 623250661Sdavidcsqla_flash_write_data_unlock_exit: 624250661Sdavidcs qla_sem_unlock(ha, Q8_FLASH_UNLOCK); 625250661Sdavidcs 626250661Sdavidcsqla_flash_write_data_exit: 627250661Sdavidcs return (rval); 628250661Sdavidcs} 629250661Sdavidcs 630250661Sdavidcsint 631250661Sdavidcsql_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf) 632250661Sdavidcs{ 633250661Sdavidcs int rval = 0; 634250661Sdavidcs void *data; 635250661Sdavidcs 636250661Sdavidcs if (size == 0) 637250661Sdavidcs return 0; 638250661Sdavidcs 639250661Sdavidcs size = size << 2; 640250661Sdavidcs 641250661Sdavidcs if (buf == NULL) 642250661Sdavidcs return -1; 643250661Sdavidcs 644250661Sdavidcs if ((data = malloc(size, M_QLA83XXBUF, M_NOWAIT)) == NULL) { 645250661Sdavidcs device_printf(ha->pci_dev, "%s: malloc failed \n", __func__); 646250661Sdavidcs rval = -1; 647250661Sdavidcs goto ql_wr_flash_buffer_exit; 648250661Sdavidcs } 649250661Sdavidcs 650250661Sdavidcs if ((rval = copyin(buf, data, size))) { 651250661Sdavidcs device_printf(ha->pci_dev, "%s copyin failed\n", __func__); 652250661Sdavidcs goto ql_wr_flash_buffer_free_exit; 653250661Sdavidcs } 654250661Sdavidcs 655250661Sdavidcs rval = qla_flash_write_data(ha, off, size, data); 656250661Sdavidcs 657250661Sdavidcsql_wr_flash_buffer_free_exit: 658250661Sdavidcs free(data, M_QLA83XXBUF); 659250661Sdavidcs 660250661Sdavidcsql_wr_flash_buffer_exit: 661250661Sdavidcs return (rval); 662250661Sdavidcs} 663250661Sdavidcs 664284741Sdavidcs#ifdef QL_LDFLASH_FW 665250661Sdavidcs/* 666250661Sdavidcs * Name: qla_load_fw_from_flash 667250661Sdavidcs * Function: Reads the Bootloader from Flash and Loads into Offchip Memory 668250661Sdavidcs */ 669250661Sdavidcsstatic void 670250661Sdavidcsqla_load_fw_from_flash(qla_host_t *ha) 671250661Sdavidcs{ 672250661Sdavidcs uint32_t flash_off = 0x10000; 673250661Sdavidcs uint64_t mem_off; 674250661Sdavidcs uint32_t count, mem_size; 675250661Sdavidcs q80_offchip_mem_val_t val; 676250661Sdavidcs 677250661Sdavidcs mem_off = (uint64_t)(READ_REG32(ha, Q8_BOOTLD_ADDR)); 678250661Sdavidcs mem_size = READ_REG32(ha, Q8_BOOTLD_SIZE); 679250661Sdavidcs 680250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x][0x%08x]\n", 681250661Sdavidcs __func__, (uint32_t)mem_off, mem_size); 682250661Sdavidcs 683250661Sdavidcs /* only bootloader needs to be loaded into memory */ 684250661Sdavidcs for (count = 0; count < mem_size ; ) { 685250661Sdavidcs ql_rd_flash32(ha, flash_off, &val.data_lo); 686250661Sdavidcs count = count + 4; 687250661Sdavidcs flash_off = flash_off + 4; 688250661Sdavidcs 689250661Sdavidcs ql_rd_flash32(ha, flash_off, &val.data_hi); 690250661Sdavidcs count = count + 4; 691250661Sdavidcs flash_off = flash_off + 4; 692250661Sdavidcs 693250661Sdavidcs ql_rd_flash32(ha, flash_off, &val.data_ulo); 694250661Sdavidcs count = count + 4; 695250661Sdavidcs flash_off = flash_off + 4; 696250661Sdavidcs 697250661Sdavidcs ql_rd_flash32(ha, flash_off, &val.data_uhi); 698250661Sdavidcs count = count + 4; 699250661Sdavidcs flash_off = flash_off + 4; 700250661Sdavidcs 701250661Sdavidcs ql_rdwr_offchip_mem(ha, mem_off, &val, 0); 702250661Sdavidcs 703250661Sdavidcs mem_off = mem_off + 16; 704250661Sdavidcs } 705250661Sdavidcs 706250661Sdavidcs return; 707250661Sdavidcs} 708284741Sdavidcs#endif /* #ifdef QL_LDFLASH_FW */ 709250661Sdavidcs 710250661Sdavidcs/* 711250661Sdavidcs * Name: qla_init_from_flash 712250661Sdavidcs * Function: Performs Initialization which consists of the following sequence 713250661Sdavidcs * - reset 714250661Sdavidcs * - CRB Init 715250661Sdavidcs * - Peg Init 716250661Sdavidcs * - Read the Bootloader from Flash and Load into Offchip Memory 717250661Sdavidcs * - Kick start the bootloader which loads the rest of the firmware 718250661Sdavidcs * and performs the remaining steps in the initialization process. 719250661Sdavidcs */ 720250661Sdavidcsstatic int 721250661Sdavidcsqla_init_from_flash(qla_host_t *ha) 722250661Sdavidcs{ 723250661Sdavidcs uint32_t delay = 300; 724250661Sdavidcs uint32_t data; 725250661Sdavidcs 726250661Sdavidcs qla_ld_fw_init(ha); 727250661Sdavidcs 728250661Sdavidcs do { 729250661Sdavidcs data = READ_REG32(ha, Q8_CMDPEG_STATE); 730250661Sdavidcs 731250661Sdavidcs QL_DPRINT2(ha, 732250661Sdavidcs (ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n", 733250661Sdavidcs __func__, ha->pci_func, data)); 734250661Sdavidcs if (data == 0xFF01) { 735250661Sdavidcs QL_DPRINT2(ha, (ha->pci_dev, 736250661Sdavidcs "%s: func[%d] init complete\n", 737250661Sdavidcs __func__, ha->pci_func)); 738250661Sdavidcs return(0); 739250661Sdavidcs } 740250661Sdavidcs qla_mdelay(__func__, 100); 741250661Sdavidcs } while (delay--); 742250661Sdavidcs 743250661Sdavidcs return (-1); 744250661Sdavidcs} 745250661Sdavidcs 746250661Sdavidcs/* 747250661Sdavidcs * Name: ql_init_hw 748250661Sdavidcs * Function: Initializes P3+ hardware. 749250661Sdavidcs */ 750250661Sdavidcsint 751250661Sdavidcsql_init_hw(qla_host_t *ha) 752250661Sdavidcs{ 753250661Sdavidcs device_t dev; 754250661Sdavidcs int ret = 0; 755250661Sdavidcs uint32_t val, delay = 300; 756250661Sdavidcs 757250661Sdavidcs dev = ha->pci_dev; 758250661Sdavidcs 759250661Sdavidcs QL_DPRINT1(ha, (dev, "%s: enter\n", __func__)); 760250661Sdavidcs 761250661Sdavidcs if (ha->pci_func & 0x1) { 762250661Sdavidcs 763250661Sdavidcs while ((ha->pci_func & 0x1) && delay--) { 764250661Sdavidcs 765250661Sdavidcs val = READ_REG32(ha, Q8_CMDPEG_STATE); 766250661Sdavidcs 767250661Sdavidcs if (val == 0xFF01) { 768250661Sdavidcs QL_DPRINT2(ha, (dev, 769250661Sdavidcs "%s: func = %d init complete\n", 770250661Sdavidcs __func__, ha->pci_func)); 771250661Sdavidcs qla_mdelay(__func__, 100); 772250661Sdavidcs goto qla_init_exit; 773250661Sdavidcs } 774250661Sdavidcs qla_mdelay(__func__, 100); 775250661Sdavidcs } 776330555Sdavidcs ret = -1; 777330555Sdavidcs goto ql_init_hw_exit; 778250661Sdavidcs } 779250661Sdavidcs 780250661Sdavidcs 781250661Sdavidcs val = READ_REG32(ha, Q8_CMDPEG_STATE); 782330555Sdavidcs if (!cold || (val != 0xFF01) || ha->qla_initiate_recovery) { 783250661Sdavidcs ret = qla_init_from_flash(ha); 784250661Sdavidcs qla_mdelay(__func__, 100); 785250661Sdavidcs } 786250661Sdavidcs 787250661Sdavidcsqla_init_exit: 788250661Sdavidcs ha->fw_ver_major = READ_REG32(ha, Q8_FW_VER_MAJOR); 789250661Sdavidcs ha->fw_ver_minor = READ_REG32(ha, Q8_FW_VER_MINOR); 790250661Sdavidcs ha->fw_ver_sub = READ_REG32(ha, Q8_FW_VER_SUB); 791250661Sdavidcs 792250661Sdavidcs if (qla_get_fdt(ha) != 0) { 793250661Sdavidcs device_printf(dev, "%s: qla_get_fdt failed\n", __func__); 794250661Sdavidcs } else { 795250661Sdavidcs ha->hw.flags.fdt_valid = 1; 796250661Sdavidcs } 797250661Sdavidcs 798330555Sdavidcsql_init_hw_exit: 799330555Sdavidcs 800330555Sdavidcs if (ret) { 801330555Sdavidcs if (ha->hw.sp_log_stop_events & Q8_SP_LOG_STOP_HW_INIT_FAILURE) 802330555Sdavidcs ha->hw.sp_log_stop = -1; 803330555Sdavidcs } 804330555Sdavidcs 805250661Sdavidcs return (ret); 806250661Sdavidcs} 807250661Sdavidcs 808250661Sdavidcsvoid 809250661Sdavidcsql_read_mac_addr(qla_host_t *ha) 810250661Sdavidcs{ 811250661Sdavidcs uint8_t *macp; 812250661Sdavidcs uint32_t mac_lo; 813250661Sdavidcs uint32_t mac_hi; 814250661Sdavidcs uint32_t flash_off; 815250661Sdavidcs 816250661Sdavidcs flash_off = Q8_BOARD_CONFIG_OFFSET + Q8_BOARD_CONFIG_MAC0_LO + 817250661Sdavidcs (ha->pci_func << 3); 818250661Sdavidcs ql_rd_flash32(ha, flash_off, &mac_lo); 819250661Sdavidcs 820250661Sdavidcs flash_off += 4; 821250661Sdavidcs ql_rd_flash32(ha, flash_off, &mac_hi); 822250661Sdavidcs 823250661Sdavidcs macp = (uint8_t *)&mac_lo; 824250661Sdavidcs ha->hw.mac_addr[5] = macp[0]; 825250661Sdavidcs ha->hw.mac_addr[4] = macp[1]; 826250661Sdavidcs ha->hw.mac_addr[3] = macp[2]; 827250661Sdavidcs ha->hw.mac_addr[2] = macp[3]; 828250661Sdavidcs 829250661Sdavidcs macp = (uint8_t *)&mac_hi; 830250661Sdavidcs ha->hw.mac_addr[1] = macp[0]; 831250661Sdavidcs ha->hw.mac_addr[0] = macp[1]; 832250661Sdavidcs 833250661Sdavidcs //device_printf(ha->pci_dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n", 834250661Sdavidcs // __func__, ha->hw.mac_addr[0], ha->hw.mac_addr[1], 835250661Sdavidcs // ha->hw.mac_addr[2], ha->hw.mac_addr[3], 836250661Sdavidcs // ha->hw.mac_addr[4], ha->hw.mac_addr[5]); 837250661Sdavidcs 838250661Sdavidcs return; 839250661Sdavidcs} 840250661Sdavidcs 841250661Sdavidcs/* 842250661Sdavidcs * Stop/Start/Initialization Handling 843250661Sdavidcs */ 844250661Sdavidcs 845250661Sdavidcsstatic uint16_t 846250661Sdavidcsqla_tmplt_16bit_checksum(qla_host_t *ha, uint16_t *buf, uint32_t size) 847250661Sdavidcs{ 848250661Sdavidcs uint32_t sum = 0; 849250661Sdavidcs uint32_t count = size >> 1; /* size in 16 bit words */ 850250661Sdavidcs 851250661Sdavidcs while (count-- > 0) 852250661Sdavidcs sum += *buf++; 853250661Sdavidcs 854250661Sdavidcs while (sum >> 16) 855250661Sdavidcs sum = (sum & 0xFFFF) + (sum >> 16); 856250661Sdavidcs 857250661Sdavidcs return (~sum); 858250661Sdavidcs} 859250661Sdavidcs 860250661Sdavidcsstatic int 861250661Sdavidcsqla_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 862250661Sdavidcs{ 863250661Sdavidcs q8_wrl_e_t *wr_l; 864250661Sdavidcs int i; 865250661Sdavidcs 866250661Sdavidcs wr_l = (q8_wrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t)); 867250661Sdavidcs 868250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, wr_l++) { 869250661Sdavidcs 870250661Sdavidcs if (ql_rdwr_indreg32(ha, wr_l->addr, &wr_l->value, 0)) { 871250661Sdavidcs device_printf(ha->pci_dev, 872250661Sdavidcs "%s: [0x%08x 0x%08x] error\n", __func__, 873250661Sdavidcs wr_l->addr, wr_l->value); 874250661Sdavidcs return -1; 875250661Sdavidcs } 876250661Sdavidcs if (ce_hdr->delay_to) { 877250661Sdavidcs DELAY(ce_hdr->delay_to); 878250661Sdavidcs } 879250661Sdavidcs } 880250661Sdavidcs return 0; 881250661Sdavidcs} 882250661Sdavidcs 883250661Sdavidcsstatic int 884250661Sdavidcsqla_rd_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 885250661Sdavidcs{ 886250661Sdavidcs q8_rdwrl_e_t *rd_wr_l; 887250661Sdavidcs uint32_t data; 888250661Sdavidcs int i; 889250661Sdavidcs 890250661Sdavidcs rd_wr_l = (q8_rdwrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t)); 891250661Sdavidcs 892250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, rd_wr_l++) { 893250661Sdavidcs 894250661Sdavidcs if (ql_rdwr_indreg32(ha, rd_wr_l->rd_addr, &data, 1)) { 895250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", 896250661Sdavidcs __func__, rd_wr_l->rd_addr); 897250661Sdavidcs 898250661Sdavidcs return -1; 899250661Sdavidcs } 900250661Sdavidcs 901250661Sdavidcs if (ql_rdwr_indreg32(ha, rd_wr_l->wr_addr, &data, 0)) { 902250661Sdavidcs device_printf(ha->pci_dev, 903250661Sdavidcs "%s: [0x%08x 0x%08x] error\n", __func__, 904250661Sdavidcs rd_wr_l->wr_addr, data); 905250661Sdavidcs return -1; 906250661Sdavidcs } 907250661Sdavidcs if (ce_hdr->delay_to) { 908250661Sdavidcs DELAY(ce_hdr->delay_to); 909250661Sdavidcs } 910250661Sdavidcs } 911250661Sdavidcs return 0; 912250661Sdavidcs} 913250661Sdavidcs 914250661Sdavidcsstatic int 915250661Sdavidcsqla_poll_reg(qla_host_t *ha, uint32_t addr, uint32_t ms_to, uint32_t tmask, 916250661Sdavidcs uint32_t tvalue) 917250661Sdavidcs{ 918250661Sdavidcs uint32_t data; 919250661Sdavidcs 920250661Sdavidcs while (ms_to) { 921250661Sdavidcs 922250661Sdavidcs if (ql_rdwr_indreg32(ha, addr, &data, 1)) { 923250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", 924250661Sdavidcs __func__, addr); 925250661Sdavidcs return -1; 926250661Sdavidcs } 927250661Sdavidcs 928250661Sdavidcs if ((data & tmask) != tvalue) { 929250661Sdavidcs ms_to--; 930250661Sdavidcs } else 931250661Sdavidcs break; 932250661Sdavidcs 933250661Sdavidcs qla_mdelay(__func__, 1); 934250661Sdavidcs } 935250661Sdavidcs return ((ms_to ? 0: -1)); 936250661Sdavidcs} 937250661Sdavidcs 938250661Sdavidcsstatic int 939250661Sdavidcsqla_poll_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 940250661Sdavidcs{ 941250661Sdavidcs int i; 942250661Sdavidcs q8_poll_hdr_t *phdr; 943250661Sdavidcs q8_poll_e_t *pe; 944250661Sdavidcs uint32_t data; 945250661Sdavidcs 946250661Sdavidcs phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t)); 947250661Sdavidcs pe = (q8_poll_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t)); 948250661Sdavidcs 949250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, pe++) { 950250661Sdavidcs if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) { 951250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", 952250661Sdavidcs __func__, pe->addr); 953250661Sdavidcs return -1; 954250661Sdavidcs } 955250661Sdavidcs 956250661Sdavidcs if (ce_hdr->delay_to) { 957250661Sdavidcs if ((data & phdr->tmask) == phdr->tvalue) 958250661Sdavidcs break; 959250661Sdavidcs if (qla_poll_reg(ha, pe->addr, ce_hdr->delay_to, 960250661Sdavidcs phdr->tmask, phdr->tvalue)) { 961250661Sdavidcs 962250661Sdavidcs if (ql_rdwr_indreg32(ha, pe->to_addr, &data, 963250661Sdavidcs 1)) { 964250661Sdavidcs device_printf(ha->pci_dev, 965250661Sdavidcs "%s: [0x%08x] error\n", 966250661Sdavidcs __func__, pe->to_addr); 967250661Sdavidcs return -1; 968250661Sdavidcs } 969250661Sdavidcs 970250661Sdavidcs if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) { 971250661Sdavidcs device_printf(ha->pci_dev, 972250661Sdavidcs "%s: [0x%08x] error\n", 973250661Sdavidcs __func__, pe->addr); 974250661Sdavidcs return -1; 975250661Sdavidcs } 976250661Sdavidcs } 977250661Sdavidcs } 978250661Sdavidcs } 979250661Sdavidcs return 0; 980250661Sdavidcs} 981250661Sdavidcs 982250661Sdavidcsstatic int 983250661Sdavidcsqla_poll_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 984250661Sdavidcs{ 985250661Sdavidcs int i; 986250661Sdavidcs q8_poll_hdr_t *phdr; 987250661Sdavidcs q8_poll_wr_e_t *wr_e; 988250661Sdavidcs 989250661Sdavidcs phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t)); 990250661Sdavidcs wr_e = (q8_poll_wr_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t)); 991250661Sdavidcs 992250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, wr_e++) { 993250661Sdavidcs 994250661Sdavidcs if (ql_rdwr_indreg32(ha, wr_e->dr_addr, &wr_e->dr_value, 0)) { 995250661Sdavidcs device_printf(ha->pci_dev, 996250661Sdavidcs "%s: [0x%08x 0x%08x] error\n", __func__, 997250661Sdavidcs wr_e->dr_addr, wr_e->dr_value); 998250661Sdavidcs return -1; 999250661Sdavidcs } 1000250661Sdavidcs if (ql_rdwr_indreg32(ha, wr_e->ar_addr, &wr_e->ar_value, 0)) { 1001250661Sdavidcs device_printf(ha->pci_dev, 1002250661Sdavidcs "%s: [0x%08x 0x%08x] error\n", __func__, 1003250661Sdavidcs wr_e->ar_addr, wr_e->ar_value); 1004250661Sdavidcs return -1; 1005250661Sdavidcs } 1006250661Sdavidcs if (ce_hdr->delay_to) { 1007250661Sdavidcs if (qla_poll_reg(ha, wr_e->ar_addr, ce_hdr->delay_to, 1008250661Sdavidcs phdr->tmask, phdr->tvalue)) 1009250661Sdavidcs device_printf(ha->pci_dev, "%s: " 1010250661Sdavidcs "[ar_addr, ar_value, delay, tmask," 1011250661Sdavidcs "tvalue] [0x%08x 0x%08x 0x%08x 0x%08x" 1012250661Sdavidcs " 0x%08x]\n", 1013250661Sdavidcs __func__, wr_e->ar_addr, wr_e->ar_value, 1014250661Sdavidcs ce_hdr->delay_to, phdr->tmask, 1015250661Sdavidcs phdr->tvalue); 1016250661Sdavidcs } 1017250661Sdavidcs } 1018250661Sdavidcs return 0; 1019250661Sdavidcs} 1020250661Sdavidcs 1021250661Sdavidcsstatic int 1022250661Sdavidcsqla_poll_read_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 1023250661Sdavidcs{ 1024250661Sdavidcs int i; 1025250661Sdavidcs q8_poll_hdr_t *phdr; 1026250661Sdavidcs q8_poll_rd_e_t *rd_e; 1027250661Sdavidcs uint32_t value; 1028250661Sdavidcs 1029250661Sdavidcs phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t)); 1030250661Sdavidcs rd_e = (q8_poll_rd_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t)); 1031250661Sdavidcs 1032250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, rd_e++) { 1033250661Sdavidcs if (ql_rdwr_indreg32(ha, rd_e->ar_addr, &rd_e->ar_value, 0)) { 1034250661Sdavidcs device_printf(ha->pci_dev, 1035250661Sdavidcs "%s: [0x%08x 0x%08x] error\n", __func__, 1036250661Sdavidcs rd_e->ar_addr, rd_e->ar_value); 1037250661Sdavidcs return -1; 1038250661Sdavidcs } 1039250661Sdavidcs 1040250661Sdavidcs if (ce_hdr->delay_to) { 1041250661Sdavidcs if (qla_poll_reg(ha, rd_e->ar_addr, ce_hdr->delay_to, 1042250661Sdavidcs phdr->tmask, phdr->tvalue)) { 1043250661Sdavidcs return (-1); 1044250661Sdavidcs } else { 1045250661Sdavidcs if (ql_rdwr_indreg32(ha, rd_e->dr_addr, 1046250661Sdavidcs &value, 1)) { 1047250661Sdavidcs device_printf(ha->pci_dev, 1048250661Sdavidcs "%s: [0x%08x] error\n", 1049250661Sdavidcs __func__, rd_e->ar_addr); 1050250661Sdavidcs return -1; 1051250661Sdavidcs } 1052250661Sdavidcs 1053250661Sdavidcs ha->hw.rst_seq[ha->hw.rst_seq_idx++] = value; 1054250661Sdavidcs if (ha->hw.rst_seq_idx == Q8_MAX_RESET_SEQ_IDX) 1055250661Sdavidcs ha->hw.rst_seq_idx = 1; 1056250661Sdavidcs } 1057250661Sdavidcs } 1058250661Sdavidcs } 1059250661Sdavidcs return 0; 1060250661Sdavidcs} 1061250661Sdavidcs 1062250661Sdavidcsstatic int 1063250661Sdavidcsqla_rdmwr(qla_host_t *ha, uint32_t raddr, uint32_t waddr, q8_rdmwr_hdr_t *hdr) 1064250661Sdavidcs{ 1065250661Sdavidcs uint32_t value; 1066250661Sdavidcs 1067250661Sdavidcs if (hdr->index_a >= Q8_MAX_RESET_SEQ_IDX) { 1068250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__, 1069250661Sdavidcs hdr->index_a); 1070250661Sdavidcs return -1; 1071250661Sdavidcs } 1072250661Sdavidcs 1073250661Sdavidcs if (hdr->index_a) { 1074250661Sdavidcs value = ha->hw.rst_seq[hdr->index_a]; 1075250661Sdavidcs } else { 1076250661Sdavidcs if (ql_rdwr_indreg32(ha, raddr, &value, 1)) { 1077250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", 1078250661Sdavidcs __func__, raddr); 1079250661Sdavidcs return -1; 1080250661Sdavidcs } 1081250661Sdavidcs } 1082250661Sdavidcs 1083250661Sdavidcs value &= hdr->and_value; 1084250661Sdavidcs value <<= hdr->shl; 1085250661Sdavidcs value >>= hdr->shr; 1086250661Sdavidcs value |= hdr->or_value; 1087250661Sdavidcs value ^= hdr->xor_value; 1088250661Sdavidcs 1089250661Sdavidcs if (ql_rdwr_indreg32(ha, waddr, &value, 0)) { 1090250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__, 1091250661Sdavidcs raddr); 1092250661Sdavidcs return -1; 1093250661Sdavidcs } 1094250661Sdavidcs return 0; 1095250661Sdavidcs} 1096250661Sdavidcs 1097250661Sdavidcsstatic int 1098250661Sdavidcsqla_read_modify_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 1099250661Sdavidcs{ 1100250661Sdavidcs int i; 1101250661Sdavidcs q8_rdmwr_hdr_t *rdmwr_hdr; 1102250661Sdavidcs q8_rdmwr_e_t *rdmwr_e; 1103250661Sdavidcs 1104250661Sdavidcs rdmwr_hdr = (q8_rdmwr_hdr_t *)((uint8_t *)ce_hdr + 1105250661Sdavidcs sizeof (q8_ce_hdr_t)); 1106250661Sdavidcs rdmwr_e = (q8_rdmwr_e_t *)((uint8_t *)rdmwr_hdr + 1107250661Sdavidcs sizeof(q8_rdmwr_hdr_t)); 1108250661Sdavidcs 1109250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, rdmwr_e++) { 1110250661Sdavidcs 1111250661Sdavidcs if (qla_rdmwr(ha, rdmwr_e->rd_addr, rdmwr_e->wr_addr, 1112250661Sdavidcs rdmwr_hdr)) { 1113250661Sdavidcs return -1; 1114250661Sdavidcs } 1115250661Sdavidcs if (ce_hdr->delay_to) { 1116250661Sdavidcs DELAY(ce_hdr->delay_to); 1117250661Sdavidcs } 1118250661Sdavidcs } 1119250661Sdavidcs return 0; 1120250661Sdavidcs} 1121250661Sdavidcs 1122250661Sdavidcsstatic int 1123250661Sdavidcsqla_tmplt_execute(qla_host_t *ha, uint8_t *buf, int start_idx, int *end_idx, 1124250661Sdavidcs uint32_t nentries) 1125250661Sdavidcs{ 1126250661Sdavidcs int i, ret = 0, proc_end = 0; 1127250661Sdavidcs q8_ce_hdr_t *ce_hdr; 1128250661Sdavidcs 1129250661Sdavidcs for (i = start_idx; ((i < nentries) && (!proc_end)); i++) { 1130250661Sdavidcs ce_hdr = (q8_ce_hdr_t *)buf; 1131250661Sdavidcs ret = 0; 1132250661Sdavidcs 1133250661Sdavidcs switch (ce_hdr->opcode) { 1134250661Sdavidcs case Q8_CE_OPCODE_NOP: 1135250661Sdavidcs break; 1136250661Sdavidcs 1137250661Sdavidcs case Q8_CE_OPCODE_WRITE_LIST: 1138250661Sdavidcs ret = qla_wr_list(ha, ce_hdr); 1139250661Sdavidcs //printf("qla_wr_list %d\n", ret); 1140250661Sdavidcs break; 1141250661Sdavidcs 1142250661Sdavidcs case Q8_CE_OPCODE_READ_WRITE_LIST: 1143250661Sdavidcs ret = qla_rd_wr_list(ha, ce_hdr); 1144250661Sdavidcs //printf("qla_rd_wr_list %d\n", ret); 1145250661Sdavidcs break; 1146250661Sdavidcs 1147250661Sdavidcs case Q8_CE_OPCODE_POLL_LIST: 1148250661Sdavidcs ret = qla_poll_list(ha, ce_hdr); 1149250661Sdavidcs //printf("qla_poll_list %d\n", ret); 1150250661Sdavidcs break; 1151250661Sdavidcs 1152250661Sdavidcs case Q8_CE_OPCODE_POLL_WRITE_LIST: 1153250661Sdavidcs ret = qla_poll_write_list(ha, ce_hdr); 1154250661Sdavidcs //printf("qla_poll_write_list %d\n", ret); 1155250661Sdavidcs break; 1156250661Sdavidcs 1157250661Sdavidcs case Q8_CE_OPCODE_POLL_RD_LIST: 1158250661Sdavidcs ret = qla_poll_read_list(ha, ce_hdr); 1159250661Sdavidcs //printf("qla_poll_read_list %d\n", ret); 1160250661Sdavidcs break; 1161250661Sdavidcs 1162250661Sdavidcs case Q8_CE_OPCODE_READ_MODIFY_WRITE: 1163250661Sdavidcs ret = qla_read_modify_write_list(ha, ce_hdr); 1164250661Sdavidcs //printf("qla_read_modify_write_list %d\n", ret); 1165250661Sdavidcs break; 1166250661Sdavidcs 1167250661Sdavidcs case Q8_CE_OPCODE_SEQ_PAUSE: 1168250661Sdavidcs if (ce_hdr->delay_to) { 1169250661Sdavidcs qla_mdelay(__func__, ce_hdr->delay_to); 1170250661Sdavidcs } 1171250661Sdavidcs break; 1172250661Sdavidcs 1173250661Sdavidcs case Q8_CE_OPCODE_SEQ_END: 1174250661Sdavidcs proc_end = 1; 1175250661Sdavidcs break; 1176250661Sdavidcs 1177250661Sdavidcs case Q8_CE_OPCODE_TMPLT_END: 1178250661Sdavidcs *end_idx = i; 1179250661Sdavidcs return 0; 1180250661Sdavidcs } 1181250661Sdavidcs 1182250661Sdavidcs if (ret) 1183250661Sdavidcs break; 1184250661Sdavidcs 1185250661Sdavidcs buf += ce_hdr->size; 1186250661Sdavidcs } 1187250661Sdavidcs *end_idx = i; 1188250661Sdavidcs 1189250661Sdavidcs return (ret); 1190250661Sdavidcs} 1191250661Sdavidcs 1192284741Sdavidcs#ifndef QL_LDFLASH_FW 1193284741Sdavidcsstatic int 1194284741Sdavidcsqla_load_offchip_mem(qla_host_t *ha, uint64_t addr, uint32_t *data32, 1195284741Sdavidcs uint32_t len32) 1196284741Sdavidcs{ 1197284741Sdavidcs q80_offchip_mem_val_t val; 1198284741Sdavidcs int ret = 0; 1199250661Sdavidcs 1200284741Sdavidcs while (len32) { 1201284741Sdavidcs if (len32 > 4) { 1202284741Sdavidcs val.data_lo = *data32++; 1203284741Sdavidcs val.data_hi = *data32++; 1204284741Sdavidcs val.data_ulo = *data32++; 1205284741Sdavidcs val.data_uhi = *data32++; 1206284741Sdavidcs len32 -= 4; 1207284741Sdavidcs if (ql_rdwr_offchip_mem(ha, addr, &val, 0)) 1208284741Sdavidcs return -1; 1209284741Sdavidcs 1210284741Sdavidcs addr += (uint64_t)16; 1211284741Sdavidcs } else { 1212284741Sdavidcs break; 1213284741Sdavidcs } 1214284741Sdavidcs } 1215284741Sdavidcs 1216284741Sdavidcs bzero(&val, sizeof(q80_offchip_mem_val_t)); 1217284741Sdavidcs 1218284741Sdavidcs switch (len32) { 1219284741Sdavidcs case 3: 1220284741Sdavidcs val.data_lo = *data32++; 1221284741Sdavidcs val.data_hi = *data32++; 1222284741Sdavidcs val.data_ulo = *data32++; 1223284741Sdavidcs ret = ql_rdwr_offchip_mem(ha, addr, &val, 0); 1224284741Sdavidcs break; 1225284741Sdavidcs 1226284741Sdavidcs case 2: 1227284741Sdavidcs val.data_lo = *data32++; 1228284741Sdavidcs val.data_hi = *data32++; 1229284741Sdavidcs ret = ql_rdwr_offchip_mem(ha, addr, &val, 0); 1230284741Sdavidcs break; 1231284741Sdavidcs 1232284741Sdavidcs case 1: 1233284741Sdavidcs val.data_lo = *data32++; 1234284741Sdavidcs ret = ql_rdwr_offchip_mem(ha, addr, &val, 0); 1235284741Sdavidcs break; 1236284741Sdavidcs 1237284741Sdavidcs default: 1238284741Sdavidcs break; 1239284741Sdavidcs 1240284741Sdavidcs } 1241284741Sdavidcs return ret; 1242284741Sdavidcs} 1243284741Sdavidcs 1244284741Sdavidcs 1245250661Sdavidcsstatic int 1246284741Sdavidcsqla_load_bootldr(qla_host_t *ha) 1247284741Sdavidcs{ 1248284741Sdavidcs uint64_t addr; 1249284741Sdavidcs uint32_t *data32; 1250284741Sdavidcs uint32_t len32; 1251284741Sdavidcs int ret; 1252284741Sdavidcs 1253284741Sdavidcs addr = (uint64_t)(READ_REG32(ha, Q8_BOOTLD_ADDR)); 1254284741Sdavidcs data32 = (uint32_t *)ql83xx_bootloader; 1255284741Sdavidcs len32 = ql83xx_bootloader_len >> 2; 1256284741Sdavidcs 1257284741Sdavidcs ret = qla_load_offchip_mem(ha, addr, data32, len32); 1258284741Sdavidcs 1259284741Sdavidcs return (ret); 1260284741Sdavidcs} 1261284741Sdavidcs 1262284741Sdavidcsstatic int 1263284741Sdavidcsqla_load_fwimage(qla_host_t *ha) 1264284741Sdavidcs{ 1265284741Sdavidcs uint64_t addr; 1266284741Sdavidcs uint32_t *data32; 1267284741Sdavidcs uint32_t len32; 1268284741Sdavidcs int ret; 1269284741Sdavidcs 1270284741Sdavidcs addr = (uint64_t)(READ_REG32(ha, Q8_FW_IMAGE_ADDR)); 1271284741Sdavidcs data32 = (uint32_t *)ql83xx_firmware; 1272284741Sdavidcs len32 = ql83xx_firmware_len >> 2; 1273284741Sdavidcs 1274284741Sdavidcs ret = qla_load_offchip_mem(ha, addr, data32, len32); 1275284741Sdavidcs 1276284741Sdavidcs return (ret); 1277284741Sdavidcs} 1278284741Sdavidcs#endif /* #ifndef QL_LDFLASH_FW */ 1279284741Sdavidcs 1280284741Sdavidcsstatic int 1281250661Sdavidcsqla_ld_fw_init(qla_host_t *ha) 1282250661Sdavidcs{ 1283250661Sdavidcs uint8_t *buf; 1284250661Sdavidcs uint32_t index = 0, end_idx; 1285250661Sdavidcs q8_tmplt_hdr_t *hdr; 1286250661Sdavidcs 1287250661Sdavidcs bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq)); 1288250661Sdavidcs 1289250661Sdavidcs hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq; 1290250661Sdavidcs 1291330555Sdavidcs device_printf(ha->pci_dev, "%s: reset sequence\n", __func__); 1292250661Sdavidcs if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq, 1293250661Sdavidcs (uint32_t)hdr->size)) { 1294250661Sdavidcs device_printf(ha->pci_dev, "%s: reset seq checksum failed\n", 1295250661Sdavidcs __func__); 1296250661Sdavidcs return -1; 1297250661Sdavidcs } 1298250661Sdavidcs 1299250661Sdavidcs 1300250661Sdavidcs buf = ql83xx_resetseq + hdr->stop_seq_off; 1301250661Sdavidcs 1302330555Sdavidcs device_printf(ha->pci_dev, "%s: stop sequence\n", __func__); 1303250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1304250661Sdavidcs device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__); 1305250661Sdavidcs return -1; 1306250661Sdavidcs } 1307250661Sdavidcs 1308250661Sdavidcs index = end_idx; 1309250661Sdavidcs 1310250661Sdavidcs buf = ql83xx_resetseq + hdr->init_seq_off; 1311250661Sdavidcs 1312330555Sdavidcs device_printf(ha->pci_dev, "%s: init sequence\n", __func__); 1313250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1314250661Sdavidcs device_printf(ha->pci_dev, "%s: init seq failed\n", __func__); 1315250661Sdavidcs return -1; 1316250661Sdavidcs } 1317250661Sdavidcs 1318284741Sdavidcs#ifdef QL_LDFLASH_FW 1319250661Sdavidcs qla_load_fw_from_flash(ha); 1320250661Sdavidcs WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0); 1321284741Sdavidcs#else 1322284741Sdavidcs if (qla_load_bootldr(ha)) 1323284741Sdavidcs return -1; 1324250661Sdavidcs 1325284741Sdavidcs if (qla_load_fwimage(ha)) 1326284741Sdavidcs return -1; 1327284741Sdavidcs 1328284741Sdavidcs WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0x12345678); 1329284741Sdavidcs#endif /* #ifdef QL_LDFLASH_FW */ 1330284741Sdavidcs 1331250661Sdavidcs index = end_idx; 1332250661Sdavidcs buf = ql83xx_resetseq + hdr->start_seq_off; 1333250661Sdavidcs 1334330555Sdavidcs device_printf(ha->pci_dev, "%s: start sequence\n", __func__); 1335250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1336250661Sdavidcs device_printf(ha->pci_dev, "%s: init seq failed\n", __func__); 1337250661Sdavidcs return -1; 1338250661Sdavidcs } 1339250661Sdavidcs 1340250661Sdavidcs return 0; 1341250661Sdavidcs} 1342250661Sdavidcs 1343250661Sdavidcsint 1344250661Sdavidcsql_stop_sequence(qla_host_t *ha) 1345250661Sdavidcs{ 1346250661Sdavidcs uint8_t *buf; 1347250661Sdavidcs uint32_t index = 0, end_idx; 1348250661Sdavidcs q8_tmplt_hdr_t *hdr; 1349250661Sdavidcs 1350250661Sdavidcs bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq)); 1351250661Sdavidcs 1352250661Sdavidcs hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq; 1353250661Sdavidcs 1354250661Sdavidcs if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq, 1355250661Sdavidcs (uint32_t)hdr->size)) { 1356250661Sdavidcs device_printf(ha->pci_dev, "%s: reset seq checksum failed\n", 1357250661Sdavidcs __func__); 1358250661Sdavidcs return (-1); 1359250661Sdavidcs } 1360250661Sdavidcs 1361250661Sdavidcs buf = ql83xx_resetseq + hdr->stop_seq_off; 1362250661Sdavidcs 1363250661Sdavidcs device_printf(ha->pci_dev, "%s: stop sequence\n", __func__); 1364250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1365250661Sdavidcs device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__); 1366250661Sdavidcs return (-1); 1367250661Sdavidcs } 1368250661Sdavidcs 1369250661Sdavidcs return end_idx; 1370250661Sdavidcs} 1371250661Sdavidcs 1372250661Sdavidcsint 1373250661Sdavidcsql_start_sequence(qla_host_t *ha, uint16_t index) 1374250661Sdavidcs{ 1375250661Sdavidcs uint8_t *buf; 1376250661Sdavidcs uint32_t end_idx; 1377250661Sdavidcs q8_tmplt_hdr_t *hdr; 1378250661Sdavidcs 1379250661Sdavidcs bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq)); 1380250661Sdavidcs 1381250661Sdavidcs hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq; 1382250661Sdavidcs 1383250661Sdavidcs if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq, 1384250661Sdavidcs (uint32_t)hdr->size)) { 1385250661Sdavidcs device_printf(ha->pci_dev, "%s: reset seq checksum failed\n", 1386250661Sdavidcs __func__); 1387250661Sdavidcs return (-1); 1388250661Sdavidcs } 1389250661Sdavidcs 1390250661Sdavidcs buf = ql83xx_resetseq + hdr->init_seq_off; 1391250661Sdavidcs 1392250661Sdavidcs device_printf(ha->pci_dev, "%s: init sequence\n", __func__); 1393250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1394250661Sdavidcs device_printf(ha->pci_dev, "%s: init seq failed\n", __func__); 1395250661Sdavidcs return (-1); 1396250661Sdavidcs } 1397250661Sdavidcs 1398284741Sdavidcs#ifdef QL_LDFLASH_FW 1399250661Sdavidcs qla_load_fw_from_flash(ha); 1400250661Sdavidcs WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0); 1401284741Sdavidcs#else 1402284741Sdavidcs if (qla_load_bootldr(ha)) 1403284741Sdavidcs return -1; 1404250661Sdavidcs 1405284741Sdavidcs if (qla_load_fwimage(ha)) 1406284741Sdavidcs return -1; 1407284741Sdavidcs 1408284741Sdavidcs WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0x12345678); 1409284741Sdavidcs#endif /* #ifdef QL_LDFLASH_FW */ 1410284741Sdavidcs 1411284741Sdavidcs 1412250661Sdavidcs index = end_idx; 1413250661Sdavidcs buf = ql83xx_resetseq + hdr->start_seq_off; 1414250661Sdavidcs 1415250661Sdavidcs device_printf(ha->pci_dev, "%s: start sequence\n", __func__); 1416250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1417250661Sdavidcs device_printf(ha->pci_dev, "%s: init seq failed\n", __func__); 1418250661Sdavidcs return -1; 1419250661Sdavidcs } 1420250661Sdavidcs 1421250661Sdavidcs return (0); 1422250661Sdavidcs} 1423250661Sdavidcs 1424