17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM * CDDL HEADER START
37836SJohn.Forte@Sun.COM *
47836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM *
87836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM * and limitations under the License.
127836SJohn.Forte@Sun.COM *
137836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM *
197836SJohn.Forte@Sun.COM * CDDL HEADER END
207836SJohn.Forte@Sun.COM */
217836SJohn.Forte@Sun.COM
2211541SDaniel.Beauregard@Sun.COM /* Copyright 2010 QLogic Corporation */
237836SJohn.Forte@Sun.COM
247836SJohn.Forte@Sun.COM /*
25*12279SDaniel.Beauregard@Sun.COM * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
267836SJohn.Forte@Sun.COM */
277836SJohn.Forte@Sun.COM
2811541SDaniel.Beauregard@Sun.COM #pragma ident "Copyright 2010 QLogic Corporation; ql_ioctl.c"
297836SJohn.Forte@Sun.COM
307836SJohn.Forte@Sun.COM /*
317836SJohn.Forte@Sun.COM * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
327836SJohn.Forte@Sun.COM * Fibre Channel Adapter (FCA) driver IOCTL source file.
337836SJohn.Forte@Sun.COM *
347836SJohn.Forte@Sun.COM * ***********************************************************************
357836SJohn.Forte@Sun.COM * * **
367836SJohn.Forte@Sun.COM * * NOTICE **
3711541SDaniel.Beauregard@Sun.COM * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION **
387836SJohn.Forte@Sun.COM * * ALL RIGHTS RESERVED **
397836SJohn.Forte@Sun.COM * * **
407836SJohn.Forte@Sun.COM * ***********************************************************************
417836SJohn.Forte@Sun.COM *
427836SJohn.Forte@Sun.COM */
437836SJohn.Forte@Sun.COM
447836SJohn.Forte@Sun.COM #include <ql_apps.h>
457836SJohn.Forte@Sun.COM #include <ql_api.h>
467836SJohn.Forte@Sun.COM #include <ql_debug.h>
477836SJohn.Forte@Sun.COM #include <ql_init.h>
487836SJohn.Forte@Sun.COM #include <ql_ioctl.h>
497836SJohn.Forte@Sun.COM #include <ql_mbx.h>
507836SJohn.Forte@Sun.COM #include <ql_xioctl.h>
517836SJohn.Forte@Sun.COM
527836SJohn.Forte@Sun.COM /*
537836SJohn.Forte@Sun.COM * Local Function Prototypes.
547836SJohn.Forte@Sun.COM */
557836SJohn.Forte@Sun.COM static int ql_busy_notification(ql_adapter_state_t *);
567836SJohn.Forte@Sun.COM static int ql_idle_notification(ql_adapter_state_t *);
577836SJohn.Forte@Sun.COM static int ql_get_feature_bits(ql_adapter_state_t *ha, uint16_t *features);
587836SJohn.Forte@Sun.COM static int ql_set_feature_bits(ql_adapter_state_t *ha, uint16_t features);
597836SJohn.Forte@Sun.COM static int ql_set_nvram_adapter_defaults(ql_adapter_state_t *ha);
607836SJohn.Forte@Sun.COM static void ql_load_nvram(ql_adapter_state_t *ha, uint8_t addr,
617836SJohn.Forte@Sun.COM uint16_t value);
627836SJohn.Forte@Sun.COM static int ql_24xx_load_nvram(ql_adapter_state_t *, uint32_t, uint32_t);
637836SJohn.Forte@Sun.COM static int ql_adm_op(ql_adapter_state_t *, void *, int);
647836SJohn.Forte@Sun.COM static int ql_adm_adapter_info(ql_adapter_state_t *, ql_adm_op_t *, int);
657836SJohn.Forte@Sun.COM static int ql_adm_extended_logging(ql_adapter_state_t *, ql_adm_op_t *);
667836SJohn.Forte@Sun.COM static int ql_adm_device_list(ql_adapter_state_t *, ql_adm_op_t *, int);
677836SJohn.Forte@Sun.COM static int ql_adm_update_properties(ql_adapter_state_t *);
687836SJohn.Forte@Sun.COM static int ql_adm_prop_update_int(ql_adapter_state_t *, ql_adm_op_t *, int);
697836SJohn.Forte@Sun.COM static int ql_adm_loop_reset(ql_adapter_state_t *);
707836SJohn.Forte@Sun.COM static int ql_adm_fw_dump(ql_adapter_state_t *, ql_adm_op_t *, void *, int);
717836SJohn.Forte@Sun.COM static int ql_adm_nvram_dump(ql_adapter_state_t *, ql_adm_op_t *, int);
727836SJohn.Forte@Sun.COM static int ql_adm_nvram_load(ql_adapter_state_t *, ql_adm_op_t *, int);
737836SJohn.Forte@Sun.COM static int ql_adm_flash_load(ql_adapter_state_t *, ql_adm_op_t *, int);
747836SJohn.Forte@Sun.COM static int ql_adm_vpd_dump(ql_adapter_state_t *, ql_adm_op_t *, int);
757836SJohn.Forte@Sun.COM static int ql_adm_vpd_load(ql_adapter_state_t *, ql_adm_op_t *, int);
767836SJohn.Forte@Sun.COM static int ql_adm_vpd_gettag(ql_adapter_state_t *, ql_adm_op_t *, int);
777836SJohn.Forte@Sun.COM static int ql_adm_updfwmodule(ql_adapter_state_t *, ql_adm_op_t *, int);
787836SJohn.Forte@Sun.COM static uint8_t *ql_vpd_findtag(ql_adapter_state_t *, uint8_t *, int8_t *);
797836SJohn.Forte@Sun.COM
807836SJohn.Forte@Sun.COM /* ************************************************************************ */
817836SJohn.Forte@Sun.COM /* cb_ops functions */
827836SJohn.Forte@Sun.COM /* ************************************************************************ */
837836SJohn.Forte@Sun.COM
847836SJohn.Forte@Sun.COM /*
857836SJohn.Forte@Sun.COM * ql_open
867836SJohn.Forte@Sun.COM * opens device
877836SJohn.Forte@Sun.COM *
887836SJohn.Forte@Sun.COM * Input:
897836SJohn.Forte@Sun.COM * dev_p = device pointer
907836SJohn.Forte@Sun.COM * flags = open flags
917836SJohn.Forte@Sun.COM * otype = open type
927836SJohn.Forte@Sun.COM * cred_p = credentials pointer
937836SJohn.Forte@Sun.COM *
947836SJohn.Forte@Sun.COM * Returns:
957836SJohn.Forte@Sun.COM * 0 = success
967836SJohn.Forte@Sun.COM *
977836SJohn.Forte@Sun.COM * Context:
987836SJohn.Forte@Sun.COM * Kernel context.
997836SJohn.Forte@Sun.COM */
1007836SJohn.Forte@Sun.COM /* ARGSUSED */
1017836SJohn.Forte@Sun.COM int
ql_open(dev_t * dev_p,int flags,int otyp,cred_t * cred_p)1027836SJohn.Forte@Sun.COM ql_open(dev_t *dev_p, int flags, int otyp, cred_t *cred_p)
1037836SJohn.Forte@Sun.COM {
1047836SJohn.Forte@Sun.COM ql_adapter_state_t *ha;
1057836SJohn.Forte@Sun.COM int rval = 0;
1067836SJohn.Forte@Sun.COM
1077836SJohn.Forte@Sun.COM ha = ddi_get_soft_state(ql_state, (int32_t)getminor(*dev_p));
1087836SJohn.Forte@Sun.COM if (ha == NULL) {
1097836SJohn.Forte@Sun.COM QL_PRINT_2(CE_CONT, "failed, no adapter\n");
1107836SJohn.Forte@Sun.COM return (ENXIO);
1117836SJohn.Forte@Sun.COM }
1127836SJohn.Forte@Sun.COM
1137836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1147836SJohn.Forte@Sun.COM
1157836SJohn.Forte@Sun.COM /* Allow only character opens */
1167836SJohn.Forte@Sun.COM if (otyp != OTYP_CHR) {
1177836SJohn.Forte@Sun.COM QL_PRINT_2(CE_CONT, "(%d): failed, open type\n",
1187836SJohn.Forte@Sun.COM ha->instance);
1197836SJohn.Forte@Sun.COM return (EINVAL);
1207836SJohn.Forte@Sun.COM }
1217836SJohn.Forte@Sun.COM
1227836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
1237836SJohn.Forte@Sun.COM if (flags & FEXCL && ha->flags & QL_OPENED) {
1247836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
1257836SJohn.Forte@Sun.COM rval = EBUSY;
1267836SJohn.Forte@Sun.COM } else {
1277836SJohn.Forte@Sun.COM ha->flags |= QL_OPENED;
1287836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
1297836SJohn.Forte@Sun.COM }
1307836SJohn.Forte@Sun.COM
1317836SJohn.Forte@Sun.COM if (rval != 0) {
1327836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
1337836SJohn.Forte@Sun.COM } else {
1347836SJohn.Forte@Sun.COM /*EMPTY*/
1357836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1367836SJohn.Forte@Sun.COM }
1377836SJohn.Forte@Sun.COM return (rval);
1387836SJohn.Forte@Sun.COM }
1397836SJohn.Forte@Sun.COM
1407836SJohn.Forte@Sun.COM /*
1417836SJohn.Forte@Sun.COM * ql_close
1427836SJohn.Forte@Sun.COM * opens device
1437836SJohn.Forte@Sun.COM *
1447836SJohn.Forte@Sun.COM * Input:
1457836SJohn.Forte@Sun.COM * dev_p = device pointer
1467836SJohn.Forte@Sun.COM * flags = open flags
1477836SJohn.Forte@Sun.COM * otype = open type
1487836SJohn.Forte@Sun.COM * cred_p = credentials pointer
1497836SJohn.Forte@Sun.COM *
1507836SJohn.Forte@Sun.COM * Returns:
1517836SJohn.Forte@Sun.COM * 0 = success
1527836SJohn.Forte@Sun.COM *
1537836SJohn.Forte@Sun.COM * Context:
1547836SJohn.Forte@Sun.COM * Kernel context.
1557836SJohn.Forte@Sun.COM */
1567836SJohn.Forte@Sun.COM /* ARGSUSED */
1577836SJohn.Forte@Sun.COM int
ql_close(dev_t dev,int flags,int otyp,cred_t * cred_p)1587836SJohn.Forte@Sun.COM ql_close(dev_t dev, int flags, int otyp, cred_t *cred_p)
1597836SJohn.Forte@Sun.COM {
1607836SJohn.Forte@Sun.COM ql_adapter_state_t *ha;
1617836SJohn.Forte@Sun.COM int rval = 0;
1627836SJohn.Forte@Sun.COM
1637836SJohn.Forte@Sun.COM ha = ddi_get_soft_state(ql_state, (int32_t)getminor(dev));
1647836SJohn.Forte@Sun.COM if (ha == NULL) {
1657836SJohn.Forte@Sun.COM QL_PRINT_2(CE_CONT, "failed, no adapter\n");
1667836SJohn.Forte@Sun.COM return (ENXIO);
1677836SJohn.Forte@Sun.COM }
1687836SJohn.Forte@Sun.COM
1697836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
1707836SJohn.Forte@Sun.COM
1717836SJohn.Forte@Sun.COM if (otyp != OTYP_CHR) {
1727836SJohn.Forte@Sun.COM QL_PRINT_2(CE_CONT, "(%d): failed, open type\n",
1737836SJohn.Forte@Sun.COM ha->instance);
1747836SJohn.Forte@Sun.COM return (EINVAL);
1757836SJohn.Forte@Sun.COM }
1767836SJohn.Forte@Sun.COM
1777836SJohn.Forte@Sun.COM ADAPTER_STATE_LOCK(ha);
1787836SJohn.Forte@Sun.COM ha->flags &= ~QL_OPENED;
1797836SJohn.Forte@Sun.COM ADAPTER_STATE_UNLOCK(ha);
1807836SJohn.Forte@Sun.COM
1817836SJohn.Forte@Sun.COM if (rval != 0) {
1827836SJohn.Forte@Sun.COM EL(ha, "failed, rval = %xh\n", rval);
1837836SJohn.Forte@Sun.COM } else {
1847836SJohn.Forte@Sun.COM /*EMPTY*/
1857836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
1867836SJohn.Forte@Sun.COM }
1877836SJohn.Forte@Sun.COM return (rval);
1887836SJohn.Forte@Sun.COM }
1897836SJohn.Forte@Sun.COM
1907836SJohn.Forte@Sun.COM /*
1917836SJohn.Forte@Sun.COM * ql_ioctl
1927836SJohn.Forte@Sun.COM * control a character device
1937836SJohn.Forte@Sun.COM *
1947836SJohn.Forte@Sun.COM * Input:
1957836SJohn.Forte@Sun.COM * dev = device number
1967836SJohn.Forte@Sun.COM * cmd = function to perform
1977836SJohn.Forte@Sun.COM * arg = data type varies with request
1987836SJohn.Forte@Sun.COM * mode = flags
1997836SJohn.Forte@Sun.COM * cred_p = credentials pointer
2007836SJohn.Forte@Sun.COM * rval_p = pointer to result value
2017836SJohn.Forte@Sun.COM *
2027836SJohn.Forte@Sun.COM * Returns:
2037836SJohn.Forte@Sun.COM * 0 = success
2047836SJohn.Forte@Sun.COM *
2057836SJohn.Forte@Sun.COM * Context:
2067836SJohn.Forte@Sun.COM * Kernel context.
2077836SJohn.Forte@Sun.COM */
2087836SJohn.Forte@Sun.COM /* ARGSUSED */
2097836SJohn.Forte@Sun.COM int
ql_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cred_p,int * rval_p)2107836SJohn.Forte@Sun.COM ql_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p,
2117836SJohn.Forte@Sun.COM int *rval_p)
2127836SJohn.Forte@Sun.COM {
2137836SJohn.Forte@Sun.COM ql_adapter_state_t *ha;
2147836SJohn.Forte@Sun.COM int rval = 0;
2157836SJohn.Forte@Sun.COM
2167836SJohn.Forte@Sun.COM if (ddi_in_panic()) {
2179446SDaniel.Beauregard@Sun.COM QL_PRINT_2(CE_CONT, "ql_ioctl: ddi_in_panic exit\n");
2187836SJohn.Forte@Sun.COM return (ENOPROTOOPT);
2197836SJohn.Forte@Sun.COM }
2207836SJohn.Forte@Sun.COM
2217836SJohn.Forte@Sun.COM ha = ddi_get_soft_state(ql_state, (int32_t)getminor(dev));
2227836SJohn.Forte@Sun.COM if (ha == NULL) {
2237836SJohn.Forte@Sun.COM QL_PRINT_2(CE_CONT, "failed, no adapter\n");
2247836SJohn.Forte@Sun.COM return (ENXIO);
2257836SJohn.Forte@Sun.COM }
2267836SJohn.Forte@Sun.COM
2277836SJohn.Forte@Sun.COM QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
2287836SJohn.Forte@Sun.COM
2297836SJohn.Forte@Sun.COM /*
2307836SJohn.Forte@Sun.COM * Quick clean exit for qla2x00 foapi calls which are
2317836SJohn.Forte@Sun.COM * not supported in qlc.
2327836SJohn.Forte@Sun.COM */
2337836SJohn.Forte@Sun.COM if (cmd >= QL_FOAPI_START && cmd <= QL_FOAPI_END) {
2347836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "failed, fo api not supported\n");
2357836SJohn.Forte@Sun.COM return (ENOTTY);
2367836SJohn.Forte@Sun.COM }
2377836SJohn.Forte@Sun.COM
2387836SJohn.Forte@Sun.COM /* PWR management busy. */
2397836SJohn.Forte@Sun.COM rval = ql_busy_notification(ha);
2407836SJohn.Forte@Sun.COM if (rval != FC_SUCCESS) {
2417836SJohn.Forte@Sun.COM EL(ha, "failed, ql_busy_notification\n");
2427836SJohn.Forte@Sun.COM return (ENXIO);
2437836SJohn.Forte@Sun.COM }
2447836SJohn.Forte@Sun.COM
2457836SJohn.Forte@Sun.COM rval = ql_xioctl(ha, cmd, arg, mode, cred_p, rval_p);
2467836SJohn.Forte@Sun.COM if (rval == ENOPROTOOPT || rval == EINVAL) {
2477836SJohn.Forte@Sun.COM switch (cmd) {
2489156SDaniel.Beauregard@Sun.COM case QL_GET_ADAPTER_FEATURE_BITS: {
2497836SJohn.Forte@Sun.COM uint16_t bits;
2507836SJohn.Forte@Sun.COM
2517836SJohn.Forte@Sun.COM rval = ql_get_feature_bits(ha, &bits);
2527836SJohn.Forte@Sun.COM
2537836SJohn.Forte@Sun.COM if (!rval && ddi_copyout((void *)&bits, (void *)arg,
2547836SJohn.Forte@Sun.COM sizeof (bits), mode)) {
2557836SJohn.Forte@Sun.COM rval = EFAULT;
2567836SJohn.Forte@Sun.COM }
2577836SJohn.Forte@Sun.COM break;
2587836SJohn.Forte@Sun.COM }
2597836SJohn.Forte@Sun.COM
2609156SDaniel.Beauregard@Sun.COM case QL_SET_ADAPTER_FEATURE_BITS: {
2617836SJohn.Forte@Sun.COM uint16_t bits;
2627836SJohn.Forte@Sun.COM
2637836SJohn.Forte@Sun.COM if (ddi_copyin((void *)arg, (void *)&bits,
2647836SJohn.Forte@Sun.COM sizeof (bits), mode)) {
2657836SJohn.Forte@Sun.COM rval = EFAULT;
2667836SJohn.Forte@Sun.COM break;
2677836SJohn.Forte@Sun.COM }
2687836SJohn.Forte@Sun.COM
2697836SJohn.Forte@Sun.COM rval = ql_set_feature_bits(ha, bits);
2707836SJohn.Forte@Sun.COM break;
2717836SJohn.Forte@Sun.COM }
2727836SJohn.Forte@Sun.COM
2737836SJohn.Forte@Sun.COM case QL_SET_ADAPTER_NVRAM_DEFAULTS:
2747836SJohn.Forte@Sun.COM rval = ql_set_nvram_adapter_defaults(ha);
2757836SJohn.Forte@Sun.COM break;
2767836SJohn.Forte@Sun.COM
2777836SJohn.Forte@Sun.COM case QL_UTIL_LOAD:
2787836SJohn.Forte@Sun.COM rval = ql_nv_util_load(ha, (void *)arg, mode);
2797836SJohn.Forte@Sun.COM break;
2807836SJohn.Forte@Sun.COM
2817836SJohn.Forte@Sun.COM case QL_UTIL_DUMP:
2827836SJohn.Forte@Sun.COM rval = ql_nv_util_dump(ha, (void *)arg, mode);
2837836SJohn.Forte@Sun.COM break;
2847836SJohn.Forte@Sun.COM
2857836SJohn.Forte@Sun.COM case QL_ADM_OP:
2867836SJohn.Forte@Sun.COM rval = ql_adm_op(ha, (void *)arg, mode);
2877836SJohn.Forte@Sun.COM break;
2887836SJohn.Forte@Sun.COM
2897836SJohn.Forte@Sun.COM default:
2907836SJohn.Forte@Sun.COM EL(ha, "unknown command = %d\n", cmd);
2917836SJohn.Forte@Sun.COM rval = ENOTTY;
2927836SJohn.Forte@Sun.COM break;
2937836SJohn.Forte@Sun.COM }
2947836SJohn.Forte@Sun.COM }
2957836SJohn.Forte@Sun.COM
2967836SJohn.Forte@Sun.COM /* PWR management idle. */
2977836SJohn.Forte@Sun.COM (void) ql_idle_notification(ha);
2987836SJohn.Forte@Sun.COM
2997836SJohn.Forte@Sun.COM if (rval != 0) {
300*12279SDaniel.Beauregard@Sun.COM /*
301*12279SDaniel.Beauregard@Sun.COM * Don't show failures caused by pps polling for
302*12279SDaniel.Beauregard@Sun.COM * non-existant virtual ports.
303*12279SDaniel.Beauregard@Sun.COM */
304*12279SDaniel.Beauregard@Sun.COM if (cmd != EXT_CC_VPORT_CMD) {
305*12279SDaniel.Beauregard@Sun.COM EL(ha, "failed, cmd=%d rval=%d\n", cmd, rval);
306*12279SDaniel.Beauregard@Sun.COM }
3077836SJohn.Forte@Sun.COM } else {
3087836SJohn.Forte@Sun.COM /*EMPTY*/
3097836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3107836SJohn.Forte@Sun.COM }
3117836SJohn.Forte@Sun.COM return (rval);
3127836SJohn.Forte@Sun.COM }
3137836SJohn.Forte@Sun.COM
3147836SJohn.Forte@Sun.COM /*
3157836SJohn.Forte@Sun.COM * ql_busy_notification
3167836SJohn.Forte@Sun.COM * Adapter busy notification.
3177836SJohn.Forte@Sun.COM *
3187836SJohn.Forte@Sun.COM * Input:
3197836SJohn.Forte@Sun.COM * ha = adapter state pointer.
3207836SJohn.Forte@Sun.COM *
3217836SJohn.Forte@Sun.COM * Returns:
3227836SJohn.Forte@Sun.COM * FC_SUCCESS
3237836SJohn.Forte@Sun.COM * FC_FAILURE
3247836SJohn.Forte@Sun.COM *
3257836SJohn.Forte@Sun.COM * Context:
3267836SJohn.Forte@Sun.COM * Kernel context.
3277836SJohn.Forte@Sun.COM */
3287836SJohn.Forte@Sun.COM static int
ql_busy_notification(ql_adapter_state_t * ha)3297836SJohn.Forte@Sun.COM ql_busy_notification(ql_adapter_state_t *ha)
3307836SJohn.Forte@Sun.COM {
3317836SJohn.Forte@Sun.COM if (!ha->pm_capable) {
3327836SJohn.Forte@Sun.COM return (FC_SUCCESS);
3337836SJohn.Forte@Sun.COM }
3347836SJohn.Forte@Sun.COM
3357836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
3367836SJohn.Forte@Sun.COM
3377836SJohn.Forte@Sun.COM QL_PM_LOCK(ha);
3387836SJohn.Forte@Sun.COM ha->busy++;
3397836SJohn.Forte@Sun.COM QL_PM_UNLOCK(ha);
3407836SJohn.Forte@Sun.COM
3417836SJohn.Forte@Sun.COM if (pm_busy_component(ha->dip, 0) != DDI_SUCCESS) {
3427836SJohn.Forte@Sun.COM QL_PM_LOCK(ha);
3437836SJohn.Forte@Sun.COM ha->busy--;
3447836SJohn.Forte@Sun.COM QL_PM_UNLOCK(ha);
3457836SJohn.Forte@Sun.COM
3467836SJohn.Forte@Sun.COM EL(ha, "pm_busy_component failed = %xh\n", FC_FAILURE);
3477836SJohn.Forte@Sun.COM return (FC_FAILURE);
3487836SJohn.Forte@Sun.COM }
3497836SJohn.Forte@Sun.COM
3507836SJohn.Forte@Sun.COM QL_PM_LOCK(ha);
3517836SJohn.Forte@Sun.COM if (ha->power_level != PM_LEVEL_D0) {
3527836SJohn.Forte@Sun.COM QL_PM_UNLOCK(ha);
3537836SJohn.Forte@Sun.COM if (pm_raise_power(ha->dip, 0, 1) != DDI_SUCCESS) {
3547836SJohn.Forte@Sun.COM QL_PM_LOCK(ha);
3557836SJohn.Forte@Sun.COM ha->busy--;
3567836SJohn.Forte@Sun.COM QL_PM_UNLOCK(ha);
3577836SJohn.Forte@Sun.COM return (FC_FAILURE);
3587836SJohn.Forte@Sun.COM }
3597836SJohn.Forte@Sun.COM } else {
3607836SJohn.Forte@Sun.COM QL_PM_UNLOCK(ha);
3617836SJohn.Forte@Sun.COM }
3627836SJohn.Forte@Sun.COM
3637836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
3647836SJohn.Forte@Sun.COM
3657836SJohn.Forte@Sun.COM return (FC_SUCCESS);
3667836SJohn.Forte@Sun.COM }
3677836SJohn.Forte@Sun.COM
3687836SJohn.Forte@Sun.COM /*
3697836SJohn.Forte@Sun.COM * ql_idle_notification
3707836SJohn.Forte@Sun.COM * Adapter idle notification.
3717836SJohn.Forte@Sun.COM *
3727836SJohn.Forte@Sun.COM * Input:
3737836SJohn.Forte@Sun.COM * ha = adapter state pointer.
3747836SJohn.Forte@Sun.COM *
3757836SJohn.Forte@Sun.COM * Returns:
3767836SJohn.Forte@Sun.COM * FC_SUCCESS
3777836SJohn.Forte@Sun.COM * FC_FAILURE
3787836SJohn.Forte@Sun.COM *
3797836SJohn.Forte@Sun.COM * Context:
3807836SJohn.Forte@Sun.COM * Kernel context.
3817836SJohn.Forte@Sun.COM */
3827836SJohn.Forte@Sun.COM static int
ql_idle_notification(ql_adapter_state_t * ha)3837836SJohn.Forte@Sun.COM ql_idle_notification(ql_adapter_state_t *ha)
3847836SJohn.Forte@Sun.COM {
3857836SJohn.Forte@Sun.COM if (!ha->pm_capable) {
3867836SJohn.Forte@Sun.COM return (FC_SUCCESS);
3877836SJohn.Forte@Sun.COM }
3887836SJohn.Forte@Sun.COM
3897836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
3907836SJohn.Forte@Sun.COM
3917836SJohn.Forte@Sun.COM if (pm_idle_component(ha->dip, 0) != DDI_SUCCESS) {
3927836SJohn.Forte@Sun.COM EL(ha, "pm_idle_component failed = %xh\n", FC_FAILURE);
3937836SJohn.Forte@Sun.COM return (FC_FAILURE);
3947836SJohn.Forte@Sun.COM }
3957836SJohn.Forte@Sun.COM
3967836SJohn.Forte@Sun.COM QL_PM_LOCK(ha);
3977836SJohn.Forte@Sun.COM ha->busy--;
3987836SJohn.Forte@Sun.COM QL_PM_UNLOCK(ha);
3997836SJohn.Forte@Sun.COM
4007836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
4017836SJohn.Forte@Sun.COM
4027836SJohn.Forte@Sun.COM return (FC_SUCCESS);
4037836SJohn.Forte@Sun.COM }
4047836SJohn.Forte@Sun.COM
4057836SJohn.Forte@Sun.COM /*
4067836SJohn.Forte@Sun.COM * Get adapter feature bits from NVRAM
4077836SJohn.Forte@Sun.COM */
4087836SJohn.Forte@Sun.COM static int
ql_get_feature_bits(ql_adapter_state_t * ha,uint16_t * features)4097836SJohn.Forte@Sun.COM ql_get_feature_bits(ql_adapter_state_t *ha, uint16_t *features)
4107836SJohn.Forte@Sun.COM {
4117836SJohn.Forte@Sun.COM int count;
4127836SJohn.Forte@Sun.COM volatile uint16_t data;
4137836SJohn.Forte@Sun.COM uint32_t nv_cmd;
4147836SJohn.Forte@Sun.COM uint32_t start_addr;
4157836SJohn.Forte@Sun.COM int rval;
4167836SJohn.Forte@Sun.COM uint32_t offset = offsetof(nvram_t, adapter_features);
4177836SJohn.Forte@Sun.COM
4187836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
4197836SJohn.Forte@Sun.COM
42011924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_24258081)) {
4217836SJohn.Forte@Sun.COM EL(ha, "Not supported for 24xx\n");
4227836SJohn.Forte@Sun.COM return (EINVAL);
4237836SJohn.Forte@Sun.COM }
4247836SJohn.Forte@Sun.COM
4257836SJohn.Forte@Sun.COM /*
4267836SJohn.Forte@Sun.COM * The offset can't be greater than max of 8 bits and
4277836SJohn.Forte@Sun.COM * the following code breaks if the offset isn't at
4287836SJohn.Forte@Sun.COM * 2 byte boundary.
4297836SJohn.Forte@Sun.COM */
4307836SJohn.Forte@Sun.COM rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
4317836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
4327836SJohn.Forte@Sun.COM EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
4337836SJohn.Forte@Sun.COM return (EIO);
4347836SJohn.Forte@Sun.COM }
4357836SJohn.Forte@Sun.COM
4367836SJohn.Forte@Sun.COM /*
4377836SJohn.Forte@Sun.COM * Have the most significant 3 bits represent the read operation
4387836SJohn.Forte@Sun.COM * followed by the 8 bits representing the offset at which we
4397836SJohn.Forte@Sun.COM * are going to perform the read operation
4407836SJohn.Forte@Sun.COM */
4417836SJohn.Forte@Sun.COM offset >>= 1;
4427836SJohn.Forte@Sun.COM offset += start_addr;
4437836SJohn.Forte@Sun.COM nv_cmd = (offset << 16) | NV_READ_OP;
4447836SJohn.Forte@Sun.COM nv_cmd <<= 5;
4457836SJohn.Forte@Sun.COM
4467836SJohn.Forte@Sun.COM /*
4477836SJohn.Forte@Sun.COM * Select the chip and feed the command and address
4487836SJohn.Forte@Sun.COM */
4497836SJohn.Forte@Sun.COM for (count = 0; count < 11; count++) {
4507836SJohn.Forte@Sun.COM if (nv_cmd & BIT_31) {
4517836SJohn.Forte@Sun.COM ql_nv_write(ha, NV_DATA_OUT);
4527836SJohn.Forte@Sun.COM } else {
4537836SJohn.Forte@Sun.COM ql_nv_write(ha, 0);
4547836SJohn.Forte@Sun.COM }
4557836SJohn.Forte@Sun.COM nv_cmd <<= 1;
4567836SJohn.Forte@Sun.COM }
4577836SJohn.Forte@Sun.COM
4587836SJohn.Forte@Sun.COM *features = 0;
4597836SJohn.Forte@Sun.COM for (count = 0; count < 16; count++) {
4607836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_SELECT | NV_CLOCK);
4617836SJohn.Forte@Sun.COM ql_nv_delay();
4627836SJohn.Forte@Sun.COM
4637836SJohn.Forte@Sun.COM data = RD16_IO_REG(ha, nvram);
4647836SJohn.Forte@Sun.COM *features <<= 1;
4657836SJohn.Forte@Sun.COM if (data & NV_DATA_IN) {
4667836SJohn.Forte@Sun.COM *features = (uint16_t)(*features | 0x1);
4677836SJohn.Forte@Sun.COM }
4687836SJohn.Forte@Sun.COM
4697836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_SELECT);
4707836SJohn.Forte@Sun.COM ql_nv_delay();
4717836SJohn.Forte@Sun.COM }
4727836SJohn.Forte@Sun.COM
4737836SJohn.Forte@Sun.COM /*
4747836SJohn.Forte@Sun.COM * Deselect the chip
4757836SJohn.Forte@Sun.COM */
4767836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_DESELECT);
4777836SJohn.Forte@Sun.COM
4787836SJohn.Forte@Sun.COM ql_release_nvram(ha);
4797836SJohn.Forte@Sun.COM
4807836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
4817836SJohn.Forte@Sun.COM
4827836SJohn.Forte@Sun.COM return (0);
4837836SJohn.Forte@Sun.COM }
4847836SJohn.Forte@Sun.COM
4857836SJohn.Forte@Sun.COM /*
4867836SJohn.Forte@Sun.COM * Set adapter feature bits in NVRAM
4877836SJohn.Forte@Sun.COM */
4887836SJohn.Forte@Sun.COM static int
ql_set_feature_bits(ql_adapter_state_t * ha,uint16_t features)4897836SJohn.Forte@Sun.COM ql_set_feature_bits(ql_adapter_state_t *ha, uint16_t features)
4907836SJohn.Forte@Sun.COM {
4917836SJohn.Forte@Sun.COM int rval;
4927836SJohn.Forte@Sun.COM uint32_t count;
4937836SJohn.Forte@Sun.COM nvram_t *nv;
4947836SJohn.Forte@Sun.COM uint16_t *wptr;
4957836SJohn.Forte@Sun.COM uint8_t *bptr;
4967836SJohn.Forte@Sun.COM uint8_t csum;
4977836SJohn.Forte@Sun.COM uint32_t start_addr;
4987836SJohn.Forte@Sun.COM
4997836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
5007836SJohn.Forte@Sun.COM
50111924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_24258081)) {
5027836SJohn.Forte@Sun.COM EL(ha, "Not supported for 24xx\n");
5037836SJohn.Forte@Sun.COM return (EINVAL);
5047836SJohn.Forte@Sun.COM }
5057836SJohn.Forte@Sun.COM
5067836SJohn.Forte@Sun.COM nv = kmem_zalloc(sizeof (*nv), KM_SLEEP);
5077836SJohn.Forte@Sun.COM if (nv == NULL) {
5087836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
5097836SJohn.Forte@Sun.COM return (ENOMEM);
5107836SJohn.Forte@Sun.COM }
5117836SJohn.Forte@Sun.COM
5127836SJohn.Forte@Sun.COM rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
5137836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
5147836SJohn.Forte@Sun.COM EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
5157836SJohn.Forte@Sun.COM kmem_free(nv, sizeof (*nv));
5167836SJohn.Forte@Sun.COM return (EIO);
5177836SJohn.Forte@Sun.COM }
5187836SJohn.Forte@Sun.COM rval = 0;
5197836SJohn.Forte@Sun.COM
5207836SJohn.Forte@Sun.COM /*
5217836SJohn.Forte@Sun.COM * Read off the whole NVRAM
5227836SJohn.Forte@Sun.COM */
5237836SJohn.Forte@Sun.COM wptr = (uint16_t *)nv;
5247836SJohn.Forte@Sun.COM csum = 0;
5257836SJohn.Forte@Sun.COM for (count = 0; count < sizeof (nvram_t) / 2; count++) {
5267836SJohn.Forte@Sun.COM *wptr = (uint16_t)ql_get_nvram_word(ha, count + start_addr);
5277836SJohn.Forte@Sun.COM csum = (uint8_t)(csum + (uint8_t)*wptr);
5287836SJohn.Forte@Sun.COM csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8));
5297836SJohn.Forte@Sun.COM wptr++;
5307836SJohn.Forte@Sun.COM }
5317836SJohn.Forte@Sun.COM
5327836SJohn.Forte@Sun.COM /*
5337836SJohn.Forte@Sun.COM * If the checksum is BAD then fail it right here.
5347836SJohn.Forte@Sun.COM */
5357836SJohn.Forte@Sun.COM if (csum) {
5367836SJohn.Forte@Sun.COM kmem_free(nv, sizeof (*nv));
5377836SJohn.Forte@Sun.COM ql_release_nvram(ha);
5387836SJohn.Forte@Sun.COM return (EBADF);
5397836SJohn.Forte@Sun.COM }
5407836SJohn.Forte@Sun.COM
5417836SJohn.Forte@Sun.COM nv->adapter_features[0] = (uint8_t)((features & 0xFF00) >> 8);
5427836SJohn.Forte@Sun.COM nv->adapter_features[1] = (uint8_t)(features & 0xFF);
5437836SJohn.Forte@Sun.COM
5447836SJohn.Forte@Sun.COM /*
5457836SJohn.Forte@Sun.COM * Recompute the chesksum now
5467836SJohn.Forte@Sun.COM */
5477836SJohn.Forte@Sun.COM bptr = (uint8_t *)nv;
5487836SJohn.Forte@Sun.COM for (count = 0; count < sizeof (nvram_t) - 1; count++) {
5497836SJohn.Forte@Sun.COM csum = (uint8_t)(csum + *bptr++);
5507836SJohn.Forte@Sun.COM }
5517836SJohn.Forte@Sun.COM csum = (uint8_t)(~csum + 1);
5527836SJohn.Forte@Sun.COM nv->checksum = csum;
5537836SJohn.Forte@Sun.COM
5547836SJohn.Forte@Sun.COM /*
5557836SJohn.Forte@Sun.COM * Now load the NVRAM
5567836SJohn.Forte@Sun.COM */
5577836SJohn.Forte@Sun.COM wptr = (uint16_t *)nv;
5587836SJohn.Forte@Sun.COM for (count = 0; count < sizeof (nvram_t) / 2; count++) {
5597836SJohn.Forte@Sun.COM ql_load_nvram(ha, (uint8_t)(count + start_addr), *wptr++);
5607836SJohn.Forte@Sun.COM }
5617836SJohn.Forte@Sun.COM
5627836SJohn.Forte@Sun.COM /*
5637836SJohn.Forte@Sun.COM * Read NVRAM and verify the contents
5647836SJohn.Forte@Sun.COM */
5657836SJohn.Forte@Sun.COM wptr = (uint16_t *)nv;
5667836SJohn.Forte@Sun.COM csum = 0;
5677836SJohn.Forte@Sun.COM for (count = 0; count < sizeof (nvram_t) / 2; count++) {
5687836SJohn.Forte@Sun.COM if (ql_get_nvram_word(ha, count + start_addr) != *wptr) {
5697836SJohn.Forte@Sun.COM rval = EIO;
5707836SJohn.Forte@Sun.COM break;
5717836SJohn.Forte@Sun.COM }
5727836SJohn.Forte@Sun.COM csum = (uint8_t)(csum + (uint8_t)*wptr);
5737836SJohn.Forte@Sun.COM csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8));
5747836SJohn.Forte@Sun.COM wptr++;
5757836SJohn.Forte@Sun.COM }
5767836SJohn.Forte@Sun.COM
5777836SJohn.Forte@Sun.COM if (csum) {
5787836SJohn.Forte@Sun.COM rval = EINVAL;
5797836SJohn.Forte@Sun.COM }
5807836SJohn.Forte@Sun.COM
5817836SJohn.Forte@Sun.COM kmem_free(nv, sizeof (*nv));
5827836SJohn.Forte@Sun.COM ql_release_nvram(ha);
5837836SJohn.Forte@Sun.COM
5847836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
5857836SJohn.Forte@Sun.COM
5867836SJohn.Forte@Sun.COM return (rval);
5877836SJohn.Forte@Sun.COM }
5887836SJohn.Forte@Sun.COM
5897836SJohn.Forte@Sun.COM /*
5907836SJohn.Forte@Sun.COM * Fix this function to update just feature bits and checksum in NVRAM
5917836SJohn.Forte@Sun.COM */
5927836SJohn.Forte@Sun.COM static int
ql_set_nvram_adapter_defaults(ql_adapter_state_t * ha)5937836SJohn.Forte@Sun.COM ql_set_nvram_adapter_defaults(ql_adapter_state_t *ha)
5947836SJohn.Forte@Sun.COM {
5957836SJohn.Forte@Sun.COM int rval;
5967836SJohn.Forte@Sun.COM uint32_t count;
5977836SJohn.Forte@Sun.COM uint32_t start_addr;
5987836SJohn.Forte@Sun.COM
5997836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
6007836SJohn.Forte@Sun.COM
6017836SJohn.Forte@Sun.COM rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
6027836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
6037836SJohn.Forte@Sun.COM EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
6047836SJohn.Forte@Sun.COM return (EIO);
6057836SJohn.Forte@Sun.COM }
6067836SJohn.Forte@Sun.COM rval = 0;
6077836SJohn.Forte@Sun.COM
60811924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_24258081)) {
6097836SJohn.Forte@Sun.COM nvram_24xx_t *nv;
6107836SJohn.Forte@Sun.COM uint32_t *longptr;
6117836SJohn.Forte@Sun.COM uint32_t csum = 0;
6127836SJohn.Forte@Sun.COM
6137836SJohn.Forte@Sun.COM nv = kmem_zalloc(sizeof (*nv), KM_SLEEP);
6147836SJohn.Forte@Sun.COM if (nv == NULL) {
6157836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
6167836SJohn.Forte@Sun.COM return (ENOMEM);
6177836SJohn.Forte@Sun.COM }
6187836SJohn.Forte@Sun.COM
6197836SJohn.Forte@Sun.COM nv->nvram_version[0] = LSB(ICB_24XX_VERSION);
6207836SJohn.Forte@Sun.COM nv->nvram_version[1] = MSB(ICB_24XX_VERSION);
6217836SJohn.Forte@Sun.COM
6227836SJohn.Forte@Sun.COM nv->version[0] = 1;
6237836SJohn.Forte@Sun.COM nv->max_frame_length[1] = 8;
6247836SJohn.Forte@Sun.COM nv->execution_throttle[0] = 16;
6257836SJohn.Forte@Sun.COM nv->login_retry_count[0] = 8;
6267836SJohn.Forte@Sun.COM
6277836SJohn.Forte@Sun.COM nv->firmware_options_1[0] = BIT_2 | BIT_1;
6287836SJohn.Forte@Sun.COM nv->firmware_options_1[1] = BIT_5;
6297836SJohn.Forte@Sun.COM nv->firmware_options_2[0] = BIT_5;
6307836SJohn.Forte@Sun.COM nv->firmware_options_2[1] = BIT_4;
6317836SJohn.Forte@Sun.COM nv->firmware_options_3[1] = BIT_6;
6327836SJohn.Forte@Sun.COM
6337836SJohn.Forte@Sun.COM /*
6347836SJohn.Forte@Sun.COM * Set default host adapter parameters
6357836SJohn.Forte@Sun.COM */
6367836SJohn.Forte@Sun.COM nv->host_p[0] = BIT_4 | BIT_1;
6377836SJohn.Forte@Sun.COM nv->host_p[1] = BIT_3 | BIT_2;
6387836SJohn.Forte@Sun.COM nv->reset_delay = 5;
6397836SJohn.Forte@Sun.COM nv->max_luns_per_target[0] = 128;
6407836SJohn.Forte@Sun.COM nv->port_down_retry_count[0] = 30;
6417836SJohn.Forte@Sun.COM nv->link_down_timeout[0] = 30;
6427836SJohn.Forte@Sun.COM
6437836SJohn.Forte@Sun.COM /*
6447836SJohn.Forte@Sun.COM * compute the chesksum now
6457836SJohn.Forte@Sun.COM */
6467836SJohn.Forte@Sun.COM longptr = (uint32_t *)nv;
6477836SJohn.Forte@Sun.COM csum = 0;
6487836SJohn.Forte@Sun.COM for (count = 0; count < (sizeof (nvram_24xx_t)/4)-1; count++) {
6497836SJohn.Forte@Sun.COM csum += *longptr;
6507836SJohn.Forte@Sun.COM longptr++;
6517836SJohn.Forte@Sun.COM }
6527836SJohn.Forte@Sun.COM csum = (uint32_t)(~csum + 1);
6537836SJohn.Forte@Sun.COM LITTLE_ENDIAN_32((long)csum);
6547836SJohn.Forte@Sun.COM *longptr = csum;
6557836SJohn.Forte@Sun.COM
6567836SJohn.Forte@Sun.COM /*
6577836SJohn.Forte@Sun.COM * Now load the NVRAM
6587836SJohn.Forte@Sun.COM */
6597836SJohn.Forte@Sun.COM longptr = (uint32_t *)nv;
6607836SJohn.Forte@Sun.COM for (count = 0; count < sizeof (nvram_24xx_t) / 4; count++) {
6617836SJohn.Forte@Sun.COM (void) ql_24xx_load_nvram(ha,
6627836SJohn.Forte@Sun.COM (uint32_t)(count + start_addr), *longptr++);
6637836SJohn.Forte@Sun.COM }
6647836SJohn.Forte@Sun.COM
6657836SJohn.Forte@Sun.COM /*
6667836SJohn.Forte@Sun.COM * Read NVRAM and verify the contents
6677836SJohn.Forte@Sun.COM */
6687836SJohn.Forte@Sun.COM csum = 0;
6697836SJohn.Forte@Sun.COM longptr = (uint32_t *)nv;
6707836SJohn.Forte@Sun.COM for (count = 0; count < sizeof (nvram_24xx_t) / 4; count++) {
6717836SJohn.Forte@Sun.COM rval = ql_24xx_read_flash(ha, count + start_addr,
6727836SJohn.Forte@Sun.COM longptr);
6737836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
6747836SJohn.Forte@Sun.COM EL(ha, "24xx_read_flash failed=%xh\n", rval);
6757836SJohn.Forte@Sun.COM break;
6767836SJohn.Forte@Sun.COM }
6777836SJohn.Forte@Sun.COM csum += *longptr;
6787836SJohn.Forte@Sun.COM }
6797836SJohn.Forte@Sun.COM
6807836SJohn.Forte@Sun.COM if (csum) {
6817836SJohn.Forte@Sun.COM rval = EINVAL;
6827836SJohn.Forte@Sun.COM }
6837836SJohn.Forte@Sun.COM kmem_free(nv, sizeof (nvram_24xx_t));
6847836SJohn.Forte@Sun.COM } else {
6857836SJohn.Forte@Sun.COM nvram_t *nv;
6867836SJohn.Forte@Sun.COM uint16_t *wptr;
6877836SJohn.Forte@Sun.COM uint8_t *bptr;
6887836SJohn.Forte@Sun.COM uint8_t csum;
6897836SJohn.Forte@Sun.COM
6907836SJohn.Forte@Sun.COM nv = kmem_zalloc(sizeof (*nv), KM_SLEEP);
6917836SJohn.Forte@Sun.COM if (nv == NULL) {
6927836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
6937836SJohn.Forte@Sun.COM return (ENOMEM);
6947836SJohn.Forte@Sun.COM }
6957836SJohn.Forte@Sun.COM /*
6967836SJohn.Forte@Sun.COM * Set default initialization control block.
6977836SJohn.Forte@Sun.COM */
6987836SJohn.Forte@Sun.COM nv->parameter_block_version = ICB_VERSION;
6997836SJohn.Forte@Sun.COM nv->firmware_options[0] = BIT_4 | BIT_3 | BIT_2 | BIT_1;
7007836SJohn.Forte@Sun.COM nv->firmware_options[1] = BIT_7 | BIT_5 | BIT_2;
7017836SJohn.Forte@Sun.COM
7027836SJohn.Forte@Sun.COM nv->max_frame_length[1] = 4;
7037836SJohn.Forte@Sun.COM nv->max_iocb_allocation[1] = 1;
7047836SJohn.Forte@Sun.COM nv->execution_throttle[0] = 16;
7057836SJohn.Forte@Sun.COM nv->login_retry_count = 8;
7067836SJohn.Forte@Sun.COM nv->port_name[0] = 33;
7077836SJohn.Forte@Sun.COM nv->port_name[3] = 224;
7087836SJohn.Forte@Sun.COM nv->port_name[4] = 139;
7097836SJohn.Forte@Sun.COM nv->login_timeout = 4;
7107836SJohn.Forte@Sun.COM
7117836SJohn.Forte@Sun.COM /*
7127836SJohn.Forte@Sun.COM * Set default host adapter parameters
7137836SJohn.Forte@Sun.COM */
7147836SJohn.Forte@Sun.COM nv->host_p[0] = BIT_1;
7157836SJohn.Forte@Sun.COM nv->host_p[1] = BIT_2;
7167836SJohn.Forte@Sun.COM nv->reset_delay = 5;
7177836SJohn.Forte@Sun.COM nv->port_down_retry_count = 8;
7187836SJohn.Forte@Sun.COM nv->maximum_luns_per_target[0] = 8;
7197836SJohn.Forte@Sun.COM
7207836SJohn.Forte@Sun.COM /*
7217836SJohn.Forte@Sun.COM * compute the chesksum now
7227836SJohn.Forte@Sun.COM */
7237836SJohn.Forte@Sun.COM bptr = (uint8_t *)nv;
7247836SJohn.Forte@Sun.COM csum = 0;
7257836SJohn.Forte@Sun.COM for (count = 0; count < sizeof (nvram_t) - 1; count++) {
7267836SJohn.Forte@Sun.COM csum = (uint8_t)(csum + *bptr++);
7277836SJohn.Forte@Sun.COM }
7287836SJohn.Forte@Sun.COM csum = (uint8_t)(~csum + 1);
7297836SJohn.Forte@Sun.COM nv->checksum = csum;
7307836SJohn.Forte@Sun.COM
7317836SJohn.Forte@Sun.COM /*
7327836SJohn.Forte@Sun.COM * Now load the NVRAM
7337836SJohn.Forte@Sun.COM */
7347836SJohn.Forte@Sun.COM wptr = (uint16_t *)nv;
7357836SJohn.Forte@Sun.COM for (count = 0; count < sizeof (nvram_t) / 2; count++) {
7367836SJohn.Forte@Sun.COM ql_load_nvram(ha, (uint8_t)(count + start_addr),
7377836SJohn.Forte@Sun.COM *wptr++);
7387836SJohn.Forte@Sun.COM }
7397836SJohn.Forte@Sun.COM
7407836SJohn.Forte@Sun.COM /*
7417836SJohn.Forte@Sun.COM * Read NVRAM and verify the contents
7427836SJohn.Forte@Sun.COM */
7437836SJohn.Forte@Sun.COM wptr = (uint16_t *)nv;
7447836SJohn.Forte@Sun.COM csum = 0;
7457836SJohn.Forte@Sun.COM for (count = 0; count < sizeof (nvram_t) / 2; count++) {
7467836SJohn.Forte@Sun.COM if (ql_get_nvram_word(ha, count + start_addr) !=
7477836SJohn.Forte@Sun.COM *wptr) {
7487836SJohn.Forte@Sun.COM rval = EIO;
7497836SJohn.Forte@Sun.COM break;
7507836SJohn.Forte@Sun.COM }
7517836SJohn.Forte@Sun.COM csum = (uint8_t)(csum + (uint8_t)*wptr);
7527836SJohn.Forte@Sun.COM csum = (uint8_t)(csum + (uint8_t)(*wptr >> 8));
7537836SJohn.Forte@Sun.COM wptr++;
7547836SJohn.Forte@Sun.COM }
7557836SJohn.Forte@Sun.COM if (csum) {
7567836SJohn.Forte@Sun.COM rval = EINVAL;
7577836SJohn.Forte@Sun.COM }
7587836SJohn.Forte@Sun.COM kmem_free(nv, sizeof (*nv));
7597836SJohn.Forte@Sun.COM }
7607836SJohn.Forte@Sun.COM ql_release_nvram(ha);
7617836SJohn.Forte@Sun.COM
7627836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
7637836SJohn.Forte@Sun.COM
7647836SJohn.Forte@Sun.COM return (rval);
7657836SJohn.Forte@Sun.COM }
7667836SJohn.Forte@Sun.COM
7677836SJohn.Forte@Sun.COM static void
ql_load_nvram(ql_adapter_state_t * ha,uint8_t addr,uint16_t value)7687836SJohn.Forte@Sun.COM ql_load_nvram(ql_adapter_state_t *ha, uint8_t addr, uint16_t value)
7697836SJohn.Forte@Sun.COM {
7707836SJohn.Forte@Sun.COM int count;
7717836SJohn.Forte@Sun.COM volatile uint16_t word;
7727836SJohn.Forte@Sun.COM volatile uint32_t nv_cmd;
7737836SJohn.Forte@Sun.COM
7747836SJohn.Forte@Sun.COM ql_nv_write(ha, NV_DATA_OUT);
7757836SJohn.Forte@Sun.COM ql_nv_write(ha, 0);
7767836SJohn.Forte@Sun.COM ql_nv_write(ha, 0);
7777836SJohn.Forte@Sun.COM
7787836SJohn.Forte@Sun.COM for (word = 0; word < 8; word++) {
7797836SJohn.Forte@Sun.COM ql_nv_write(ha, NV_DATA_OUT);
7807836SJohn.Forte@Sun.COM }
7817836SJohn.Forte@Sun.COM
7827836SJohn.Forte@Sun.COM /*
7837836SJohn.Forte@Sun.COM * Deselect the chip
7847836SJohn.Forte@Sun.COM */
7857836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_DESELECT);
7867836SJohn.Forte@Sun.COM ql_nv_delay();
7877836SJohn.Forte@Sun.COM
7887836SJohn.Forte@Sun.COM /*
7897836SJohn.Forte@Sun.COM * Erase Location
7907836SJohn.Forte@Sun.COM */
7917836SJohn.Forte@Sun.COM nv_cmd = (addr << 16) | NV_ERASE_OP;
7927836SJohn.Forte@Sun.COM nv_cmd <<= 5;
7937836SJohn.Forte@Sun.COM for (count = 0; count < 11; count++) {
7947836SJohn.Forte@Sun.COM if (nv_cmd & BIT_31) {
7957836SJohn.Forte@Sun.COM ql_nv_write(ha, NV_DATA_OUT);
7967836SJohn.Forte@Sun.COM } else {
7977836SJohn.Forte@Sun.COM ql_nv_write(ha, 0);
7987836SJohn.Forte@Sun.COM }
7997836SJohn.Forte@Sun.COM nv_cmd <<= 1;
8007836SJohn.Forte@Sun.COM }
8017836SJohn.Forte@Sun.COM
8027836SJohn.Forte@Sun.COM /*
8037836SJohn.Forte@Sun.COM * Wait for Erase to Finish
8047836SJohn.Forte@Sun.COM */
8057836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_DESELECT);
8067836SJohn.Forte@Sun.COM ql_nv_delay();
8077836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_SELECT);
8087836SJohn.Forte@Sun.COM word = 0;
8097836SJohn.Forte@Sun.COM while ((word & NV_DATA_IN) == 0) {
8107836SJohn.Forte@Sun.COM ql_nv_delay();
8117836SJohn.Forte@Sun.COM word = RD16_IO_REG(ha, nvram);
8127836SJohn.Forte@Sun.COM }
8137836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_DESELECT);
8147836SJohn.Forte@Sun.COM ql_nv_delay();
8157836SJohn.Forte@Sun.COM
8167836SJohn.Forte@Sun.COM /*
8177836SJohn.Forte@Sun.COM * Write data now
8187836SJohn.Forte@Sun.COM */
8197836SJohn.Forte@Sun.COM nv_cmd = (addr << 16) | NV_WRITE_OP;
8207836SJohn.Forte@Sun.COM nv_cmd |= value;
8217836SJohn.Forte@Sun.COM nv_cmd <<= 5;
8227836SJohn.Forte@Sun.COM for (count = 0; count < 27; count++) {
8237836SJohn.Forte@Sun.COM if (nv_cmd & BIT_31) {
8247836SJohn.Forte@Sun.COM ql_nv_write(ha, NV_DATA_OUT);
8257836SJohn.Forte@Sun.COM } else {
8267836SJohn.Forte@Sun.COM ql_nv_write(ha, 0);
8277836SJohn.Forte@Sun.COM }
8287836SJohn.Forte@Sun.COM nv_cmd <<= 1;
8297836SJohn.Forte@Sun.COM }
8307836SJohn.Forte@Sun.COM
8317836SJohn.Forte@Sun.COM /*
8327836SJohn.Forte@Sun.COM * Wait for NVRAM to become ready
8337836SJohn.Forte@Sun.COM */
8347836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_DESELECT);
8357836SJohn.Forte@Sun.COM ql_nv_delay();
8367836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_SELECT);
8377836SJohn.Forte@Sun.COM word = 0;
8387836SJohn.Forte@Sun.COM while ((word & NV_DATA_IN) == 0) {
8397836SJohn.Forte@Sun.COM ql_nv_delay();
8407836SJohn.Forte@Sun.COM word = RD16_IO_REG(ha, nvram);
8417836SJohn.Forte@Sun.COM }
8427836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_DESELECT);
8437836SJohn.Forte@Sun.COM ql_nv_delay();
8447836SJohn.Forte@Sun.COM
8457836SJohn.Forte@Sun.COM /*
8467836SJohn.Forte@Sun.COM * Disable writes
8477836SJohn.Forte@Sun.COM */
8487836SJohn.Forte@Sun.COM ql_nv_write(ha, NV_DATA_OUT);
8497836SJohn.Forte@Sun.COM for (count = 0; count < 10; count++) {
8507836SJohn.Forte@Sun.COM ql_nv_write(ha, 0);
8517836SJohn.Forte@Sun.COM }
8527836SJohn.Forte@Sun.COM
8537836SJohn.Forte@Sun.COM /*
8547836SJohn.Forte@Sun.COM * Deselect the chip now
8557836SJohn.Forte@Sun.COM */
8567836SJohn.Forte@Sun.COM WRT16_IO_REG(ha, nvram, NV_DESELECT);
8577836SJohn.Forte@Sun.COM }
8587836SJohn.Forte@Sun.COM
8597836SJohn.Forte@Sun.COM /*
8607836SJohn.Forte@Sun.COM * ql_24xx_load_nvram
8617836SJohn.Forte@Sun.COM * Enable NVRAM and writes a 32bit word to ISP24xx NVRAM.
8627836SJohn.Forte@Sun.COM *
8637836SJohn.Forte@Sun.COM * Input:
8647836SJohn.Forte@Sun.COM * ha: adapter state pointer.
8657836SJohn.Forte@Sun.COM * addr: NVRAM address.
8667836SJohn.Forte@Sun.COM * value: data.
8677836SJohn.Forte@Sun.COM *
8687836SJohn.Forte@Sun.COM * Returns:
8697836SJohn.Forte@Sun.COM * ql local function return status code.
8707836SJohn.Forte@Sun.COM *
8717836SJohn.Forte@Sun.COM * Context:
8727836SJohn.Forte@Sun.COM * Kernel context.
8737836SJohn.Forte@Sun.COM */
8747836SJohn.Forte@Sun.COM static int
ql_24xx_load_nvram(ql_adapter_state_t * ha,uint32_t addr,uint32_t value)8757836SJohn.Forte@Sun.COM ql_24xx_load_nvram(ql_adapter_state_t *ha, uint32_t addr, uint32_t value)
8767836SJohn.Forte@Sun.COM {
8777836SJohn.Forte@Sun.COM int rval;
8787836SJohn.Forte@Sun.COM
8797836SJohn.Forte@Sun.COM /* Enable flash write. */
88011924SDaniel.Beauregard@Sun.COM if (!(CFG_IST(ha, CFG_CTRL_8081))) {
8819446SDaniel.Beauregard@Sun.COM WRT32_IO_REG(ha, ctrl_status,
8829446SDaniel.Beauregard@Sun.COM RD32_IO_REG(ha, ctrl_status) | ISP_FLASH_ENABLE);
8839446SDaniel.Beauregard@Sun.COM RD32_IO_REG(ha, ctrl_status); /* PCI Posting. */
8849446SDaniel.Beauregard@Sun.COM }
8857836SJohn.Forte@Sun.COM
8867836SJohn.Forte@Sun.COM /* Disable NVRAM write-protection. */
8877836SJohn.Forte@Sun.COM if (CFG_IST(ha, CFG_CTRL_2422)) {
8887836SJohn.Forte@Sun.COM (void) ql_24xx_write_flash(ha, NVRAM_CONF_ADDR | 0x101, 0);
8897836SJohn.Forte@Sun.COM } else {
8909446SDaniel.Beauregard@Sun.COM if ((rval = ql_24xx_unprotect_flash(ha)) != QL_SUCCESS) {
8919446SDaniel.Beauregard@Sun.COM EL(ha, "unprotect_flash failed, rval=%xh\n", rval);
8929446SDaniel.Beauregard@Sun.COM return (rval);
8939446SDaniel.Beauregard@Sun.COM }
8947836SJohn.Forte@Sun.COM }
8957836SJohn.Forte@Sun.COM
8967836SJohn.Forte@Sun.COM /* Write to flash. */
8977836SJohn.Forte@Sun.COM rval = ql_24xx_write_flash(ha, addr, value);
8987836SJohn.Forte@Sun.COM
8997836SJohn.Forte@Sun.COM /* Enable NVRAM write-protection. */
9007836SJohn.Forte@Sun.COM if (CFG_IST(ha, CFG_CTRL_2422)) {
9017836SJohn.Forte@Sun.COM /* TODO: Check if 0x8c is correct -- sb: 0x9c ? */
9027836SJohn.Forte@Sun.COM (void) ql_24xx_write_flash(ha, NVRAM_CONF_ADDR | 0x101, 0x8c);
9037836SJohn.Forte@Sun.COM } else {
9047836SJohn.Forte@Sun.COM ql_24xx_protect_flash(ha);
9057836SJohn.Forte@Sun.COM }
9067836SJohn.Forte@Sun.COM
9077836SJohn.Forte@Sun.COM /* Disable flash write. */
9089446SDaniel.Beauregard@Sun.COM if (!(CFG_IST(ha, CFG_CTRL_81XX))) {
9099446SDaniel.Beauregard@Sun.COM WRT32_IO_REG(ha, ctrl_status,
9109446SDaniel.Beauregard@Sun.COM RD32_IO_REG(ha, ctrl_status) & ~ISP_FLASH_ENABLE);
9119446SDaniel.Beauregard@Sun.COM RD32_IO_REG(ha, ctrl_status); /* PCI Posting. */
9129446SDaniel.Beauregard@Sun.COM }
9137836SJohn.Forte@Sun.COM
9147836SJohn.Forte@Sun.COM return (rval);
9157836SJohn.Forte@Sun.COM }
9167836SJohn.Forte@Sun.COM
9177836SJohn.Forte@Sun.COM /*
9187836SJohn.Forte@Sun.COM * ql_nv_util_load
9197836SJohn.Forte@Sun.COM * Loads NVRAM from application.
9207836SJohn.Forte@Sun.COM *
9217836SJohn.Forte@Sun.COM * Input:
9227836SJohn.Forte@Sun.COM * ha = adapter state pointer.
9237836SJohn.Forte@Sun.COM * bp = user buffer address.
9247836SJohn.Forte@Sun.COM *
9257836SJohn.Forte@Sun.COM * Returns:
9267836SJohn.Forte@Sun.COM *
9277836SJohn.Forte@Sun.COM * Context:
9287836SJohn.Forte@Sun.COM * Kernel context.
9297836SJohn.Forte@Sun.COM */
9307836SJohn.Forte@Sun.COM int
ql_nv_util_load(ql_adapter_state_t * ha,void * bp,int mode)9317836SJohn.Forte@Sun.COM ql_nv_util_load(ql_adapter_state_t *ha, void *bp, int mode)
9327836SJohn.Forte@Sun.COM {
9337836SJohn.Forte@Sun.COM uint8_t cnt;
9347836SJohn.Forte@Sun.COM void *nv;
9357836SJohn.Forte@Sun.COM uint16_t *wptr;
9367836SJohn.Forte@Sun.COM uint16_t data;
93711541SDaniel.Beauregard@Sun.COM uint32_t start_addr, *lptr, data32;
9387836SJohn.Forte@Sun.COM nvram_t *nptr;
9397836SJohn.Forte@Sun.COM int rval;
9407836SJohn.Forte@Sun.COM
9417836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
9427836SJohn.Forte@Sun.COM
94311541SDaniel.Beauregard@Sun.COM if ((nv = kmem_zalloc(ha->nvram_cache->size, KM_SLEEP)) == NULL) {
9447836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
9457836SJohn.Forte@Sun.COM return (ENOMEM);
9467836SJohn.Forte@Sun.COM }
9477836SJohn.Forte@Sun.COM
94811541SDaniel.Beauregard@Sun.COM if (ddi_copyin(bp, nv, ha->nvram_cache->size, mode) != 0) {
9497836SJohn.Forte@Sun.COM EL(ha, "Buffer copy failed\n");
95011541SDaniel.Beauregard@Sun.COM kmem_free(nv, ha->nvram_cache->size);
9517836SJohn.Forte@Sun.COM return (EFAULT);
9527836SJohn.Forte@Sun.COM }
9537836SJohn.Forte@Sun.COM
9547836SJohn.Forte@Sun.COM /* See if the buffer passed to us looks sane */
9557836SJohn.Forte@Sun.COM nptr = (nvram_t *)nv;
9567836SJohn.Forte@Sun.COM if (nptr->id[0] != 'I' || nptr->id[1] != 'S' || nptr->id[2] != 'P' ||
9577836SJohn.Forte@Sun.COM nptr->id[3] != ' ') {
9587836SJohn.Forte@Sun.COM EL(ha, "failed, buffer sanity check\n");
95911541SDaniel.Beauregard@Sun.COM kmem_free(nv, ha->nvram_cache->size);
9607836SJohn.Forte@Sun.COM return (EINVAL);
9617836SJohn.Forte@Sun.COM }
9627836SJohn.Forte@Sun.COM
9637836SJohn.Forte@Sun.COM /* Quiesce I/O */
9647836SJohn.Forte@Sun.COM if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
9657836SJohn.Forte@Sun.COM EL(ha, "ql_stall_driver failed\n");
96611541SDaniel.Beauregard@Sun.COM kmem_free(nv, ha->nvram_cache->size);
9677836SJohn.Forte@Sun.COM return (EBUSY);
9687836SJohn.Forte@Sun.COM }
9697836SJohn.Forte@Sun.COM
9707836SJohn.Forte@Sun.COM rval = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
9717836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
9727836SJohn.Forte@Sun.COM EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
97311541SDaniel.Beauregard@Sun.COM kmem_free(nv, ha->nvram_cache->size);
9747836SJohn.Forte@Sun.COM ql_restart_driver(ha);
9757836SJohn.Forte@Sun.COM return (EIO);
9767836SJohn.Forte@Sun.COM }
9777836SJohn.Forte@Sun.COM
9787836SJohn.Forte@Sun.COM /* Load NVRAM. */
97911924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_258081)) {
9807836SJohn.Forte@Sun.COM GLOBAL_HW_UNLOCK();
9819446SDaniel.Beauregard@Sun.COM start_addr &= ~ha->flash_data_addr;
9829446SDaniel.Beauregard@Sun.COM start_addr <<= 2;
98311541SDaniel.Beauregard@Sun.COM if ((rval = ql_r_m_w_flash(ha, bp, ha->nvram_cache->size,
98411541SDaniel.Beauregard@Sun.COM start_addr, mode)) != QL_SUCCESS) {
9857836SJohn.Forte@Sun.COM EL(ha, "nvram load failed, rval = %0xh\n", rval);
9867836SJohn.Forte@Sun.COM }
9877836SJohn.Forte@Sun.COM GLOBAL_HW_LOCK();
9887836SJohn.Forte@Sun.COM } else if (CFG_IST(ha, CFG_CTRL_2422)) {
9897836SJohn.Forte@Sun.COM lptr = (uint32_t *)nv;
99011541SDaniel.Beauregard@Sun.COM for (cnt = 0; cnt < ha->nvram_cache->size / 4; cnt++) {
9917836SJohn.Forte@Sun.COM data32 = *lptr++;
9927836SJohn.Forte@Sun.COM LITTLE_ENDIAN_32(&data32);
9937836SJohn.Forte@Sun.COM rval = ql_24xx_load_nvram(ha, cnt + start_addr,
9947836SJohn.Forte@Sun.COM data32);
9957836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
9967836SJohn.Forte@Sun.COM EL(ha, "failed, 24xx_load_nvram=%xh\n", rval);
9977836SJohn.Forte@Sun.COM break;
9987836SJohn.Forte@Sun.COM }
9997836SJohn.Forte@Sun.COM }
10007836SJohn.Forte@Sun.COM } else {
10017836SJohn.Forte@Sun.COM wptr = (uint16_t *)nv;
100211541SDaniel.Beauregard@Sun.COM for (cnt = 0; cnt < ha->nvram_cache->size / 2; cnt++) {
10037836SJohn.Forte@Sun.COM data = *wptr++;
10047836SJohn.Forte@Sun.COM LITTLE_ENDIAN_16(&data);
10057836SJohn.Forte@Sun.COM ql_load_nvram(ha, (uint8_t)(cnt + start_addr), data);
10067836SJohn.Forte@Sun.COM }
10077836SJohn.Forte@Sun.COM }
100811541SDaniel.Beauregard@Sun.COM /* switch to the new one */
100911541SDaniel.Beauregard@Sun.COM NVRAM_CACHE_LOCK(ha);
10107836SJohn.Forte@Sun.COM
101111541SDaniel.Beauregard@Sun.COM kmem_free(ha->nvram_cache->cache, ha->nvram_cache->size);
101211541SDaniel.Beauregard@Sun.COM ha->nvram_cache->cache = (void *)nptr;
101311541SDaniel.Beauregard@Sun.COM
101411541SDaniel.Beauregard@Sun.COM NVRAM_CACHE_UNLOCK(ha);
101511541SDaniel.Beauregard@Sun.COM
10167836SJohn.Forte@Sun.COM ql_release_nvram(ha);
10177836SJohn.Forte@Sun.COM ql_restart_driver(ha);
10187836SJohn.Forte@Sun.COM
10197836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
10207836SJohn.Forte@Sun.COM
10217836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS) {
10227836SJohn.Forte@Sun.COM return (0);
10237836SJohn.Forte@Sun.COM }
10247836SJohn.Forte@Sun.COM
10257836SJohn.Forte@Sun.COM return (EFAULT);
10267836SJohn.Forte@Sun.COM }
10277836SJohn.Forte@Sun.COM
10287836SJohn.Forte@Sun.COM /*
10297836SJohn.Forte@Sun.COM * ql_nv_util_dump
10307836SJohn.Forte@Sun.COM * Dumps NVRAM to application.
10317836SJohn.Forte@Sun.COM *
10327836SJohn.Forte@Sun.COM * Input:
10337836SJohn.Forte@Sun.COM * ha = adapter state pointer.
10347836SJohn.Forte@Sun.COM * bp = user buffer address.
10357836SJohn.Forte@Sun.COM *
10367836SJohn.Forte@Sun.COM * Returns:
10377836SJohn.Forte@Sun.COM *
10387836SJohn.Forte@Sun.COM * Context:
10397836SJohn.Forte@Sun.COM * Kernel context.
10407836SJohn.Forte@Sun.COM */
10417836SJohn.Forte@Sun.COM int
ql_nv_util_dump(ql_adapter_state_t * ha,void * bp,int mode)10427836SJohn.Forte@Sun.COM ql_nv_util_dump(ql_adapter_state_t *ha, void *bp, int mode)
10437836SJohn.Forte@Sun.COM {
10447836SJohn.Forte@Sun.COM uint32_t start_addr;
10457836SJohn.Forte@Sun.COM int rval2, rval = 0;
10467836SJohn.Forte@Sun.COM
10477836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
10487836SJohn.Forte@Sun.COM
104911541SDaniel.Beauregard@Sun.COM if (ha->nvram_cache == NULL ||
105011541SDaniel.Beauregard@Sun.COM ha->nvram_cache->size == NULL ||
105111541SDaniel.Beauregard@Sun.COM ha->nvram_cache->cache == NULL) {
10527836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
10537836SJohn.Forte@Sun.COM return (ENOMEM);
105411541SDaniel.Beauregard@Sun.COM } else if (ha->nvram_cache->valid != 1) {
105511541SDaniel.Beauregard@Sun.COM
105611541SDaniel.Beauregard@Sun.COM /* Quiesce I/O */
105711541SDaniel.Beauregard@Sun.COM if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
105811541SDaniel.Beauregard@Sun.COM EL(ha, "ql_stall_driver failed\n");
105911541SDaniel.Beauregard@Sun.COM return (EBUSY);
106011541SDaniel.Beauregard@Sun.COM }
106111541SDaniel.Beauregard@Sun.COM
106211541SDaniel.Beauregard@Sun.COM rval2 = ql_lock_nvram(ha, &start_addr, LNF_NVRAM_DATA);
106311541SDaniel.Beauregard@Sun.COM if (rval2 != QL_SUCCESS) {
106411541SDaniel.Beauregard@Sun.COM EL(ha, "failed, ql_lock_nvram=%xh\n", rval2);
106511541SDaniel.Beauregard@Sun.COM ql_restart_driver(ha);
106611541SDaniel.Beauregard@Sun.COM return (EIO);
106711541SDaniel.Beauregard@Sun.COM }
106811541SDaniel.Beauregard@Sun.COM NVRAM_CACHE_LOCK(ha);
10697836SJohn.Forte@Sun.COM
107011541SDaniel.Beauregard@Sun.COM rval2 = ql_get_nvram(ha, ha->nvram_cache->cache,
107111541SDaniel.Beauregard@Sun.COM start_addr, ha->nvram_cache->size);
107211541SDaniel.Beauregard@Sun.COM if (rval2 != QL_SUCCESS) {
107311541SDaniel.Beauregard@Sun.COM rval = rval2;
107411541SDaniel.Beauregard@Sun.COM } else {
107511541SDaniel.Beauregard@Sun.COM ha->nvram_cache->valid = 1;
107611541SDaniel.Beauregard@Sun.COM EL(ha, "nvram cache now valid.");
107711541SDaniel.Beauregard@Sun.COM }
107811541SDaniel.Beauregard@Sun.COM
107911541SDaniel.Beauregard@Sun.COM NVRAM_CACHE_UNLOCK(ha);
108011541SDaniel.Beauregard@Sun.COM
108111541SDaniel.Beauregard@Sun.COM ql_release_nvram(ha);
108211541SDaniel.Beauregard@Sun.COM ql_restart_driver(ha);
108311541SDaniel.Beauregard@Sun.COM
108411541SDaniel.Beauregard@Sun.COM if (rval != 0) {
108511541SDaniel.Beauregard@Sun.COM EL(ha, "failed to dump nvram, rval=%x\n", rval);
108611541SDaniel.Beauregard@Sun.COM return (rval);
108711541SDaniel.Beauregard@Sun.COM }
10887836SJohn.Forte@Sun.COM }
10897836SJohn.Forte@Sun.COM
109011541SDaniel.Beauregard@Sun.COM if (ddi_copyout(ha->nvram_cache->cache, bp,
109111541SDaniel.Beauregard@Sun.COM ha->nvram_cache->size, mode) != 0) {
109211541SDaniel.Beauregard@Sun.COM EL(ha, "Buffer copy failed\n");
109311541SDaniel.Beauregard@Sun.COM return (EFAULT);
10947836SJohn.Forte@Sun.COM }
10957836SJohn.Forte@Sun.COM
109611541SDaniel.Beauregard@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
109711541SDaniel.Beauregard@Sun.COM
109811541SDaniel.Beauregard@Sun.COM return (0);
109911541SDaniel.Beauregard@Sun.COM }
110011541SDaniel.Beauregard@Sun.COM
110111541SDaniel.Beauregard@Sun.COM int
ql_get_nvram(ql_adapter_state_t * ha,void * dest_addr,uint32_t src_addr,uint32_t size)110211541SDaniel.Beauregard@Sun.COM ql_get_nvram(ql_adapter_state_t *ha, void *dest_addr, uint32_t src_addr,
110311541SDaniel.Beauregard@Sun.COM uint32_t size)
110411541SDaniel.Beauregard@Sun.COM {
110511541SDaniel.Beauregard@Sun.COM int rval = QL_SUCCESS;
110611541SDaniel.Beauregard@Sun.COM int cnt;
11077836SJohn.Forte@Sun.COM /* Dump NVRAM. */
110811924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_24258081)) {
110911541SDaniel.Beauregard@Sun.COM uint32_t *lptr = (uint32_t *)dest_addr;
11107836SJohn.Forte@Sun.COM
111111541SDaniel.Beauregard@Sun.COM for (cnt = 0; cnt < size / 4; cnt++) {
111211541SDaniel.Beauregard@Sun.COM rval = ql_24xx_read_flash(ha, src_addr++, lptr);
111311541SDaniel.Beauregard@Sun.COM if (rval != QL_SUCCESS) {
111411541SDaniel.Beauregard@Sun.COM EL(ha, "read_flash failed=%xh\n", rval);
11157836SJohn.Forte@Sun.COM rval = EAGAIN;
11167836SJohn.Forte@Sun.COM break;
11177836SJohn.Forte@Sun.COM }
11187836SJohn.Forte@Sun.COM LITTLE_ENDIAN_32(lptr);
11197836SJohn.Forte@Sun.COM lptr++;
11207836SJohn.Forte@Sun.COM }
11217836SJohn.Forte@Sun.COM } else {
11227836SJohn.Forte@Sun.COM uint16_t data;
112311541SDaniel.Beauregard@Sun.COM uint16_t *wptr = (uint16_t *)dest_addr;
11247836SJohn.Forte@Sun.COM
112511541SDaniel.Beauregard@Sun.COM for (cnt = 0; cnt < size / 2; cnt++) {
11267836SJohn.Forte@Sun.COM data = (uint16_t)ql_get_nvram_word(ha, cnt +
112711541SDaniel.Beauregard@Sun.COM src_addr);
11287836SJohn.Forte@Sun.COM LITTLE_ENDIAN_16(&data);
11297836SJohn.Forte@Sun.COM *wptr++ = data;
11307836SJohn.Forte@Sun.COM }
11317836SJohn.Forte@Sun.COM }
113211541SDaniel.Beauregard@Sun.COM return (rval);
11337836SJohn.Forte@Sun.COM }
11347836SJohn.Forte@Sun.COM
11357836SJohn.Forte@Sun.COM /*
11367836SJohn.Forte@Sun.COM * ql_vpd_load
11377836SJohn.Forte@Sun.COM * Loads VPD from application.
11387836SJohn.Forte@Sun.COM *
11397836SJohn.Forte@Sun.COM * Input:
11407836SJohn.Forte@Sun.COM * ha = adapter state pointer.
11417836SJohn.Forte@Sun.COM * bp = user buffer address.
11427836SJohn.Forte@Sun.COM *
11437836SJohn.Forte@Sun.COM * Returns:
11447836SJohn.Forte@Sun.COM *
11457836SJohn.Forte@Sun.COM * Context:
11467836SJohn.Forte@Sun.COM * Kernel context.
11477836SJohn.Forte@Sun.COM */
11487836SJohn.Forte@Sun.COM int
ql_vpd_load(ql_adapter_state_t * ha,void * bp,int mode)11497836SJohn.Forte@Sun.COM ql_vpd_load(ql_adapter_state_t *ha, void *bp, int mode)
11507836SJohn.Forte@Sun.COM {
11517836SJohn.Forte@Sun.COM uint8_t cnt;
11527836SJohn.Forte@Sun.COM uint8_t *vpd, *vpdptr, *vbuf;
11537836SJohn.Forte@Sun.COM uint32_t start_addr, vpd_size, *lptr, data32;
11547836SJohn.Forte@Sun.COM int rval;
11557836SJohn.Forte@Sun.COM
11567836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
11577836SJohn.Forte@Sun.COM
115811924SDaniel.Beauregard@Sun.COM if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
11597836SJohn.Forte@Sun.COM EL(ha, "unsupported adapter feature\n");
11607836SJohn.Forte@Sun.COM return (ENOTSUP);
11617836SJohn.Forte@Sun.COM }
11627836SJohn.Forte@Sun.COM
11637836SJohn.Forte@Sun.COM vpd_size = QL_24XX_VPD_SIZE;
11647836SJohn.Forte@Sun.COM
11657836SJohn.Forte@Sun.COM if ((vpd = kmem_zalloc(vpd_size, KM_SLEEP)) == NULL) {
11667836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
11677836SJohn.Forte@Sun.COM return (ENOMEM);
11687836SJohn.Forte@Sun.COM }
11697836SJohn.Forte@Sun.COM
11707836SJohn.Forte@Sun.COM if (ddi_copyin(bp, vpd, vpd_size, mode) != 0) {
11717836SJohn.Forte@Sun.COM EL(ha, "Buffer copy failed\n");
11727836SJohn.Forte@Sun.COM kmem_free(vpd, vpd_size);
11737836SJohn.Forte@Sun.COM return (EFAULT);
11747836SJohn.Forte@Sun.COM }
11757836SJohn.Forte@Sun.COM
11767836SJohn.Forte@Sun.COM /* Sanity check the user supplied data via checksum */
11777836SJohn.Forte@Sun.COM if ((vpdptr = ql_vpd_findtag(ha, vpd, "RV")) == NULL) {
11787836SJohn.Forte@Sun.COM EL(ha, "vpd RV tag missing\n");
11797836SJohn.Forte@Sun.COM kmem_free(vpd, vpd_size);
11807836SJohn.Forte@Sun.COM return (EINVAL);
11817836SJohn.Forte@Sun.COM }
11827836SJohn.Forte@Sun.COM
11837836SJohn.Forte@Sun.COM vpdptr += 3;
11847836SJohn.Forte@Sun.COM cnt = 0;
11857836SJohn.Forte@Sun.COM vbuf = vpd;
11867836SJohn.Forte@Sun.COM while (vbuf <= vpdptr) {
11877836SJohn.Forte@Sun.COM cnt += *vbuf++;
11887836SJohn.Forte@Sun.COM }
11897836SJohn.Forte@Sun.COM if (cnt != 0) {
11907836SJohn.Forte@Sun.COM EL(ha, "mismatched checksum, cal=%xh, passed=%xh\n",
11917836SJohn.Forte@Sun.COM (uint8_t)cnt, (uintptr_t)vpdptr);
11927836SJohn.Forte@Sun.COM kmem_free(vpd, vpd_size);
11937836SJohn.Forte@Sun.COM return (EINVAL);
11947836SJohn.Forte@Sun.COM }
11957836SJohn.Forte@Sun.COM
11967836SJohn.Forte@Sun.COM /* Quiesce I/O */
11977836SJohn.Forte@Sun.COM if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
11987836SJohn.Forte@Sun.COM EL(ha, "ql_stall_driver failed\n");
11997836SJohn.Forte@Sun.COM kmem_free(vpd, vpd_size);
12007836SJohn.Forte@Sun.COM return (EBUSY);
12017836SJohn.Forte@Sun.COM }
12027836SJohn.Forte@Sun.COM
12037836SJohn.Forte@Sun.COM rval = ql_lock_nvram(ha, &start_addr, LNF_VPD_DATA);
12047836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
12057836SJohn.Forte@Sun.COM EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
12067836SJohn.Forte@Sun.COM kmem_free(vpd, vpd_size);
12077836SJohn.Forte@Sun.COM ql_restart_driver(ha);
12087836SJohn.Forte@Sun.COM return (EIO);
12097836SJohn.Forte@Sun.COM }
12107836SJohn.Forte@Sun.COM
12117836SJohn.Forte@Sun.COM /* Load VPD. */
121211924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_258081)) {
12137836SJohn.Forte@Sun.COM GLOBAL_HW_UNLOCK();
12149446SDaniel.Beauregard@Sun.COM start_addr &= ~ha->flash_data_addr;
12159446SDaniel.Beauregard@Sun.COM start_addr <<= 2;
12169446SDaniel.Beauregard@Sun.COM if ((rval = ql_r_m_w_flash(ha, bp, vpd_size, start_addr,
12179446SDaniel.Beauregard@Sun.COM mode)) != QL_SUCCESS) {
12187836SJohn.Forte@Sun.COM EL(ha, "vpd load error: %xh\n", rval);
12197836SJohn.Forte@Sun.COM }
12207836SJohn.Forte@Sun.COM GLOBAL_HW_LOCK();
12217836SJohn.Forte@Sun.COM } else {
12227836SJohn.Forte@Sun.COM lptr = (uint32_t *)vpd;
12237836SJohn.Forte@Sun.COM for (cnt = 0; cnt < vpd_size / 4; cnt++) {
12247836SJohn.Forte@Sun.COM data32 = *lptr++;
12257836SJohn.Forte@Sun.COM LITTLE_ENDIAN_32(&data32);
12267836SJohn.Forte@Sun.COM rval = ql_24xx_load_nvram(ha, cnt + start_addr,
12277836SJohn.Forte@Sun.COM data32);
12287836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
12297836SJohn.Forte@Sun.COM EL(ha, "failed, 24xx_load_nvram=%xh\n", rval);
12307836SJohn.Forte@Sun.COM break;
12317836SJohn.Forte@Sun.COM }
12327836SJohn.Forte@Sun.COM }
12337836SJohn.Forte@Sun.COM }
12347836SJohn.Forte@Sun.COM
12357836SJohn.Forte@Sun.COM kmem_free(vpd, vpd_size);
12367836SJohn.Forte@Sun.COM
12377836SJohn.Forte@Sun.COM /* Update the vcache */
12387836SJohn.Forte@Sun.COM CACHE_LOCK(ha);
12397836SJohn.Forte@Sun.COM
12407836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
12417836SJohn.Forte@Sun.COM EL(ha, "failed, load\n");
12427836SJohn.Forte@Sun.COM } else if ((ha->vcache == NULL) && ((ha->vcache =
12437836SJohn.Forte@Sun.COM kmem_zalloc(vpd_size, KM_SLEEP)) == NULL)) {
12447836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc2\n");
12457836SJohn.Forte@Sun.COM } else if (ddi_copyin(bp, ha->vcache, vpd_size, mode) != 0) {
12467836SJohn.Forte@Sun.COM EL(ha, "Buffer copy2 failed\n");
12477836SJohn.Forte@Sun.COM kmem_free(ha->vcache, vpd_size);
12487836SJohn.Forte@Sun.COM ha->vcache = NULL;
12497836SJohn.Forte@Sun.COM }
12507836SJohn.Forte@Sun.COM
12517836SJohn.Forte@Sun.COM CACHE_UNLOCK(ha);
12527836SJohn.Forte@Sun.COM
12537836SJohn.Forte@Sun.COM ql_release_nvram(ha);
12547836SJohn.Forte@Sun.COM ql_restart_driver(ha);
12557836SJohn.Forte@Sun.COM
12567836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
12577836SJohn.Forte@Sun.COM
12587836SJohn.Forte@Sun.COM if (rval == QL_SUCCESS) {
12597836SJohn.Forte@Sun.COM return (0);
12607836SJohn.Forte@Sun.COM }
12617836SJohn.Forte@Sun.COM
12627836SJohn.Forte@Sun.COM return (EFAULT);
12637836SJohn.Forte@Sun.COM }
12647836SJohn.Forte@Sun.COM
12657836SJohn.Forte@Sun.COM /*
12667836SJohn.Forte@Sun.COM * ql_vpd_dump
12677836SJohn.Forte@Sun.COM * Dumps VPD to application buffer.
12687836SJohn.Forte@Sun.COM *
12697836SJohn.Forte@Sun.COM * Input:
12707836SJohn.Forte@Sun.COM * ha = adapter state pointer.
12717836SJohn.Forte@Sun.COM * bp = user buffer address.
12727836SJohn.Forte@Sun.COM *
12737836SJohn.Forte@Sun.COM * Returns:
12747836SJohn.Forte@Sun.COM *
12757836SJohn.Forte@Sun.COM * Context:
12767836SJohn.Forte@Sun.COM * Kernel context.
12777836SJohn.Forte@Sun.COM */
12787836SJohn.Forte@Sun.COM int
ql_vpd_dump(ql_adapter_state_t * ha,void * bp,int mode)12797836SJohn.Forte@Sun.COM ql_vpd_dump(ql_adapter_state_t *ha, void *bp, int mode)
12807836SJohn.Forte@Sun.COM {
12817836SJohn.Forte@Sun.COM uint8_t cnt;
12827836SJohn.Forte@Sun.COM void *vpd;
12837836SJohn.Forte@Sun.COM uint32_t start_addr, vpd_size, *lptr;
12847836SJohn.Forte@Sun.COM int rval = 0;
12857836SJohn.Forte@Sun.COM
12867836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
12877836SJohn.Forte@Sun.COM
128811924SDaniel.Beauregard@Sun.COM if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
12897836SJohn.Forte@Sun.COM EL(ha, "unsupported adapter feature\n");
12907836SJohn.Forte@Sun.COM return (EACCES);
12917836SJohn.Forte@Sun.COM }
12927836SJohn.Forte@Sun.COM
12937836SJohn.Forte@Sun.COM vpd_size = QL_24XX_VPD_SIZE;
12947836SJohn.Forte@Sun.COM
12957836SJohn.Forte@Sun.COM CACHE_LOCK(ha);
12967836SJohn.Forte@Sun.COM
12977836SJohn.Forte@Sun.COM if (ha->vcache != NULL) {
12987836SJohn.Forte@Sun.COM /* copy back the vpd cache data */
12997836SJohn.Forte@Sun.COM if (ddi_copyout(ha->vcache, bp, vpd_size, mode) != 0) {
13007836SJohn.Forte@Sun.COM EL(ha, "Buffer copy failed\n");
13017836SJohn.Forte@Sun.COM rval = EFAULT;
13027836SJohn.Forte@Sun.COM }
13037836SJohn.Forte@Sun.COM CACHE_UNLOCK(ha);
13047836SJohn.Forte@Sun.COM return (rval);
13057836SJohn.Forte@Sun.COM }
13067836SJohn.Forte@Sun.COM
13077836SJohn.Forte@Sun.COM if ((vpd = kmem_zalloc(vpd_size, KM_SLEEP)) == NULL) {
13087836SJohn.Forte@Sun.COM CACHE_UNLOCK(ha);
13097836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
13107836SJohn.Forte@Sun.COM return (ENOMEM);
13117836SJohn.Forte@Sun.COM }
13127836SJohn.Forte@Sun.COM
13137836SJohn.Forte@Sun.COM /* Quiesce I/O */
13147836SJohn.Forte@Sun.COM if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
13157836SJohn.Forte@Sun.COM CACHE_UNLOCK(ha);
13167836SJohn.Forte@Sun.COM EL(ha, "ql_stall_driver failed\n");
13177836SJohn.Forte@Sun.COM kmem_free(vpd, vpd_size);
13187836SJohn.Forte@Sun.COM return (EBUSY);
13197836SJohn.Forte@Sun.COM }
13207836SJohn.Forte@Sun.COM
13217836SJohn.Forte@Sun.COM rval = ql_lock_nvram(ha, &start_addr, LNF_VPD_DATA);
13227836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
13237836SJohn.Forte@Sun.COM CACHE_UNLOCK(ha);
13247836SJohn.Forte@Sun.COM EL(ha, "failed, ql_lock_nvram=%xh\n", rval);
13257836SJohn.Forte@Sun.COM kmem_free(vpd, vpd_size);
13267836SJohn.Forte@Sun.COM ql_restart_driver(ha);
13277836SJohn.Forte@Sun.COM return (EIO);
13287836SJohn.Forte@Sun.COM }
13297836SJohn.Forte@Sun.COM
13307836SJohn.Forte@Sun.COM /* Dump VPD. */
13317836SJohn.Forte@Sun.COM lptr = (uint32_t *)vpd;
13327836SJohn.Forte@Sun.COM
13337836SJohn.Forte@Sun.COM for (cnt = 0; cnt < vpd_size / 4; cnt++) {
13347836SJohn.Forte@Sun.COM rval = ql_24xx_read_flash(ha, start_addr++, lptr);
13357836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
13367836SJohn.Forte@Sun.COM EL(ha, "read_flash failed=%xh\n", rval);
13377836SJohn.Forte@Sun.COM rval = EAGAIN;
13387836SJohn.Forte@Sun.COM break;
13397836SJohn.Forte@Sun.COM }
13407836SJohn.Forte@Sun.COM LITTLE_ENDIAN_32(lptr);
13417836SJohn.Forte@Sun.COM lptr++;
13427836SJohn.Forte@Sun.COM }
13437836SJohn.Forte@Sun.COM
13447836SJohn.Forte@Sun.COM ql_release_nvram(ha);
13457836SJohn.Forte@Sun.COM ql_restart_driver(ha);
13467836SJohn.Forte@Sun.COM
13477836SJohn.Forte@Sun.COM if (ddi_copyout(vpd, bp, vpd_size, mode) != 0) {
13487836SJohn.Forte@Sun.COM CACHE_UNLOCK(ha);
13497836SJohn.Forte@Sun.COM EL(ha, "Buffer copy failed\n");
13507836SJohn.Forte@Sun.COM kmem_free(vpd, vpd_size);
13517836SJohn.Forte@Sun.COM return (EFAULT);
13527836SJohn.Forte@Sun.COM }
13537836SJohn.Forte@Sun.COM
13547836SJohn.Forte@Sun.COM ha->vcache = vpd;
13557836SJohn.Forte@Sun.COM
13567836SJohn.Forte@Sun.COM CACHE_UNLOCK(ha);
13577836SJohn.Forte@Sun.COM
13587836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
13597836SJohn.Forte@Sun.COM
13607836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
13617836SJohn.Forte@Sun.COM return (EFAULT);
13627836SJohn.Forte@Sun.COM } else {
13637836SJohn.Forte@Sun.COM return (0);
13647836SJohn.Forte@Sun.COM }
13657836SJohn.Forte@Sun.COM }
13667836SJohn.Forte@Sun.COM
13677836SJohn.Forte@Sun.COM /*
13687836SJohn.Forte@Sun.COM * ql_vpd_findtag
13697836SJohn.Forte@Sun.COM * Search the passed vpd buffer for the requested VPD tag type.
13707836SJohn.Forte@Sun.COM *
13717836SJohn.Forte@Sun.COM * Input:
13727836SJohn.Forte@Sun.COM * ha = adapter state pointer.
13737836SJohn.Forte@Sun.COM * vpdbuf = Pointer to start of the buffer to search
13747836SJohn.Forte@Sun.COM * op = VPD opcode to find (must be NULL terminated).
13757836SJohn.Forte@Sun.COM *
13767836SJohn.Forte@Sun.COM * Returns:
13777836SJohn.Forte@Sun.COM * Pointer to the opcode in the buffer if opcode found.
13787836SJohn.Forte@Sun.COM * NULL if opcode is not found.
13797836SJohn.Forte@Sun.COM *
13807836SJohn.Forte@Sun.COM * Context:
13817836SJohn.Forte@Sun.COM * Kernel context.
13827836SJohn.Forte@Sun.COM */
13837836SJohn.Forte@Sun.COM static uint8_t *
ql_vpd_findtag(ql_adapter_state_t * ha,uint8_t * vpdbuf,int8_t * opcode)13847836SJohn.Forte@Sun.COM ql_vpd_findtag(ql_adapter_state_t *ha, uint8_t *vpdbuf, int8_t *opcode)
13857836SJohn.Forte@Sun.COM {
13867836SJohn.Forte@Sun.COM uint8_t *vpd = vpdbuf;
13877836SJohn.Forte@Sun.COM uint8_t *end = vpdbuf + QL_24XX_VPD_SIZE;
13887836SJohn.Forte@Sun.COM uint32_t found = 0;
13897836SJohn.Forte@Sun.COM
13907836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
13917836SJohn.Forte@Sun.COM
13927836SJohn.Forte@Sun.COM if (vpdbuf == NULL || opcode == NULL) {
13937836SJohn.Forte@Sun.COM EL(ha, "null parameter passed!\n");
13947836SJohn.Forte@Sun.COM return (NULL);
13957836SJohn.Forte@Sun.COM }
13967836SJohn.Forte@Sun.COM
13977836SJohn.Forte@Sun.COM while (vpd < end) {
13987836SJohn.Forte@Sun.COM
13997836SJohn.Forte@Sun.COM /* check for end of vpd */
14007836SJohn.Forte@Sun.COM if (vpd[0] == VPD_TAG_END) {
14017836SJohn.Forte@Sun.COM if (opcode[0] == VPD_TAG_END) {
14027836SJohn.Forte@Sun.COM found = 1;
14037836SJohn.Forte@Sun.COM } else {
14047836SJohn.Forte@Sun.COM found = 0;
14057836SJohn.Forte@Sun.COM }
14067836SJohn.Forte@Sun.COM break;
14077836SJohn.Forte@Sun.COM }
14087836SJohn.Forte@Sun.COM
14097836SJohn.Forte@Sun.COM /* check opcode */
14107836SJohn.Forte@Sun.COM if (bcmp(opcode, vpd, strlen(opcode)) == 0) {
14117836SJohn.Forte@Sun.COM /* found opcode requested */
14127836SJohn.Forte@Sun.COM found = 1;
14137836SJohn.Forte@Sun.COM break;
14147836SJohn.Forte@Sun.COM }
14157836SJohn.Forte@Sun.COM
14167836SJohn.Forte@Sun.COM /*
14177836SJohn.Forte@Sun.COM * Didn't find the opcode, so calculate start of
14187836SJohn.Forte@Sun.COM * next tag. Depending on the current tag type,
14197836SJohn.Forte@Sun.COM * the length field can be 1 or 2 bytes
14207836SJohn.Forte@Sun.COM */
14217836SJohn.Forte@Sun.COM if (!(strncmp((char *)vpd, (char *)VPD_TAG_PRODID, 1))) {
14227836SJohn.Forte@Sun.COM vpd += (vpd[2] << 8) + vpd[1] + 3;
14237836SJohn.Forte@Sun.COM } else if (*vpd == VPD_TAG_LRT || *vpd == VPD_TAG_LRTC) {
14247836SJohn.Forte@Sun.COM vpd += 3;
14257836SJohn.Forte@Sun.COM } else {
14267836SJohn.Forte@Sun.COM vpd += vpd[2] +3;
14277836SJohn.Forte@Sun.COM }
14287836SJohn.Forte@Sun.COM }
14297836SJohn.Forte@Sun.COM
14309446SDaniel.Beauregard@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
14317836SJohn.Forte@Sun.COM
14327836SJohn.Forte@Sun.COM return (found == 1 ? vpd : NULL);
14337836SJohn.Forte@Sun.COM }
14347836SJohn.Forte@Sun.COM
14357836SJohn.Forte@Sun.COM /*
14367836SJohn.Forte@Sun.COM * ql_vpd_lookup
14377836SJohn.Forte@Sun.COM * Return the VPD data for the request VPD tag
14387836SJohn.Forte@Sun.COM *
14397836SJohn.Forte@Sun.COM * Input:
14407836SJohn.Forte@Sun.COM * ha = adapter state pointer.
14417836SJohn.Forte@Sun.COM * opcode = VPD opcode to find (must be NULL terminated).
14427836SJohn.Forte@Sun.COM * bp = Pointer to returned data buffer.
14437836SJohn.Forte@Sun.COM * bplen = Length of returned data buffer.
14447836SJohn.Forte@Sun.COM *
14457836SJohn.Forte@Sun.COM * Returns:
14467836SJohn.Forte@Sun.COM * Length of data copied into returned data buffer.
14477836SJohn.Forte@Sun.COM * >0 = VPD data field (NULL terminated)
14487836SJohn.Forte@Sun.COM * 0 = no data.
14497836SJohn.Forte@Sun.COM * -1 = Could not find opcode in vpd buffer / error.
14507836SJohn.Forte@Sun.COM *
14517836SJohn.Forte@Sun.COM * Context:
14527836SJohn.Forte@Sun.COM * Kernel context.
14537836SJohn.Forte@Sun.COM *
14547836SJohn.Forte@Sun.COM * NB: The opcode buffer and the bp buffer *could* be the same buffer!
14557836SJohn.Forte@Sun.COM *
14567836SJohn.Forte@Sun.COM */
14577836SJohn.Forte@Sun.COM int32_t
ql_vpd_lookup(ql_adapter_state_t * ha,uint8_t * opcode,uint8_t * bp,int32_t bplen)14587836SJohn.Forte@Sun.COM ql_vpd_lookup(ql_adapter_state_t *ha, uint8_t *opcode, uint8_t *bp,
14597836SJohn.Forte@Sun.COM int32_t bplen)
14607836SJohn.Forte@Sun.COM {
14617836SJohn.Forte@Sun.COM uint8_t *vpd;
14627836SJohn.Forte@Sun.COM uint8_t *vpdbuf;
14637836SJohn.Forte@Sun.COM int32_t len = -1;
14647836SJohn.Forte@Sun.COM
14657836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
14667836SJohn.Forte@Sun.COM
14677836SJohn.Forte@Sun.COM if (opcode == NULL || bp == NULL || bplen < 1) {
14687836SJohn.Forte@Sun.COM EL(ha, "invalid parameter passed: opcode=%ph, "
14697836SJohn.Forte@Sun.COM "bp=%ph, bplen=%xh\n", opcode, bp, bplen);
14707836SJohn.Forte@Sun.COM return (len);
14717836SJohn.Forte@Sun.COM }
14727836SJohn.Forte@Sun.COM
147311924SDaniel.Beauregard@Sun.COM if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
14747836SJohn.Forte@Sun.COM return (len);
14757836SJohn.Forte@Sun.COM }
14767836SJohn.Forte@Sun.COM
14777836SJohn.Forte@Sun.COM if ((vpdbuf = (uint8_t *)kmem_zalloc(QL_24XX_VPD_SIZE,
14787836SJohn.Forte@Sun.COM KM_SLEEP)) == NULL) {
14797836SJohn.Forte@Sun.COM EL(ha, "unable to allocate vpd memory\n");
14807836SJohn.Forte@Sun.COM return (len);
14817836SJohn.Forte@Sun.COM }
14827836SJohn.Forte@Sun.COM
14837836SJohn.Forte@Sun.COM if ((ql_vpd_dump(ha, vpdbuf, (int)FKIOCTL)) != 0) {
14847836SJohn.Forte@Sun.COM kmem_free(vpdbuf, QL_24XX_VPD_SIZE);
14857836SJohn.Forte@Sun.COM EL(ha, "unable to retrieve VPD data\n");
14867836SJohn.Forte@Sun.COM return (len);
14877836SJohn.Forte@Sun.COM }
14887836SJohn.Forte@Sun.COM
14897836SJohn.Forte@Sun.COM if ((vpd = ql_vpd_findtag(ha, vpdbuf, (int8_t *)opcode)) != NULL) {
14907836SJohn.Forte@Sun.COM /*
14917836SJohn.Forte@Sun.COM * Found the tag
14927836SJohn.Forte@Sun.COM */
14937836SJohn.Forte@Sun.COM if (*opcode == VPD_TAG_END || *opcode == VPD_TAG_LRT ||
14947836SJohn.Forte@Sun.COM *opcode == VPD_TAG_LRTC) {
14957836SJohn.Forte@Sun.COM /*
14967836SJohn.Forte@Sun.COM * we found it, but the tag doesn't have a data
14977836SJohn.Forte@Sun.COM * field.
14987836SJohn.Forte@Sun.COM */
14997836SJohn.Forte@Sun.COM len = 0;
15007836SJohn.Forte@Sun.COM } else if (!(strncmp((char *)vpd, (char *)
15017836SJohn.Forte@Sun.COM VPD_TAG_PRODID, 1))) {
15027836SJohn.Forte@Sun.COM len = vpd[2] << 8;
15037836SJohn.Forte@Sun.COM len += vpd[1];
15047836SJohn.Forte@Sun.COM } else {
15057836SJohn.Forte@Sun.COM len = vpd[2];
15067836SJohn.Forte@Sun.COM }
15077836SJohn.Forte@Sun.COM
15087836SJohn.Forte@Sun.COM /*
15097836SJohn.Forte@Sun.COM * make sure that the vpd len doesn't exceed the
15107836SJohn.Forte@Sun.COM * vpd end
15117836SJohn.Forte@Sun.COM */
15127836SJohn.Forte@Sun.COM if (vpd+len > vpdbuf + QL_24XX_VPD_SIZE) {
15137836SJohn.Forte@Sun.COM EL(ha, "vpd tag len (%xh) exceeds vpd buffer "
15147836SJohn.Forte@Sun.COM "length\n", len);
15157836SJohn.Forte@Sun.COM len = -1;
15167836SJohn.Forte@Sun.COM }
15177836SJohn.Forte@Sun.COM }
15187836SJohn.Forte@Sun.COM
15197836SJohn.Forte@Sun.COM if (len >= 0) {
15207836SJohn.Forte@Sun.COM /*
15217836SJohn.Forte@Sun.COM * make sure we don't exceed callers buffer space len
15227836SJohn.Forte@Sun.COM */
15237836SJohn.Forte@Sun.COM if (len > bplen) {
15247836SJohn.Forte@Sun.COM len = bplen-1;
15257836SJohn.Forte@Sun.COM }
15267836SJohn.Forte@Sun.COM
15277836SJohn.Forte@Sun.COM /* copy the data back */
15287836SJohn.Forte@Sun.COM (void) strncpy((int8_t *)bp, (int8_t *)(vpd+3), (int64_t)len);
15297836SJohn.Forte@Sun.COM bp[len] = NULL;
15307836SJohn.Forte@Sun.COM } else {
15317836SJohn.Forte@Sun.COM /* error -- couldn't find tag */
15327836SJohn.Forte@Sun.COM bp[0] = NULL;
15337836SJohn.Forte@Sun.COM if (opcode[1] != NULL) {
15347836SJohn.Forte@Sun.COM EL(ha, "unable to find tag '%s'\n", opcode);
15357836SJohn.Forte@Sun.COM } else {
15367836SJohn.Forte@Sun.COM EL(ha, "unable to find tag '%xh'\n", opcode[0]);
15377836SJohn.Forte@Sun.COM }
15387836SJohn.Forte@Sun.COM }
15397836SJohn.Forte@Sun.COM
15407836SJohn.Forte@Sun.COM kmem_free(vpdbuf, QL_24XX_VPD_SIZE);
15417836SJohn.Forte@Sun.COM
15429446SDaniel.Beauregard@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
15437836SJohn.Forte@Sun.COM
15447836SJohn.Forte@Sun.COM return (len);
15457836SJohn.Forte@Sun.COM }
15467836SJohn.Forte@Sun.COM
15479446SDaniel.Beauregard@Sun.COM /*
15489446SDaniel.Beauregard@Sun.COM * ql_r_m_w_flash
15499446SDaniel.Beauregard@Sun.COM * Read modify write from user space to flash.
15509446SDaniel.Beauregard@Sun.COM *
15519446SDaniel.Beauregard@Sun.COM * Input:
15529446SDaniel.Beauregard@Sun.COM * ha: adapter state pointer.
15539446SDaniel.Beauregard@Sun.COM * dp: source byte pointer.
15549446SDaniel.Beauregard@Sun.COM * bc: byte count.
15559446SDaniel.Beauregard@Sun.COM * faddr: flash byte address.
15569446SDaniel.Beauregard@Sun.COM * mode: flags.
15579446SDaniel.Beauregard@Sun.COM *
15589446SDaniel.Beauregard@Sun.COM * Returns:
15599446SDaniel.Beauregard@Sun.COM * ql local function return status code.
15609446SDaniel.Beauregard@Sun.COM *
15619446SDaniel.Beauregard@Sun.COM * Context:
15629446SDaniel.Beauregard@Sun.COM * Kernel context.
15639446SDaniel.Beauregard@Sun.COM */
15649446SDaniel.Beauregard@Sun.COM int
ql_r_m_w_flash(ql_adapter_state_t * ha,caddr_t dp,uint32_t bc,uint32_t faddr,int mode)15659446SDaniel.Beauregard@Sun.COM ql_r_m_w_flash(ql_adapter_state_t *ha, caddr_t dp, uint32_t bc, uint32_t faddr,
15669446SDaniel.Beauregard@Sun.COM int mode)
15677836SJohn.Forte@Sun.COM {
15687836SJohn.Forte@Sun.COM uint8_t *bp;
15699446SDaniel.Beauregard@Sun.COM uint32_t xfer, bsize, saddr, ofst;
15709446SDaniel.Beauregard@Sun.COM int rval = 0;
15719446SDaniel.Beauregard@Sun.COM
15729446SDaniel.Beauregard@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started, dp=%ph, faddr=%xh, bc=%xh\n",
15739446SDaniel.Beauregard@Sun.COM ha->instance, (void *)dp, faddr, bc);
15749446SDaniel.Beauregard@Sun.COM
15759446SDaniel.Beauregard@Sun.COM bsize = ha->xioctl->fdesc.block_size;
15769446SDaniel.Beauregard@Sun.COM saddr = faddr & ~(bsize - 1);
15779446SDaniel.Beauregard@Sun.COM ofst = faddr & (bsize - 1);
15787836SJohn.Forte@Sun.COM
15797836SJohn.Forte@Sun.COM if ((bp = kmem_zalloc(bsize, KM_SLEEP)) == NULL) {
15809446SDaniel.Beauregard@Sun.COM EL(ha, "kmem_zalloc=null\n");
15819446SDaniel.Beauregard@Sun.COM return (QL_MEMORY_ALLOC_FAILED);
15827836SJohn.Forte@Sun.COM }
15837836SJohn.Forte@Sun.COM
15849446SDaniel.Beauregard@Sun.COM while (bc) {
15859446SDaniel.Beauregard@Sun.COM xfer = bc > bsize ? bsize : bc;
15869446SDaniel.Beauregard@Sun.COM if (ofst + xfer > bsize) {
15879446SDaniel.Beauregard@Sun.COM xfer = bsize - ofst;
15889446SDaniel.Beauregard@Sun.COM }
15899446SDaniel.Beauregard@Sun.COM QL_PRINT_9(CE_CONT, "(%d): dp=%ph, saddr=%xh, bc=%xh, "
15909446SDaniel.Beauregard@Sun.COM "ofst=%xh, xfer=%xh\n", ha->instance, (void *)dp, saddr,
15919446SDaniel.Beauregard@Sun.COM bc, ofst, xfer);
15927836SJohn.Forte@Sun.COM
15939446SDaniel.Beauregard@Sun.COM if (ofst || xfer < bsize) {
15949446SDaniel.Beauregard@Sun.COM /* Dump Flash sector. */
15959446SDaniel.Beauregard@Sun.COM if ((rval = ql_dump_fcode(ha, bp, bsize, saddr)) !=
15969446SDaniel.Beauregard@Sun.COM QL_SUCCESS) {
15979446SDaniel.Beauregard@Sun.COM EL(ha, "dump_flash status=%x\n", rval);
15989446SDaniel.Beauregard@Sun.COM break;
15999446SDaniel.Beauregard@Sun.COM }
16009446SDaniel.Beauregard@Sun.COM }
16019446SDaniel.Beauregard@Sun.COM
16027836SJohn.Forte@Sun.COM /* Set new data. */
16039446SDaniel.Beauregard@Sun.COM if ((rval = ddi_copyin(dp, (caddr_t)(bp + ofst), xfer,
16049446SDaniel.Beauregard@Sun.COM mode)) != 0) {
16059446SDaniel.Beauregard@Sun.COM EL(ha, "ddi_copyin status=%xh, dp=%ph, ofst=%xh, "
16069446SDaniel.Beauregard@Sun.COM "xfer=%xh\n", rval, (void *)dp, ofst, xfer);
16079446SDaniel.Beauregard@Sun.COM rval = QL_FUNCTION_FAILED;
16089446SDaniel.Beauregard@Sun.COM break;
16099446SDaniel.Beauregard@Sun.COM }
16107836SJohn.Forte@Sun.COM
16117836SJohn.Forte@Sun.COM /* Write to flash. */
16129446SDaniel.Beauregard@Sun.COM if ((rval = ql_load_fcode(ha, bp, bsize, saddr)) !=
16139446SDaniel.Beauregard@Sun.COM QL_SUCCESS) {
16149446SDaniel.Beauregard@Sun.COM EL(ha, "load_flash status=%x\n", rval);
16159446SDaniel.Beauregard@Sun.COM break;
16169446SDaniel.Beauregard@Sun.COM }
16179446SDaniel.Beauregard@Sun.COM bc -= xfer;
16189446SDaniel.Beauregard@Sun.COM dp += xfer;
16199446SDaniel.Beauregard@Sun.COM saddr += bsize;
16209446SDaniel.Beauregard@Sun.COM ofst = 0;
16217836SJohn.Forte@Sun.COM }
16227836SJohn.Forte@Sun.COM
16237836SJohn.Forte@Sun.COM kmem_free(bp, bsize);
16247836SJohn.Forte@Sun.COM
16259446SDaniel.Beauregard@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
16269446SDaniel.Beauregard@Sun.COM
16277836SJohn.Forte@Sun.COM return (rval);
16287836SJohn.Forte@Sun.COM }
16297836SJohn.Forte@Sun.COM
16307836SJohn.Forte@Sun.COM /*
16317836SJohn.Forte@Sun.COM * ql_adm_op
16327836SJohn.Forte@Sun.COM * Performs qladm utility operations
16337836SJohn.Forte@Sun.COM *
16347836SJohn.Forte@Sun.COM * Input:
16357836SJohn.Forte@Sun.COM * ha: adapter state pointer.
16367836SJohn.Forte@Sun.COM * arg: driver_op_t structure pointer.
16377836SJohn.Forte@Sun.COM * mode: flags.
16387836SJohn.Forte@Sun.COM *
16397836SJohn.Forte@Sun.COM * Returns:
16407836SJohn.Forte@Sun.COM *
16417836SJohn.Forte@Sun.COM * Context:
16427836SJohn.Forte@Sun.COM * Kernel context.
16437836SJohn.Forte@Sun.COM */
16447836SJohn.Forte@Sun.COM static int
ql_adm_op(ql_adapter_state_t * ha,void * arg,int mode)16457836SJohn.Forte@Sun.COM ql_adm_op(ql_adapter_state_t *ha, void *arg, int mode)
16467836SJohn.Forte@Sun.COM {
16477836SJohn.Forte@Sun.COM ql_adm_op_t dop;
16487836SJohn.Forte@Sun.COM int rval = 0;
16497836SJohn.Forte@Sun.COM
16507836SJohn.Forte@Sun.COM if (ddi_copyin(arg, &dop, sizeof (ql_adm_op_t), mode) != 0) {
16517836SJohn.Forte@Sun.COM EL(ha, "failed, driver_op_t ddi_copyin\n");
16527836SJohn.Forte@Sun.COM return (EFAULT);
16537836SJohn.Forte@Sun.COM }
16547836SJohn.Forte@Sun.COM
16559446SDaniel.Beauregard@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started, cmd=%xh, buffer=%llx,"
16567836SJohn.Forte@Sun.COM " length=%xh, option=%xh\n", ha->instance, dop.cmd, dop.buffer,
16577836SJohn.Forte@Sun.COM dop.length, dop.option);
16587836SJohn.Forte@Sun.COM
16597836SJohn.Forte@Sun.COM switch (dop.cmd) {
16607836SJohn.Forte@Sun.COM case QL_ADAPTER_INFO:
16617836SJohn.Forte@Sun.COM rval = ql_adm_adapter_info(ha, &dop, mode);
16627836SJohn.Forte@Sun.COM break;
16637836SJohn.Forte@Sun.COM
16647836SJohn.Forte@Sun.COM case QL_EXTENDED_LOGGING:
16657836SJohn.Forte@Sun.COM rval = ql_adm_extended_logging(ha, &dop);
16667836SJohn.Forte@Sun.COM break;
16677836SJohn.Forte@Sun.COM
16687836SJohn.Forte@Sun.COM case QL_LOOP_RESET:
16697836SJohn.Forte@Sun.COM rval = ql_adm_loop_reset(ha);
16707836SJohn.Forte@Sun.COM break;
16717836SJohn.Forte@Sun.COM
16727836SJohn.Forte@Sun.COM case QL_DEVICE_LIST:
16737836SJohn.Forte@Sun.COM rval = ql_adm_device_list(ha, &dop, mode);
16747836SJohn.Forte@Sun.COM break;
16757836SJohn.Forte@Sun.COM
16767836SJohn.Forte@Sun.COM case QL_PROP_UPDATE_INT:
16777836SJohn.Forte@Sun.COM rval = ql_adm_prop_update_int(ha, &dop, mode);
16787836SJohn.Forte@Sun.COM break;
16797836SJohn.Forte@Sun.COM
16807836SJohn.Forte@Sun.COM case QL_UPDATE_PROPERTIES:
16817836SJohn.Forte@Sun.COM rval = ql_adm_update_properties(ha);
16827836SJohn.Forte@Sun.COM break;
16837836SJohn.Forte@Sun.COM
16847836SJohn.Forte@Sun.COM case QL_FW_DUMP:
16857836SJohn.Forte@Sun.COM rval = ql_adm_fw_dump(ha, &dop, arg, mode);
16867836SJohn.Forte@Sun.COM break;
16877836SJohn.Forte@Sun.COM
16887836SJohn.Forte@Sun.COM case QL_NVRAM_LOAD:
16897836SJohn.Forte@Sun.COM rval = ql_adm_nvram_load(ha, &dop, mode);
16907836SJohn.Forte@Sun.COM break;
16917836SJohn.Forte@Sun.COM
16927836SJohn.Forte@Sun.COM case QL_NVRAM_DUMP:
16937836SJohn.Forte@Sun.COM rval = ql_adm_nvram_dump(ha, &dop, mode);
16947836SJohn.Forte@Sun.COM break;
16957836SJohn.Forte@Sun.COM
16967836SJohn.Forte@Sun.COM case QL_FLASH_LOAD:
16977836SJohn.Forte@Sun.COM rval = ql_adm_flash_load(ha, &dop, mode);
16987836SJohn.Forte@Sun.COM break;
16997836SJohn.Forte@Sun.COM
17007836SJohn.Forte@Sun.COM case QL_VPD_LOAD:
17017836SJohn.Forte@Sun.COM rval = ql_adm_vpd_load(ha, &dop, mode);
17027836SJohn.Forte@Sun.COM break;
17037836SJohn.Forte@Sun.COM
17047836SJohn.Forte@Sun.COM case QL_VPD_DUMP:
17057836SJohn.Forte@Sun.COM rval = ql_adm_vpd_dump(ha, &dop, mode);
17067836SJohn.Forte@Sun.COM break;
17077836SJohn.Forte@Sun.COM
17087836SJohn.Forte@Sun.COM case QL_VPD_GETTAG:
17097836SJohn.Forte@Sun.COM rval = ql_adm_vpd_gettag(ha, &dop, mode);
17107836SJohn.Forte@Sun.COM break;
17117836SJohn.Forte@Sun.COM
17127836SJohn.Forte@Sun.COM case QL_UPD_FWMODULE:
17137836SJohn.Forte@Sun.COM rval = ql_adm_updfwmodule(ha, &dop, mode);
17147836SJohn.Forte@Sun.COM break;
17157836SJohn.Forte@Sun.COM
17167836SJohn.Forte@Sun.COM default:
17177836SJohn.Forte@Sun.COM EL(ha, "unsupported driver op cmd: %x\n", dop.cmd);
17187836SJohn.Forte@Sun.COM return (EINVAL);
17197836SJohn.Forte@Sun.COM }
17207836SJohn.Forte@Sun.COM
17217836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
17227836SJohn.Forte@Sun.COM
17237836SJohn.Forte@Sun.COM return (rval);
17247836SJohn.Forte@Sun.COM }
17257836SJohn.Forte@Sun.COM
17267836SJohn.Forte@Sun.COM /*
17277836SJohn.Forte@Sun.COM * ql_adm_adapter_info
17287836SJohn.Forte@Sun.COM * Performs qladm QL_ADAPTER_INFO command
17297836SJohn.Forte@Sun.COM *
17307836SJohn.Forte@Sun.COM * Input:
17317836SJohn.Forte@Sun.COM * ha: adapter state pointer.
17327836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
17337836SJohn.Forte@Sun.COM * mode: flags.
17347836SJohn.Forte@Sun.COM *
17357836SJohn.Forte@Sun.COM * Returns:
17367836SJohn.Forte@Sun.COM *
17377836SJohn.Forte@Sun.COM * Context:
17387836SJohn.Forte@Sun.COM * Kernel context.
17397836SJohn.Forte@Sun.COM */
17407836SJohn.Forte@Sun.COM static int
ql_adm_adapter_info(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)17417836SJohn.Forte@Sun.COM ql_adm_adapter_info(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
17427836SJohn.Forte@Sun.COM {
17437836SJohn.Forte@Sun.COM ql_adapter_info_t hba;
17447836SJohn.Forte@Sun.COM uint8_t *dp;
17457836SJohn.Forte@Sun.COM uint32_t length;
17467836SJohn.Forte@Sun.COM int rval, i;
17477836SJohn.Forte@Sun.COM
17487836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
17497836SJohn.Forte@Sun.COM
17507836SJohn.Forte@Sun.COM hba.device_id = ha->device_id;
17517836SJohn.Forte@Sun.COM
175211924SDaniel.Beauregard@Sun.COM dp = CFG_IST(ha, CFG_CTRL_24258081) ?
17537836SJohn.Forte@Sun.COM &ha->init_ctrl_blk.cb24.port_name[0] :
17547836SJohn.Forte@Sun.COM &ha->init_ctrl_blk.cb.port_name[0];
17557836SJohn.Forte@Sun.COM bcopy(dp, hba.wwpn, 8);
17567836SJohn.Forte@Sun.COM
17577836SJohn.Forte@Sun.COM hba.d_id = ha->d_id.b24;
17587836SJohn.Forte@Sun.COM
17597836SJohn.Forte@Sun.COM if (ha->xioctl->fdesc.flash_size == 0 &&
17607836SJohn.Forte@Sun.COM !(CFG_IST(ha, CFG_CTRL_2200) && !ha->subven_id)) {
17617836SJohn.Forte@Sun.COM if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
17627836SJohn.Forte@Sun.COM EL(ha, "ql_stall_driver failed\n");
17637836SJohn.Forte@Sun.COM return (EBUSY);
17647836SJohn.Forte@Sun.COM }
17657836SJohn.Forte@Sun.COM
17669446SDaniel.Beauregard@Sun.COM if ((rval = ql_setup_fcache(ha)) != QL_SUCCESS) {
17677836SJohn.Forte@Sun.COM EL(ha, "ql_setup_flash failed=%xh\n", rval);
17687836SJohn.Forte@Sun.COM if (rval == QL_FUNCTION_TIMEOUT) {
17697836SJohn.Forte@Sun.COM return (EBUSY);
17707836SJohn.Forte@Sun.COM }
17717836SJohn.Forte@Sun.COM return (EIO);
17727836SJohn.Forte@Sun.COM }
17737836SJohn.Forte@Sun.COM
17747836SJohn.Forte@Sun.COM /* Resume I/O */
177511924SDaniel.Beauregard@Sun.COM if (CFG_IST(ha, CFG_CTRL_24258081)) {
17767836SJohn.Forte@Sun.COM ql_restart_driver(ha);
17777836SJohn.Forte@Sun.COM } else {
17787836SJohn.Forte@Sun.COM EL(ha, "isp_abort_needed for restart\n");
17797836SJohn.Forte@Sun.COM ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED,
17807836SJohn.Forte@Sun.COM DRIVER_STALL);
17817836SJohn.Forte@Sun.COM }
17827836SJohn.Forte@Sun.COM }
17837836SJohn.Forte@Sun.COM hba.flash_size = ha->xioctl->fdesc.flash_size;
17847836SJohn.Forte@Sun.COM
17857836SJohn.Forte@Sun.COM (void) strcpy(hba.driver_ver, QL_VERSION);
17867836SJohn.Forte@Sun.COM
17877836SJohn.Forte@Sun.COM (void) sprintf(hba.fw_ver, "%d.%d.%d", ha->fw_major_version,
17887836SJohn.Forte@Sun.COM ha->fw_minor_version, ha->fw_subminor_version);
17897836SJohn.Forte@Sun.COM
17907836SJohn.Forte@Sun.COM bzero(hba.fcode_ver, sizeof (hba.fcode_ver));
17917836SJohn.Forte@Sun.COM
17927836SJohn.Forte@Sun.COM /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
17937836SJohn.Forte@Sun.COM rval = ddi_getlongprop(DDI_DEV_T_ANY, ha->dip,
17949156SDaniel.Beauregard@Sun.COM DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version", (caddr_t)&dp, &i);
17957836SJohn.Forte@Sun.COM length = i;
17967836SJohn.Forte@Sun.COM if (rval != DDI_PROP_SUCCESS) {
17977836SJohn.Forte@Sun.COM EL(ha, "failed, ddi_getlongprop=%xh\n", rval);
17987836SJohn.Forte@Sun.COM } else {
17997836SJohn.Forte@Sun.COM if (length > (uint32_t)sizeof (hba.fcode_ver)) {
18007836SJohn.Forte@Sun.COM length = sizeof (hba.fcode_ver) - 1;
18017836SJohn.Forte@Sun.COM }
18027836SJohn.Forte@Sun.COM bcopy((void *)dp, (void *)hba.fcode_ver, length);
18037836SJohn.Forte@Sun.COM kmem_free(dp, length);
18047836SJohn.Forte@Sun.COM }
18057836SJohn.Forte@Sun.COM
18067836SJohn.Forte@Sun.COM if (ddi_copyout((void *)&hba, (void *)(uintptr_t)dop->buffer,
18079156SDaniel.Beauregard@Sun.COM dop->length, mode) != 0) {
18087836SJohn.Forte@Sun.COM EL(ha, "failed, ddi_copyout\n");
18097836SJohn.Forte@Sun.COM return (EFAULT);
18107836SJohn.Forte@Sun.COM }
18117836SJohn.Forte@Sun.COM
18127836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
18137836SJohn.Forte@Sun.COM
18147836SJohn.Forte@Sun.COM return (0);
18157836SJohn.Forte@Sun.COM }
18167836SJohn.Forte@Sun.COM
18177836SJohn.Forte@Sun.COM /*
18187836SJohn.Forte@Sun.COM * ql_adm_extended_logging
18197836SJohn.Forte@Sun.COM * Performs qladm QL_EXTENDED_LOGGING command
18207836SJohn.Forte@Sun.COM *
18217836SJohn.Forte@Sun.COM * Input:
18227836SJohn.Forte@Sun.COM * ha: adapter state pointer.
18237836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
18247836SJohn.Forte@Sun.COM *
18257836SJohn.Forte@Sun.COM * Returns:
18267836SJohn.Forte@Sun.COM *
18277836SJohn.Forte@Sun.COM * Context:
18287836SJohn.Forte@Sun.COM * Kernel context.
18297836SJohn.Forte@Sun.COM */
18307836SJohn.Forte@Sun.COM static int
ql_adm_extended_logging(ql_adapter_state_t * ha,ql_adm_op_t * dop)18317836SJohn.Forte@Sun.COM ql_adm_extended_logging(ql_adapter_state_t *ha, ql_adm_op_t *dop)
18327836SJohn.Forte@Sun.COM {
18337836SJohn.Forte@Sun.COM char prop_name[MAX_PROP_LENGTH];
18347836SJohn.Forte@Sun.COM int rval;
18357836SJohn.Forte@Sun.COM
18367836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
18377836SJohn.Forte@Sun.COM
18387836SJohn.Forte@Sun.COM (void) sprintf(prop_name, "hba%d-extended-logging", ha->instance);
18397836SJohn.Forte@Sun.COM
18407836SJohn.Forte@Sun.COM /*LINTED [Solaris DDI_DEV_T_NONE Lint warning]*/
18417836SJohn.Forte@Sun.COM rval = ddi_prop_update_int(DDI_DEV_T_NONE, ha->dip, prop_name,
18427836SJohn.Forte@Sun.COM (int)dop->option);
18437836SJohn.Forte@Sun.COM if (rval != DDI_PROP_SUCCESS) {
18447836SJohn.Forte@Sun.COM EL(ha, "failed, prop_update = %xh\n", rval);
18457836SJohn.Forte@Sun.COM return (EINVAL);
18467836SJohn.Forte@Sun.COM } else {
18477836SJohn.Forte@Sun.COM dop->option ?
18487836SJohn.Forte@Sun.COM (ha->cfg_flags |= CFG_ENABLE_EXTENDED_LOGGING) :
18497836SJohn.Forte@Sun.COM (ha->cfg_flags &= ~CFG_ENABLE_EXTENDED_LOGGING);
18507836SJohn.Forte@Sun.COM }
18517836SJohn.Forte@Sun.COM
18527836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
18537836SJohn.Forte@Sun.COM
18547836SJohn.Forte@Sun.COM return (0);
18557836SJohn.Forte@Sun.COM }
18567836SJohn.Forte@Sun.COM
18577836SJohn.Forte@Sun.COM /*
18587836SJohn.Forte@Sun.COM * ql_adm_loop_reset
18597836SJohn.Forte@Sun.COM * Performs qladm QL_LOOP_RESET command
18607836SJohn.Forte@Sun.COM *
18617836SJohn.Forte@Sun.COM * Input:
18627836SJohn.Forte@Sun.COM * ha: adapter state pointer.
18637836SJohn.Forte@Sun.COM *
18647836SJohn.Forte@Sun.COM * Returns:
18657836SJohn.Forte@Sun.COM *
18667836SJohn.Forte@Sun.COM * Context:
18677836SJohn.Forte@Sun.COM * Kernel context.
18687836SJohn.Forte@Sun.COM */
18697836SJohn.Forte@Sun.COM static int
ql_adm_loop_reset(ql_adapter_state_t * ha)18707836SJohn.Forte@Sun.COM ql_adm_loop_reset(ql_adapter_state_t *ha)
18717836SJohn.Forte@Sun.COM {
18727836SJohn.Forte@Sun.COM int rval;
18737836SJohn.Forte@Sun.COM
18747836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
18757836SJohn.Forte@Sun.COM
18767836SJohn.Forte@Sun.COM if (ha->task_daemon_flags & LOOP_DOWN) {
18777836SJohn.Forte@Sun.COM (void) ql_full_login_lip(ha);
18787836SJohn.Forte@Sun.COM } else if ((rval = ql_full_login_lip(ha)) != QL_SUCCESS) {
18797836SJohn.Forte@Sun.COM EL(ha, "failed, ql_initiate_lip=%xh\n", rval);
18807836SJohn.Forte@Sun.COM return (EIO);
18817836SJohn.Forte@Sun.COM }
18827836SJohn.Forte@Sun.COM
18837836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
18847836SJohn.Forte@Sun.COM
18857836SJohn.Forte@Sun.COM return (0);
18867836SJohn.Forte@Sun.COM }
18877836SJohn.Forte@Sun.COM
18887836SJohn.Forte@Sun.COM /*
18897836SJohn.Forte@Sun.COM * ql_adm_device_list
18907836SJohn.Forte@Sun.COM * Performs qladm QL_DEVICE_LIST command
18917836SJohn.Forte@Sun.COM *
18927836SJohn.Forte@Sun.COM * Input:
18937836SJohn.Forte@Sun.COM * ha: adapter state pointer.
18947836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
18957836SJohn.Forte@Sun.COM * mode: flags.
18967836SJohn.Forte@Sun.COM *
18977836SJohn.Forte@Sun.COM * Returns:
18987836SJohn.Forte@Sun.COM *
18997836SJohn.Forte@Sun.COM * Context:
19007836SJohn.Forte@Sun.COM * Kernel context.
19017836SJohn.Forte@Sun.COM */
19027836SJohn.Forte@Sun.COM static int
ql_adm_device_list(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)19037836SJohn.Forte@Sun.COM ql_adm_device_list(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
19047836SJohn.Forte@Sun.COM {
19057836SJohn.Forte@Sun.COM ql_device_info_t dev;
19067836SJohn.Forte@Sun.COM ql_link_t *link;
19077836SJohn.Forte@Sun.COM ql_tgt_t *tq;
19087836SJohn.Forte@Sun.COM uint32_t index, cnt;
19097836SJohn.Forte@Sun.COM
19107836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
19117836SJohn.Forte@Sun.COM
19127836SJohn.Forte@Sun.COM cnt = 0;
19137836SJohn.Forte@Sun.COM dev.address = 0xffffffff;
19147836SJohn.Forte@Sun.COM
19157836SJohn.Forte@Sun.COM /* Scan port list for requested target and fill in the values */
19167836SJohn.Forte@Sun.COM for (link = NULL, index = 0;
19177836SJohn.Forte@Sun.COM index < DEVICE_HEAD_LIST_SIZE && link == NULL; index++) {
19187836SJohn.Forte@Sun.COM for (link = ha->dev[index].first; link != NULL;
19197836SJohn.Forte@Sun.COM link = link->next) {
19207836SJohn.Forte@Sun.COM tq = link->base_address;
19217836SJohn.Forte@Sun.COM
19227836SJohn.Forte@Sun.COM if (!VALID_TARGET_ID(ha, tq->loop_id)) {
19237836SJohn.Forte@Sun.COM continue;
19247836SJohn.Forte@Sun.COM }
19257836SJohn.Forte@Sun.COM if (cnt != dop->option) {
19267836SJohn.Forte@Sun.COM cnt++;
19277836SJohn.Forte@Sun.COM continue;
19287836SJohn.Forte@Sun.COM }
19297836SJohn.Forte@Sun.COM /* fill in the values */
19307836SJohn.Forte@Sun.COM bcopy(tq->port_name, dev.wwpn, 8);
19317836SJohn.Forte@Sun.COM dev.address = tq->d_id.b24;
19327836SJohn.Forte@Sun.COM dev.loop_id = tq->loop_id;
19337836SJohn.Forte@Sun.COM if (tq->flags & TQF_TAPE_DEVICE) {
19347836SJohn.Forte@Sun.COM dev.type = FCT_TAPE;
19357836SJohn.Forte@Sun.COM } else if (tq->flags & TQF_INITIATOR_DEVICE) {
19367836SJohn.Forte@Sun.COM dev.type = FCT_INITIATOR;
19377836SJohn.Forte@Sun.COM } else {
19387836SJohn.Forte@Sun.COM dev.type = FCT_TARGET;
19397836SJohn.Forte@Sun.COM }
19407836SJohn.Forte@Sun.COM break;
19417836SJohn.Forte@Sun.COM }
19427836SJohn.Forte@Sun.COM }
19437836SJohn.Forte@Sun.COM
19447836SJohn.Forte@Sun.COM if (ddi_copyout((void *)&dev, (void *)(uintptr_t)dop->buffer,
19459156SDaniel.Beauregard@Sun.COM dop->length, mode) != 0) {
19467836SJohn.Forte@Sun.COM EL(ha, "failed, ddi_copyout\n");
19477836SJohn.Forte@Sun.COM return (EFAULT);
19487836SJohn.Forte@Sun.COM }
19497836SJohn.Forte@Sun.COM
19507836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
19517836SJohn.Forte@Sun.COM
19527836SJohn.Forte@Sun.COM return (0);
19537836SJohn.Forte@Sun.COM }
19547836SJohn.Forte@Sun.COM
19557836SJohn.Forte@Sun.COM /*
19567836SJohn.Forte@Sun.COM * ql_adm_update_properties
19577836SJohn.Forte@Sun.COM * Performs qladm QL_UPDATE_PROPERTIES command
19587836SJohn.Forte@Sun.COM *
19597836SJohn.Forte@Sun.COM * Input:
19607836SJohn.Forte@Sun.COM * ha: adapter state pointer.
19617836SJohn.Forte@Sun.COM *
19627836SJohn.Forte@Sun.COM * Returns:
19637836SJohn.Forte@Sun.COM *
19647836SJohn.Forte@Sun.COM * Context:
19657836SJohn.Forte@Sun.COM * Kernel context.
19667836SJohn.Forte@Sun.COM */
19677836SJohn.Forte@Sun.COM static int
ql_adm_update_properties(ql_adapter_state_t * ha)19687836SJohn.Forte@Sun.COM ql_adm_update_properties(ql_adapter_state_t *ha)
19697836SJohn.Forte@Sun.COM {
19707836SJohn.Forte@Sun.COM ql_comb_init_cb_t init_ctrl_blk;
19717836SJohn.Forte@Sun.COM ql_comb_ip_init_cb_t ip_init_ctrl_blk;
19727836SJohn.Forte@Sun.COM
19737836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
19747836SJohn.Forte@Sun.COM
19757836SJohn.Forte@Sun.COM /* Stall driver instance. */
19767836SJohn.Forte@Sun.COM (void) ql_stall_driver(ha, 0);
19777836SJohn.Forte@Sun.COM
19787836SJohn.Forte@Sun.COM /* Save init control blocks. */
19797836SJohn.Forte@Sun.COM bcopy(&ha->init_ctrl_blk, &init_ctrl_blk, sizeof (ql_comb_init_cb_t));
19807836SJohn.Forte@Sun.COM bcopy(&ha->ip_init_ctrl_blk, &ip_init_ctrl_blk,
19817836SJohn.Forte@Sun.COM sizeof (ql_comb_ip_init_cb_t));
19827836SJohn.Forte@Sun.COM
19837836SJohn.Forte@Sun.COM /* Update PCI configration. */
19847836SJohn.Forte@Sun.COM (void) ql_pci_sbus_config(ha);
19857836SJohn.Forte@Sun.COM
19867836SJohn.Forte@Sun.COM /* Get configuration properties. */
19877836SJohn.Forte@Sun.COM (void) ql_nvram_config(ha);
19887836SJohn.Forte@Sun.COM
19897836SJohn.Forte@Sun.COM /* Check for init firmware required. */
19907836SJohn.Forte@Sun.COM if (bcmp(&ha->init_ctrl_blk, &init_ctrl_blk,
19917836SJohn.Forte@Sun.COM sizeof (ql_comb_init_cb_t)) != 0 ||
19927836SJohn.Forte@Sun.COM bcmp(&ha->ip_init_ctrl_blk, &ip_init_ctrl_blk,
19937836SJohn.Forte@Sun.COM sizeof (ql_comb_ip_init_cb_t)) != 0) {
19947836SJohn.Forte@Sun.COM
19957836SJohn.Forte@Sun.COM EL(ha, "isp_abort_needed\n");
19967836SJohn.Forte@Sun.COM ha->loop_down_timer = LOOP_DOWN_TIMER_START;
19977836SJohn.Forte@Sun.COM TASK_DAEMON_LOCK(ha);
19987836SJohn.Forte@Sun.COM ha->task_daemon_flags |= LOOP_DOWN | ISP_ABORT_NEEDED;
19997836SJohn.Forte@Sun.COM TASK_DAEMON_UNLOCK(ha);
20007836SJohn.Forte@Sun.COM }
20017836SJohn.Forte@Sun.COM
20027836SJohn.Forte@Sun.COM /* Update AEN queue. */
20037836SJohn.Forte@Sun.COM if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) {
20047836SJohn.Forte@Sun.COM ql_enqueue_aen(ha, MBA_PORT_UPDATE, NULL);
20057836SJohn.Forte@Sun.COM }
20067836SJohn.Forte@Sun.COM
20077836SJohn.Forte@Sun.COM /* Restart driver instance. */
20087836SJohn.Forte@Sun.COM ql_restart_driver(ha);
20097836SJohn.Forte@Sun.COM
20107836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
20117836SJohn.Forte@Sun.COM
20127836SJohn.Forte@Sun.COM return (0);
20137836SJohn.Forte@Sun.COM }
20147836SJohn.Forte@Sun.COM
20157836SJohn.Forte@Sun.COM /*
20167836SJohn.Forte@Sun.COM * ql_adm_prop_update_int
20177836SJohn.Forte@Sun.COM * Performs qladm QL_PROP_UPDATE_INT command
20187836SJohn.Forte@Sun.COM *
20197836SJohn.Forte@Sun.COM * Input:
20207836SJohn.Forte@Sun.COM * ha: adapter state pointer.
20217836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
20227836SJohn.Forte@Sun.COM * mode: flags.
20237836SJohn.Forte@Sun.COM *
20247836SJohn.Forte@Sun.COM * Returns:
20257836SJohn.Forte@Sun.COM *
20267836SJohn.Forte@Sun.COM * Context:
20277836SJohn.Forte@Sun.COM * Kernel context.
20287836SJohn.Forte@Sun.COM */
20297836SJohn.Forte@Sun.COM static int
ql_adm_prop_update_int(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)20307836SJohn.Forte@Sun.COM ql_adm_prop_update_int(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
20317836SJohn.Forte@Sun.COM {
20327836SJohn.Forte@Sun.COM char *prop_name;
20337836SJohn.Forte@Sun.COM int rval;
20347836SJohn.Forte@Sun.COM
20357836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
20367836SJohn.Forte@Sun.COM
20377836SJohn.Forte@Sun.COM prop_name = kmem_zalloc(dop->length, KM_SLEEP);
20387836SJohn.Forte@Sun.COM if (prop_name == NULL) {
20397836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
20407836SJohn.Forte@Sun.COM return (ENOMEM);
20417836SJohn.Forte@Sun.COM }
20427836SJohn.Forte@Sun.COM
20437836SJohn.Forte@Sun.COM if (ddi_copyin((void *)(uintptr_t)dop->buffer, prop_name, dop->length,
20447836SJohn.Forte@Sun.COM mode) != 0) {
20457836SJohn.Forte@Sun.COM EL(ha, "failed, prop_name ddi_copyin\n");
20467836SJohn.Forte@Sun.COM kmem_free(prop_name, dop->length);
20477836SJohn.Forte@Sun.COM return (EFAULT);
20487836SJohn.Forte@Sun.COM }
20497836SJohn.Forte@Sun.COM
20507836SJohn.Forte@Sun.COM /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
20517836SJohn.Forte@Sun.COM if ((rval = ddi_prop_update_int(DDI_DEV_T_NONE, ha->dip, prop_name,
20527836SJohn.Forte@Sun.COM (int)dop->option)) != DDI_PROP_SUCCESS) {
20537836SJohn.Forte@Sun.COM EL(ha, "failed, prop_update=%xh\n", rval);
20547836SJohn.Forte@Sun.COM kmem_free(prop_name, dop->length);
20557836SJohn.Forte@Sun.COM return (EINVAL);
20567836SJohn.Forte@Sun.COM }
20577836SJohn.Forte@Sun.COM
20587836SJohn.Forte@Sun.COM kmem_free(prop_name, dop->length);
20597836SJohn.Forte@Sun.COM
20607836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
20617836SJohn.Forte@Sun.COM
20627836SJohn.Forte@Sun.COM return (0);
20637836SJohn.Forte@Sun.COM }
20647836SJohn.Forte@Sun.COM
20657836SJohn.Forte@Sun.COM /*
20667836SJohn.Forte@Sun.COM * ql_adm_fw_dump
20677836SJohn.Forte@Sun.COM * Performs qladm QL_FW_DUMP command
20687836SJohn.Forte@Sun.COM *
20697836SJohn.Forte@Sun.COM * Input:
20707836SJohn.Forte@Sun.COM * ha: adapter state pointer.
20717836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
20727836SJohn.Forte@Sun.COM * udop: user space ql_adm_op_t structure pointer.
20737836SJohn.Forte@Sun.COM * mode: flags.
20747836SJohn.Forte@Sun.COM *
20757836SJohn.Forte@Sun.COM * Returns:
20767836SJohn.Forte@Sun.COM *
20777836SJohn.Forte@Sun.COM * Context:
20787836SJohn.Forte@Sun.COM * Kernel context.
20797836SJohn.Forte@Sun.COM */
20807836SJohn.Forte@Sun.COM static int
ql_adm_fw_dump(ql_adapter_state_t * ha,ql_adm_op_t * dop,void * udop,int mode)20817836SJohn.Forte@Sun.COM ql_adm_fw_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, void *udop, int mode)
20827836SJohn.Forte@Sun.COM {
20837836SJohn.Forte@Sun.COM caddr_t dmp;
20847836SJohn.Forte@Sun.COM
20857836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
20867836SJohn.Forte@Sun.COM
20877836SJohn.Forte@Sun.COM if (dop->length < ha->risc_dump_size) {
20887836SJohn.Forte@Sun.COM EL(ha, "failed, incorrect length=%xh, size=%xh\n",
20897836SJohn.Forte@Sun.COM dop->length, ha->risc_dump_size);
20907836SJohn.Forte@Sun.COM return (EINVAL);
20917836SJohn.Forte@Sun.COM }
20927836SJohn.Forte@Sun.COM
20939156SDaniel.Beauregard@Sun.COM if (ha->ql_dump_state & QL_DUMP_VALID) {
20947836SJohn.Forte@Sun.COM dmp = kmem_zalloc(ha->risc_dump_size, KM_SLEEP);
20957836SJohn.Forte@Sun.COM if (dmp == NULL) {
20967836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
20977836SJohn.Forte@Sun.COM return (ENOMEM);
20987836SJohn.Forte@Sun.COM }
20997836SJohn.Forte@Sun.COM
21007836SJohn.Forte@Sun.COM dop->length = (uint32_t)ql_ascii_fw_dump(ha, dmp);
21017836SJohn.Forte@Sun.COM if (ddi_copyout((void *)dmp, (void *)(uintptr_t)dop->buffer,
21027836SJohn.Forte@Sun.COM dop->length, mode) != 0) {
21037836SJohn.Forte@Sun.COM EL(ha, "failed, ddi_copyout\n");
21047836SJohn.Forte@Sun.COM kmem_free(dmp, ha->risc_dump_size);
21057836SJohn.Forte@Sun.COM return (EFAULT);
21067836SJohn.Forte@Sun.COM }
21077836SJohn.Forte@Sun.COM
21087836SJohn.Forte@Sun.COM kmem_free(dmp, ha->risc_dump_size);
21099156SDaniel.Beauregard@Sun.COM ha->ql_dump_state |= QL_DUMP_UPLOADED;
21107836SJohn.Forte@Sun.COM
21117836SJohn.Forte@Sun.COM } else {
21127836SJohn.Forte@Sun.COM EL(ha, "failed, no dump file\n");
21137836SJohn.Forte@Sun.COM dop->length = 0;
21147836SJohn.Forte@Sun.COM }
21157836SJohn.Forte@Sun.COM
21167836SJohn.Forte@Sun.COM if (ddi_copyout(dop, udop, sizeof (ql_adm_op_t), mode) != 0) {
21177836SJohn.Forte@Sun.COM EL(ha, "failed, driver_op_t ddi_copyout\n");
21187836SJohn.Forte@Sun.COM return (EFAULT);
21197836SJohn.Forte@Sun.COM }
21207836SJohn.Forte@Sun.COM
21217836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
21227836SJohn.Forte@Sun.COM
21237836SJohn.Forte@Sun.COM return (0);
21247836SJohn.Forte@Sun.COM }
21257836SJohn.Forte@Sun.COM
21267836SJohn.Forte@Sun.COM /*
21277836SJohn.Forte@Sun.COM * ql_adm_nvram_dump
21287836SJohn.Forte@Sun.COM * Performs qladm QL_NVRAM_DUMP command
21297836SJohn.Forte@Sun.COM *
21307836SJohn.Forte@Sun.COM * Input:
21317836SJohn.Forte@Sun.COM * ha: adapter state pointer.
21327836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
21337836SJohn.Forte@Sun.COM * mode: flags.
21347836SJohn.Forte@Sun.COM *
21357836SJohn.Forte@Sun.COM * Returns:
21367836SJohn.Forte@Sun.COM *
21377836SJohn.Forte@Sun.COM * Context:
21387836SJohn.Forte@Sun.COM * Kernel context.
21397836SJohn.Forte@Sun.COM */
21407836SJohn.Forte@Sun.COM static int
ql_adm_nvram_dump(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)21417836SJohn.Forte@Sun.COM ql_adm_nvram_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
21427836SJohn.Forte@Sun.COM {
21437836SJohn.Forte@Sun.COM int rval;
21447836SJohn.Forte@Sun.COM
21457836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
21467836SJohn.Forte@Sun.COM
214711541SDaniel.Beauregard@Sun.COM if (dop->length < ha->nvram_cache->size) {
214811541SDaniel.Beauregard@Sun.COM EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
214911541SDaniel.Beauregard@Sun.COM ha->nvram_cache->size);
21507836SJohn.Forte@Sun.COM return (EINVAL);
21517836SJohn.Forte@Sun.COM }
21527836SJohn.Forte@Sun.COM
21537836SJohn.Forte@Sun.COM if ((rval = ql_nv_util_dump(ha, (void *)(uintptr_t)dop->buffer,
21547836SJohn.Forte@Sun.COM mode)) != 0) {
21557836SJohn.Forte@Sun.COM EL(ha, "failed, ql_nv_util_dump\n");
21567836SJohn.Forte@Sun.COM } else {
21577836SJohn.Forte@Sun.COM /*EMPTY*/
21587836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
21597836SJohn.Forte@Sun.COM }
21607836SJohn.Forte@Sun.COM
21617836SJohn.Forte@Sun.COM return (rval);
21627836SJohn.Forte@Sun.COM }
21637836SJohn.Forte@Sun.COM
21647836SJohn.Forte@Sun.COM /*
21657836SJohn.Forte@Sun.COM * ql_adm_nvram_load
21667836SJohn.Forte@Sun.COM * Performs qladm QL_NVRAM_LOAD command
21677836SJohn.Forte@Sun.COM *
21687836SJohn.Forte@Sun.COM * Input:
21697836SJohn.Forte@Sun.COM * ha: adapter state pointer.
21707836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
21717836SJohn.Forte@Sun.COM * mode: flags.
21727836SJohn.Forte@Sun.COM *
21737836SJohn.Forte@Sun.COM * Returns:
21747836SJohn.Forte@Sun.COM *
21757836SJohn.Forte@Sun.COM * Context:
21767836SJohn.Forte@Sun.COM * Kernel context.
21777836SJohn.Forte@Sun.COM */
21787836SJohn.Forte@Sun.COM static int
ql_adm_nvram_load(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)21797836SJohn.Forte@Sun.COM ql_adm_nvram_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
21807836SJohn.Forte@Sun.COM {
21817836SJohn.Forte@Sun.COM int rval;
21827836SJohn.Forte@Sun.COM
21837836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
21847836SJohn.Forte@Sun.COM
218511541SDaniel.Beauregard@Sun.COM if (dop->length < ha->nvram_cache->size) {
218611541SDaniel.Beauregard@Sun.COM EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
218711541SDaniel.Beauregard@Sun.COM ha->nvram_cache->size);
21887836SJohn.Forte@Sun.COM return (EINVAL);
21897836SJohn.Forte@Sun.COM }
21907836SJohn.Forte@Sun.COM
21917836SJohn.Forte@Sun.COM if ((rval = ql_nv_util_load(ha, (void *)(uintptr_t)dop->buffer,
21927836SJohn.Forte@Sun.COM mode)) != 0) {
21937836SJohn.Forte@Sun.COM EL(ha, "failed, ql_nv_util_dump\n");
21947836SJohn.Forte@Sun.COM } else {
21957836SJohn.Forte@Sun.COM /*EMPTY*/
21967836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
21977836SJohn.Forte@Sun.COM }
21987836SJohn.Forte@Sun.COM
21997836SJohn.Forte@Sun.COM return (rval);
22007836SJohn.Forte@Sun.COM }
22017836SJohn.Forte@Sun.COM
22027836SJohn.Forte@Sun.COM /*
22037836SJohn.Forte@Sun.COM * ql_adm_flash_load
22047836SJohn.Forte@Sun.COM * Performs qladm QL_FLASH_LOAD command
22057836SJohn.Forte@Sun.COM *
22067836SJohn.Forte@Sun.COM * Input:
22077836SJohn.Forte@Sun.COM * ha: adapter state pointer.
22087836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
22097836SJohn.Forte@Sun.COM * mode: flags.
22107836SJohn.Forte@Sun.COM *
22117836SJohn.Forte@Sun.COM * Returns:
22127836SJohn.Forte@Sun.COM *
22137836SJohn.Forte@Sun.COM * Context:
22147836SJohn.Forte@Sun.COM * Kernel context.
22157836SJohn.Forte@Sun.COM */
22167836SJohn.Forte@Sun.COM static int
ql_adm_flash_load(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)22177836SJohn.Forte@Sun.COM ql_adm_flash_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
22187836SJohn.Forte@Sun.COM {
22197836SJohn.Forte@Sun.COM uint8_t *dp;
22207836SJohn.Forte@Sun.COM int rval;
22217836SJohn.Forte@Sun.COM
22227836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
22237836SJohn.Forte@Sun.COM
22247836SJohn.Forte@Sun.COM if ((dp = kmem_zalloc(dop->length, KM_SLEEP)) == NULL) {
22257836SJohn.Forte@Sun.COM EL(ha, "failed, kmem_zalloc\n");
22267836SJohn.Forte@Sun.COM return (ENOMEM);
22277836SJohn.Forte@Sun.COM }
22287836SJohn.Forte@Sun.COM
22297836SJohn.Forte@Sun.COM if (ddi_copyin((void *)(uintptr_t)dop->buffer, dp, dop->length,
22307836SJohn.Forte@Sun.COM mode) != 0) {
22317836SJohn.Forte@Sun.COM EL(ha, "ddi_copyin failed\n");
22327836SJohn.Forte@Sun.COM kmem_free(dp, dop->length);
22337836SJohn.Forte@Sun.COM return (EFAULT);
22347836SJohn.Forte@Sun.COM }
22357836SJohn.Forte@Sun.COM
22367836SJohn.Forte@Sun.COM if (ql_stall_driver(ha, 0) != QL_SUCCESS) {
22377836SJohn.Forte@Sun.COM EL(ha, "ql_stall_driver failed\n");
22387836SJohn.Forte@Sun.COM kmem_free(dp, dop->length);
22397836SJohn.Forte@Sun.COM return (EBUSY);
22407836SJohn.Forte@Sun.COM }
22417836SJohn.Forte@Sun.COM
224211924SDaniel.Beauregard@Sun.COM rval = (CFG_IST(ha, CFG_CTRL_24258081) ?
22437836SJohn.Forte@Sun.COM ql_24xx_load_flash(ha, dp, dop->length, dop->option) :
22447836SJohn.Forte@Sun.COM ql_load_flash(ha, dp, dop->length));
22457836SJohn.Forte@Sun.COM
22467836SJohn.Forte@Sun.COM ql_restart_driver(ha);
22477836SJohn.Forte@Sun.COM
22487836SJohn.Forte@Sun.COM kmem_free(dp, dop->length);
22497836SJohn.Forte@Sun.COM
22507836SJohn.Forte@Sun.COM if (rval != QL_SUCCESS) {
22517836SJohn.Forte@Sun.COM EL(ha, "failed\n");
22527836SJohn.Forte@Sun.COM return (EIO);
22537836SJohn.Forte@Sun.COM }
22547836SJohn.Forte@Sun.COM
22557836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
22567836SJohn.Forte@Sun.COM
22577836SJohn.Forte@Sun.COM return (0);
22587836SJohn.Forte@Sun.COM }
22597836SJohn.Forte@Sun.COM
22607836SJohn.Forte@Sun.COM /*
22617836SJohn.Forte@Sun.COM * ql_adm_vpd_dump
22627836SJohn.Forte@Sun.COM * Performs qladm QL_VPD_DUMP command
22637836SJohn.Forte@Sun.COM *
22647836SJohn.Forte@Sun.COM * Input:
22657836SJohn.Forte@Sun.COM * ha: adapter state pointer.
22667836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
22677836SJohn.Forte@Sun.COM * mode: flags.
22687836SJohn.Forte@Sun.COM *
22697836SJohn.Forte@Sun.COM * Returns:
22707836SJohn.Forte@Sun.COM *
22717836SJohn.Forte@Sun.COM * Context:
22727836SJohn.Forte@Sun.COM * Kernel context.
22737836SJohn.Forte@Sun.COM */
22747836SJohn.Forte@Sun.COM static int
ql_adm_vpd_dump(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)22757836SJohn.Forte@Sun.COM ql_adm_vpd_dump(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
22767836SJohn.Forte@Sun.COM {
22777836SJohn.Forte@Sun.COM int rval;
22787836SJohn.Forte@Sun.COM
22797836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
22807836SJohn.Forte@Sun.COM
228111924SDaniel.Beauregard@Sun.COM if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
22827836SJohn.Forte@Sun.COM EL(ha, "hba does not support VPD\n");
22837836SJohn.Forte@Sun.COM return (EINVAL);
22847836SJohn.Forte@Sun.COM }
22857836SJohn.Forte@Sun.COM
22867836SJohn.Forte@Sun.COM if (dop->length < QL_24XX_VPD_SIZE) {
22877836SJohn.Forte@Sun.COM EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
22887836SJohn.Forte@Sun.COM QL_24XX_VPD_SIZE);
22897836SJohn.Forte@Sun.COM return (EINVAL);
22907836SJohn.Forte@Sun.COM }
22917836SJohn.Forte@Sun.COM
22929156SDaniel.Beauregard@Sun.COM if ((rval = ql_vpd_dump(ha, (void *)(uintptr_t)dop->buffer, mode))
22939156SDaniel.Beauregard@Sun.COM != 0) {
22947836SJohn.Forte@Sun.COM EL(ha, "failed, ql_vpd_dump\n");
22957836SJohn.Forte@Sun.COM } else {
22967836SJohn.Forte@Sun.COM /*EMPTY*/
22977836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
22987836SJohn.Forte@Sun.COM }
22997836SJohn.Forte@Sun.COM
23007836SJohn.Forte@Sun.COM return (rval);
23017836SJohn.Forte@Sun.COM }
23027836SJohn.Forte@Sun.COM
23037836SJohn.Forte@Sun.COM /*
23047836SJohn.Forte@Sun.COM * ql_adm_vpd_load
23057836SJohn.Forte@Sun.COM * Performs qladm QL_VPD_LOAD command
23067836SJohn.Forte@Sun.COM *
23077836SJohn.Forte@Sun.COM * Input:
23087836SJohn.Forte@Sun.COM * ha: adapter state pointer.
23097836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
23107836SJohn.Forte@Sun.COM * mode: flags.
23117836SJohn.Forte@Sun.COM *
23127836SJohn.Forte@Sun.COM * Returns:
23137836SJohn.Forte@Sun.COM *
23147836SJohn.Forte@Sun.COM * Context:
23157836SJohn.Forte@Sun.COM * Kernel context.
23167836SJohn.Forte@Sun.COM */
23177836SJohn.Forte@Sun.COM static int
ql_adm_vpd_load(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)23187836SJohn.Forte@Sun.COM ql_adm_vpd_load(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
23197836SJohn.Forte@Sun.COM {
23207836SJohn.Forte@Sun.COM int rval;
23217836SJohn.Forte@Sun.COM
23227836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
23237836SJohn.Forte@Sun.COM
232411924SDaniel.Beauregard@Sun.COM if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
23257836SJohn.Forte@Sun.COM EL(ha, "hba does not support VPD\n");
23267836SJohn.Forte@Sun.COM return (EINVAL);
23277836SJohn.Forte@Sun.COM }
23287836SJohn.Forte@Sun.COM
23297836SJohn.Forte@Sun.COM if (dop->length < QL_24XX_VPD_SIZE) {
23307836SJohn.Forte@Sun.COM EL(ha, "failed, length=%xh, size=%xh\n", dop->length,
23317836SJohn.Forte@Sun.COM QL_24XX_VPD_SIZE);
23327836SJohn.Forte@Sun.COM return (EINVAL);
23337836SJohn.Forte@Sun.COM }
23347836SJohn.Forte@Sun.COM
23359156SDaniel.Beauregard@Sun.COM if ((rval = ql_vpd_load(ha, (void *)(uintptr_t)dop->buffer, mode))
23369156SDaniel.Beauregard@Sun.COM != 0) {
23377836SJohn.Forte@Sun.COM EL(ha, "failed, ql_vpd_dump\n");
23387836SJohn.Forte@Sun.COM } else {
23397836SJohn.Forte@Sun.COM /*EMPTY*/
23407836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
23417836SJohn.Forte@Sun.COM }
23427836SJohn.Forte@Sun.COM
23437836SJohn.Forte@Sun.COM return (rval);
23447836SJohn.Forte@Sun.COM }
23457836SJohn.Forte@Sun.COM
23467836SJohn.Forte@Sun.COM /*
23477836SJohn.Forte@Sun.COM * ql_adm_vpd_gettag
23487836SJohn.Forte@Sun.COM * Performs qladm QL_VPD_GETTAG command
23497836SJohn.Forte@Sun.COM *
23507836SJohn.Forte@Sun.COM * Input:
23517836SJohn.Forte@Sun.COM * ha: adapter state pointer.
23527836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
23537836SJohn.Forte@Sun.COM * mode: flags.
23547836SJohn.Forte@Sun.COM *
23557836SJohn.Forte@Sun.COM * Returns:
23567836SJohn.Forte@Sun.COM *
23577836SJohn.Forte@Sun.COM * Context:
23587836SJohn.Forte@Sun.COM * Kernel context.
23597836SJohn.Forte@Sun.COM */
23607836SJohn.Forte@Sun.COM static int
ql_adm_vpd_gettag(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)23617836SJohn.Forte@Sun.COM ql_adm_vpd_gettag(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
23627836SJohn.Forte@Sun.COM {
23637836SJohn.Forte@Sun.COM int rval = 0;
23647836SJohn.Forte@Sun.COM uint8_t *lbuf;
23657836SJohn.Forte@Sun.COM
23667836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
23677836SJohn.Forte@Sun.COM
236811924SDaniel.Beauregard@Sun.COM if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
23697836SJohn.Forte@Sun.COM EL(ha, "hba does not support VPD\n");
23707836SJohn.Forte@Sun.COM return (EINVAL);
23717836SJohn.Forte@Sun.COM }
23727836SJohn.Forte@Sun.COM
23737836SJohn.Forte@Sun.COM if ((lbuf = (uint8_t *)kmem_zalloc(dop->length, KM_SLEEP)) == NULL) {
23747836SJohn.Forte@Sun.COM EL(ha, "mem alloc failure of %xh bytes\n", dop->length);
23757836SJohn.Forte@Sun.COM rval = EFAULT;
23767836SJohn.Forte@Sun.COM } else {
23777836SJohn.Forte@Sun.COM if (ddi_copyin((void *)(uintptr_t)dop->buffer, lbuf,
23787836SJohn.Forte@Sun.COM dop->length, mode) != 0) {
23797836SJohn.Forte@Sun.COM EL(ha, "ddi_copyin failed\n");
23807836SJohn.Forte@Sun.COM kmem_free(lbuf, dop->length);
23817836SJohn.Forte@Sun.COM return (EFAULT);
23827836SJohn.Forte@Sun.COM }
23837836SJohn.Forte@Sun.COM
23847836SJohn.Forte@Sun.COM if ((rval = ql_vpd_lookup(ha, lbuf, lbuf, (int32_t)
23857836SJohn.Forte@Sun.COM dop->length)) < 0) {
23867836SJohn.Forte@Sun.COM EL(ha, "failed vpd_lookup\n");
23877836SJohn.Forte@Sun.COM } else {
23887836SJohn.Forte@Sun.COM if (ddi_copyout(lbuf, (void *)(uintptr_t)dop->buffer,
23897836SJohn.Forte@Sun.COM strlen((int8_t *)lbuf)+1, mode) != 0) {
23907836SJohn.Forte@Sun.COM EL(ha, "failed, ddi_copyout\n");
23917836SJohn.Forte@Sun.COM rval = EFAULT;
23927836SJohn.Forte@Sun.COM } else {
23937836SJohn.Forte@Sun.COM rval = 0;
23947836SJohn.Forte@Sun.COM }
23957836SJohn.Forte@Sun.COM }
23967836SJohn.Forte@Sun.COM kmem_free(lbuf, dop->length);
23977836SJohn.Forte@Sun.COM }
23987836SJohn.Forte@Sun.COM
23999446SDaniel.Beauregard@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
24007836SJohn.Forte@Sun.COM
24017836SJohn.Forte@Sun.COM return (rval);
24027836SJohn.Forte@Sun.COM }
24037836SJohn.Forte@Sun.COM
24047836SJohn.Forte@Sun.COM /*
24057836SJohn.Forte@Sun.COM * ql_adm_updfwmodule
24067836SJohn.Forte@Sun.COM * Performs qladm QL_UPD_FWMODULE command
24077836SJohn.Forte@Sun.COM *
24087836SJohn.Forte@Sun.COM * Input:
24097836SJohn.Forte@Sun.COM * ha: adapter state pointer.
24107836SJohn.Forte@Sun.COM * dop: ql_adm_op_t structure pointer.
24117836SJohn.Forte@Sun.COM * mode: flags.
24127836SJohn.Forte@Sun.COM *
24137836SJohn.Forte@Sun.COM * Returns:
24147836SJohn.Forte@Sun.COM *
24157836SJohn.Forte@Sun.COM * Context:
24167836SJohn.Forte@Sun.COM * Kernel context.
24177836SJohn.Forte@Sun.COM */
24187836SJohn.Forte@Sun.COM /* ARGSUSED */
24197836SJohn.Forte@Sun.COM static int
ql_adm_updfwmodule(ql_adapter_state_t * ha,ql_adm_op_t * dop,int mode)24207836SJohn.Forte@Sun.COM ql_adm_updfwmodule(ql_adapter_state_t *ha, ql_adm_op_t *dop, int mode)
24217836SJohn.Forte@Sun.COM {
24227836SJohn.Forte@Sun.COM int rval = DDI_SUCCESS;
24237836SJohn.Forte@Sun.COM ql_link_t *link;
24247836SJohn.Forte@Sun.COM ql_adapter_state_t *ha2 = NULL;
24257836SJohn.Forte@Sun.COM uint16_t fw_class = (uint16_t)dop->option;
24267836SJohn.Forte@Sun.COM
24277836SJohn.Forte@Sun.COM QL_PRINT_9(CE_CONT, "(%d): started\n", ha->instance);
24287836SJohn.Forte@Sun.COM
24297836SJohn.Forte@Sun.COM /* zero the firmware module reference count */
24307836SJohn.Forte@Sun.COM for (link = ql_hba.first; link != NULL; link = link->next) {
24317836SJohn.Forte@Sun.COM ha2 = link->base_address;
24327836SJohn.Forte@Sun.COM if (fw_class == ha2->fw_class) {
24337836SJohn.Forte@Sun.COM if ((rval = ddi_modclose(ha2->fw_module)) !=
24347836SJohn.Forte@Sun.COM DDI_SUCCESS) {
24357836SJohn.Forte@Sun.COM EL(ha2, "modclose rval=%xh\n", rval);
24367836SJohn.Forte@Sun.COM break;
24377836SJohn.Forte@Sun.COM }
24387836SJohn.Forte@Sun.COM ha2->fw_module = NULL;
24397836SJohn.Forte@Sun.COM }
24407836SJohn.Forte@Sun.COM }
24417836SJohn.Forte@Sun.COM
24427836SJohn.Forte@Sun.COM /* reload the f/w modules */
24437836SJohn.Forte@Sun.COM for (link = ql_hba.first; link != NULL; link = link->next) {
24447836SJohn.Forte@Sun.COM ha2 = link->base_address;
24457836SJohn.Forte@Sun.COM
24467836SJohn.Forte@Sun.COM if ((fw_class == ha2->fw_class) && (ha2->fw_class == NULL)) {
24477836SJohn.Forte@Sun.COM if ((rval = (int32_t)ql_fwmodule_resolve(ha2)) !=
24487836SJohn.Forte@Sun.COM QL_SUCCESS) {
24497836SJohn.Forte@Sun.COM EL(ha2, "unable to load f/w module: '%x' "
24507836SJohn.Forte@Sun.COM "(rval=%xh)\n", ha2->fw_class, rval);
24517836SJohn.Forte@Sun.COM rval = EFAULT;
24527836SJohn.Forte@Sun.COM } else {
24537836SJohn.Forte@Sun.COM EL(ha2, "f/w module updated: '%x'\n",
24547836SJohn.Forte@Sun.COM ha2->fw_class);
24557836SJohn.Forte@Sun.COM }
24567836SJohn.Forte@Sun.COM
24577836SJohn.Forte@Sun.COM EL(ha2, "isp abort needed (%d)\n", ha->instance);
24587836SJohn.Forte@Sun.COM
24597836SJohn.Forte@Sun.COM ql_awaken_task_daemon(ha2, NULL, ISP_ABORT_NEEDED, 0);
24607836SJohn.Forte@Sun.COM
24617836SJohn.Forte@Sun.COM rval = 0;
24627836SJohn.Forte@Sun.COM }
24637836SJohn.Forte@Sun.COM }
24647836SJohn.Forte@Sun.COM
24659446SDaniel.Beauregard@Sun.COM QL_PRINT_9(CE_CONT, "(%d): done\n", ha->instance);
24667836SJohn.Forte@Sun.COM
24677836SJohn.Forte@Sun.COM return (rval);
24687836SJohn.Forte@Sun.COM }
2469