freebsd-src/sys/dev/isp/ispreg.h
Joerg Pulz 10ed63fc06 isp(4): Rework firmware handling/loading
Correctly identify the active firmware in flash on adapters with
primary and secondary firmware region in flash.
Correctly identify the active NVRAM on adapters with primary
and secondary NVRAM region in flash.

Loading ispfw(4) moved from isp_pci_attach() to isp_reset().
Drop the reference to ispfw(4) after using it so one can kldunload(8) it.
New isp_load_ram() function to load either ispfw(4) or flash firmware
into RISC's RAM.
New functions to read data from flash. The old ones will be removed later.
A bunch of new helper functions to identify and validate active flash
regions for firmware, auxiliary and NVRAM.
Overhaul ISP_FW_* macros and make use of it when comparing firmware
versions. We can handle firmware versions up to 255.255.255.

Firmware load priority slightly changed:
For 27xx and newer adapters:
- load ispfw(4) firmware
- request (active) flash firmware information
- compare version numbers of ispfw(4) and flash firmware
- load firmware with highest version into RISC's RAM
- if loading ispfw(4) is disabled or failed - load firmware from flash
- if everything else fails use MBOX_LOAD_FLASH_FIRMWARE as fallback

For 26xx and older adapters nothing changed:
- load ispfw(4) firmware and load it into RISC's RAM
- if loading ispfw(4) is disabled or failed use MBOX_EXEC_FIRMWARE
- for 26xx a preceding MBOX_LOAD_FLASH_FIRMWARE is used

New read only sysctl(8)'s:
 dev.isp.N.fw_version_run: the firmware version actually running
 dev.isp.N.fw_version_ispfw: the firmware version provided by ispfw(4)
 dev.isp.N.fw_version_flash: the (active) firmware version in flash

While here:
  - firmware attribute handling/parsing reworked
    + renamed defines from ISP2400_FW_ATTR_* to ISP_FW_ATTR_*
    + changed values to match new handling/parsing
    + added some more attributes
  - enable FLT support on 26xx based adapters
  - log level adjustments
  - new function return status codes (some for now, some for later use)
  - some minor style changes

Tested and approved to work on real hardware with:
  - Qlogic ISP 2532 (QLogic QLE2560 8Gb FC Adapter)
  - Qlogic ISP 2031 (QLogic QLE2662 16Gbit 2Port FC Adapter)
  - Qlogic ISP 2722 (QLogic QLE2690 16Gb FC Adapter)
  - Qlogic ISP 2812 (QLogic QLE2772 32Gbit 2Port FC Adapter)

PR:		273263
Reviewed by:	mav
Pull Request:	https://github.com/freebsd/freebsd-src/pull/877
MFC after:	1 month
Sponsored by:	Technical University of Munich
2023-12-28 13:33:07 -05:00

358 lines
12 KiB
C

/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2020 Alexander Motin <mav@FreeBSD.org>
* Copyright (c) 1997-2009 by Matthew Jacob
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* Machine Independent (well, as best as possible) register
* definitions for Qlogic ISP SCSI adapters.
*/
#ifndef _ISPREG_H
#define _ISPREG_H
/*
* Hardware definitions for the Qlogic ISP registers.
*/
/*
* This defines types of access to various registers.
*
* R: Read Only
* W: Write Only
* RW: Read/Write
*
* R*, W*, RW*: Read Only, Write Only, Read/Write, but only
* if RISC processor in ISP is paused.
*/
/*
* NB: The *_BLOCK definitions have no specific hardware meaning.
* They serve simply to note to the MD layer which block of
* registers offsets are being accessed.
*/
#define _NREG_BLKS 2
#define _BLK_REG_SHFT 7
#define _BLK_REG_MASK (1 << _BLK_REG_SHFT)
#define BIU_BLOCK (0 << _BLK_REG_SHFT)
#define MBOX_BLOCK (1 << _BLK_REG_SHFT)
#define BIU_R2HST_INTR (1 << 15) /* RISC to Host Interrupt */
#define BIU_R2HST_PAUSED (1 << 8) /* RISC paused */
#define BIU_R2HST_ISTAT_MASK 0xff /* intr information && status */
#define ISPR2HST_ROM_MBX_OK 0x1 /* ROM mailbox cmd done ok */
#define ISPR2HST_ROM_MBX_FAIL 0x2 /* ROM mailbox cmd done fail */
#define ISPR2HST_MBX_OK 0x10 /* mailbox cmd done ok */
#define ISPR2HST_MBX_FAIL 0x11 /* mailbox cmd done fail */
#define ISPR2HST_ASYNC_EVENT 0x12 /* Async Event */
#define ISPR2HST_RSPQ_UPDATE 0x13 /* Response Queue Update */
#define ISPR2HST_RSPQ_UPDATE2 0x14 /* Response Queue Update */
#define ISPR2HST_RIO_16 0x15 /* RIO 1-16 */
#define ISPR2HST_FPOST 0x16 /* Low 16 bits fast post */
#define ISPR2HST_FPOST_CTIO 0x17 /* Low 16 bits fast post ctio */
#define ISPR2HST_ATIO_UPDATE 0x1C /* ATIO Queue Update */
#define ISPR2HST_ATIO_RSPQ_UPDATE 0x1D /* ATIO & Request Update */
#define ISPR2HST_ATIO_UPDATE2 0x1E /* ATIO Queue Update */
/*
* 2400 Interface Offsets and Register Definitions
*
* The 2400 looks quite different in terms of registers from other QLogic cards.
* It is getting to be a genuine pain and challenge to keep the same model
* for all.
*/
#define BIU2400_FLASH_ADDR (BIU_BLOCK+0x00) /* Flash Access Address */
#define BIU2400_FLASH_DATA (BIU_BLOCK+0x04) /* Flash Data */
#define BIU2400_CSR (BIU_BLOCK+0x08) /* ISP Control/Status */
#define BIU2400_ICR (BIU_BLOCK+0x0C) /* ISP to PCI Interrupt Control */
#define BIU2400_ISR (BIU_BLOCK+0x10) /* ISP to PCI Interrupt Status */
#define BIU2400_REQINP (BIU_BLOCK+0x1C) /* Request Queue In */
#define BIU2400_REQOUTP (BIU_BLOCK+0x20) /* Request Queue Out */
#define BIU2400_RSPINP (BIU_BLOCK+0x24) /* Response Queue In */
#define BIU2400_RSPOUTP (BIU_BLOCK+0x28) /* Response Queue Out */
#define BIU2400_PRI_REQINP (BIU_BLOCK+0x2C) /* Priority Request Q In */
#define BIU2400_PRI_REQOUTP (BIU_BLOCK+0x30) /* Priority Request Q Out */
#define BIU2400_ATIO_RSPINP (BIU_BLOCK+0x3C) /* ATIO Queue In */
#define BIU2400_ATIO_RSPOUTP (BIU_BLOCK+0x40) /* ATIO Queue Out */
#define BIU2400_R2HSTS (BIU_BLOCK+0x44) /* RISC to Host Status */
#define BIU2400_HCCR (BIU_BLOCK+0x48) /* Host Command and Control Status */
#define BIU2400_GPIOD (BIU_BLOCK+0x4C) /* General Purpose I/O Data */
#define BIU2400_GPIOE (BIU_BLOCK+0x50) /* General Purpose I/O Enable */
#define BIU2400_IOBBA (BIU_BLOCK+0x54) /* I/O Bus Base Address */
#define BIU2400_HSEMA (BIU_BLOCK+0x58) /* Host-to-Host Semaphore */
/* BIU2400_FLASH_ADDR definitions */
#define BIU2400_FLASH_DFLAG (1 << 30)
/* BIU2400_CSR definitions */
#define BIU2400_NVERR (1 << 18)
#define BIU2400_DMA_ACTIVE (1 << 17) /* RO */
#define BIU2400_DMA_STOP (1 << 16)
#define BIU2400_FUNCTION (1 << 15) /* RO */
#define BIU2400_PCIX_MODE(x) (((x) >> 8) & 0xf) /* RO */
#define BIU2400_CSR_64BIT (1 << 2) /* RO */
#define BIU2400_FLASH_ENABLE (1 << 1)
#define BIU2400_SOFT_RESET (1 << 0)
/* BIU2400_ICR definitions */
#define BIU2400_ICR_ENA_RISC_INT 0x8
#define BIU2400_IMASK (BIU2400_ICR_ENA_RISC_INT)
/* BIU2400_ISR definitions */
#define BIU2400_ISR_RISC_INT 0x8
/* BIU2400_HCCR definitions */
#define HCCR_2400_CMD_NOP 0x00000000
#define HCCR_2400_CMD_RESET 0x10000000
#define HCCR_2400_CMD_CLEAR_RESET 0x20000000
#define HCCR_2400_CMD_PAUSE 0x30000000
#define HCCR_2400_CMD_RELEASE 0x40000000
#define HCCR_2400_CMD_SET_HOST_INT 0x50000000
#define HCCR_2400_CMD_CLEAR_HOST_INT 0x60000000
#define HCCR_2400_CMD_CLEAR_RISC_INT 0xA0000000
#define HCCR_2400_RISC_ERR(x) (((x) >> 12) & 0x7) /* RO */
#define HCCR_2400_RISC2HOST_INT (1 << 6) /* RO */
#define HCCR_2400_RISC_RESET (1 << 5) /* RO */
/*
* Mailbox Block Register Offsets
*/
#define INMAILBOX0 (MBOX_BLOCK+0x0)
#define INMAILBOX1 (MBOX_BLOCK+0x2)
#define INMAILBOX2 (MBOX_BLOCK+0x4)
#define INMAILBOX3 (MBOX_BLOCK+0x6)
#define INMAILBOX4 (MBOX_BLOCK+0x8)
#define INMAILBOX5 (MBOX_BLOCK+0xA)
#define INMAILBOX6 (MBOX_BLOCK+0xC)
#define INMAILBOX7 (MBOX_BLOCK+0xE)
#define OUTMAILBOX0 (MBOX_BLOCK+0x0)
#define OUTMAILBOX1 (MBOX_BLOCK+0x2)
#define OUTMAILBOX2 (MBOX_BLOCK+0x4)
#define OUTMAILBOX3 (MBOX_BLOCK+0x6)
#define OUTMAILBOX4 (MBOX_BLOCK+0x8)
#define OUTMAILBOX5 (MBOX_BLOCK+0xA)
#define OUTMAILBOX6 (MBOX_BLOCK+0xC)
#define OUTMAILBOX7 (MBOX_BLOCK+0xE)
#define MBOX_OFF(n) (MBOX_BLOCK + ((n) << 1))
#define ISP_NMBOX(isp) 32
#define MAX_MAILBOX 32
/* if timeout == 0, then default timeout is picked */
#define MBCMD_DEFAULT_TIMEOUT 100000 /* 100 ms */
typedef struct {
uint16_t param[MAX_MAILBOX];
uint32_t ibits; /* bits to add for register copyin */
uint32_t obits; /* bits to add for register copyout */
uint32_t ibitm; /* bits to mask for register copyin */
uint32_t obitm; /* bits to mask for register copyout */
uint32_t logval; /* Bitmask of status codes to log */
uint32_t timeout;
uint32_t lineno;
const char *func;
} mbreg_t;
#define MBSINIT(mbxp, code, loglev, timo) \
ISP_MEMZERO((mbxp), sizeof (mbreg_t)); \
(mbxp)->ibitm = ~0; \
(mbxp)->obitm = ~0; \
(mbxp)->param[0] = code; \
(mbxp)->lineno = __LINE__; \
(mbxp)->func = __func__; \
(mbxp)->logval = loglev; \
(mbxp)->timeout = timo
/*
* Defines for Interrupts
*/
#define ISP_INTS_ENABLED(isp) \
(ISP_READ(isp, BIU2400_ICR) & BIU2400_IMASK)
#define ISP_ENABLE_INTS(isp) \
ISP_WRITE(isp, BIU2400_ICR, BIU2400_IMASK)
#define ISP_DISABLE_INTS(isp) \
ISP_WRITE(isp, BIU2400_ICR, 0)
/*
* NVRAM Definitions (PCI cards only)
*/
/*
* Qlogic 2400 NVRAM is an array of 512 bytes with a 32 bit checksum.
*/
#define ISP2400_NVRAM_PORT_ADDR(c) (0x100 * (c) + 0x80)
#define ISP2400_NVRAM_SIZE 512
#define ISP2400_NVRAM_VERSION(c) ((c)[4] | ((c)[5] << 8))
#define ISP2400_NVRAM_MAXFRAMELENGTH(c) (((c)[12]) | ((c)[13] << 8))
#define ISP2400_NVRAM_HARDLOOPID(c) ((c)[18] | ((c)[19] << 8))
#define ISP2400_NVRAM_PORT_NAME(c) (\
(((uint64_t)(c)[20]) << 56) | \
(((uint64_t)(c)[21]) << 48) | \
(((uint64_t)(c)[22]) << 40) | \
(((uint64_t)(c)[23]) << 32) | \
(((uint64_t)(c)[24]) << 24) | \
(((uint64_t)(c)[25]) << 16) | \
(((uint64_t)(c)[26]) << 8) | \
(((uint64_t)(c)[27]) << 0))
#define ISP2400_NVRAM_NODE_NAME(c) (\
(((uint64_t)(c)[28]) << 56) | \
(((uint64_t)(c)[29]) << 48) | \
(((uint64_t)(c)[30]) << 40) | \
(((uint64_t)(c)[31]) << 32) | \
(((uint64_t)(c)[32]) << 24) | \
(((uint64_t)(c)[33]) << 16) | \
(((uint64_t)(c)[34]) << 8) | \
(((uint64_t)(c)[35]) << 0))
#define ISP2400_NVRAM_LOGIN_RETRY_CNT(c) ((c)[36] | ((c)[37] << 8))
#define ISP2400_NVRAM_LINK_DOWN_ON_NOS(c) ((c)[38] | ((c)[39] << 8))
#define ISP2400_NVRAM_INTERRUPT_DELAY(c) ((c)[40] | ((c)[41] << 8))
#define ISP2400_NVRAM_LOGIN_TIMEOUT(c) ((c)[42] | ((c)[43] << 8))
#define ISP2400_NVRAM_FIRMWARE_OPTIONS1(c) \
((c)[44] | ((c)[45] << 8) | ((c)[46] << 16) | ((c)[47] << 24))
#define ISP2400_NVRAM_FIRMWARE_OPTIONS2(c) \
((c)[48] | ((c)[49] << 8) | ((c)[50] << 16) | ((c)[51] << 24))
#define ISP2400_NVRAM_FIRMWARE_OPTIONS3(c) \
((c)[52] | ((c)[53] << 8) | ((c)[54] << 16) | ((c)[55] << 24))
/*
* Qlogic FLT
*/
#define ISP24XX_BASE_ADDR 0x7ff00000
#define ISP24XX_FLT_ADDR 0x11400
#define ISP25XX_BASE_ADDR ISP24XX_BASE_ADDR
#define ISP25XX_FLT_ADDR 0x50400
#define ISP27XX_BASE_ADDR 0x7f800000
#define ISP27XX_FLT_ADDR (0x3F1000 / 4)
#define ISP28XX_BASE_ADDR 0x7f7d0000
#define ISP28XX_FLT_ADDR (0x11000 / 4)
#define FLT_HEADER_SIZE 8
#define FLT_REGION_SIZE 16
#define FLT_MAX_REGIONS 0xFF
#define FLT_REGIONS_SIZE (FLT_REGION_SIZE * FLT_MAX_REGIONS)
#define ISP2XXX_FLT_VERSION(c) ((c)[0] | ((c)[1] << 8))
#define ISP2XXX_FLT_LENGTH(c) ((c)[2] | ((c)[3] << 8))
#define ISP2XXX_FLT_CSUM(c) ((c)[4] | ((c)[5] << 8))
#define ISP2XXX_FLT_REG_CODE(c, o) \
((c)[0 + FLT_REGION_SIZE * o] | ((c)[1 + FLT_REGION_SIZE * o] << 8))
#define ISP2XXX_FLT_REG_ATTR(c, o) ((c)[2 + FLT_REGION_SIZE * o])
#define ISP2XXX_FLT_REG_RES(c, o) ((c)[3 + FLT_REGION_SIZE * o])
#define ISP2XXX_FLT_REG_SIZE(c, o) (\
((uint32_t)(c)[4 + FLT_REGION_SIZE * o] << 0) | \
((uint32_t)(c)[5 + FLT_REGION_SIZE * o] << 8) | \
((uint32_t)(c)[6 + FLT_REGION_SIZE * o] << 16) | \
((uint32_t)(c)[7 + FLT_REGION_SIZE * o] << 24))
#define ISP2XXX_FLT_REG_START(c, o) (\
((uint32_t)(c)[8 + FLT_REGION_SIZE * o] << 0) | \
((uint32_t)(c)[9 + FLT_REGION_SIZE * o] << 8) | \
((uint32_t)(c)[10 + FLT_REGION_SIZE * o] << 16) | \
((uint32_t)(c)[11 + FLT_REGION_SIZE * o] << 24))
#define ISP2XXX_FLT_REG_END(c, o) (\
((uint32_t)(c)[12 + FLT_REGION_SIZE * o] << 0) | \
((uint32_t)(c)[13 + FLT_REGION_SIZE * o] << 8) | \
((uint32_t)(c)[14 + FLT_REGION_SIZE * o] << 16) | \
((uint32_t)(c)[15 + FLT_REGION_SIZE * o] << 24))
struct flt_region {
uint16_t code;
uint8_t attribute;
uint8_t reserved;
uint32_t size;
uint32_t start;
uint32_t end;
};
#define FLT_REG_FW 0x01
#define FLT_REG_BOOT_CODE 0x07
#define FLT_REG_VPD_0 0x14
#define FLT_REG_NVRAM_0 0x15
#define FLT_REG_VPD_1 0x16
#define FLT_REG_NVRAM_1 0x17
#define FLT_REG_VPD_2 0xd4
#define FLT_REG_NVRAM_2 0xd5
#define FLT_REG_VPD_3 0xd6
#define FLT_REG_NVRAM_3 0xd7
#define FLT_REG_FDT 0x1a
#define FLT_REG_FLT 0x1c
#define FLT_REG_NPIV_CONF_0 0x29
#define FLT_REG_NPIV_CONF_1 0x2a
#define FLT_REG_GOLD_FW 0x2f
#define FLT_REG_FCP_PRIO_0 0x87
#define FLT_REG_FCP_PRIO_1 0x88
/* 27xx */
#define FLT_REG_IMG_PRI_27XX 0x95
#define FLT_REG_IMG_SEC_27XX 0x96
#define FLT_REG_FW_SEC_27XX 0x02
#define FLT_REG_BOOTLOAD_SEC_27XX 0x9
#define FLT_REG_VPD_SEC_27XX_0 0x50
#define FLT_REG_VPD_SEC_27XX_1 0x52
#define FLT_REG_VPD_SEC_27XX_2 0xd8
#define FLT_REG_VPD_SEC_27XX_3 0xda
/* 28xx */
#define FLT_REG_AUX_IMG_PRI_28XX 0x125
#define FLT_REG_AUX_IMG_SEC_28XX 0x126
#define FLT_REG_NVRAM_SEC_28XX_0 0x10d
#define FLT_REG_NVRAM_SEC_28XX_1 0x10f
#define FLT_REG_NVRAM_SEC_28XX_2 0x111
#define FLT_REG_NVRAM_SEC_28XX_3 0x113
#define FLT_REG_VPD_SEC_28XX_0 0x10c
#define FLT_REG_VPD_SEC_28XX_1 0x10e
#define FLT_REG_VPD_SEC_28XX_2 0x110
#define FLT_REG_VPD_SEC_28XX_3 0x112
#define ISP27XX_IMG_STATUS_VER_MAJOR 0x01
#define ISP27XX_IMG_STATUS_VER_MINOR 0x00
#define ISP27XX_IMG_STATUS_SIGN 0xfacefade
#define ISP28XX_IMG_STATUS_SIGN 0xfacefadf
#define ISP28XX_AUX_IMG_STATUS_SIGN 0xfacefaed
#define ISP27XX_DEFAULT_IMAGE 0
#define ISP27XX_PRIMARY_IMAGE 1
#define ISP27XX_SECONDARY_IMAGE 2
#define ISP_RISC_CODE_SEGMENTS 2
#endif /* _ISPREG_H */