ql_misc.c revision 254976
1250661Sdavidcs/* 2250661Sdavidcs * Copyright (c) 2013-2014 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: head/sys/dev/qlxgbe/ql_misc.c 254976 2013-08-27 21:29:21Z davidcs $"); 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); 80250661Sdavidcs ha->qla_initiate_recovery = 1; 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 213250661Sdavidcs ha->qla_initiate_recovery = 1; 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 664250661Sdavidcs/* 665250661Sdavidcs * Name: qla_load_fw_from_flash 666250661Sdavidcs * Function: Reads the Bootloader from Flash and Loads into Offchip Memory 667250661Sdavidcs */ 668250661Sdavidcsstatic void 669250661Sdavidcsqla_load_fw_from_flash(qla_host_t *ha) 670250661Sdavidcs{ 671250661Sdavidcs uint32_t flash_off = 0x10000; 672250661Sdavidcs uint64_t mem_off; 673250661Sdavidcs uint32_t count, mem_size; 674250661Sdavidcs q80_offchip_mem_val_t val; 675250661Sdavidcs 676250661Sdavidcs mem_off = (uint64_t)(READ_REG32(ha, Q8_BOOTLD_ADDR)); 677250661Sdavidcs mem_size = READ_REG32(ha, Q8_BOOTLD_SIZE); 678250661Sdavidcs 679250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x][0x%08x]\n", 680250661Sdavidcs __func__, (uint32_t)mem_off, mem_size); 681250661Sdavidcs 682250661Sdavidcs /* only bootloader needs to be loaded into memory */ 683250661Sdavidcs for (count = 0; count < mem_size ; ) { 684250661Sdavidcs ql_rd_flash32(ha, flash_off, &val.data_lo); 685250661Sdavidcs count = count + 4; 686250661Sdavidcs flash_off = flash_off + 4; 687250661Sdavidcs 688250661Sdavidcs ql_rd_flash32(ha, flash_off, &val.data_hi); 689250661Sdavidcs count = count + 4; 690250661Sdavidcs flash_off = flash_off + 4; 691250661Sdavidcs 692250661Sdavidcs ql_rd_flash32(ha, flash_off, &val.data_ulo); 693250661Sdavidcs count = count + 4; 694250661Sdavidcs flash_off = flash_off + 4; 695250661Sdavidcs 696250661Sdavidcs ql_rd_flash32(ha, flash_off, &val.data_uhi); 697250661Sdavidcs count = count + 4; 698250661Sdavidcs flash_off = flash_off + 4; 699250661Sdavidcs 700250661Sdavidcs ql_rdwr_offchip_mem(ha, mem_off, &val, 0); 701250661Sdavidcs 702250661Sdavidcs mem_off = mem_off + 16; 703250661Sdavidcs } 704250661Sdavidcs 705250661Sdavidcs return; 706250661Sdavidcs} 707250661Sdavidcs 708250661Sdavidcs/* 709250661Sdavidcs * Name: qla_init_from_flash 710250661Sdavidcs * Function: Performs Initialization which consists of the following sequence 711250661Sdavidcs * - reset 712250661Sdavidcs * - CRB Init 713250661Sdavidcs * - Peg Init 714250661Sdavidcs * - Read the Bootloader from Flash and Load into Offchip Memory 715250661Sdavidcs * - Kick start the bootloader which loads the rest of the firmware 716250661Sdavidcs * and performs the remaining steps in the initialization process. 717250661Sdavidcs */ 718250661Sdavidcsstatic int 719250661Sdavidcsqla_init_from_flash(qla_host_t *ha) 720250661Sdavidcs{ 721250661Sdavidcs uint32_t delay = 300; 722250661Sdavidcs uint32_t data; 723250661Sdavidcs 724250661Sdavidcs qla_ld_fw_init(ha); 725250661Sdavidcs 726250661Sdavidcs do { 727250661Sdavidcs data = READ_REG32(ha, Q8_CMDPEG_STATE); 728250661Sdavidcs 729250661Sdavidcs QL_DPRINT2(ha, 730250661Sdavidcs (ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n", 731250661Sdavidcs __func__, ha->pci_func, data)); 732250661Sdavidcs if (data == 0xFF01) { 733250661Sdavidcs QL_DPRINT2(ha, (ha->pci_dev, 734250661Sdavidcs "%s: func[%d] init complete\n", 735250661Sdavidcs __func__, ha->pci_func)); 736250661Sdavidcs return(0); 737250661Sdavidcs } 738250661Sdavidcs qla_mdelay(__func__, 100); 739250661Sdavidcs } while (delay--); 740250661Sdavidcs 741250661Sdavidcs return (-1); 742250661Sdavidcs} 743250661Sdavidcs 744250661Sdavidcs/* 745250661Sdavidcs * Name: ql_init_hw 746250661Sdavidcs * Function: Initializes P3+ hardware. 747250661Sdavidcs */ 748250661Sdavidcsint 749250661Sdavidcsql_init_hw(qla_host_t *ha) 750250661Sdavidcs{ 751250661Sdavidcs device_t dev; 752250661Sdavidcs int ret = 0; 753250661Sdavidcs uint32_t val, delay = 300; 754250661Sdavidcs 755250661Sdavidcs dev = ha->pci_dev; 756250661Sdavidcs 757250661Sdavidcs QL_DPRINT1(ha, (dev, "%s: enter\n", __func__)); 758250661Sdavidcs 759250661Sdavidcs if (ha->pci_func & 0x1) { 760250661Sdavidcs 761250661Sdavidcs while ((ha->pci_func & 0x1) && delay--) { 762250661Sdavidcs 763250661Sdavidcs val = READ_REG32(ha, Q8_CMDPEG_STATE); 764250661Sdavidcs 765250661Sdavidcs if (val == 0xFF01) { 766250661Sdavidcs QL_DPRINT2(ha, (dev, 767250661Sdavidcs "%s: func = %d init complete\n", 768250661Sdavidcs __func__, ha->pci_func)); 769250661Sdavidcs qla_mdelay(__func__, 100); 770250661Sdavidcs goto qla_init_exit; 771250661Sdavidcs } 772250661Sdavidcs qla_mdelay(__func__, 100); 773250661Sdavidcs } 774250661Sdavidcs return (-1); 775250661Sdavidcs } 776250661Sdavidcs 777250661Sdavidcs 778250661Sdavidcs val = READ_REG32(ha, Q8_CMDPEG_STATE); 779250661Sdavidcs if (!cold || (val != 0xFF01)) { 780250661Sdavidcs ret = qla_init_from_flash(ha); 781250661Sdavidcs qla_mdelay(__func__, 100); 782250661Sdavidcs } 783250661Sdavidcs 784250661Sdavidcsqla_init_exit: 785250661Sdavidcs ha->fw_ver_major = READ_REG32(ha, Q8_FW_VER_MAJOR); 786250661Sdavidcs ha->fw_ver_minor = READ_REG32(ha, Q8_FW_VER_MINOR); 787250661Sdavidcs ha->fw_ver_sub = READ_REG32(ha, Q8_FW_VER_SUB); 788250661Sdavidcs 789250661Sdavidcs if (qla_get_fdt(ha) != 0) { 790250661Sdavidcs device_printf(dev, "%s: qla_get_fdt failed\n", __func__); 791250661Sdavidcs } else { 792250661Sdavidcs ha->hw.flags.fdt_valid = 1; 793250661Sdavidcs } 794250661Sdavidcs 795250661Sdavidcs return (ret); 796250661Sdavidcs} 797250661Sdavidcs 798250661Sdavidcsvoid 799250661Sdavidcsql_read_mac_addr(qla_host_t *ha) 800250661Sdavidcs{ 801250661Sdavidcs uint8_t *macp; 802250661Sdavidcs uint32_t mac_lo; 803250661Sdavidcs uint32_t mac_hi; 804250661Sdavidcs uint32_t flash_off; 805250661Sdavidcs 806250661Sdavidcs flash_off = Q8_BOARD_CONFIG_OFFSET + Q8_BOARD_CONFIG_MAC0_LO + 807250661Sdavidcs (ha->pci_func << 3); 808250661Sdavidcs ql_rd_flash32(ha, flash_off, &mac_lo); 809250661Sdavidcs 810250661Sdavidcs flash_off += 4; 811250661Sdavidcs ql_rd_flash32(ha, flash_off, &mac_hi); 812250661Sdavidcs 813250661Sdavidcs macp = (uint8_t *)&mac_lo; 814250661Sdavidcs ha->hw.mac_addr[5] = macp[0]; 815250661Sdavidcs ha->hw.mac_addr[4] = macp[1]; 816250661Sdavidcs ha->hw.mac_addr[3] = macp[2]; 817250661Sdavidcs ha->hw.mac_addr[2] = macp[3]; 818250661Sdavidcs 819250661Sdavidcs macp = (uint8_t *)&mac_hi; 820250661Sdavidcs ha->hw.mac_addr[1] = macp[0]; 821250661Sdavidcs ha->hw.mac_addr[0] = macp[1]; 822250661Sdavidcs 823250661Sdavidcs //device_printf(ha->pci_dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n", 824250661Sdavidcs // __func__, ha->hw.mac_addr[0], ha->hw.mac_addr[1], 825250661Sdavidcs // ha->hw.mac_addr[2], ha->hw.mac_addr[3], 826250661Sdavidcs // ha->hw.mac_addr[4], ha->hw.mac_addr[5]); 827250661Sdavidcs 828250661Sdavidcs return; 829250661Sdavidcs} 830250661Sdavidcs 831250661Sdavidcs/* 832250661Sdavidcs * Stop/Start/Initialization Handling 833250661Sdavidcs */ 834250661Sdavidcs 835250661Sdavidcsstatic uint16_t 836250661Sdavidcsqla_tmplt_16bit_checksum(qla_host_t *ha, uint16_t *buf, uint32_t size) 837250661Sdavidcs{ 838250661Sdavidcs uint32_t sum = 0; 839250661Sdavidcs uint32_t count = size >> 1; /* size in 16 bit words */ 840250661Sdavidcs 841250661Sdavidcs while (count-- > 0) 842250661Sdavidcs sum += *buf++; 843250661Sdavidcs 844250661Sdavidcs while (sum >> 16) 845250661Sdavidcs sum = (sum & 0xFFFF) + (sum >> 16); 846250661Sdavidcs 847250661Sdavidcs return (~sum); 848250661Sdavidcs} 849250661Sdavidcs 850250661Sdavidcsstatic int 851250661Sdavidcsqla_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 852250661Sdavidcs{ 853250661Sdavidcs q8_wrl_e_t *wr_l; 854250661Sdavidcs int i; 855250661Sdavidcs 856250661Sdavidcs wr_l = (q8_wrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t)); 857250661Sdavidcs 858250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, wr_l++) { 859250661Sdavidcs 860250661Sdavidcs if (ql_rdwr_indreg32(ha, wr_l->addr, &wr_l->value, 0)) { 861250661Sdavidcs device_printf(ha->pci_dev, 862250661Sdavidcs "%s: [0x%08x 0x%08x] error\n", __func__, 863250661Sdavidcs wr_l->addr, wr_l->value); 864250661Sdavidcs return -1; 865250661Sdavidcs } 866250661Sdavidcs if (ce_hdr->delay_to) { 867250661Sdavidcs DELAY(ce_hdr->delay_to); 868250661Sdavidcs } 869250661Sdavidcs } 870250661Sdavidcs return 0; 871250661Sdavidcs} 872250661Sdavidcs 873250661Sdavidcsstatic int 874250661Sdavidcsqla_rd_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 875250661Sdavidcs{ 876250661Sdavidcs q8_rdwrl_e_t *rd_wr_l; 877250661Sdavidcs uint32_t data; 878250661Sdavidcs int i; 879250661Sdavidcs 880250661Sdavidcs rd_wr_l = (q8_rdwrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t)); 881250661Sdavidcs 882250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, rd_wr_l++) { 883250661Sdavidcs 884250661Sdavidcs if (ql_rdwr_indreg32(ha, rd_wr_l->rd_addr, &data, 1)) { 885250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", 886250661Sdavidcs __func__, rd_wr_l->rd_addr); 887250661Sdavidcs 888250661Sdavidcs return -1; 889250661Sdavidcs } 890250661Sdavidcs 891250661Sdavidcs if (ql_rdwr_indreg32(ha, rd_wr_l->wr_addr, &data, 0)) { 892250661Sdavidcs device_printf(ha->pci_dev, 893250661Sdavidcs "%s: [0x%08x 0x%08x] error\n", __func__, 894250661Sdavidcs rd_wr_l->wr_addr, data); 895250661Sdavidcs return -1; 896250661Sdavidcs } 897250661Sdavidcs if (ce_hdr->delay_to) { 898250661Sdavidcs DELAY(ce_hdr->delay_to); 899250661Sdavidcs } 900250661Sdavidcs } 901250661Sdavidcs return 0; 902250661Sdavidcs} 903250661Sdavidcs 904250661Sdavidcsstatic int 905250661Sdavidcsqla_poll_reg(qla_host_t *ha, uint32_t addr, uint32_t ms_to, uint32_t tmask, 906250661Sdavidcs uint32_t tvalue) 907250661Sdavidcs{ 908250661Sdavidcs uint32_t data; 909250661Sdavidcs 910250661Sdavidcs while (ms_to) { 911250661Sdavidcs 912250661Sdavidcs if (ql_rdwr_indreg32(ha, addr, &data, 1)) { 913250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", 914250661Sdavidcs __func__, addr); 915250661Sdavidcs return -1; 916250661Sdavidcs } 917250661Sdavidcs 918250661Sdavidcs if ((data & tmask) != tvalue) { 919250661Sdavidcs ms_to--; 920250661Sdavidcs } else 921250661Sdavidcs break; 922250661Sdavidcs 923250661Sdavidcs qla_mdelay(__func__, 1); 924250661Sdavidcs } 925250661Sdavidcs return ((ms_to ? 0: -1)); 926250661Sdavidcs} 927250661Sdavidcs 928250661Sdavidcsstatic int 929250661Sdavidcsqla_poll_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 930250661Sdavidcs{ 931250661Sdavidcs int i; 932250661Sdavidcs q8_poll_hdr_t *phdr; 933250661Sdavidcs q8_poll_e_t *pe; 934250661Sdavidcs uint32_t data; 935250661Sdavidcs 936250661Sdavidcs phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t)); 937250661Sdavidcs pe = (q8_poll_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t)); 938250661Sdavidcs 939250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, pe++) { 940250661Sdavidcs if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) { 941250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", 942250661Sdavidcs __func__, pe->addr); 943250661Sdavidcs return -1; 944250661Sdavidcs } 945250661Sdavidcs 946250661Sdavidcs if (ce_hdr->delay_to) { 947250661Sdavidcs if ((data & phdr->tmask) == phdr->tvalue) 948250661Sdavidcs break; 949250661Sdavidcs if (qla_poll_reg(ha, pe->addr, ce_hdr->delay_to, 950250661Sdavidcs phdr->tmask, phdr->tvalue)) { 951250661Sdavidcs 952250661Sdavidcs if (ql_rdwr_indreg32(ha, pe->to_addr, &data, 953250661Sdavidcs 1)) { 954250661Sdavidcs device_printf(ha->pci_dev, 955250661Sdavidcs "%s: [0x%08x] error\n", 956250661Sdavidcs __func__, pe->to_addr); 957250661Sdavidcs return -1; 958250661Sdavidcs } 959250661Sdavidcs 960250661Sdavidcs if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) { 961250661Sdavidcs device_printf(ha->pci_dev, 962250661Sdavidcs "%s: [0x%08x] error\n", 963250661Sdavidcs __func__, pe->addr); 964250661Sdavidcs return -1; 965250661Sdavidcs } 966250661Sdavidcs } 967250661Sdavidcs } 968250661Sdavidcs } 969250661Sdavidcs return 0; 970250661Sdavidcs} 971250661Sdavidcs 972250661Sdavidcsstatic int 973250661Sdavidcsqla_poll_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 974250661Sdavidcs{ 975250661Sdavidcs int i; 976250661Sdavidcs q8_poll_hdr_t *phdr; 977250661Sdavidcs q8_poll_wr_e_t *wr_e; 978250661Sdavidcs 979250661Sdavidcs phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t)); 980250661Sdavidcs wr_e = (q8_poll_wr_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t)); 981250661Sdavidcs 982250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, wr_e++) { 983250661Sdavidcs 984250661Sdavidcs if (ql_rdwr_indreg32(ha, wr_e->dr_addr, &wr_e->dr_value, 0)) { 985250661Sdavidcs device_printf(ha->pci_dev, 986250661Sdavidcs "%s: [0x%08x 0x%08x] error\n", __func__, 987250661Sdavidcs wr_e->dr_addr, wr_e->dr_value); 988250661Sdavidcs return -1; 989250661Sdavidcs } 990250661Sdavidcs if (ql_rdwr_indreg32(ha, wr_e->ar_addr, &wr_e->ar_value, 0)) { 991250661Sdavidcs device_printf(ha->pci_dev, 992250661Sdavidcs "%s: [0x%08x 0x%08x] error\n", __func__, 993250661Sdavidcs wr_e->ar_addr, wr_e->ar_value); 994250661Sdavidcs return -1; 995250661Sdavidcs } 996250661Sdavidcs if (ce_hdr->delay_to) { 997250661Sdavidcs if (qla_poll_reg(ha, wr_e->ar_addr, ce_hdr->delay_to, 998250661Sdavidcs phdr->tmask, phdr->tvalue)) 999250661Sdavidcs device_printf(ha->pci_dev, "%s: " 1000250661Sdavidcs "[ar_addr, ar_value, delay, tmask," 1001250661Sdavidcs "tvalue] [0x%08x 0x%08x 0x%08x 0x%08x" 1002250661Sdavidcs " 0x%08x]\n", 1003250661Sdavidcs __func__, wr_e->ar_addr, wr_e->ar_value, 1004250661Sdavidcs ce_hdr->delay_to, phdr->tmask, 1005250661Sdavidcs phdr->tvalue); 1006250661Sdavidcs } 1007250661Sdavidcs } 1008250661Sdavidcs return 0; 1009250661Sdavidcs} 1010250661Sdavidcs 1011250661Sdavidcsstatic int 1012250661Sdavidcsqla_poll_read_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 1013250661Sdavidcs{ 1014250661Sdavidcs int i; 1015250661Sdavidcs q8_poll_hdr_t *phdr; 1016250661Sdavidcs q8_poll_rd_e_t *rd_e; 1017250661Sdavidcs uint32_t value; 1018250661Sdavidcs 1019250661Sdavidcs phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t)); 1020250661Sdavidcs rd_e = (q8_poll_rd_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t)); 1021250661Sdavidcs 1022250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, rd_e++) { 1023250661Sdavidcs if (ql_rdwr_indreg32(ha, rd_e->ar_addr, &rd_e->ar_value, 0)) { 1024250661Sdavidcs device_printf(ha->pci_dev, 1025250661Sdavidcs "%s: [0x%08x 0x%08x] error\n", __func__, 1026250661Sdavidcs rd_e->ar_addr, rd_e->ar_value); 1027250661Sdavidcs return -1; 1028250661Sdavidcs } 1029250661Sdavidcs 1030250661Sdavidcs if (ce_hdr->delay_to) { 1031250661Sdavidcs if (qla_poll_reg(ha, rd_e->ar_addr, ce_hdr->delay_to, 1032250661Sdavidcs phdr->tmask, phdr->tvalue)) { 1033250661Sdavidcs return (-1); 1034250661Sdavidcs } else { 1035250661Sdavidcs if (ql_rdwr_indreg32(ha, rd_e->dr_addr, 1036250661Sdavidcs &value, 1)) { 1037250661Sdavidcs device_printf(ha->pci_dev, 1038250661Sdavidcs "%s: [0x%08x] error\n", 1039250661Sdavidcs __func__, rd_e->ar_addr); 1040250661Sdavidcs return -1; 1041250661Sdavidcs } 1042250661Sdavidcs 1043250661Sdavidcs ha->hw.rst_seq[ha->hw.rst_seq_idx++] = value; 1044250661Sdavidcs if (ha->hw.rst_seq_idx == Q8_MAX_RESET_SEQ_IDX) 1045250661Sdavidcs ha->hw.rst_seq_idx = 1; 1046250661Sdavidcs } 1047250661Sdavidcs } 1048250661Sdavidcs } 1049250661Sdavidcs return 0; 1050250661Sdavidcs} 1051250661Sdavidcs 1052250661Sdavidcsstatic int 1053250661Sdavidcsqla_rdmwr(qla_host_t *ha, uint32_t raddr, uint32_t waddr, q8_rdmwr_hdr_t *hdr) 1054250661Sdavidcs{ 1055250661Sdavidcs uint32_t value; 1056250661Sdavidcs 1057250661Sdavidcs if (hdr->index_a >= Q8_MAX_RESET_SEQ_IDX) { 1058250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__, 1059250661Sdavidcs hdr->index_a); 1060250661Sdavidcs return -1; 1061250661Sdavidcs } 1062250661Sdavidcs 1063250661Sdavidcs if (hdr->index_a) { 1064250661Sdavidcs value = ha->hw.rst_seq[hdr->index_a]; 1065250661Sdavidcs } else { 1066250661Sdavidcs if (ql_rdwr_indreg32(ha, raddr, &value, 1)) { 1067250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", 1068250661Sdavidcs __func__, raddr); 1069250661Sdavidcs return -1; 1070250661Sdavidcs } 1071250661Sdavidcs } 1072250661Sdavidcs 1073250661Sdavidcs value &= hdr->and_value; 1074250661Sdavidcs value <<= hdr->shl; 1075250661Sdavidcs value >>= hdr->shr; 1076250661Sdavidcs value |= hdr->or_value; 1077250661Sdavidcs value ^= hdr->xor_value; 1078250661Sdavidcs 1079250661Sdavidcs if (ql_rdwr_indreg32(ha, waddr, &value, 0)) { 1080250661Sdavidcs device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__, 1081250661Sdavidcs raddr); 1082250661Sdavidcs return -1; 1083250661Sdavidcs } 1084250661Sdavidcs return 0; 1085250661Sdavidcs} 1086250661Sdavidcs 1087250661Sdavidcsstatic int 1088250661Sdavidcsqla_read_modify_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr) 1089250661Sdavidcs{ 1090250661Sdavidcs int i; 1091250661Sdavidcs q8_rdmwr_hdr_t *rdmwr_hdr; 1092250661Sdavidcs q8_rdmwr_e_t *rdmwr_e; 1093250661Sdavidcs 1094250661Sdavidcs rdmwr_hdr = (q8_rdmwr_hdr_t *)((uint8_t *)ce_hdr + 1095250661Sdavidcs sizeof (q8_ce_hdr_t)); 1096250661Sdavidcs rdmwr_e = (q8_rdmwr_e_t *)((uint8_t *)rdmwr_hdr + 1097250661Sdavidcs sizeof(q8_rdmwr_hdr_t)); 1098250661Sdavidcs 1099250661Sdavidcs for (i = 0; i < ce_hdr->opcount; i++, rdmwr_e++) { 1100250661Sdavidcs 1101250661Sdavidcs if (qla_rdmwr(ha, rdmwr_e->rd_addr, rdmwr_e->wr_addr, 1102250661Sdavidcs rdmwr_hdr)) { 1103250661Sdavidcs return -1; 1104250661Sdavidcs } 1105250661Sdavidcs if (ce_hdr->delay_to) { 1106250661Sdavidcs DELAY(ce_hdr->delay_to); 1107250661Sdavidcs } 1108250661Sdavidcs } 1109250661Sdavidcs return 0; 1110250661Sdavidcs} 1111250661Sdavidcs 1112250661Sdavidcsstatic int 1113250661Sdavidcsqla_tmplt_execute(qla_host_t *ha, uint8_t *buf, int start_idx, int *end_idx, 1114250661Sdavidcs uint32_t nentries) 1115250661Sdavidcs{ 1116250661Sdavidcs int i, ret = 0, proc_end = 0; 1117250661Sdavidcs q8_ce_hdr_t *ce_hdr; 1118250661Sdavidcs 1119250661Sdavidcs for (i = start_idx; ((i < nentries) && (!proc_end)); i++) { 1120250661Sdavidcs ce_hdr = (q8_ce_hdr_t *)buf; 1121250661Sdavidcs ret = 0; 1122250661Sdavidcs 1123250661Sdavidcs switch (ce_hdr->opcode) { 1124250661Sdavidcs case Q8_CE_OPCODE_NOP: 1125250661Sdavidcs break; 1126250661Sdavidcs 1127250661Sdavidcs case Q8_CE_OPCODE_WRITE_LIST: 1128250661Sdavidcs ret = qla_wr_list(ha, ce_hdr); 1129250661Sdavidcs //printf("qla_wr_list %d\n", ret); 1130250661Sdavidcs break; 1131250661Sdavidcs 1132250661Sdavidcs case Q8_CE_OPCODE_READ_WRITE_LIST: 1133250661Sdavidcs ret = qla_rd_wr_list(ha, ce_hdr); 1134250661Sdavidcs //printf("qla_rd_wr_list %d\n", ret); 1135250661Sdavidcs break; 1136250661Sdavidcs 1137250661Sdavidcs case Q8_CE_OPCODE_POLL_LIST: 1138250661Sdavidcs ret = qla_poll_list(ha, ce_hdr); 1139250661Sdavidcs //printf("qla_poll_list %d\n", ret); 1140250661Sdavidcs break; 1141250661Sdavidcs 1142250661Sdavidcs case Q8_CE_OPCODE_POLL_WRITE_LIST: 1143250661Sdavidcs ret = qla_poll_write_list(ha, ce_hdr); 1144250661Sdavidcs //printf("qla_poll_write_list %d\n", ret); 1145250661Sdavidcs break; 1146250661Sdavidcs 1147250661Sdavidcs case Q8_CE_OPCODE_POLL_RD_LIST: 1148250661Sdavidcs ret = qla_poll_read_list(ha, ce_hdr); 1149250661Sdavidcs //printf("qla_poll_read_list %d\n", ret); 1150250661Sdavidcs break; 1151250661Sdavidcs 1152250661Sdavidcs case Q8_CE_OPCODE_READ_MODIFY_WRITE: 1153250661Sdavidcs ret = qla_read_modify_write_list(ha, ce_hdr); 1154250661Sdavidcs //printf("qla_read_modify_write_list %d\n", ret); 1155250661Sdavidcs break; 1156250661Sdavidcs 1157250661Sdavidcs case Q8_CE_OPCODE_SEQ_PAUSE: 1158250661Sdavidcs if (ce_hdr->delay_to) { 1159250661Sdavidcs qla_mdelay(__func__, ce_hdr->delay_to); 1160250661Sdavidcs } 1161250661Sdavidcs break; 1162250661Sdavidcs 1163250661Sdavidcs case Q8_CE_OPCODE_SEQ_END: 1164250661Sdavidcs proc_end = 1; 1165250661Sdavidcs break; 1166250661Sdavidcs 1167250661Sdavidcs case Q8_CE_OPCODE_TMPLT_END: 1168250661Sdavidcs *end_idx = i; 1169250661Sdavidcs return 0; 1170250661Sdavidcs } 1171250661Sdavidcs 1172250661Sdavidcs if (ret) 1173250661Sdavidcs break; 1174250661Sdavidcs 1175250661Sdavidcs buf += ce_hdr->size; 1176250661Sdavidcs } 1177250661Sdavidcs *end_idx = i; 1178250661Sdavidcs 1179250661Sdavidcs return (ret); 1180250661Sdavidcs} 1181250661Sdavidcs 1182250661Sdavidcs 1183250661Sdavidcsstatic int 1184250661Sdavidcsqla_ld_fw_init(qla_host_t *ha) 1185250661Sdavidcs{ 1186250661Sdavidcs uint8_t *buf; 1187250661Sdavidcs uint32_t index = 0, end_idx; 1188250661Sdavidcs q8_tmplt_hdr_t *hdr; 1189250661Sdavidcs 1190250661Sdavidcs bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq)); 1191250661Sdavidcs 1192250661Sdavidcs hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq; 1193250661Sdavidcs 1194250661Sdavidcs if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq, 1195250661Sdavidcs (uint32_t)hdr->size)) { 1196250661Sdavidcs device_printf(ha->pci_dev, "%s: reset seq checksum failed\n", 1197250661Sdavidcs __func__); 1198250661Sdavidcs return -1; 1199250661Sdavidcs } 1200250661Sdavidcs 1201250661Sdavidcs 1202250661Sdavidcs buf = ql83xx_resetseq + hdr->stop_seq_off; 1203250661Sdavidcs 1204250661Sdavidcs// device_printf(ha->pci_dev, "%s: stop sequence\n", __func__); 1205250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1206250661Sdavidcs device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__); 1207250661Sdavidcs return -1; 1208250661Sdavidcs } 1209250661Sdavidcs 1210250661Sdavidcs index = end_idx; 1211250661Sdavidcs 1212250661Sdavidcs buf = ql83xx_resetseq + hdr->init_seq_off; 1213250661Sdavidcs 1214250661Sdavidcs// device_printf(ha->pci_dev, "%s: init sequence\n", __func__); 1215250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1216250661Sdavidcs device_printf(ha->pci_dev, "%s: init seq failed\n", __func__); 1217250661Sdavidcs return -1; 1218250661Sdavidcs } 1219250661Sdavidcs 1220250661Sdavidcs qla_load_fw_from_flash(ha); 1221250661Sdavidcs WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0); 1222250661Sdavidcs 1223250661Sdavidcs index = end_idx; 1224250661Sdavidcs buf = ql83xx_resetseq + hdr->start_seq_off; 1225250661Sdavidcs 1226250661Sdavidcs// device_printf(ha->pci_dev, "%s: start sequence\n", __func__); 1227250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1228250661Sdavidcs device_printf(ha->pci_dev, "%s: init seq failed\n", __func__); 1229250661Sdavidcs return -1; 1230250661Sdavidcs } 1231250661Sdavidcs 1232250661Sdavidcs return 0; 1233250661Sdavidcs} 1234250661Sdavidcs 1235250661Sdavidcsint 1236250661Sdavidcsql_stop_sequence(qla_host_t *ha) 1237250661Sdavidcs{ 1238250661Sdavidcs uint8_t *buf; 1239250661Sdavidcs uint32_t index = 0, end_idx; 1240250661Sdavidcs q8_tmplt_hdr_t *hdr; 1241250661Sdavidcs 1242250661Sdavidcs bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq)); 1243250661Sdavidcs 1244250661Sdavidcs hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq; 1245250661Sdavidcs 1246250661Sdavidcs if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq, 1247250661Sdavidcs (uint32_t)hdr->size)) { 1248250661Sdavidcs device_printf(ha->pci_dev, "%s: reset seq checksum failed\n", 1249250661Sdavidcs __func__); 1250250661Sdavidcs return (-1); 1251250661Sdavidcs } 1252250661Sdavidcs 1253250661Sdavidcs buf = ql83xx_resetseq + hdr->stop_seq_off; 1254250661Sdavidcs 1255250661Sdavidcs device_printf(ha->pci_dev, "%s: stop sequence\n", __func__); 1256250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1257250661Sdavidcs device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__); 1258250661Sdavidcs return (-1); 1259250661Sdavidcs } 1260250661Sdavidcs 1261250661Sdavidcs return end_idx; 1262250661Sdavidcs} 1263250661Sdavidcs 1264250661Sdavidcsint 1265250661Sdavidcsql_start_sequence(qla_host_t *ha, uint16_t index) 1266250661Sdavidcs{ 1267250661Sdavidcs uint8_t *buf; 1268250661Sdavidcs uint32_t end_idx; 1269250661Sdavidcs q8_tmplt_hdr_t *hdr; 1270250661Sdavidcs 1271250661Sdavidcs bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq)); 1272250661Sdavidcs 1273250661Sdavidcs hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq; 1274250661Sdavidcs 1275250661Sdavidcs if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq, 1276250661Sdavidcs (uint32_t)hdr->size)) { 1277250661Sdavidcs device_printf(ha->pci_dev, "%s: reset seq checksum failed\n", 1278250661Sdavidcs __func__); 1279250661Sdavidcs return (-1); 1280250661Sdavidcs } 1281250661Sdavidcs 1282250661Sdavidcs buf = ql83xx_resetseq + hdr->init_seq_off; 1283250661Sdavidcs 1284250661Sdavidcs device_printf(ha->pci_dev, "%s: init sequence\n", __func__); 1285250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1286250661Sdavidcs device_printf(ha->pci_dev, "%s: init seq failed\n", __func__); 1287250661Sdavidcs return (-1); 1288250661Sdavidcs } 1289250661Sdavidcs 1290250661Sdavidcs qla_load_fw_from_flash(ha); 1291250661Sdavidcs WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0); 1292250661Sdavidcs 1293250661Sdavidcs index = end_idx; 1294250661Sdavidcs buf = ql83xx_resetseq + hdr->start_seq_off; 1295250661Sdavidcs 1296250661Sdavidcs device_printf(ha->pci_dev, "%s: start sequence\n", __func__); 1297250661Sdavidcs if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) { 1298250661Sdavidcs device_printf(ha->pci_dev, "%s: init seq failed\n", __func__); 1299250661Sdavidcs return -1; 1300250661Sdavidcs } 1301250661Sdavidcs 1302250661Sdavidcs return (0); 1303250661Sdavidcs} 1304250661Sdavidcs 1305