9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CDDL HEADER START
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The contents of this file are subject to the terms of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Common Development and Distribution License (the "License").
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * You may not use this file except in compliance with the License.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * or http://www.opensolaris.org/os/licensing.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * See the License for the specific language governing permissions
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and limitations under the License.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * When distributing Covered Code, include this CDDL HEADER in each
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If applicable, add the following below this CDDL HEADER, with the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fields enclosed by brackets "[]" replaced with your own identifying
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information: Portions Copyright [yyyy] [name of copyright owner]
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CDDL HEADER END
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl.c
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Hemron IOCTL Routines
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Implements all ioctl access into the driver. This includes all routines
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * necessary for updating firmware, accessing the hermon flash device, and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * providing interfaces for VTS.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/types.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/conf.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/ddi.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/sunddi.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/modctl.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/file.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/ib/adapters/hermon/hermon.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Hemron HCA state pointer (extern) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorextern void *hermon_statep;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorextern int hermon_verbose;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#define DO_WRCONF 1
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int do_bar0 = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The ioctl declarations (for firmware flash burning, register read/write
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (DEBUG-only), and VTS interfaces)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_flash_read(hermon_state_t *state, dev_t dev,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor intptr_t arg, int mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_flash_write(hermon_state_t *state, dev_t dev,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor intptr_t arg, int mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_flash_erase(hermon_state_t *state, dev_t dev,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor intptr_t arg, int mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_flash_init(hermon_state_t *state, dev_t dev,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor intptr_t arg, int mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_flash_fini(hermon_state_t *state, dev_t dev);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_flash_cleanup(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_flash_cleanup_nolock(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef DEBUG
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_reg_write(hermon_state_t *state, intptr_t arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_reg_read(hermon_state_t *state, intptr_t arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* DEBUG */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_write_boot_addr(hermon_state_t *state, dev_t dev,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor intptr_t arg, int mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_info(hermon_state_t *state, dev_t dev,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor intptr_t arg, int mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_ports(hermon_state_t *state, intptr_t arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_ioctl_loopback(hermon_state_t *state, intptr_t arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Hemron Flash Functions */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_flash_spi_exec_command(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl, uint32_t cmd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_read_sector(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t sector_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_read_quadlet(hermon_state_t *state, uint32_t *data,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t addr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_write_sector(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t sector_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_spi_write_dword(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t addr, uint32_t data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_write_byte(hermon_state_t *state, uint32_t addr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uchar_t data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_erase_sector(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t sector_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_erase_chip(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_bank(hermon_state_t *state, uint32_t addr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic uint32_t hermon_flash_read(hermon_state_t *state, uint32_t addr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int *err);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_flash_write(hermon_state_t *state, uint32_t addr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uchar_t data, int *err);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_spi_wait_wip(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_flash_spi_write_enable(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_init(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_cfi_init(hermon_state_t *state, uint32_t *cfi_info,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int *intel_xcmd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_fini(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_flash_reset(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic uint32_t hermon_flash_read_cfg(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_config_hdl, uint32_t addr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef DO_WRCONF
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_flash_write_cfg(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_config_hdl, uint32_t addr, uint32_t data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_flash_write_cfg_helper(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_config_hdl, uint32_t addr, uint32_t data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_flash_write_confirm(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_config_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_flash_cfi_byte(uint8_t *ch, uint32_t dword, int i);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_flash_cfi_dword(uint32_t *dword, uint8_t *ch, int i);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Hemron loopback test functions */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_loopback_free_qps(hermon_loopback_state_t *lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_loopback_free_state(hermon_loopback_state_t *lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_loopback_init(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_state_t *lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_loopback_init_qp_info(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *comm);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_loopback_alloc_mem(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *comm, int sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_loopback_alloc_qps(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *comm);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_loopback_modify_qp(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *comm, uint_t qp_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_loopback_copyout(hermon_loopback_ioctl_t *lb,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor intptr_t arg, int mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_loopback_post_send(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *tx, hermon_loopback_comm_t *rx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_loopback_poll_cq(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *comm);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Patchable timeout values for flash operations */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint hermon_hw_flash_timeout_gpio_sema = HERMON_HW_FLASH_TIMEOUT_GPIO_SEMA;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint hermon_hw_flash_timeout_config = HERMON_HW_FLASH_TIMEOUT_CONFIG;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint hermon_hw_flash_timeout_write = HERMON_HW_FLASH_TIMEOUT_WRITE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint hermon_hw_flash_timeout_erase = HERMON_HW_FLASH_TIMEOUT_ERASE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int *rvalp)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_state_t *state;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor minor_t instance;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (drv_priv(credp) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EPERM);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor instance = HERMON_DEV_INSTANCE(dev);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (instance == (minor_t)-1) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EBADF);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state = ddi_get_soft_state(hermon_statep, instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EBADF);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (cmd) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_FLASH_READ:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_flash_read(state, dev, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_FLASH_WRITE:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_flash_write(state, dev, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_FLASH_ERASE:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_flash_erase(state, dev, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_FLASH_INIT:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_flash_init(state, dev, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_FLASH_FINI:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_flash_fini(state, dev);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_INFO:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_info(state, dev, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_PORTS:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_ports(state, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_LOOPBACK:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_loopback(state, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef DEBUG
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_REG_WRITE:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_reg_write(state, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_REG_READ:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_reg_read(state, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* DEBUG */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_DDR_READ:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* XXX guard until the ioctl header is cleaned up */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ENODEV;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_IOCTL_WRITE_BOOT_ADDR:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_write_boot_addr(state, dev, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ENOTTY;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *rvalp = status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_flash_read()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_flash_read(hermon_state_t *state, dev_t dev, intptr_t arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int mode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_ioctl_t ioctl_info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check that flash init ioctl has been called first. And check
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that the same dev_t that called init is the one calling read now.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((state->hs_fw_flashdev != dev) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_fw_flashstarted == 0)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* copy user struct to kernel */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _MULTI_DATAMODEL
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_ioctl32_t info32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &info32,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_flash_ioctl32_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_type = info32.af_type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_sector = (caddr_t)(uintptr_t)info32.af_sector;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_sector_num = info32.af_sector_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_addr = info32.af_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* _MULTI_DATAMODEL */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &ioctl_info, sizeof (hermon_flash_ioctl_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine type of READ ioctl
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (ioctl_info.af_type) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_READ_SECTOR:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check if sector num is too large for flash device */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ioctl_info.af_sector_num >=
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_fw_device_sz >> state->hs_fw_log_sector_sz)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Perform the Sector Read */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_reset(state)) != 0 ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (status = hermon_flash_read_sector(state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_sector_num)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* copyout the firmware sector image data */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(&state->hs_fw_sector[0],
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &ioctl_info.af_sector[0], 1 << state->hs_fw_log_sector_sz,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_READ_QUADLET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check if addr is too large for flash device */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ioctl_info.af_addr >= state->hs_fw_device_sz) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Perform the Quadlet Read */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_reset(state)) != 0 ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (status = hermon_flash_read_quadlet(state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &ioctl_info.af_quadlet, ioctl_info.af_addr)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* copy results back to userland */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _MULTI_DATAMODEL
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_ioctl32_t info32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info32.af_quadlet = ioctl_info.af_quadlet;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info32.af_type = ioctl_info.af_type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info32.af_sector_num = ioctl_info.af_sector_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info32.af_sector = (caddr32_t)(uintptr_t)ioctl_info.af_sector;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info32.af_addr = ioctl_info.af_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(&info32, (void *)arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_flash_ioctl32_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* _MULTI_DATAMODEL */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(&ioctl_info, (void *)arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_flash_ioctl_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_flash_write()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_flash_write(hermon_state_t *state, dev_t dev, intptr_t arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int mode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_ioctl_t ioctl_info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check that flash init ioctl has been called first. And check
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that the same dev_t that called init is the one calling write now.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((state->hs_fw_flashdev != dev) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_fw_flashstarted == 0)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* copy user struct to kernel */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _MULTI_DATAMODEL
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_ioctl32_t info32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &info32,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_flash_ioctl32_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_type = info32.af_type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_sector = (caddr_t)(uintptr_t)info32.af_sector;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_sector_num = info32.af_sector_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_addr = info32.af_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_byte = info32.af_byte;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* _MULTI_DATAMODEL */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &ioctl_info,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_flash_ioctl_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine type of WRITE ioctl
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (ioctl_info.af_type) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_WRITE_SECTOR:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check if sector num is too large for flash device */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ioctl_info.af_sector_num >=
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_fw_device_sz >> state->hs_fw_log_sector_sz)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* copy in fw sector image data */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin(&ioctl_info.af_sector[0],
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_fw_sector[0], 1 << state->hs_fw_log_sector_sz,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Perform Write Sector */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_write_sector(state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_sector_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_WRITE_BYTE:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check if addr is too large for flash device */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ioctl_info.af_addr >= state->hs_fw_device_sz) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Perform Write Byte */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CMJ -- is a reset really needed before and after writing
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * each byte? This code came from arbel, but we should look
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * into this. Also, for SPI, no reset is actually performed.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_bank(state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_addr)) != 0 ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (status = hermon_flash_reset(state)) != 0 ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (status = hermon_flash_write_byte(state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_addr, ioctl_info.af_byte)) != 0 ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (status = hermon_flash_reset(state)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = EINVAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_flash_erase()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_flash_erase(hermon_state_t *state, dev_t dev, intptr_t arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int mode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_ioctl_t ioctl_info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check that flash init ioctl has been called first. And check
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that the same dev_t that called init is the one calling erase now.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((state->hs_fw_flashdev != dev) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_fw_flashstarted == 0)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* copy user struct to kernel */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _MULTI_DATAMODEL
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_ioctl32_t info32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &info32,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_flash_ioctl32_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_type = info32.af_type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_sector_num = info32.af_sector_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* _MULTI_DATAMODEL */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &ioctl_info, sizeof (hermon_flash_ioctl_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine type of ERASE ioctl
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (ioctl_info.af_type) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_ERASE_SECTOR:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check if sector num is too large for flash device */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ioctl_info.af_sector_num >=
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_fw_device_sz >> state->hs_fw_log_sector_sz)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Perform Sector Erase */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_erase_sector(state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_sector_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_ERASE_CHIP:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Perform Chip Erase */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_erase_chip(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = EINVAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_flash_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_flash_init(hermon_state_t *state, dev_t dev, intptr_t arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int mode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_init_ioctl_t init_info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int ret;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int intel_xcmd = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_sector = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * init cannot be called more than once. If we have already init'd the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * flash, return directly.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fw_flashstarted == 1) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* copyin the user struct to kernel */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &init_info,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_flash_init_ioctl_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Init Flash */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((ret = hermon_flash_init(state)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ret == EIO) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto pio_error;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ret);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Read CFI info */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((ret = hermon_flash_cfi_init(state, &init_info.af_cfi_info[0],
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &intel_xcmd)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ret == EIO) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto pio_error;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ret);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Return error if the command set is unknown.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fw_cmdset == HERMON_FLASH_UNKNOWN_CMDSET) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((ret = hermon_ioctl_flash_cleanup_nolock(state)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ret == EIO) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto pio_error;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ret);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, pci_hdl, pio_error,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Read HWREV - least significant 8 bits is revision ID */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_info.af_hwrev = pci_config_get32(pci_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_CFG_HWREV) & 0xFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, pci_hdl, pio_error, fm_loop_cnt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Fill in the firmwate revision numbers */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_info.af_fwrev.afi_maj = state->hs_fw.fw_rev_major;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_info.af_fwrev.afi_min = state->hs_fw.fw_rev_minor;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_info.af_fwrev.afi_sub = state->hs_fw.fw_rev_subminor;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Alloc flash mem for one sector size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_sector = (uint32_t *)kmem_zalloc(1 <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_log_sector_sz, KM_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set HW part number and length */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_info.af_pn_len = state->hs_hca_pn_len;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_hca_pn_len != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) memcpy(init_info.af_hwpn, state->hs_hca_pn,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_hca_pn_len);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Copy ioctl results back to userland */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(&init_info, (void *)arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_flash_init_ioctl_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((ret = hermon_ioctl_flash_cleanup_nolock(state)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ret == EIO) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto pio_error;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ret);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set flash state to started */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_flashstarted = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_flashdev = dev;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If "flash init" is successful, add an "on close" callback to the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * current dev node to ensure that "flash fini" gets called later
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * even if the userland process prematurely exits.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ret = hermon_umap_db_set_onclose_cb(dev,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ONCLOSE_FLASH_INPROGRESS,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (int (*)(void *))hermon_ioctl_flash_cleanup, state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ret != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status = hermon_ioctl_flash_fini(state, dev);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == EIO) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_flash_fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_flash_fini(hermon_state_t *state, dev_t dev)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int ret;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check that flash init ioctl has been called first. And check
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that the same dev_t that called init is the one calling fini now.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((state->hs_fw_flashdev != dev) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_fw_flashstarted == 0)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((ret = hermon_ioctl_flash_cleanup_nolock(state)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ret == EIO) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ret);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If "flash fini" is successful, remove the "on close" callback
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that was setup during "flash init".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ret = hermon_umap_db_clear_onclose_cb(dev,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ONCLOSE_FLASH_INPROGRESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ret != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_flash_cleanup()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_flash_cleanup(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_ioctl_flash_cleanup_nolock(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_flash_cleanup_nolock()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_flash_cleanup_nolock(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(MUTEX_HELD(&state->hs_fw_flashlock));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* free flash mem */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fw_sector) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(state->hs_fw_sector, 1 << state->hs_fw_log_sector_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Fini the Flash */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_fini(state)) != 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set flash state to fini */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_flashstarted = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_flashdev = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_info()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_info(hermon_state_t *state, dev_t dev, intptr_t arg, int mode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_info_ioctl_t info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_init_ioctl_t init_info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Access to Hemron VTS ioctls is not allowed in "maintenance mode".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_operational_mode == HERMON_MAINTENANCE_MODE) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* copyin the user struct to kernel */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &info, sizeof (hermon_info_ioctl_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check ioctl revision
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (info.ai_revision != HERMON_VTS_IOCTL_REVISION) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the 'fw_device_sz' has not been initialized yet, we initialize it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * here. This is done by leveraging the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_flash_init()/fini() calls. We also hold our own mutex
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * around this operation in case we have multiple VTS threads in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * process at the same time.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&state->hs_info_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fw_device_sz == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_ioctl_flash_init(state, dev, (intptr_t)&init_info,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (FKIOCTL | mode)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_info_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_ioctl_flash_fini(state, dev);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_info_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info.ai_hw_rev = state->hs_revision_id;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info.ai_flash_sz = state->hs_fw_device_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info.ai_fw_rev.afi_maj = state->hs_fw.fw_rev_major;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info.ai_fw_rev.afi_min = state->hs_fw.fw_rev_minor;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info.ai_fw_rev.afi_sub = state->hs_fw.fw_rev_subminor;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Copy ioctl results back to user struct */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(&info, (void *)arg, sizeof (hermon_info_ioctl_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_ports()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_ports(hermon_state_t *state, intptr_t arg, int mode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_ports_ioctl_t info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_stat_port_ioctl_t portstat;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_hca_portinfo_t pi;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t tbl_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_gid_t *sgid_tbl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_pkey_t *pkey_tbl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Access to Hemron VTS ioctls is not allowed in "maintenance mode".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_operational_mode == HERMON_MAINTENANCE_MODE) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* copyin the user struct to kernel */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _MULTI_DATAMODEL
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_ports_ioctl32_t info32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &info32,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_ports_ioctl32_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info.ap_revision = info32.ap_revision;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info.ap_ports =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (hermon_stat_port_ioctl_t *)(uintptr_t)info32.ap_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info.ap_num_ports = info32.ap_num_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* _MULTI_DATAMODEL */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &info, sizeof (hermon_ports_ioctl_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check ioctl revision
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (info.ap_revision != HERMON_VTS_IOCTL_REVISION) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate space for temporary GID table/PKey table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = (1 << state->hs_cfg_profile->cp_log_max_gidtbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgid_tbl = (ib_gid_t *)kmem_zalloc(tbl_size * sizeof (ib_gid_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor KM_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = (1 << state->hs_cfg_profile->cp_log_max_pkeytbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pkey_tbl = (ib_pkey_t *)kmem_zalloc(tbl_size * sizeof (ib_pkey_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor KM_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sgid_tbl, *pkey_tbl))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Setup the number of ports, then loop through all ports and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * query properties of each.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info.ap_num_ports = (uint8_t)state->hs_cfg_profile->cp_num_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < info.ap_num_ports; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Get portstate information from the device. If
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_port_query() fails, leave zeroes in user
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * struct port entry and continue.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&pi, sizeof (ibt_hca_portinfo_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi.p_sgid_tbl = sgid_tbl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi.p_pkey_tbl = pkey_tbl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_port_query(state, i + 1, &pi);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor portstat.asp_port_num = pi.p_port_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor portstat.asp_state = pi.p_linkstate;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor portstat.asp_guid = pi.p_sgid_tbl[0].gid_guid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Copy queried port results back to user struct. If
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * this fails, then break out of loop, attempt to copy
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * out remaining info to user struct, and return (without
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * error).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(&portstat,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &(((hermon_stat_port_ioctl_t *)info.ap_ports)[i]),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_stat_port_ioctl_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the temporary space used for GID table/PKey table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = (1 << state->hs_cfg_profile->cp_log_max_gidtbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(sgid_tbl, tbl_size * sizeof (ib_gid_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = (1 << state->hs_cfg_profile->cp_log_max_pkeytbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(pkey_tbl, tbl_size * sizeof (ib_pkey_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Copy ioctl results back to user struct */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _MULTI_DATAMODEL
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_ports_ioctl32_t info32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info32.ap_revision = info.ap_revision;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info32.ap_ports = (caddr32_t)(uintptr_t)info.ap_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor info32.ap_num_ports = info.ap_num_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(&info32, (void *)arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_ports_ioctl32_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* _MULTI_DATAMODEL */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(&info, (void *)arg, sizeof (hermon_ports_ioctl_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_loopback()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_loopback(hermon_state_t *state, intptr_t arg, int mode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_ioctl_t lb;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_state_t lstate;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_hca_portinfo_t pi;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t tbl_size, loopmax, max_usec;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_gid_t *sgid_tbl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ib_pkey_t *pkey_tbl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int j, iter, ret;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(lstate))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Access to Hemron VTS ioctls is not allowed in "maintenance mode".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_operational_mode == HERMON_MAINTENANCE_MODE) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* copyin the user struct to kernel */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _MULTI_DATAMODEL
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_ioctl32_t lb32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &lb32,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_loopback_ioctl32_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_revision = lb32.alb_revision;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_send_buf = (caddr_t)(uintptr_t)lb32.alb_send_buf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_fail_buf = (caddr_t)(uintptr_t)lb32.alb_fail_buf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_buf_sz = lb32.alb_buf_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_num_iter = lb32.alb_num_iter;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_pass_done = lb32.alb_pass_done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_timeout = lb32.alb_timeout;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = lb32.alb_error_type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_port_num = lb32.alb_port_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_num_retry = lb32.alb_num_retry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* _MULTI_DATAMODEL */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &lb, sizeof (hermon_loopback_ioctl_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the internal loopback test state structure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&lstate, sizeof (hermon_loopback_state_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check ioctl revision
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lb.alb_revision != HERMON_VTS_IOCTL_REVISION) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = HERMON_LOOPBACK_INVALID_REVISION;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Validate that specified port number is legal */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!hermon_portnum_is_valid(state, lb.alb_port_num)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = HERMON_LOOPBACK_INVALID_PORT;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate space for temporary GID table/PKey table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = (1 << state->hs_cfg_profile->cp_log_max_gidtbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sgid_tbl = (ib_gid_t *)kmem_zalloc(tbl_size * sizeof (ib_gid_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor KM_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = (1 << state->hs_cfg_profile->cp_log_max_pkeytbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pkey_tbl = (ib_pkey_t *)kmem_zalloc(tbl_size * sizeof (ib_pkey_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor KM_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Get portstate information from specific port on device
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&pi, sizeof (ibt_hca_portinfo_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi.p_sgid_tbl = sgid_tbl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pi.p_pkey_tbl = pkey_tbl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_port_query(state, lb.alb_port_num, &pi) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the temporary space used for GID table/PKey table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = (1 << state->hs_cfg_profile->cp_log_max_gidtbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(sgid_tbl, tbl_size * sizeof (ib_gid_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = (1 << state->hs_cfg_profile->cp_log_max_pkeytbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(pkey_tbl, tbl_size * sizeof (ib_pkey_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = HERMON_LOOPBACK_INVALID_PORT;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_port = pi.p_port_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_lid = pi.p_base_lid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_pkey_ix = (pi.p_linkstate == HERMON_PORT_LINK_ACTIVE) ?
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 1 : 0; /* XXX bogus assumption of a SUN subnet manager */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_state = state;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_retry = lb.alb_num_retry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the temporary space used for GID table/PKey table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = (1 << state->hs_cfg_profile->cp_log_max_gidtbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(sgid_tbl, tbl_size * sizeof (ib_gid_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tbl_size = (1 << state->hs_cfg_profile->cp_log_max_pkeytbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(pkey_tbl, tbl_size * sizeof (ib_pkey_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Compute the timeout duration in usec per the formula:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to_usec_per_retry = 4.096us * (2 ^ supplied_timeout)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (plus we add a little fudge-factor here too)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_timeout = lb.alb_timeout;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor max_usec = (4096 * (1 << lstate.hls_timeout)) / 1000;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor max_usec = max_usec * (lstate.hls_retry + 1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor max_usec = max_usec + 10000;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine how many times we should loop before declaring a
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * timeout failure.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor loopmax = max_usec/HERMON_VTS_LOOPBACK_MIN_WAIT_DUR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((max_usec % HERMON_VTS_LOOPBACK_MIN_WAIT_DUR) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor loopmax++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lb.alb_send_buf == NULL || lb.alb_buf_sz == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = HERMON_LOOPBACK_SEND_BUF_INVALID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate protection domain (PD) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_loopback_init(state, &lstate) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = lstate.hls_err;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate and register a TX buffer */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_loopback_alloc_mem(&lstate, &lstate.hls_tx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_buf_sz) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_LOOPBACK_SEND_BUF_MEM_REGION_ALLOC_FAIL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate and register an RX buffer */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_loopback_alloc_mem(&lstate, &lstate.hls_rx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_buf_sz) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_LOOPBACK_RECV_BUF_MEM_REGION_ALLOC_FAIL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Copy in the transmit buffer data */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)lb.alb_send_buf, lstate.hls_tx.hlc_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_buf_sz, mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = HERMON_LOOPBACK_SEND_BUF_COPY_FAIL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate the transmit QP and CQs */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_err = HERMON_LOOPBACK_XMIT_SEND_CQ_ALLOC_FAIL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_loopback_alloc_qps(&lstate, &lstate.hls_tx) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = lstate.hls_err;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate the receive QP and CQs */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_err = HERMON_LOOPBACK_RECV_SEND_CQ_ALLOC_FAIL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_loopback_alloc_qps(&lstate, &lstate.hls_rx) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = lstate.hls_err;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Activate the TX QP (connect to RX QP) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_err = HERMON_LOOPBACK_XMIT_QP_INIT_FAIL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_loopback_modify_qp(&lstate, &lstate.hls_tx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_rx.hlc_qp_num) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = lstate.hls_err;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Activate the RX QP (connect to TX QP) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_err = HERMON_LOOPBACK_RECV_QP_INIT_FAIL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_loopback_modify_qp(&lstate, &lstate.hls_rx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_tx.hlc_qp_num) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = lstate.hls_err;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Run the loopback test (for specified number of iterations) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_pass_done = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (iter = 0; iter < lb.alb_num_iter; iter++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_err = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(lstate.hls_rx.hlc_buf, lb.alb_buf_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Post RDMA Write work request */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_loopback_post_send(&lstate, &lstate.hls_tx,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &lstate.hls_rx) != IBT_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = HERMON_LOOPBACK_WQE_POST_FAIL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Poll the TX CQ for a completion every few ticks */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = 0; j < loopmax; j++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor delay(drv_usectohz(HERMON_VTS_LOOPBACK_MIN_WAIT_DUR));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ret = hermon_loopback_poll_cq(&lstate, &lstate.hls_tx);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (((ret != IBT_SUCCESS) && (ret != IBT_CQ_EMPTY)) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((ret == IBT_CQ_EMPTY) && (j == loopmax - 1))) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_LOOPBACK_CQ_POLL_FAIL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(lstate.hls_rx.hlc_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_fail_buf, lstate.hls_tx.hlc_buf_sz,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (ret == IBT_CQ_EMPTY) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Compare the data buffers */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (bcmp(lstate.hls_tx.hlc_buf, lstate.hls_rx.hlc_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_buf_sz) == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_LOOPBACK_SEND_RECV_COMPARE_FAIL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(lstate.hls_rx.hlc_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_fail_buf, lstate.hls_tx.hlc_buf_sz,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate.hls_err = HERMON_LOOPBACK_SUCCESS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_pass_done = iter + 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb.alb_error_type = HERMON_LOOPBACK_SUCCESS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Copy ioctl results back to user struct */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ret = hermon_loopback_copyout(&lb, arg, mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free up everything and release all consumed resources */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_state(&lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ret);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef DEBUG
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_reg_read()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_reg_read(hermon_state_t *state, intptr_t arg, int mode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_reg_ioctl_t rdreg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t *addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uintptr_t baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t handle;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Access to Hemron registers is not allowed in "maintenance mode".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This is primarily because the device may not have BARs to access
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_operational_mode == HERMON_MAINTENANCE_MODE) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Copy in the hermon_reg_ioctl_t structure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_copyin((void *)arg, &rdreg, sizeof (hermon_reg_ioctl_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine base address for requested register set */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (rdreg.arg_reg_set) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMD_BAR:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor baseaddr = (uintptr_t)state->hs_reg_cmd_baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor handle = hermon_get_cmdhdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_UAR_BAR:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor baseaddr = (uintptr_t)state->hs_reg_uar_baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor handle = hermon_get_uarhdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Ensure that address is properly-aligned */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr = (uint32_t *)((baseaddr + rdreg.arg_offset) & ~0x3);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, handle, pio_error, fm_loop_cnt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Read the register pointed to by addr */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rdreg.arg_data = ddi_get32(handle, addr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, handle, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Copy in the result into the hermon_reg_ioctl_t structure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_copyout(&rdreg, (void *)arg, sizeof (hermon_reg_ioctl_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_ioctl_reg_write()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_reg_write(hermon_state_t *state, intptr_t arg, int mode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_reg_ioctl_t wrreg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t *addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uintptr_t baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t handle;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Access to Hermon registers is not allowed in "maintenance mode".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This is primarily because the device may not have BARs to access
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_operational_mode == HERMON_MAINTENANCE_MODE) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Copy in the hermon_reg_ioctl_t structure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_copyin((void *)arg, &wrreg, sizeof (hermon_reg_ioctl_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine base address for requested register set */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (wrreg.arg_reg_set) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMD_BAR:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor baseaddr = (uintptr_t)state->hs_reg_cmd_baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor handle = hermon_get_cmdhdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_UAR_BAR:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor baseaddr = (uintptr_t)state->hs_reg_uar_baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor handle = hermon_get_uarhdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Ensure that address is properly-aligned */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr = (uint32_t *)((baseaddr + wrreg.arg_offset) & ~0x3);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, handle, pio_error, fm_loop_cnt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Write the data to the register pointed to by addr */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put32(handle, addr, wrreg.arg_data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, handle, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* DEBUG */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_ioctl_write_boot_addr(hermon_state_t *state, dev_t dev, intptr_t arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int mode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_ioctl_t ioctl_info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check that flash init ioctl has been called first. And check
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that the same dev_t that called init is the one calling write now.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((state->hs_fw_flashdev != dev) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_fw_flashstarted == 0)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* copy user struct to kernel */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _MULTI_DATAMODEL
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_ioctl32_t info32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &info32,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_flash_ioctl32_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_type = info32.af_type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_sector = (caddr_t)(uintptr_t)info32.af_sector;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_sector_num = info32.af_sector_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_addr = info32.af_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ioctl_info.af_byte = info32.af_byte;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* _MULTI_DATAMODEL */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyin((void *)arg, &ioctl_info,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_flash_ioctl_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (state->hs_fw_cmdset) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_AMD_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_INTEL_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_SPI_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, pci_hdl, pio_error,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, pci_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_BOOT_ADDR_REG,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (ioctl_info.af_addr << 8) | 0x06);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, pci_hdl, pio_error,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_UNKNOWN_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_reset()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_reset(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Performs a reset to the flash device. After a reset the flash will
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * be operating in normal mode (capable of read/write, etc.).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (state->hs_fw_cmdset) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_AMD_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, 0x555, HERMON_HW_FLASH_RESET_AMD,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_INTEL_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, 0x555, HERMON_HW_FLASH_RESET_INTEL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* It appears no reset is needed for SPI */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_SPI_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_UNKNOWN_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = EINVAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_read_sector()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_read_sector(hermon_state_t *state, uint32_t sector_num)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t end_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t *image;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor image = (uint32_t *)&state->hs_fw_sector[0];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Calculate the start and end address of the sector, based on the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * sector number passed in.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr = sector_num << state->hs_fw_log_sector_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor end_addr = addr + (1 << state->hs_fw_log_sector_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the flash bank correctly for the given address */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_bank(state, addr)) != 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Read the entire sector, one quadlet at a time */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; addr < end_addr; i++, addr += 4) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor image[i] = hermon_flash_read(state, addr, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_read_quadlet()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_read_quadlet(hermon_state_t *state, uint32_t *data,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t addr)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the flash bank correctly for the given address */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_bank(state, addr)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Read one quadlet of data */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *data = hermon_flash_read(state, addr, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_write_sector()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_write_sector(hermon_state_t *state, uint32_t sector_num)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t end_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t *databuf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uchar_t *sector;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sector = (uchar_t *)&state->hs_fw_sector[0];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Calculate the start and end address of the sector, based on the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * sector number passed in.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr = sector_num << state->hs_fw_log_sector_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor end_addr = addr + (1 << state->hs_fw_log_sector_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the flash bank correctly for the given address */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_bank(state, addr)) != 0 ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (status = hermon_flash_reset(state)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Erase the sector before writing */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_erase_sector(state, sector_num);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (state->hs_fw_cmdset) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_SPI_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor databuf = (uint32_t *)(void *)sector;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Write the sector, one dword at a time */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; addr < end_addr; i++, addr += 4) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_spi_write_dword(state, addr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor htonl(databuf[i]))) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_reset(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_INTEL_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_AMD_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Write the sector, one byte at a time */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; addr < end_addr; i++, addr++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_write_byte(state, addr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sector[i]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_reset(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_UNKNOWN_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = EINVAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_spi_write_dword()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * NOTE: This function assumes that "data" is in network byte order.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_spi_write_dword(hermon_state_t *state, uint32_t addr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t data)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, hdl, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Issue Write Enable */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_spi_write_enable(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the Address */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_SPI_ADDR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr & HERMON_HW_FLASH_SPI_ADDR_MASK);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the Data */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_SPI_DATA, data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the Page Program and execute */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_spi_exec_command(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_INSTR_PHASE_OFF |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_ADDR_PHASE_OFF |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_DATA_PHASE_OFF |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_TRANS_SZ_4B |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (HERMON_HW_FLASH_SPI_PAGE_PROGRAM <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_INSTR_SHIFT));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Wait for write to complete */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_spi_wait_wip(state)) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, hdl, pio_error, fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_write_byte()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_write_byte(hermon_state_t *state, uint32_t addr, uchar_t data)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t stat;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int dword_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int byte_offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor union {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint8_t bytes[4];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t dword;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } dword;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (state->hs_fw_cmdset) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_AMD_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Issue Flash Byte program command */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, 0xAA, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, 0x55, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, 0xA0, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, data, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Wait for Write Byte to Complete */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor stat = hermon_flash_read(state, addr & ~3, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (i == hermon_hw_flash_timeout_write) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_flash_write_byte: ACS write "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "timeout: addr: 0x%x, data: 0x%x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr, data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while (data != ((stat >> ((3 - (addr & 3)) << 3)) & 0xFF));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_INTEL_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Issue Flash Byte program command */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, HERMON_HW_FLASH_ICS_WRITE,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, data, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Wait for Write Byte to Complete */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor stat = hermon_flash_read(state, addr & ~3, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (i == hermon_hw_flash_timeout_write) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_flash_write_byte: ICS write "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "timeout: addr: %x, data: %x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr, data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while ((stat & HERMON_HW_FLASH_ICS_READY) == 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (stat & HERMON_HW_FLASH_ICS_ERROR) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_flash_write_byte: ICS write cmd error: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "addr: %x, data: %x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr, data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_SPI_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Our lowest write granularity on SPI is a dword.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * To support this ioctl option, we can read in the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * dword that contains this byte, modify this byte,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and write the dword back out.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine dword offset and byte offset within the dword */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor byte_offset = addr & 3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dword_addr = addr - byte_offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _LITTLE_ENDIAN
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor byte_offset = 3 - byte_offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Read in dword */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_read_quadlet(state, &dword.dword,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dword_addr)) != 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set "data" to the appopriate byte */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dword.bytes[byte_offset] = data;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Write modified dword back out */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_spi_write_dword(state, dword_addr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dword.dword);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_UNKNOWN_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_flash_write_byte: unknown cmd set: 0x%x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_cmdset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = EINVAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_erase_sector()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_erase_sector(hermon_state_t *state, uint32_t sector_num)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t stat;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get address from sector num */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr = sector_num << state->hs_fw_log_sector_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (state->hs_fw_cmdset) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_AMD_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Issue Flash Sector Erase Command */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, 0xAA, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, 0x55, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, 0x80, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, 0xAA, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, 0x55, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, 0x30, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Wait for Sector Erase to complete */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor stat = hermon_flash_read(state, addr, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (i == hermon_hw_flash_timeout_erase) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_flash_erase_sector: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "ACS erase timeout\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while (stat != 0xFFFFFFFF);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_INTEL_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Issue Flash Sector Erase Command */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, HERMON_HW_FLASH_ICS_ERASE,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, addr, HERMON_HW_FLASH_ICS_CONFIRM,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Wait for Sector Erase to complete */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor stat = hermon_flash_read(state, addr & ~3, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (i == hermon_hw_flash_timeout_erase) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_flash_erase_sector: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "ICS erase timeout\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while ((stat & HERMON_HW_FLASH_ICS_READY) == 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (stat & HERMON_HW_FLASH_ICS_ERROR) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_flash_erase_sector: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "ICS erase cmd error\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_SPI_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, hdl, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Issue Write Enable */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_spi_write_enable(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the Address */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_SPI_ADDR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr & HERMON_HW_FLASH_SPI_ADDR_MASK);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Issue Flash Sector Erase */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_spi_exec_command(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_INSTR_PHASE_OFF |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_ADDR_PHASE_OFF |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((uint32_t)(HERMON_HW_FLASH_SPI_SECTOR_ERASE) <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_INSTR_SHIFT));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, hdl, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Wait for Sector Erase to complete */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_spi_wait_wip(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_UNKNOWN_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_flash_erase_sector: unknown cmd set: 0x%x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_cmdset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = EINVAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Reset the flash device */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_reset(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_erase_chip()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_erase_chip(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t stat;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int num_sect;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (state->hs_fw_cmdset) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_AMD_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Issue Flash Chip Erase Command */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, 0, 0xAA, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, 0, 0x55, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, 0, 0x80, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, 0, 0xAA, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, 0, 0x55, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, 0, 0x10, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Wait for Chip Erase to Complete */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor stat = hermon_flash_read(state, 0, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (i == hermon_hw_flash_timeout_erase) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_flash_erase_chip: erase timeout\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while (stat != 0xFFFFFFFF);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_INTEL_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_SPI_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * These chips don't have a chip erase command, so erase
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * all blocks one at a time.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor size = (0x1 << state->hs_fw_log_sector_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_sect = state->hs_fw_device_sz / size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < num_sect; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_erase_sector(state, i);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_flash_erase_chip: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "sector %d erase error\n", i);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_UNKNOWN_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN, "hermon_flash_erase_chip: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "unknown cmd set: 0x%x\n", state->hs_fw_cmdset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = EINVAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_spi_write_enable()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_spi_write_enable(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_spi_exec_command(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_INSTR_PHASE_OFF |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (HERMON_HW_FLASH_SPI_WRITE_ENABLE <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_INSTR_SHIFT));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_spi_wait_wip()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_spi_wait_wip(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, hdl, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* wait on the gateway to clear busy */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_read_cfg(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_GW);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while (status & HERMON_HW_FLASH_SPI_BUSY);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* now, get the status and check for WIP to clear */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_spi_exec_command(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_READ_OP |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_INSTR_PHASE_OFF |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_DATA_PHASE_OFF |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_TRANS_SZ_4B |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (HERMON_HW_FLASH_SPI_READ_STATUS_REG <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_INSTR_SHIFT));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_flash_read_cfg(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_DATA);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while (status & HERMON_HW_FLASH_SPI_WIP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, hdl, pio_error, fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_bank()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_bank(hermon_state_t *state, uint32_t addr)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t bank;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine the bank setting from the address */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bank = addr & HERMON_HW_FLASH_BANK_MASK;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(state->hs_fw_flashbank))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the bank is different from the currently set bank, we need to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * change it. Also, if an 'addr' of 0 is given, this allows the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * capability to force the flash bank to 0. This is useful at init
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * time to initially set the bank value
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fw_flashbank != bank || addr == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (state->hs_fw_cmdset) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_SPI_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* CMJ: not needed for hermon */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_INTEL_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_AMD_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, hdl, pio_error, fm_loop_cnt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_GPIO_DATACLEAR, 0x70);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_GPIO_DATASET, (bank >> 15) & 0x70);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, hdl, pio_error, fm_loop_cnt,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_UNKNOWN_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_flashbank = bank;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_spi_exec_command()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_spi_exec_command(hermon_state_t *state, ddi_acc_handle_t hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t cmd)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t data;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int timeout = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmd |= HERMON_HW_FLASH_SPI_BUSY | HERMON_HW_FLASH_SPI_ENABLE_OFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_SPI_GW, cmd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data = hermon_flash_read_cfg(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_GW);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor timeout++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while ((data & HERMON_HW_FLASH_SPI_BUSY) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (timeout < hermon_hw_flash_timeout_config));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_read()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic uint32_t
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_read(hermon_state_t *state, uint32_t addr, int *err)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t data = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int timeout, status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, hdl, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (state->hs_fw_cmdset) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_SPI_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the transaction address */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_SPI_ADDR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (addr & HERMON_HW_FLASH_SPI_ADDR_MASK));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_spi_exec_command(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_READ_OP |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_INSTR_PHASE_OFF |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_ADDR_PHASE_OFF |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_DATA_PHASE_OFF |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_TRANS_SZ_4B |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (HERMON_HW_FLASH_SPI_READ <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_INSTR_SHIFT));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data = hermon_flash_read_cfg(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_SPI_DATA);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_INTEL_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_AMD_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The Read operation does the following:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 1) Write the masked address to the HERMON_FLASH_ADDR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * register. Only the least significant 19 bits are valid.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 2) Read back the register until the command has completed.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 3) Read the data retrieved from the address at the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * HERMON_FLASH_DATA register.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_ADDR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (addr & HERMON_HW_FLASH_ADDR_MASK) | (1 << 29));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor timeout = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data = hermon_flash_read_cfg(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_ADDR);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor timeout++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while ((data & HERMON_HW_FLASH_CMD_MASK) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (timeout < hermon_hw_flash_timeout_config));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
261906274d77b4a1c6d61c75d170ab5a8e85a6a7Shantkumar Hiremath if (timeout == hermon_hw_flash_timeout_config) {
261906274d77b4a1c6d61c75d170ab5a8e85a6a7Shantkumar Hiremath cmn_err(CE_WARN, "hermon_flash_read: command timed "
261906274d77b4a1c6d61c75d170ab5a8e85a6a7Shantkumar Hiremath "out.\n");
261906274d77b4a1c6d61c75d170ab5a8e85a6a7Shantkumar Hiremath *err = EIO;
261906274d77b4a1c6d61c75d170ab5a8e85a6a7Shantkumar Hiremath hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
261906274d77b4a1c6d61c75d170ab5a8e85a6a7Shantkumar Hiremath return (data);
261906274d77b4a1c6d61c75d170ab5a8e85a6a7Shantkumar Hiremath }
261906274d77b4a1c6d61c75d170ab5a8e85a6a7Shantkumar Hiremath
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data = hermon_flash_read_cfg(state, hdl, HERMON_HW_FLASH_DATA);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_FLASH_UNKNOWN_CMDSET:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "hermon_flash_read: unknown cmdset: 0x%x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_cmdset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = EINVAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, hdl, pio_error, fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *err = status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *err = EIO;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_write()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_write(hermon_state_t *state, uint32_t addr, uchar_t data, int *err)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int cmd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int timeout;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, hdl, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The Write operation does the following:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 1) Write the data to be written to the HERMON_FLASH_DATA offset.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 2) Write the address to write the data to to the HERMON_FLASH_ADDR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * offset.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 3) Wait until the write completes.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_DATA, data << 24);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_ADDR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (addr & 0x7FFFF) | (2 << 29));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor timeout = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmd = hermon_flash_read_cfg(state, hdl, HERMON_HW_FLASH_ADDR);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor timeout++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while ((cmd & HERMON_HW_FLASH_CMD_MASK) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (timeout < hermon_hw_flash_timeout_config));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (timeout == hermon_hw_flash_timeout_config) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN, "hermon_flash_write: config cmd timeout.\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *err = EIO;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, hdl, pio_error, fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *err = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *err = EIO;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_init(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t word;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int sema_cnt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int gpio;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, hdl, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Init the flash */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef DO_WRCONF
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Grab the WRCONF semaphore.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor word = hermon_flash_read_cfg(state, hdl, HERMON_HW_FLASH_WRCONF_SEMA);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Grab the GPIO semaphore. This allows us exclusive access to the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * GPIO settings on the Hermon for the duration of the flash burning
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * procedure.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sema_cnt = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor word = hermon_flash_read_cfg(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_GPIO_SEMA);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (word == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sema_cnt++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while (sema_cnt < hermon_hw_flash_timeout_gpio_sema);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine if we timed out trying to grab the GPIO semaphore
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sema_cnt == hermon_hw_flash_timeout_gpio_sema) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN, "hermon_flash_init: GPIO SEMA timeout\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN, "GPIO_SEMA value: 0x%x\n", word);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Save away original GPIO Values */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_gpio[0] = hermon_flash_read_cfg(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_GPIO_DATA);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set new GPIO value */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor gpio = state->hs_fw_gpio[0] | HERMON_HW_FLASH_GPIO_PIN_ENABLE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_GPIO_DATA, gpio);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Save away original GPIO Values */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_gpio[1] = hermon_flash_read_cfg(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_GPIO_MOD0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_gpio[2] = hermon_flash_read_cfg(state, hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_GPIO_MOD1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* unlock GPIO */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_GPIO_LOCK,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_GPIO_UNLOCK_VAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Set new GPIO values
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor gpio = state->hs_fw_gpio[1] | HERMON_HW_FLASH_GPIO_PIN_ENABLE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_GPIO_MOD0, gpio);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor gpio = state->hs_fw_gpio[2] & ~HERMON_HW_FLASH_GPIO_PIN_ENABLE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_GPIO_MOD1, gpio);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* re-lock GPIO */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_GPIO_LOCK, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set CPUMODE to enable hermon to access the flash device */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* CMJ This code came from arbel. Hermon doesn't seem to need it. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_CPUMODE,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 1 << HERMON_HW_FLASH_CPU_SHIFT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, hdl, pio_error, fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_cfi_init
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Implements access to the CFI (Common Flash Interface) data
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_cfi_init(hermon_state_t *state, uint32_t *cfi_info,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int *intel_xcmd)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t data;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t sector_sz_bytes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t bit_count;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint8_t cfi_ch_info[HERMON_CFI_INFO_SIZE];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t cfi_dw_info[HERMON_CFI_INFO_QSIZE];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Right now, all hermon cards use SPI. */
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor if (hermon_device_mode(state)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Don't use CFI for SPI part. Just fill in what we need
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and return.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_cmdset = HERMON_FLASH_SPI_CMDSET;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_log_sector_sz = HERMON_FLASH_SPI_LOG_SECTOR_SIZE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_device_sz = HERMON_FLASH_SPI_DEVICE_SIZE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * set this to inform caller of cmdset type.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x13] = HERMON_FLASH_SPI_CMDSET;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_cfi_dword(&cfi_info[4], cfi_ch_info, 0x10);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine if the user command supports the Intel Extended
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Command Set. The query string is contained in the fourth
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * quad word.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_cfi_byte(cfi_ch_info, cfi_info[0x04], 0x10);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (cfi_ch_info[0x10] == 'M' &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x11] == 'X' &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x12] == '2') {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *intel_xcmd = 1; /* support is there */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_verbose) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "Support for Intel X is present\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* CFI QUERY */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write(state, 0x55, HERMON_FLASH_CFI_INIT, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* temporarily set the cmdset in order to do the initial read */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_cmdset = HERMON_FLASH_INTEL_CMDSET;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Read in CFI data */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_CFI_INFO_SIZE; i += 4) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data = hermon_flash_read(state, i, &status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_dw_info[i >> 2] = data;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_cfi_byte(cfi_ch_info, data, i);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine chip set */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_cmdset = HERMON_FLASH_UNKNOWN_CMDSET;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (cfi_ch_info[0x20] == 'Q' &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x22] == 'R' &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x24] == 'Y') {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Mode: x16 working in x8 mode (Intel).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Pack data - skip spacing bytes.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_verbose) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "x16 working in x8 mode (Intel)\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_CFI_INFO_SIZE; i += 2) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[i/2] = cfi_ch_info[i];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_cmdset = cfi_ch_info[0x13];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fw_cmdset != HERMON_FLASH_INTEL_CMDSET &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_cmdset != HERMON_FLASH_AMD_CMDSET) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_flash_cfi_init: UNKNOWN chip cmd set 0x%04x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_cmdset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_cmdset = HERMON_FLASH_UNKNOWN_CMDSET;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine total bytes in one sector size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sector_sz_bytes = ((cfi_ch_info[0x30] << 8) | cfi_ch_info[0x2F]) << 8;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Calculate equivalent of log2 (n) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (bit_count = 0; sector_sz_bytes > 1; bit_count++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sector_sz_bytes >>= 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set sector size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_log_sector_sz = bit_count;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set flash size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_device_sz = 0x1 << cfi_ch_info[0x27];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Reset to turn off CFI mode */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_reset(state)) != 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto out;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Pass CFI data back to user command. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_FLASH_CFI_SIZE_QUADLET; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_cfi_dword(&cfi_info[i], cfi_ch_info, i << 2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (*intel_xcmd == 1) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Inform the user cmd that this driver does support the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Intel Extended Command Set.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x10] = 'M';
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x11] = 'X';
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x12] = '2';
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x10] = 'Q';
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x11] = 'R';
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x12] = 'Y';
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfi_ch_info[0x13] = state->hs_fw_cmdset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_cfi_dword(&cfi_info[0x4], cfi_ch_info, 0x10);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorout:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_fini(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status = hermon_flash_bank(state, 0)) != 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, hdl, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Restore original GPIO Values
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_GPIO_DATA,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_gpio[0]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* unlock GPIOs */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_GPIO_LOCK,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_GPIO_UNLOCK_VAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_GPIO_MOD0,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_gpio[1]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_GPIO_MOD1,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_gpio[2]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* re-lock GPIOs */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_GPIO_LOCK, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Give up gpio semaphore */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg(state, hdl, HERMON_HW_FLASH_GPIO_SEMA, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, hdl, pio_error, fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_IOCTL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_read_cfg
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic uint32_t
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_read_cfg(hermon_state_t *state, ddi_acc_handle_t pci_config_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t addr)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t read;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (do_bar0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor read = ddi_get32(hermon_get_cmdhdl(state), (uint32_t *)(void *)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_reg_cmd_baseaddr + addr));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Perform flash read operation:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 1) Place addr to read from on the HERMON_HW_FLASH_CFG_ADDR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * register
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 2) Read data at that addr from the HERMON_HW_FLASH_CFG_DATA
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * register
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put32(pci_config_hdl, HERMON_HW_FLASH_CFG_ADDR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor read = pci_config_get32(pci_config_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_CFG_DATA);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (read);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef DO_WRCONF
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_write_cfg(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_config_hdl, uint32_t addr, uint32_t data)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg_helper(state, pci_config_hdl, addr, data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_confirm(state, pci_config_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_write_confirm(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_config_hdl)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t sem_value = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_flash_write_cfg_helper(state, pci_config_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_WRCONF_SEMA, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor while (sem_value) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sem_value = hermon_flash_read_cfg(state, pci_config_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_HW_FLASH_WRCONF_SEMA);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_flash_write_cfg
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef DO_WRCONF
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_write_cfg_helper(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_config_hdl, uint32_t addr, uint32_t data)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_write_cfg(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_config_hdl, uint32_t addr, uint32_t data)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (do_bar0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put32(hermon_get_cmdhdl(state), (uint32_t *)(void *)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_reg_cmd_baseaddr + addr), data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Perform flash write operation:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 1) Place addr to write to on the HERMON_HW_FLASH_CFG_ADDR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * register
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 2) Place data to write on to the HERMON_HW_FLASH_CFG_DATA
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * register
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put32(pci_config_hdl, HERMON_HW_FLASH_CFG_ADDR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put32(pci_config_hdl, HERMON_HW_FLASH_CFG_DATA,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Support routines to convert Common Flash Interface (CFI) data
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * from a 32 bit word to a char array, and from a char array to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * a 32 bit word.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_cfi_byte(uint8_t *ch, uint32_t dword, int i)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ch[i] = (uint8_t)((dword & 0xFF000000) >> 24);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ch[i+1] = (uint8_t)((dword & 0x00FF0000) >> 16);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ch[i+2] = (uint8_t)((dword & 0x0000FF00) >> 8);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ch[i+3] = (uint8_t)((dword & 0x000000FF));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_flash_cfi_dword(uint32_t *dword, uint8_t *ch, int i)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *dword = (uint32_t)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((uint32_t)ch[i] << 24 |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint32_t)ch[i+1] << 16 |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint32_t)ch[i+2] << 8 |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint32_t)ch[i+3]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_loopback_free_qps
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_loopback_free_qps(hermon_loopback_state_t *lstate)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lstate->hls_tx.hlc_qp_hdl != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_qp_free(lstate->hls_state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &lstate->hls_tx.hlc_qp_hdl, IBC_FREE_QP_AND_QPN, NULL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lstate->hls_rx.hlc_qp_hdl != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_qp_free(lstate->hls_state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &lstate->hls_rx.hlc_qp_hdl, IBC_FREE_QP_AND_QPN, NULL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_tx.hlc_qp_hdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_rx.hlc_qp_hdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < 2; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lstate->hls_tx.hlc_cqhdl[i] != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_cq_free(lstate->hls_state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &lstate->hls_tx.hlc_cqhdl[i], HERMON_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lstate->hls_rx.hlc_cqhdl[i] != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_cq_free(lstate->hls_state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &lstate->hls_rx.hlc_cqhdl[i], HERMON_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_tx.hlc_cqhdl[i] = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_rx.hlc_cqhdl[i] = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_loopback_free_state
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_loopback_free_state(hermon_loopback_state_t *lstate)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_free_qps(lstate);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lstate->hls_tx.hlc_mrhdl != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_mr_deregister(lstate->hls_state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &lstate->hls_tx.hlc_mrhdl, HERMON_MR_DEREG_ALL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lstate->hls_rx.hlc_mrhdl != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_mr_deregister(lstate->hls_state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &lstate->hls_rx.hlc_mrhdl, HERMON_MR_DEREG_ALL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lstate->hls_pd_hdl != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_pd_free(lstate->hls_state, &lstate->hls_pd_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lstate->hls_tx.hlc_buf != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(lstate->hls_tx.hlc_buf, lstate->hls_tx.hlc_buf_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lstate->hls_rx.hlc_buf != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(lstate->hls_rx.hlc_buf, lstate->hls_rx.hlc_buf_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(lstate, sizeof (hermon_loopback_state_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_loopback_init
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_loopback_init(hermon_state_t *state, hermon_loopback_state_t *lstate)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_hca_hdl = (ibc_hca_hdl_t)state;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_status = hermon_pd_alloc(lstate->hls_state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &lstate->hls_pd_hdl, HERMON_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (lstate->hls_status != IBT_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_err = HERMON_LOOPBACK_PROT_DOMAIN_ALLOC_FAIL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_loopback_init_qp_info
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_loopback_init_qp_info(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *comm)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&comm->hlc_cq_attr, sizeof (ibt_cq_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&comm->hlc_qp_attr, sizeof (ibt_qp_alloc_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&comm->hlc_qp_info, sizeof (ibt_qp_info_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_wrid = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_cq_attr.cq_size = 128;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_attr.qp_sizes.cs_sq_sgl = 3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_attr.qp_sizes.cs_rq_sgl = 3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_attr.qp_sizes.cs_sq = 16;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_attr.qp_sizes.cs_rq = 16;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_attr.qp_flags = IBT_WR_SIGNALED;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_state = IBT_STATE_RESET;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_trans = IBT_RC_SRV;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_flags = IBT_CEP_RDMA_RD | IBT_CEP_RDMA_WR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_path.cep_hca_port_num =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_port;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_path.cep_pkey_ix =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_pkey_ix;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_path.cep_timeout =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_timeout;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_srvl = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_srate =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBT_SRATE_4X;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_send_grh = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dlid =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_lid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_retry_cnt = lstate->hls_retry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_sq_psn = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_rq_psn = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_rdma_ra_in = 4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_rdma_ra_out = 4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_dst_qpn = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_min_rnr_nak = IBT_RNR_NAK_655ms;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_path_mtu = IB_MTU_1K;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_loopback_alloc_mem
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_loopback_alloc_mem(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *comm, int sz)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate buffer of specified size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_buf_sz = sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_buf = kmem_zalloc(sz, KM_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (comm->hlc_buf == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Register the buffer as a memory region */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_memattr.mr_vaddr = (uint64_t)(uintptr_t)comm->hlc_buf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_memattr.mr_len = (ib_msglen_t)sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_memattr.mr_as = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_memattr.mr_flags = IBT_MR_NOSLEEP |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBT_MR_ENABLE_REMOTE_WRITE | IBT_MR_ENABLE_LOCAL_WRITE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_status = hermon_mr_register(lstate->hls_state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_pd_hdl, &comm->hlc_memattr, &comm->hlc_mrhdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor NULL, HERMON_MPT_DMPT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm->hlc_mrhdl))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_mrdesc.md_vaddr = comm->hlc_mrhdl->mr_bindinfo.bi_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_mrdesc.md_lkey = comm->hlc_mrhdl->mr_lkey;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_mrdesc.md_rkey = comm->hlc_mrhdl->mr_rkey;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (comm->hlc_status != IBT_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_loopback_alloc_qps
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_loopback_alloc_qps(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *comm)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t i, real_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_qp_info_t qpinfo;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate send and recv CQs */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < 2; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&comm->hlc_cq_attr, sizeof (ibt_cq_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_cq_attr.cq_size = 128;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_status = hermon_cq_alloc(lstate->hls_state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (ibt_cq_hdl_t)NULL, &comm->hlc_cq_attr, &real_size,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &comm->hlc_cqhdl[i], HERMON_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (comm->hlc_status != IBT_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_err += i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate the QP */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_init_qp_info(lstate, comm);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_attr.qp_pd_hdl = (ibt_pd_hdl_t)lstate->hls_pd_hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_attr.qp_scq_hdl = (ibt_cq_hdl_t)comm->hlc_cqhdl[0];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_attr.qp_rcq_hdl = (ibt_cq_hdl_t)comm->hlc_cqhdl[1];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_attr.qp_ibc_scq_hdl = (ibt_opaque1_t)comm->hlc_cqhdl[0];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_attr.qp_ibc_rcq_hdl = (ibt_opaque1_t)comm->hlc_cqhdl[1];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qpinfo.qpi_attrp = &comm->hlc_qp_attr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qpinfo.qpi_type = IBT_RC_RQP;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qpinfo.qpi_ibt_qphdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qpinfo.qpi_queueszp = &comm->hlc_chan_sizes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor qpinfo.qpi_qpn = &comm->hlc_qp_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_status = hermon_qp_alloc(lstate->hls_state, &qpinfo,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_NOSLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (comm->hlc_status == DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_hdl = qpinfo.qpi_qphdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (comm->hlc_status != IBT_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_err += 2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_loopback_modify_qp
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_loopback_modify_qp(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *comm, uint_t qp_num)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Modify QP to INIT */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_init_qp_info(lstate, comm);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_state = IBT_STATE_INIT;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_status = hermon_qp_modify(lstate->hls_state, comm->hlc_qp_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBT_CEP_SET_STATE, &comm->hlc_qp_info, &comm->hlc_queue_sizes);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (comm->hlc_status != IBT_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Modify QP to RTR (set destination LID and QP number to local
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * LID and QP number)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_state = IBT_STATE_RTR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dlid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor = lstate->hls_lid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_transport.rc.rc_dst_qpn = qp_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_status = hermon_qp_modify(lstate->hls_state, comm->hlc_qp_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBT_CEP_SET_STATE, &comm->hlc_qp_info, &comm->hlc_queue_sizes);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (comm->hlc_status != IBT_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_err += 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Modify QP to RTS */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_current_state = IBT_STATE_RTR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_qp_info.qp_state = IBT_STATE_RTS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_status = hermon_qp_modify(lstate->hls_state, comm->hlc_qp_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBT_CEP_SET_STATE, &comm->hlc_qp_info, &comm->hlc_queue_sizes);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (comm->hlc_status != IBT_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lstate->hls_err += 2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_loopback_copyout
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_loopback_copyout(hermon_loopback_ioctl_t *lb, intptr_t arg, int mode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _MULTI_DATAMODEL
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_ioctl32_t lb32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb32.alb_revision = lb->alb_revision;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb32.alb_send_buf =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (caddr32_t)(uintptr_t)lb->alb_send_buf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb32.alb_fail_buf =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (caddr32_t)(uintptr_t)lb->alb_fail_buf;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb32.alb_buf_sz = lb->alb_buf_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb32.alb_num_iter = lb->alb_num_iter;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb32.alb_pass_done = lb->alb_pass_done;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb32.alb_timeout = lb->alb_timeout;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb32.alb_error_type = lb->alb_error_type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb32.alb_port_num = lb->alb_port_num;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor lb32.alb_num_retry = lb->alb_num_retry;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(&lb32, (void *)arg,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_loopback_ioctl32_t), mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* _MULTI_DATAMODEL */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_copyout(lb, (void *)arg, sizeof (hermon_loopback_ioctl_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mode) != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_loopback_post_send
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_loopback_post_send(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *tx, hermon_loopback_comm_t *rx)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int ret;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tx))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&tx->hlc_sgl, sizeof (ibt_wr_ds_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&tx->hlc_wr, sizeof (ibt_send_wr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize local address for TX buffer */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_sgl.ds_va = tx->hlc_mrdesc.md_vaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_sgl.ds_key = tx->hlc_mrdesc.md_lkey;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_sgl.ds_len = tx->hlc_buf_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the remaining details of the work request */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_wr.wr_id = tx->hlc_wrid++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_wr.wr_flags = IBT_WR_SEND_SIGNAL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_wr.wr_nds = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_wr.wr_sgl = &tx->hlc_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_wr.wr_opcode = IBT_WRC_RDMAW;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_wr.wr_trans = IBT_RC_SRV;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the remote address for RX buffer */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_wr.wr.rc.rcwr.rdma.rdma_raddr = rx->hlc_mrdesc.md_vaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_wr.wr.rc.rcwr.rdma.rdma_rkey = rx->hlc_mrdesc.md_rkey;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tx->hlc_complete = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ret = hermon_post_send(lstate->hls_state, tx->hlc_qp_hdl, &tx->hlc_wr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 1, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ret != IBT_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EFAULT);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_loopback_poll_cq
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_loopback_poll_cq(hermon_loopback_state_t *lstate,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_loopback_comm_t *comm)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_wc.wc_status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_num_polled = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_status = hermon_cq_poll(lstate->hls_state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_cqhdl[0], &comm->hlc_wc, 1, &comm->hlc_num_polled);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((comm->hlc_status == IBT_SUCCESS) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (comm->hlc_wc.wc_status != IBT_WC_SUCCESS)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor comm->hlc_status = ibc_get_ci_failure(0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (comm->hlc_status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}