xref: /onnv-gate/usr/src/uts/common/io/ib/adapters/hermon/hermon_cmd.c (revision 12965:b65a8427f8fe)
19517SBill.Taylor@Sun.COM /*
29517SBill.Taylor@Sun.COM  * CDDL HEADER START
39517SBill.Taylor@Sun.COM  *
49517SBill.Taylor@Sun.COM  * The contents of this file are subject to the terms of the
59517SBill.Taylor@Sun.COM  * Common Development and Distribution License (the "License").
69517SBill.Taylor@Sun.COM  * You may not use this file except in compliance with the License.
79517SBill.Taylor@Sun.COM  *
89517SBill.Taylor@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99517SBill.Taylor@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109517SBill.Taylor@Sun.COM  * See the License for the specific language governing permissions
119517SBill.Taylor@Sun.COM  * and limitations under the License.
129517SBill.Taylor@Sun.COM  *
139517SBill.Taylor@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149517SBill.Taylor@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159517SBill.Taylor@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169517SBill.Taylor@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179517SBill.Taylor@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189517SBill.Taylor@Sun.COM  *
199517SBill.Taylor@Sun.COM  * CDDL HEADER END
209517SBill.Taylor@Sun.COM  */
219517SBill.Taylor@Sun.COM 
229517SBill.Taylor@Sun.COM /*
23*12965SWilliam.Taylor@Oracle.COM  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
249517SBill.Taylor@Sun.COM  */
259517SBill.Taylor@Sun.COM 
269517SBill.Taylor@Sun.COM /*
279517SBill.Taylor@Sun.COM  * hermon_cmd.c
289517SBill.Taylor@Sun.COM  *    Hermon Firmware Command Routines
299517SBill.Taylor@Sun.COM  *
309517SBill.Taylor@Sun.COM  *    Implements all the routines necessary for allocating, posting, and
319517SBill.Taylor@Sun.COM  *    freeing commands for the Hermon firmware.  These routines manage a
329517SBill.Taylor@Sun.COM  *    preallocated list of command mailboxes and provide interfaces to post
339517SBill.Taylor@Sun.COM  *    each of the several dozen commands to the Hermon firmware.
349517SBill.Taylor@Sun.COM  */
359517SBill.Taylor@Sun.COM 
369517SBill.Taylor@Sun.COM #include <sys/types.h>
379517SBill.Taylor@Sun.COM #include <sys/conf.h>
389517SBill.Taylor@Sun.COM #include <sys/ddi.h>
399517SBill.Taylor@Sun.COM #include <sys/sunddi.h>
409517SBill.Taylor@Sun.COM #include <sys/modctl.h>
419517SBill.Taylor@Sun.COM #include <sys/bitmap.h>
429517SBill.Taylor@Sun.COM 
439517SBill.Taylor@Sun.COM #include <sys/ib/adapters/hermon/hermon.h>
449517SBill.Taylor@Sun.COM 
459517SBill.Taylor@Sun.COM static int hermon_impl_mbox_alloc(hermon_state_t *state,
469517SBill.Taylor@Sun.COM     hermon_mboxlist_t *mblist, hermon_mbox_t **mb, uint_t mbox_wait);
479517SBill.Taylor@Sun.COM static void hermon_impl_mbox_free(hermon_mboxlist_t *mblist,
489517SBill.Taylor@Sun.COM     hermon_mbox_t **mb);
499517SBill.Taylor@Sun.COM static int hermon_impl_mboxlist_init(hermon_state_t *state,
509517SBill.Taylor@Sun.COM     hermon_mboxlist_t *mblist, uint_t num_mbox, hermon_rsrc_type_t type);
519517SBill.Taylor@Sun.COM static void hermon_impl_mboxlist_fini(hermon_state_t *state,
529517SBill.Taylor@Sun.COM     hermon_mboxlist_t *mblist);
539517SBill.Taylor@Sun.COM static int hermon_outstanding_cmd_alloc(hermon_state_t *state,
549517SBill.Taylor@Sun.COM     hermon_cmd_t **cmd_ptr, uint_t cmd_wait);
559517SBill.Taylor@Sun.COM static void hermon_outstanding_cmd_free(hermon_state_t *state,
569517SBill.Taylor@Sun.COM     hermon_cmd_t **cmd_ptr);
579517SBill.Taylor@Sun.COM static int hermon_write_hcr(hermon_state_t *state, hermon_cmd_post_t *cmdpost,
589517SBill.Taylor@Sun.COM     uint16_t token, int *hwerr);
599517SBill.Taylor@Sun.COM static void hermon_mbox_sync(hermon_mbox_t *mbox, uint_t offset,
609517SBill.Taylor@Sun.COM     uint_t length, uint_t flag);
619517SBill.Taylor@Sun.COM static void hermon_cmd_check_status(hermon_state_t *state, int status);
629517SBill.Taylor@Sun.COM 
639517SBill.Taylor@Sun.COM /*
649517SBill.Taylor@Sun.COM  * hermon_cmd_post()
659517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
669517SBill.Taylor@Sun.COM  *
679517SBill.Taylor@Sun.COM  *    The "cp_flags" field in cmdpost
689517SBill.Taylor@Sun.COM  *    is used to determine whether to wait for an available
699517SBill.Taylor@Sun.COM  *    outstanding command (if necessary) or to return error.
709517SBill.Taylor@Sun.COM  */
719517SBill.Taylor@Sun.COM int
hermon_cmd_post(hermon_state_t * state,hermon_cmd_post_t * cmdpost)729517SBill.Taylor@Sun.COM hermon_cmd_post(hermon_state_t *state, hermon_cmd_post_t *cmdpost)
739517SBill.Taylor@Sun.COM {
749517SBill.Taylor@Sun.COM 	hermon_cmd_t	*cmdptr;
759517SBill.Taylor@Sun.COM 	int		status, retry_cnt, retry_cnt2, hw_err;
769517SBill.Taylor@Sun.COM 	uint16_t	token;
779517SBill.Taylor@Sun.COM 
789517SBill.Taylor@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cmdpost))
799517SBill.Taylor@Sun.COM 
809517SBill.Taylor@Sun.COM 	/* Determine if we are going to spin until completion */
819517SBill.Taylor@Sun.COM 	if (cmdpost->cp_flags == HERMON_CMD_NOSLEEP_SPIN) {
829517SBill.Taylor@Sun.COM 
839517SBill.Taylor@Sun.COM 		/* Write the command to the HCR */
849517SBill.Taylor@Sun.COM 		retry_cnt = HCA_PIO_RETRY_CNT;
859517SBill.Taylor@Sun.COM 		do {
869517SBill.Taylor@Sun.COM 			status = hermon_write_hcr(state, cmdpost, 0, &hw_err);
879517SBill.Taylor@Sun.COM 		} while (status == HERMON_CMD_INTERNAL_ERR && retry_cnt-- > 0);
889517SBill.Taylor@Sun.COM 
899517SBill.Taylor@Sun.COM 		/* Check if there is an error status in hermon_write_hcr() */
909517SBill.Taylor@Sun.COM 		if (status != HERMON_CMD_SUCCESS) {
919517SBill.Taylor@Sun.COM 			/*
929517SBill.Taylor@Sun.COM 			 * If there is a HW error, call hermon_cmd_retry_ok()
939517SBill.Taylor@Sun.COM 			 * to check the side-effect of the operation retry.
949517SBill.Taylor@Sun.COM 			 */
959517SBill.Taylor@Sun.COM 			if ((retry_cnt == HCA_PIO_RETRY_CNT &&
969517SBill.Taylor@Sun.COM 			    hw_err == HCA_PIO_OK) ||
979517SBill.Taylor@Sun.COM 			    !hermon_cmd_retry_ok(cmdpost, status)) {
989517SBill.Taylor@Sun.COM 				hermon_cmd_check_status(state, status);
999517SBill.Taylor@Sun.COM 				return (status);
1009517SBill.Taylor@Sun.COM 			}
1019517SBill.Taylor@Sun.COM 		/* Check if there is a transient internal error */
1029517SBill.Taylor@Sun.COM 		} else if (retry_cnt != HCA_PIO_RETRY_CNT) {
1039517SBill.Taylor@Sun.COM 			hermon_fm_ereport(state, HCA_IBA_ERR,
1049517SBill.Taylor@Sun.COM 			    HCA_ERR_TRANSIENT);
1059517SBill.Taylor@Sun.COM 		}
1069517SBill.Taylor@Sun.COM 
1079517SBill.Taylor@Sun.COM 	} else {  /* "HERMON_CMD_SLEEP_NOSPIN" */
1089517SBill.Taylor@Sun.COM 		ASSERT(HERMON_SLEEPFLAG_FOR_CONTEXT() != HERMON_NOSLEEP);
1099517SBill.Taylor@Sun.COM 
1109517SBill.Taylor@Sun.COM 		/* NOTE: Expect threads to be waiting in here */
1119517SBill.Taylor@Sun.COM 		status = hermon_outstanding_cmd_alloc(state, &cmdptr,
1129517SBill.Taylor@Sun.COM 		    cmdpost->cp_flags);
1139517SBill.Taylor@Sun.COM 		if (status != HERMON_CMD_SUCCESS) {
1149517SBill.Taylor@Sun.COM 			return (status);
1159517SBill.Taylor@Sun.COM 		}
1169517SBill.Taylor@Sun.COM 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cmdptr))
1179517SBill.Taylor@Sun.COM 
1189517SBill.Taylor@Sun.COM 		retry_cnt = HCA_PIO_RETRY_CNT;
1199517SBill.Taylor@Sun.COM retry:
1209517SBill.Taylor@Sun.COM 		/*
1219517SBill.Taylor@Sun.COM 		 * Set status to "HERMON_CMD_INVALID_STATUS".  It is
1229517SBill.Taylor@Sun.COM 		 * appropriate to do this here without the "cmd_comp_lock"
1239517SBill.Taylor@Sun.COM 		 * because this register is overloaded.  Later it will be
1249517SBill.Taylor@Sun.COM 		 * used to indicate - through a change from this invalid
1259517SBill.Taylor@Sun.COM 		 * value to some other value - that the condition variable
1269517SBill.Taylor@Sun.COM 		 * has been signaled.  Once it has, status will then contain
1279517SBill.Taylor@Sun.COM 		 * the _real_ completion status
1289517SBill.Taylor@Sun.COM 		 */
1299517SBill.Taylor@Sun.COM 		cmdptr->cmd_status = HERMON_CMD_INVALID_STATUS;
1309517SBill.Taylor@Sun.COM 
1319517SBill.Taylor@Sun.COM 		/* Write the command to the HCR */
1329517SBill.Taylor@Sun.COM 		token = (uint16_t)cmdptr->cmd_indx;
1339517SBill.Taylor@Sun.COM 		retry_cnt2 = HCA_PIO_RETRY_CNT;
1349517SBill.Taylor@Sun.COM 		do {
1359517SBill.Taylor@Sun.COM 			status = hermon_write_hcr(state, cmdpost, token,
1369517SBill.Taylor@Sun.COM 			    &hw_err);
1379517SBill.Taylor@Sun.COM 		} while (status == HERMON_CMD_INTERNAL_ERR && retry_cnt2-- > 0);
1389517SBill.Taylor@Sun.COM 
1399517SBill.Taylor@Sun.COM 		/* Check if there is an error status in hermon_write_hcr() */
1409517SBill.Taylor@Sun.COM 		if (status != HERMON_CMD_SUCCESS) {
1419517SBill.Taylor@Sun.COM 			/*
1429517SBill.Taylor@Sun.COM 			 * If there is a HW error, call hermon_cmd_retry_ok()
1439517SBill.Taylor@Sun.COM 			 * to check the side-effect of the operation retry.
1449517SBill.Taylor@Sun.COM 			 */
1459517SBill.Taylor@Sun.COM 			if ((retry_cnt == HCA_PIO_RETRY_CNT &&
1469517SBill.Taylor@Sun.COM 			    hw_err == HCA_PIO_OK) ||
1479517SBill.Taylor@Sun.COM 			    !hermon_cmd_retry_ok(cmdpost, status)) {
1489517SBill.Taylor@Sun.COM 				hermon_cmd_check_status(state, status);
1499517SBill.Taylor@Sun.COM 				hermon_outstanding_cmd_free(state, &cmdptr);
1509517SBill.Taylor@Sun.COM 				return (status);
1519517SBill.Taylor@Sun.COM 			}
1529517SBill.Taylor@Sun.COM 		/* Check if there is a transient internal error */
1539517SBill.Taylor@Sun.COM 		} else if (retry_cnt2 != HCA_PIO_RETRY_CNT) {
1549517SBill.Taylor@Sun.COM 			hermon_fm_ereport(state, HCA_IBA_ERR,
1559517SBill.Taylor@Sun.COM 			    HCA_ERR_TRANSIENT);
1569517SBill.Taylor@Sun.COM 		}
1579517SBill.Taylor@Sun.COM 
1589517SBill.Taylor@Sun.COM 		/*
1599517SBill.Taylor@Sun.COM 		 * cv_wait() on the "command_complete" condition variable.
1609517SBill.Taylor@Sun.COM 		 * Note: We have the "__lock_lint" here to workaround warlock.
1619517SBill.Taylor@Sun.COM 		 * Since warlock doesn't know that other parts of the Hermon
1629517SBill.Taylor@Sun.COM 		 * may occasionally call this routine while holding their own
1639517SBill.Taylor@Sun.COM 		 * locks, it complains about this cv_wait.  In reality,
1649517SBill.Taylor@Sun.COM 		 * however, the rest of the driver never calls this routine
1659517SBill.Taylor@Sun.COM 		 * with a lock held unless they pass HERMON_CMD_NOSLEEP.
1669517SBill.Taylor@Sun.COM 		 */
1679517SBill.Taylor@Sun.COM 		_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*cmdptr))
1689517SBill.Taylor@Sun.COM 		mutex_enter(&cmdptr->cmd_comp_lock);
1699517SBill.Taylor@Sun.COM 		while (cmdptr->cmd_status == HERMON_CMD_INVALID_STATUS) {
1709517SBill.Taylor@Sun.COM #ifndef	__lock_lint
1719517SBill.Taylor@Sun.COM 			cv_wait(&cmdptr->cmd_comp_cv, &cmdptr->cmd_comp_lock);
1729517SBill.Taylor@Sun.COM 			/* NOTE: EXPECT SEVERAL THREADS TO BE WAITING HERE */
1739517SBill.Taylor@Sun.COM #endif
1749517SBill.Taylor@Sun.COM 		}
1759517SBill.Taylor@Sun.COM 		mutex_exit(&cmdptr->cmd_comp_lock);
1769517SBill.Taylor@Sun.COM 		_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cmdptr))
1779517SBill.Taylor@Sun.COM 
1789517SBill.Taylor@Sun.COM 		/*
1799517SBill.Taylor@Sun.COM 		 * Wake up after command completes (cv_signal).  Read status
1809517SBill.Taylor@Sun.COM 		 * from the command (success, fail, etc.).  It is appropriate
1819517SBill.Taylor@Sun.COM 		 * here (as above) to read the status field without the
1829517SBill.Taylor@Sun.COM 		 * "cmd_comp_lock" because it is no longer being used to
1839517SBill.Taylor@Sun.COM 		 * indicate whether the condition variable has been signaled
1849517SBill.Taylor@Sun.COM 		 * (i.e. at this point we are certain that it already has).
1859517SBill.Taylor@Sun.COM 		 */
1869517SBill.Taylor@Sun.COM 		status = cmdptr->cmd_status;
1879517SBill.Taylor@Sun.COM 
1889517SBill.Taylor@Sun.COM 		/* retry the operation if an internal error occurs */
1899517SBill.Taylor@Sun.COM 		if (status == HERMON_CMD_INTERNAL_ERR && retry_cnt-- > 0)
1909517SBill.Taylor@Sun.COM 			goto retry;
1919517SBill.Taylor@Sun.COM 
1929517SBill.Taylor@Sun.COM 		/* Save the "outparam" values into the cmdpost struct */
1939517SBill.Taylor@Sun.COM 		cmdpost->cp_outparm = cmdptr->cmd_outparm;
1949517SBill.Taylor@Sun.COM 
1959517SBill.Taylor@Sun.COM 		/*
1969517SBill.Taylor@Sun.COM 		 * Add the command back to the "outstanding commands list".
1979517SBill.Taylor@Sun.COM 		 * Signal the "cmd_list" condition variable, if necessary.
1989517SBill.Taylor@Sun.COM 		 */
1999517SBill.Taylor@Sun.COM 		hermon_outstanding_cmd_free(state, &cmdptr);
2009517SBill.Taylor@Sun.COM 
2019517SBill.Taylor@Sun.COM 		/* Check if there is an error status in hermon_write_hcr() */
2029517SBill.Taylor@Sun.COM 		if (status != HERMON_CMD_SUCCESS) {
2039517SBill.Taylor@Sun.COM 			/*
2049517SBill.Taylor@Sun.COM 			 * If there is a HW error, call hermon_cmd_retry_ok()
2059517SBill.Taylor@Sun.COM 			 * to check the side-effect of the operation retry.
2069517SBill.Taylor@Sun.COM 			 */
2079517SBill.Taylor@Sun.COM 			if ((retry_cnt == HCA_PIO_RETRY_CNT &&
2089517SBill.Taylor@Sun.COM 			    hw_err == HCA_PIO_OK) ||
2099517SBill.Taylor@Sun.COM 			    !hermon_cmd_retry_ok(cmdpost, status)) {
2109517SBill.Taylor@Sun.COM 				hermon_cmd_check_status(state, status);
2119517SBill.Taylor@Sun.COM 				cmn_err(CE_NOTE, "hermon%d: post cmd failed "
2129517SBill.Taylor@Sun.COM 				    "opcode (0x%x) status (0x%x)\n",
2139517SBill.Taylor@Sun.COM 				    state->hs_instance, cmdpost->cp_opcode,
2149517SBill.Taylor@Sun.COM 				    status);
2159517SBill.Taylor@Sun.COM 				return (status);
2169517SBill.Taylor@Sun.COM 			}
2179517SBill.Taylor@Sun.COM 		/* Check if there is a transient internal error */
2189517SBill.Taylor@Sun.COM 		} else if (retry_cnt != HCA_PIO_RETRY_CNT) {
2199517SBill.Taylor@Sun.COM 			hermon_fm_ereport(state, HCA_IBA_ERR,
2209517SBill.Taylor@Sun.COM 			    HCA_ERR_TRANSIENT);
2219517SBill.Taylor@Sun.COM 		}
2229517SBill.Taylor@Sun.COM 	}
2239517SBill.Taylor@Sun.COM 
2249517SBill.Taylor@Sun.COM 	return (HERMON_CMD_SUCCESS);
2259517SBill.Taylor@Sun.COM }
2269517SBill.Taylor@Sun.COM 
2279517SBill.Taylor@Sun.COM /*
2289517SBill.Taylor@Sun.COM  * hermon_cmd_check_status()
2299517SBill.Taylor@Sun.COM  *	Context:  Can be called from interrupt or base
2309517SBill.Taylor@Sun.COM  *
2319517SBill.Taylor@Sun.COM  * checks the status returned from write_hcr and does the right
2329517SBill.Taylor@Sun.COM  * notice to the console, if any
2339517SBill.Taylor@Sun.COM  */
2349517SBill.Taylor@Sun.COM static void
hermon_cmd_check_status(hermon_state_t * state,int status)2359517SBill.Taylor@Sun.COM hermon_cmd_check_status(hermon_state_t *state, int status)
2369517SBill.Taylor@Sun.COM {
2379517SBill.Taylor@Sun.COM 	switch (status) {
2389517SBill.Taylor@Sun.COM 		case HERMON_CMD_TIMEOUT_TOGGLE:
2399517SBill.Taylor@Sun.COM 			HERMON_FMANOTE(state, HERMON_FMA_TOTOG);
2409517SBill.Taylor@Sun.COM 			hermon_fm_ereport(state, HCA_IBA_ERR,
2419517SBill.Taylor@Sun.COM 			    HCA_ERR_NON_FATAL);
2429517SBill.Taylor@Sun.COM 			break;
2439517SBill.Taylor@Sun.COM 
2449517SBill.Taylor@Sun.COM 		case HERMON_CMD_TIMEOUT_GOBIT:
2459517SBill.Taylor@Sun.COM 			HERMON_FMANOTE(state, HERMON_FMA_GOBIT);
2469517SBill.Taylor@Sun.COM 			hermon_fm_ereport(state, HCA_IBA_ERR,
2479517SBill.Taylor@Sun.COM 			    HCA_ERR_NON_FATAL);
2489517SBill.Taylor@Sun.COM 			break;
2499517SBill.Taylor@Sun.COM 
2509517SBill.Taylor@Sun.COM 		case HERMON_CMD_INSUFF_RSRC:
2519517SBill.Taylor@Sun.COM 			HERMON_FMANOTE(state, HERMON_FMA_RSRC);
2529517SBill.Taylor@Sun.COM 			break;
2539517SBill.Taylor@Sun.COM 
2549517SBill.Taylor@Sun.COM 		case HERMON_CMD_INVALID_STATUS:
2559517SBill.Taylor@Sun.COM 			HERMON_FMANOTE(state, HERMON_FMA_CMDINV);
2569517SBill.Taylor@Sun.COM 			hermon_fm_ereport(state, HCA_IBA_ERR,
2579517SBill.Taylor@Sun.COM 			    HCA_ERR_NON_FATAL);
2589517SBill.Taylor@Sun.COM 			break;
2599517SBill.Taylor@Sun.COM 
2609517SBill.Taylor@Sun.COM 		case HERMON_CMD_INTERNAL_ERR:
2619517SBill.Taylor@Sun.COM 			HERMON_FMANOTE(state, HERMON_FMA_HCRINT);
2629517SBill.Taylor@Sun.COM 			hermon_fm_ereport(state, HCA_IBA_ERR,
2639517SBill.Taylor@Sun.COM 			    HCA_ERR_NON_FATAL);
2649517SBill.Taylor@Sun.COM 			break;
2659517SBill.Taylor@Sun.COM 
2669517SBill.Taylor@Sun.COM 		case HERMON_CMD_BAD_NVMEM:
26710125SEiji.Ota@Sun.COM 			/*
26810125SEiji.Ota@Sun.COM 			 * No need of an ereport here since this case
26910125SEiji.Ota@Sun.COM 			 * is treated as a degradation later.
27010125SEiji.Ota@Sun.COM 			 */
2719517SBill.Taylor@Sun.COM 			HERMON_FMANOTE(state, HERMON_FMA_NVMEM);
2729517SBill.Taylor@Sun.COM 			break;
2739517SBill.Taylor@Sun.COM 
2749517SBill.Taylor@Sun.COM 		default:
2759517SBill.Taylor@Sun.COM 			break;
2769517SBill.Taylor@Sun.COM 	}
2779517SBill.Taylor@Sun.COM }
2789517SBill.Taylor@Sun.COM 
2799517SBill.Taylor@Sun.COM /*
2809517SBill.Taylor@Sun.COM  * hermon_mbox_alloc()
2819517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
2829517SBill.Taylor@Sun.COM  *
2839517SBill.Taylor@Sun.COM  *    The "mbox_wait" parameter is used to determine whether to
2849517SBill.Taylor@Sun.COM  *    wait for a mailbox to become available or not.
2859517SBill.Taylor@Sun.COM  */
2869517SBill.Taylor@Sun.COM int
hermon_mbox_alloc(hermon_state_t * state,hermon_mbox_info_t * mbox_info,uint_t mbox_wait)2879517SBill.Taylor@Sun.COM hermon_mbox_alloc(hermon_state_t *state, hermon_mbox_info_t *mbox_info,
2889517SBill.Taylor@Sun.COM     uint_t mbox_wait)
2899517SBill.Taylor@Sun.COM {
2909517SBill.Taylor@Sun.COM 	int		status;
2919517SBill.Taylor@Sun.COM 	uint_t		sleep_context;
2929517SBill.Taylor@Sun.COM 
2939517SBill.Taylor@Sun.COM 	sleep_context = HERMON_SLEEPFLAG_FOR_CONTEXT();
2949517SBill.Taylor@Sun.COM 
2959517SBill.Taylor@Sun.COM 	/* Allocate an "In" mailbox */
2969517SBill.Taylor@Sun.COM 	if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_INMBOX) {
2979517SBill.Taylor@Sun.COM 		/* Determine correct mboxlist based on calling context */
2989517SBill.Taylor@Sun.COM 		if (sleep_context == HERMON_NOSLEEP) {
2999517SBill.Taylor@Sun.COM 			status = hermon_impl_mbox_alloc(state,
3009517SBill.Taylor@Sun.COM 			    &state->hs_in_intr_mblist,
3019517SBill.Taylor@Sun.COM 			    &mbox_info->mbi_in, mbox_wait);
3029517SBill.Taylor@Sun.COM 
3039517SBill.Taylor@Sun.COM 			ASSERT(status == HERMON_CMD_SUCCESS);
3049517SBill.Taylor@Sun.COM 		} else {
3059517SBill.Taylor@Sun.COM 			/* NOTE: Expect threads to be waiting in here */
3069517SBill.Taylor@Sun.COM 			status = hermon_impl_mbox_alloc(state,
3079517SBill.Taylor@Sun.COM 			    &state->hs_in_mblist, &mbox_info->mbi_in,
3089517SBill.Taylor@Sun.COM 			    mbox_wait);
3099517SBill.Taylor@Sun.COM 			if (status != HERMON_CMD_SUCCESS) {
3109517SBill.Taylor@Sun.COM 				return (status);
3119517SBill.Taylor@Sun.COM 			}
3129517SBill.Taylor@Sun.COM 		}
3139517SBill.Taylor@Sun.COM 
3149517SBill.Taylor@Sun.COM 	}
3159517SBill.Taylor@Sun.COM 
3169517SBill.Taylor@Sun.COM 	/* Allocate an "Out" mailbox */
3179517SBill.Taylor@Sun.COM 	if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_OUTMBOX) {
3189517SBill.Taylor@Sun.COM 		/* Determine correct mboxlist based on calling context */
3199517SBill.Taylor@Sun.COM 		if (sleep_context == HERMON_NOSLEEP) {
3209517SBill.Taylor@Sun.COM 			status = hermon_impl_mbox_alloc(state,
3219517SBill.Taylor@Sun.COM 			    &state->hs_out_intr_mblist,
3229517SBill.Taylor@Sun.COM 			    &mbox_info->mbi_out, mbox_wait);
3239517SBill.Taylor@Sun.COM 
3249517SBill.Taylor@Sun.COM 			ASSERT(status == HERMON_CMD_SUCCESS);
3259517SBill.Taylor@Sun.COM 		} else {
3269517SBill.Taylor@Sun.COM 			/* NOTE: Expect threads to be waiting in here */
3279517SBill.Taylor@Sun.COM 			status = hermon_impl_mbox_alloc(state,
3289517SBill.Taylor@Sun.COM 			    &state->hs_out_mblist, &mbox_info->mbi_out,
3299517SBill.Taylor@Sun.COM 			    mbox_wait);
3309517SBill.Taylor@Sun.COM 			if (status != HERMON_CMD_SUCCESS) {
3319517SBill.Taylor@Sun.COM 				/* If we allocated an "In" mailbox, free it */
3329517SBill.Taylor@Sun.COM 				if (mbox_info->mbi_alloc_flags &
3339517SBill.Taylor@Sun.COM 				    HERMON_ALLOC_INMBOX) {
3349517SBill.Taylor@Sun.COM 					hermon_impl_mbox_free(
3359517SBill.Taylor@Sun.COM 					    &state->hs_in_mblist,
3369517SBill.Taylor@Sun.COM 					    &mbox_info->mbi_in);
3379517SBill.Taylor@Sun.COM 				}
3389517SBill.Taylor@Sun.COM 				return (status);
3399517SBill.Taylor@Sun.COM 			}
3409517SBill.Taylor@Sun.COM 		}
3419517SBill.Taylor@Sun.COM 	}
3429517SBill.Taylor@Sun.COM 
3439517SBill.Taylor@Sun.COM 	/* Store appropriate context in mbox_info */
3449517SBill.Taylor@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(mbox_info->mbi_sleep_context))
3459517SBill.Taylor@Sun.COM 	mbox_info->mbi_sleep_context = sleep_context;
3469517SBill.Taylor@Sun.COM 
3479517SBill.Taylor@Sun.COM 	return (HERMON_CMD_SUCCESS);
3489517SBill.Taylor@Sun.COM }
3499517SBill.Taylor@Sun.COM 
3509517SBill.Taylor@Sun.COM 
3519517SBill.Taylor@Sun.COM /*
3529517SBill.Taylor@Sun.COM  * hermon_mbox_free()
3539517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
3549517SBill.Taylor@Sun.COM  */
3559517SBill.Taylor@Sun.COM void
hermon_mbox_free(hermon_state_t * state,hermon_mbox_info_t * mbox_info)3569517SBill.Taylor@Sun.COM hermon_mbox_free(hermon_state_t *state, hermon_mbox_info_t *mbox_info)
3579517SBill.Taylor@Sun.COM {
3589517SBill.Taylor@Sun.COM 	/*
3599517SBill.Taylor@Sun.COM 	 * The mailbox has to be freed in the same context from which it was
3609517SBill.Taylor@Sun.COM 	 * allocated.  The context is stored in the mbox_info at
3619517SBill.Taylor@Sun.COM 	 * hermon_mbox_alloc() time.  We check the stored context against the
3629517SBill.Taylor@Sun.COM 	 * current context here.
3639517SBill.Taylor@Sun.COM 	 */
3649517SBill.Taylor@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(mbox_info->mbi_sleep_context))
3659517SBill.Taylor@Sun.COM 	ASSERT(mbox_info->mbi_sleep_context == HERMON_SLEEPFLAG_FOR_CONTEXT());
3669517SBill.Taylor@Sun.COM 
3679517SBill.Taylor@Sun.COM 	/* Determine correct mboxlist based on calling context */
3689517SBill.Taylor@Sun.COM 	if (mbox_info->mbi_sleep_context == HERMON_NOSLEEP) {
3699517SBill.Taylor@Sun.COM 		/* Free the intr "In" mailbox */
3709517SBill.Taylor@Sun.COM 		if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_INMBOX) {
3719517SBill.Taylor@Sun.COM 			hermon_impl_mbox_free(&state->hs_in_intr_mblist,
3729517SBill.Taylor@Sun.COM 			    &mbox_info->mbi_in);
3739517SBill.Taylor@Sun.COM 		}
3749517SBill.Taylor@Sun.COM 
3759517SBill.Taylor@Sun.COM 		/* Free the intr "Out" mailbox */
3769517SBill.Taylor@Sun.COM 		if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_OUTMBOX) {
3779517SBill.Taylor@Sun.COM 			hermon_impl_mbox_free(&state->hs_out_intr_mblist,
3789517SBill.Taylor@Sun.COM 			    &mbox_info->mbi_out);
3799517SBill.Taylor@Sun.COM 		}
3809517SBill.Taylor@Sun.COM 	} else {
3819517SBill.Taylor@Sun.COM 		/* Free the "In" mailbox */
3829517SBill.Taylor@Sun.COM 		if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_INMBOX) {
3839517SBill.Taylor@Sun.COM 			hermon_impl_mbox_free(&state->hs_in_mblist,
3849517SBill.Taylor@Sun.COM 			    &mbox_info->mbi_in);
3859517SBill.Taylor@Sun.COM 		}
3869517SBill.Taylor@Sun.COM 
3879517SBill.Taylor@Sun.COM 		/* Free the "Out" mailbox */
3889517SBill.Taylor@Sun.COM 		if (mbox_info->mbi_alloc_flags & HERMON_ALLOC_OUTMBOX) {
3899517SBill.Taylor@Sun.COM 			hermon_impl_mbox_free(&state->hs_out_mblist,
3909517SBill.Taylor@Sun.COM 			    &mbox_info->mbi_out);
3919517SBill.Taylor@Sun.COM 		}
3929517SBill.Taylor@Sun.COM 	}
3939517SBill.Taylor@Sun.COM }
3949517SBill.Taylor@Sun.COM 
3959517SBill.Taylor@Sun.COM 
3969517SBill.Taylor@Sun.COM 
3979517SBill.Taylor@Sun.COM /*
3989517SBill.Taylor@Sun.COM  * hermon_cmd_complete_handler()
3999517SBill.Taylor@Sun.COM  *    Context: Called only from interrupt context.
4009517SBill.Taylor@Sun.COM  */
401*12965SWilliam.Taylor@Oracle.COM /* ARGSUSED */
4029517SBill.Taylor@Sun.COM int
hermon_cmd_complete_handler(hermon_state_t * state,hermon_eqhdl_t eq,hermon_hw_eqe_t * eqe)4039517SBill.Taylor@Sun.COM hermon_cmd_complete_handler(hermon_state_t *state, hermon_eqhdl_t eq,
4049517SBill.Taylor@Sun.COM     hermon_hw_eqe_t *eqe)
4059517SBill.Taylor@Sun.COM {
4069517SBill.Taylor@Sun.COM 	hermon_cmd_t		*cmdp;
4079517SBill.Taylor@Sun.COM 
4089517SBill.Taylor@Sun.COM 	/*
4099517SBill.Taylor@Sun.COM 	 * Find the outstanding command pointer based on value returned
4109517SBill.Taylor@Sun.COM 	 * in "token"
4119517SBill.Taylor@Sun.COM 	 */
4129517SBill.Taylor@Sun.COM 	cmdp = &state->hs_cmd_list.cml_cmd[HERMON_EQE_CMDTOKEN_GET(eq, eqe)];
4139517SBill.Taylor@Sun.COM 
4149517SBill.Taylor@Sun.COM 	/* Signal the waiting thread */
4159517SBill.Taylor@Sun.COM 	mutex_enter(&cmdp->cmd_comp_lock);
4169517SBill.Taylor@Sun.COM 	cmdp->cmd_outparm = ((uint64_t)HERMON_EQE_CMDOUTP0_GET(eq, eqe) << 32) |
4179517SBill.Taylor@Sun.COM 	    HERMON_EQE_CMDOUTP1_GET(eq, eqe);
4189517SBill.Taylor@Sun.COM 	cmdp->cmd_status = HERMON_EQE_CMDSTATUS_GET(eq, eqe);
4199517SBill.Taylor@Sun.COM 
4209517SBill.Taylor@Sun.COM 	cv_signal(&cmdp->cmd_comp_cv);
4219517SBill.Taylor@Sun.COM 	mutex_exit(&cmdp->cmd_comp_lock);
4229517SBill.Taylor@Sun.COM 
4239517SBill.Taylor@Sun.COM 	return (DDI_SUCCESS);
4249517SBill.Taylor@Sun.COM }
4259517SBill.Taylor@Sun.COM 
4269517SBill.Taylor@Sun.COM 
4279517SBill.Taylor@Sun.COM /*
4289517SBill.Taylor@Sun.COM  * hermon_inmbox_list_init()
4299517SBill.Taylor@Sun.COM  *    Context: Only called from attach() path context
4309517SBill.Taylor@Sun.COM  */
4319517SBill.Taylor@Sun.COM int
hermon_inmbox_list_init(hermon_state_t * state)4329517SBill.Taylor@Sun.COM hermon_inmbox_list_init(hermon_state_t *state)
4339517SBill.Taylor@Sun.COM {
4349517SBill.Taylor@Sun.COM 	int		status;
4359517SBill.Taylor@Sun.COM 	uint_t		num_inmbox;
4369517SBill.Taylor@Sun.COM 
4379517SBill.Taylor@Sun.COM 	/* Initialize the "In" mailbox list */
4389517SBill.Taylor@Sun.COM 	num_inmbox  =  (1 << state->hs_cfg_profile->cp_log_num_inmbox);
4399517SBill.Taylor@Sun.COM 	status = hermon_impl_mboxlist_init(state, &state->hs_in_mblist,
4409517SBill.Taylor@Sun.COM 	    num_inmbox, HERMON_IN_MBOX);
4419517SBill.Taylor@Sun.COM 	if (status != DDI_SUCCESS) {
4429517SBill.Taylor@Sun.COM 		return (DDI_FAILURE);
4439517SBill.Taylor@Sun.COM 	}
4449517SBill.Taylor@Sun.COM 
4459517SBill.Taylor@Sun.COM 	return (DDI_SUCCESS);
4469517SBill.Taylor@Sun.COM }
4479517SBill.Taylor@Sun.COM 
4489517SBill.Taylor@Sun.COM 
4499517SBill.Taylor@Sun.COM /*
4509517SBill.Taylor@Sun.COM  * hermon_intr_inmbox_list_init()
4519517SBill.Taylor@Sun.COM  *    Context: Only called from attach() path context
4529517SBill.Taylor@Sun.COM  */
4539517SBill.Taylor@Sun.COM int
hermon_intr_inmbox_list_init(hermon_state_t * state)4549517SBill.Taylor@Sun.COM hermon_intr_inmbox_list_init(hermon_state_t *state)
4559517SBill.Taylor@Sun.COM {
4569517SBill.Taylor@Sun.COM 	int		status;
4579517SBill.Taylor@Sun.COM 	uint_t		num_inmbox;
4589517SBill.Taylor@Sun.COM 
4599517SBill.Taylor@Sun.COM 	/* Initialize the interrupt "In" mailbox list */
4609517SBill.Taylor@Sun.COM 	num_inmbox  =  (1 << state->hs_cfg_profile->cp_log_num_intr_inmbox);
4619517SBill.Taylor@Sun.COM 	status = hermon_impl_mboxlist_init(state, &state->hs_in_intr_mblist,
4629517SBill.Taylor@Sun.COM 	    num_inmbox, HERMON_INTR_IN_MBOX);
4639517SBill.Taylor@Sun.COM 	if (status != DDI_SUCCESS) {
4649517SBill.Taylor@Sun.COM 		return (DDI_FAILURE);
4659517SBill.Taylor@Sun.COM 	}
4669517SBill.Taylor@Sun.COM 
4679517SBill.Taylor@Sun.COM 	return (DDI_SUCCESS);
4689517SBill.Taylor@Sun.COM }
4699517SBill.Taylor@Sun.COM 
4709517SBill.Taylor@Sun.COM 
4719517SBill.Taylor@Sun.COM /*
4729517SBill.Taylor@Sun.COM  * hermon_outmbox_list_init()
4739517SBill.Taylor@Sun.COM  *    Context: Only called from attach() path context
4749517SBill.Taylor@Sun.COM  */
4759517SBill.Taylor@Sun.COM int
hermon_outmbox_list_init(hermon_state_t * state)4769517SBill.Taylor@Sun.COM hermon_outmbox_list_init(hermon_state_t *state)
4779517SBill.Taylor@Sun.COM {
4789517SBill.Taylor@Sun.COM 	int		status;
4799517SBill.Taylor@Sun.COM 	uint_t		num_outmbox;
4809517SBill.Taylor@Sun.COM 
4819517SBill.Taylor@Sun.COM 	/* Initialize the "Out" mailbox list */
4829517SBill.Taylor@Sun.COM 	num_outmbox  =  (1 << state->hs_cfg_profile->cp_log_num_outmbox);
4839517SBill.Taylor@Sun.COM 	status = hermon_impl_mboxlist_init(state, &state->hs_out_mblist,
4849517SBill.Taylor@Sun.COM 	    num_outmbox, HERMON_OUT_MBOX);
4859517SBill.Taylor@Sun.COM 	if (status != DDI_SUCCESS) {
4869517SBill.Taylor@Sun.COM 		return (DDI_FAILURE);
4879517SBill.Taylor@Sun.COM 	}
4889517SBill.Taylor@Sun.COM 
4899517SBill.Taylor@Sun.COM 	return (DDI_SUCCESS);
4909517SBill.Taylor@Sun.COM }
4919517SBill.Taylor@Sun.COM 
4929517SBill.Taylor@Sun.COM 
4939517SBill.Taylor@Sun.COM /*
4949517SBill.Taylor@Sun.COM  * hermon_intr_outmbox_list_init()
4959517SBill.Taylor@Sun.COM  *    Context: Only called from attach() path context
4969517SBill.Taylor@Sun.COM  */
4979517SBill.Taylor@Sun.COM int
hermon_intr_outmbox_list_init(hermon_state_t * state)4989517SBill.Taylor@Sun.COM hermon_intr_outmbox_list_init(hermon_state_t *state)
4999517SBill.Taylor@Sun.COM {
5009517SBill.Taylor@Sun.COM 	int		status;
5019517SBill.Taylor@Sun.COM 	uint_t		num_outmbox;
5029517SBill.Taylor@Sun.COM 
5039517SBill.Taylor@Sun.COM 	/* Initialize the interrupts "Out" mailbox list */
5049517SBill.Taylor@Sun.COM 	num_outmbox  =  (1 << state->hs_cfg_profile->cp_log_num_intr_outmbox);
5059517SBill.Taylor@Sun.COM 	status = hermon_impl_mboxlist_init(state, &state->hs_out_intr_mblist,
5069517SBill.Taylor@Sun.COM 	    num_outmbox, HERMON_INTR_OUT_MBOX);
5079517SBill.Taylor@Sun.COM 	if (status != DDI_SUCCESS) {
5089517SBill.Taylor@Sun.COM 		return (DDI_FAILURE);
5099517SBill.Taylor@Sun.COM 	}
5109517SBill.Taylor@Sun.COM 
5119517SBill.Taylor@Sun.COM 	return (DDI_SUCCESS);
5129517SBill.Taylor@Sun.COM }
5139517SBill.Taylor@Sun.COM 
5149517SBill.Taylor@Sun.COM 
5159517SBill.Taylor@Sun.COM /*
5169517SBill.Taylor@Sun.COM  * hermon_inmbox_list_fini()
5179517SBill.Taylor@Sun.COM  *    Context: Only called from attach() and/or detach() path contexts
5189517SBill.Taylor@Sun.COM  */
5199517SBill.Taylor@Sun.COM void
hermon_inmbox_list_fini(hermon_state_t * state)5209517SBill.Taylor@Sun.COM hermon_inmbox_list_fini(hermon_state_t *state)
5219517SBill.Taylor@Sun.COM {
5229517SBill.Taylor@Sun.COM 	/* Free up the "In" mailbox list */
5239517SBill.Taylor@Sun.COM 	hermon_impl_mboxlist_fini(state, &state->hs_in_mblist);
5249517SBill.Taylor@Sun.COM }
5259517SBill.Taylor@Sun.COM 
5269517SBill.Taylor@Sun.COM 
5279517SBill.Taylor@Sun.COM /*
5289517SBill.Taylor@Sun.COM  * hermon_intr_inmbox_list_fini()
5299517SBill.Taylor@Sun.COM  *    Context: Only called from attach() and/or detach() path contexts
5309517SBill.Taylor@Sun.COM  */
5319517SBill.Taylor@Sun.COM void
hermon_intr_inmbox_list_fini(hermon_state_t * state)5329517SBill.Taylor@Sun.COM hermon_intr_inmbox_list_fini(hermon_state_t *state)
5339517SBill.Taylor@Sun.COM {
5349517SBill.Taylor@Sun.COM 	/* Free up the interupts "In" mailbox list */
5359517SBill.Taylor@Sun.COM 	hermon_impl_mboxlist_fini(state, &state->hs_in_intr_mblist);
5369517SBill.Taylor@Sun.COM }
5379517SBill.Taylor@Sun.COM 
5389517SBill.Taylor@Sun.COM 
5399517SBill.Taylor@Sun.COM /*
5409517SBill.Taylor@Sun.COM  * hermon_outmbox_list_fini()
5419517SBill.Taylor@Sun.COM  *    Context: Only called from attach() and/or detach() path contexts
5429517SBill.Taylor@Sun.COM  */
5439517SBill.Taylor@Sun.COM void
hermon_outmbox_list_fini(hermon_state_t * state)5449517SBill.Taylor@Sun.COM hermon_outmbox_list_fini(hermon_state_t *state)
5459517SBill.Taylor@Sun.COM {
5469517SBill.Taylor@Sun.COM 	/* Free up the "Out" mailbox list */
5479517SBill.Taylor@Sun.COM 	hermon_impl_mboxlist_fini(state, &state->hs_out_mblist);
5489517SBill.Taylor@Sun.COM }
5499517SBill.Taylor@Sun.COM 
5509517SBill.Taylor@Sun.COM 
5519517SBill.Taylor@Sun.COM /*
5529517SBill.Taylor@Sun.COM  * hermon_intr_outmbox_list_fini()
5539517SBill.Taylor@Sun.COM  *    Context: Only called from attach() and/or detach() path contexts
5549517SBill.Taylor@Sun.COM  */
5559517SBill.Taylor@Sun.COM void
hermon_intr_outmbox_list_fini(hermon_state_t * state)5569517SBill.Taylor@Sun.COM hermon_intr_outmbox_list_fini(hermon_state_t *state)
5579517SBill.Taylor@Sun.COM {
5589517SBill.Taylor@Sun.COM 	/* Free up the interrupt "Out" mailbox list */
5599517SBill.Taylor@Sun.COM 	hermon_impl_mboxlist_fini(state, &state->hs_out_intr_mblist);
5609517SBill.Taylor@Sun.COM }
5619517SBill.Taylor@Sun.COM 
5629517SBill.Taylor@Sun.COM 
5639517SBill.Taylor@Sun.COM /*
5649517SBill.Taylor@Sun.COM  * hermon_impl_mbox_alloc()
5659517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
5669517SBill.Taylor@Sun.COM  */
5679517SBill.Taylor@Sun.COM static int
hermon_impl_mbox_alloc(hermon_state_t * state,hermon_mboxlist_t * mblist,hermon_mbox_t ** mb,uint_t mbox_wait)5689517SBill.Taylor@Sun.COM hermon_impl_mbox_alloc(hermon_state_t *state, hermon_mboxlist_t *mblist,
5699517SBill.Taylor@Sun.COM     hermon_mbox_t **mb, uint_t mbox_wait)
5709517SBill.Taylor@Sun.COM {
5719517SBill.Taylor@Sun.COM 	hermon_mbox_t	*mbox_ptr;
5729517SBill.Taylor@Sun.COM 	uint_t		index, next, prev;
5739517SBill.Taylor@Sun.COM 	uint_t		count, countmax;
5749517SBill.Taylor@Sun.COM 
5759517SBill.Taylor@Sun.COM 	/*
5769517SBill.Taylor@Sun.COM 	 * If the mailbox list is empty, then wait (if appropriate in the
5779517SBill.Taylor@Sun.COM 	 * current context).  Otherwise, grab the next available mailbox.
5789517SBill.Taylor@Sun.COM 	 */
5799517SBill.Taylor@Sun.COM 	if (mbox_wait == HERMON_NOSLEEP) {
5809517SBill.Taylor@Sun.COM 		count	 = 0;
5819517SBill.Taylor@Sun.COM 		countmax = state->hs_cfg_profile->cp_cmd_poll_max;
5829517SBill.Taylor@Sun.COM 
5839517SBill.Taylor@Sun.COM 		mutex_enter(&mblist->mbl_lock);
5849517SBill.Taylor@Sun.COM 		mblist->mbl_pollers++;
5859517SBill.Taylor@Sun.COM 		while (mblist->mbl_entries_free == 0) {
5869517SBill.Taylor@Sun.COM 			mutex_exit(&mblist->mbl_lock);
5879517SBill.Taylor@Sun.COM 			/* Delay loop polling for an available mbox */
5889517SBill.Taylor@Sun.COM 			if (++count > countmax) {
5899517SBill.Taylor@Sun.COM 				return (HERMON_CMD_INSUFF_RSRC);
5909517SBill.Taylor@Sun.COM 			}
5919517SBill.Taylor@Sun.COM 
5929517SBill.Taylor@Sun.COM 			/* Delay before polling for mailbox again */
5939517SBill.Taylor@Sun.COM 			drv_usecwait(state->hs_cfg_profile->cp_cmd_poll_delay);
5949517SBill.Taylor@Sun.COM 			mutex_enter(&mblist->mbl_lock);
5959517SBill.Taylor@Sun.COM 		}
5969517SBill.Taylor@Sun.COM 		mblist->mbl_pollers--;
5979517SBill.Taylor@Sun.COM 
5989517SBill.Taylor@Sun.COM 	/* HERMON_SLEEP */
5999517SBill.Taylor@Sun.COM 	} else {
6009517SBill.Taylor@Sun.COM 		/*
6019517SBill.Taylor@Sun.COM 		 * Grab lock here as we prepare to cv_wait if needed.
6029517SBill.Taylor@Sun.COM 		 */
6039517SBill.Taylor@Sun.COM 		mutex_enter(&mblist->mbl_lock);
6049517SBill.Taylor@Sun.COM 		while (mblist->mbl_entries_free == 0) {
6059517SBill.Taylor@Sun.COM 			/*
6069517SBill.Taylor@Sun.COM 			 * Wait (on cv) for a mailbox to become free.  Note:
6079517SBill.Taylor@Sun.COM 			 * Just as we do above in hermon_cmd_post(), we also
6089517SBill.Taylor@Sun.COM 			 * have the "__lock_lint" here to workaround warlock.
6099517SBill.Taylor@Sun.COM 			 * Warlock doesn't know that other parts of the Hermon
6109517SBill.Taylor@Sun.COM 			 * may occasionally call this routine while holding
6119517SBill.Taylor@Sun.COM 			 * their own locks, so it complains about this cv_wait.
6129517SBill.Taylor@Sun.COM 			 * In reality, however, the rest of the driver never
6139517SBill.Taylor@Sun.COM 			 * calls this routine with a lock held unless they pass
6149517SBill.Taylor@Sun.COM 			 * HERMON_CMD_NOSLEEP.
6159517SBill.Taylor@Sun.COM 			 */
6169517SBill.Taylor@Sun.COM 			mblist->mbl_waiters++;
6179517SBill.Taylor@Sun.COM #ifndef	__lock_lint
6189517SBill.Taylor@Sun.COM 			cv_wait(&mblist->mbl_cv, &mblist->mbl_lock);
6199517SBill.Taylor@Sun.COM #endif
6209517SBill.Taylor@Sun.COM 		}
6219517SBill.Taylor@Sun.COM 	}
6229517SBill.Taylor@Sun.COM 
6239517SBill.Taylor@Sun.COM 	/* Grab the next available mailbox from list */
6249517SBill.Taylor@Sun.COM 	mbox_ptr = mblist->mbl_mbox;
6259517SBill.Taylor@Sun.COM 	index	 = mblist->mbl_head_indx;
6269517SBill.Taylor@Sun.COM 	next	 = mbox_ptr[index].mb_next;
6279517SBill.Taylor@Sun.COM 	prev	 = mbox_ptr[index].mb_prev;
6289517SBill.Taylor@Sun.COM 
6299517SBill.Taylor@Sun.COM 	/* Remove it from the mailbox list */
6309517SBill.Taylor@Sun.COM 	mblist->mbl_mbox[next].mb_prev	= prev;
6319517SBill.Taylor@Sun.COM 	mblist->mbl_mbox[prev].mb_next	= next;
6329517SBill.Taylor@Sun.COM 	mblist->mbl_head_indx		= next;
6339517SBill.Taylor@Sun.COM 
6349517SBill.Taylor@Sun.COM 	/* Update the "free" count and return the mailbox pointer */
6359517SBill.Taylor@Sun.COM 	mblist->mbl_entries_free--;
6369517SBill.Taylor@Sun.COM 	*mb = &mbox_ptr[index];
6379517SBill.Taylor@Sun.COM 
6389517SBill.Taylor@Sun.COM 	mutex_exit(&mblist->mbl_lock);
6399517SBill.Taylor@Sun.COM 
6409517SBill.Taylor@Sun.COM 	return (HERMON_CMD_SUCCESS);
6419517SBill.Taylor@Sun.COM }
6429517SBill.Taylor@Sun.COM 
6439517SBill.Taylor@Sun.COM 
6449517SBill.Taylor@Sun.COM /*
6459517SBill.Taylor@Sun.COM  * hermon_impl_mbox_free()
6469517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
6479517SBill.Taylor@Sun.COM  */
6489517SBill.Taylor@Sun.COM static void
hermon_impl_mbox_free(hermon_mboxlist_t * mblist,hermon_mbox_t ** mb)6499517SBill.Taylor@Sun.COM hermon_impl_mbox_free(hermon_mboxlist_t *mblist, hermon_mbox_t **mb)
6509517SBill.Taylor@Sun.COM {
6519517SBill.Taylor@Sun.COM 	uint_t		mbox_indx;
6529517SBill.Taylor@Sun.COM 
6539517SBill.Taylor@Sun.COM 	mutex_enter(&mblist->mbl_lock);
6549517SBill.Taylor@Sun.COM 
6559517SBill.Taylor@Sun.COM 	/* Pull the "index" from mailbox entry */
6569517SBill.Taylor@Sun.COM 	mbox_indx = (*mb)->mb_indx;
6579517SBill.Taylor@Sun.COM 
6589517SBill.Taylor@Sun.COM 	/*
6599517SBill.Taylor@Sun.COM 	 * If mailbox list is not empty, then insert the entry.  Otherwise,
6609517SBill.Taylor@Sun.COM 	 * this is the only entry.  So update the pointers appropriately.
6619517SBill.Taylor@Sun.COM 	 */
6629517SBill.Taylor@Sun.COM 	if (mblist->mbl_entries_free++ != 0) {
6639517SBill.Taylor@Sun.COM 		/* Update the current mailbox */
6649517SBill.Taylor@Sun.COM 		(*mb)->mb_next = mblist->mbl_head_indx;
6659517SBill.Taylor@Sun.COM 		(*mb)->mb_prev = mblist->mbl_tail_indx;
6669517SBill.Taylor@Sun.COM 
6679517SBill.Taylor@Sun.COM 		/* Update head and tail mailboxes */
6689517SBill.Taylor@Sun.COM 		mblist->mbl_mbox[mblist->mbl_head_indx].mb_prev = mbox_indx;
6699517SBill.Taylor@Sun.COM 		mblist->mbl_mbox[mblist->mbl_tail_indx].mb_next = mbox_indx;
6709517SBill.Taylor@Sun.COM 
6719517SBill.Taylor@Sun.COM 		/* Update tail index */
6729517SBill.Taylor@Sun.COM 		mblist->mbl_tail_indx = mbox_indx;
6739517SBill.Taylor@Sun.COM 
6749517SBill.Taylor@Sun.COM 	} else {
6759517SBill.Taylor@Sun.COM 		/* Update the current mailbox */
6769517SBill.Taylor@Sun.COM 		(*mb)->mb_next = mbox_indx;
6779517SBill.Taylor@Sun.COM 		(*mb)->mb_prev = mbox_indx;
6789517SBill.Taylor@Sun.COM 
6799517SBill.Taylor@Sun.COM 		/* Update head and tail indexes */
6809517SBill.Taylor@Sun.COM 		mblist->mbl_tail_indx = mbox_indx;
6819517SBill.Taylor@Sun.COM 		mblist->mbl_head_indx = mbox_indx;
6829517SBill.Taylor@Sun.COM 	}
6839517SBill.Taylor@Sun.COM 
6849517SBill.Taylor@Sun.COM 	/*
6859517SBill.Taylor@Sun.COM 	 * Because we can have both waiters (SLEEP treads waiting for a
6869517SBill.Taylor@Sun.COM 	 * cv_signal to continue processing) and pollers (NOSLEEP treads
6879517SBill.Taylor@Sun.COM 	 * polling for a mailbox to become available), we try to share CPU time
6889517SBill.Taylor@Sun.COM 	 * between them.  We do this by signalling the waiters only every other
6899517SBill.Taylor@Sun.COM 	 * call to mbox_free.  This gives the pollers a chance to get some CPU
6909517SBill.Taylor@Sun.COM 	 * time to do their command.  If we signalled every time, the pollers
6919517SBill.Taylor@Sun.COM 	 * would have a much harder time getting CPU time.
6929517SBill.Taylor@Sun.COM 	 *
6939517SBill.Taylor@Sun.COM 	 * If there are waiters and no pollers, then we signal always.
6949517SBill.Taylor@Sun.COM 	 *
6959517SBill.Taylor@Sun.COM 	 * Otherwise, if there are either no waiters, there may in fact be
6969517SBill.Taylor@Sun.COM 	 * pollers, so we do not signal in that case.
6979517SBill.Taylor@Sun.COM 	 */
6989517SBill.Taylor@Sun.COM 	if (mblist->mbl_pollers > 0 && mblist->mbl_waiters > 0) {
6999517SBill.Taylor@Sun.COM 		/* flip the signal value */
7009517SBill.Taylor@Sun.COM 		mblist->mbl_signal = (++mblist->mbl_signal) % 2;
7019517SBill.Taylor@Sun.COM 	} else if (mblist->mbl_waiters > 0) {
7029517SBill.Taylor@Sun.COM 		mblist->mbl_signal = 1;
7039517SBill.Taylor@Sun.COM 	} else {
7049517SBill.Taylor@Sun.COM 		mblist->mbl_signal = 0;
7059517SBill.Taylor@Sun.COM 	}
7069517SBill.Taylor@Sun.COM 
7079517SBill.Taylor@Sun.COM 	/*
7089517SBill.Taylor@Sun.COM 	 * Depending on the conditions in the previous check, we signal only if
7099517SBill.Taylor@Sun.COM 	 * we are supposed to.
7109517SBill.Taylor@Sun.COM 	 */
7119517SBill.Taylor@Sun.COM 	if (mblist->mbl_signal) {
7129517SBill.Taylor@Sun.COM 		mblist->mbl_waiters--;
7139517SBill.Taylor@Sun.COM 		cv_signal(&mblist->mbl_cv);
7149517SBill.Taylor@Sun.COM 	}
7159517SBill.Taylor@Sun.COM 
7169517SBill.Taylor@Sun.COM 	/* Clear out the mailbox entry pointer */
7179517SBill.Taylor@Sun.COM 	*mb = NULL;
7189517SBill.Taylor@Sun.COM 
7199517SBill.Taylor@Sun.COM 	mutex_exit(&mblist->mbl_lock);
7209517SBill.Taylor@Sun.COM }
7219517SBill.Taylor@Sun.COM 
7229517SBill.Taylor@Sun.COM 
7239517SBill.Taylor@Sun.COM /*
7249517SBill.Taylor@Sun.COM  * hermon_impl_mboxlist_init()
7259517SBill.Taylor@Sun.COM  *    Context: Only called from attach() path context
7269517SBill.Taylor@Sun.COM  */
7279517SBill.Taylor@Sun.COM static int
hermon_impl_mboxlist_init(hermon_state_t * state,hermon_mboxlist_t * mblist,uint_t num_mbox,hermon_rsrc_type_t type)7289517SBill.Taylor@Sun.COM hermon_impl_mboxlist_init(hermon_state_t *state, hermon_mboxlist_t *mblist,
7299517SBill.Taylor@Sun.COM     uint_t num_mbox, hermon_rsrc_type_t type)
7309517SBill.Taylor@Sun.COM {
7319517SBill.Taylor@Sun.COM 	hermon_rsrc_t		*rsrc;
7329517SBill.Taylor@Sun.COM 	ddi_dma_cookie_t	dma_cookie;
7339517SBill.Taylor@Sun.COM 	uint_t			dma_cookiecnt;
7349517SBill.Taylor@Sun.COM 	int			status, i;
7359517SBill.Taylor@Sun.COM 
7369517SBill.Taylor@Sun.COM 	/* Allocate the memory for the mailbox entries list */
7379517SBill.Taylor@Sun.COM 	mblist->mbl_list_sz = num_mbox;
7389517SBill.Taylor@Sun.COM 	mblist->mbl_mbox = kmem_zalloc(mblist->mbl_list_sz *
7399517SBill.Taylor@Sun.COM 	    sizeof (hermon_mbox_t), KM_SLEEP);
7409517SBill.Taylor@Sun.COM 
7419517SBill.Taylor@Sun.COM 	/* Initialize the mailbox entries list */
7429517SBill.Taylor@Sun.COM 	mblist->mbl_head_indx	 = 0;
7439517SBill.Taylor@Sun.COM 	mblist->mbl_tail_indx	 = mblist->mbl_list_sz - 1;
7449517SBill.Taylor@Sun.COM 	mblist->mbl_entries_free = mblist->mbl_list_sz;
7459517SBill.Taylor@Sun.COM 	mblist->mbl_waiters	 = 0;
7469517SBill.Taylor@Sun.COM 	mblist->mbl_num_alloc	 = 0;
7479517SBill.Taylor@Sun.COM 
7489517SBill.Taylor@Sun.COM 	/* Set up the mailbox list's cv and mutex */
7499517SBill.Taylor@Sun.COM 	mutex_init(&mblist->mbl_lock, NULL, MUTEX_DRIVER,
7509517SBill.Taylor@Sun.COM 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
7519517SBill.Taylor@Sun.COM 	cv_init(&mblist->mbl_cv, NULL, CV_DRIVER, NULL);
7529517SBill.Taylor@Sun.COM 
7539517SBill.Taylor@Sun.COM 	/* Initialize the mailbox list entries */
7549517SBill.Taylor@Sun.COM 	for (i = 0; i < mblist->mbl_list_sz; i++) {
7559517SBill.Taylor@Sun.COM 		/* Allocate resources for the mailbox */
7569517SBill.Taylor@Sun.COM 		status = hermon_rsrc_alloc(state, type, 1, HERMON_SLEEP,
7579517SBill.Taylor@Sun.COM 		    &rsrc);
7589517SBill.Taylor@Sun.COM 		if (status != DDI_SUCCESS) {
7599517SBill.Taylor@Sun.COM 			/* Jump to cleanup and return error */
7609517SBill.Taylor@Sun.COM 			goto mboxlist_init_fail;
7619517SBill.Taylor@Sun.COM 		}
7629517SBill.Taylor@Sun.COM 
7639517SBill.Taylor@Sun.COM 		/* Save away the mailbox resource info */
7649517SBill.Taylor@Sun.COM 		mblist->mbl_mbox[i].mb_rsrcptr	= rsrc;
7659517SBill.Taylor@Sun.COM 		mblist->mbl_mbox[i].mb_addr	= rsrc->hr_addr;
7669517SBill.Taylor@Sun.COM 		mblist->mbl_mbox[i].mb_acchdl	= rsrc->hr_acchdl;
7679517SBill.Taylor@Sun.COM 
7689517SBill.Taylor@Sun.COM 		/*
7699517SBill.Taylor@Sun.COM 		 * Get a PCI mapped address for each mailbox.  Note: this
7709517SBill.Taylor@Sun.COM 		 * uses the ddi_dma_handle return from the resource
7719517SBill.Taylor@Sun.COM 		 * allocation routine
7729517SBill.Taylor@Sun.COM 		 */
7739517SBill.Taylor@Sun.COM 		status = ddi_dma_addr_bind_handle(rsrc->hr_dmahdl, NULL,
7749517SBill.Taylor@Sun.COM 		    rsrc->hr_addr, rsrc->hr_len,
7759517SBill.Taylor@Sun.COM 		    (DDI_DMA_RDWR | DDI_DMA_CONSISTENT),
7769517SBill.Taylor@Sun.COM 		    DDI_DMA_SLEEP, NULL, &dma_cookie, &dma_cookiecnt);
7779517SBill.Taylor@Sun.COM 		if (status != DDI_SUCCESS) {
7789517SBill.Taylor@Sun.COM 			/* Jump to cleanup and return error */
7799517SBill.Taylor@Sun.COM 			hermon_rsrc_free(state, &rsrc);
7809517SBill.Taylor@Sun.COM 			goto mboxlist_init_fail;
7819517SBill.Taylor@Sun.COM 		}
7829517SBill.Taylor@Sun.COM 
7839517SBill.Taylor@Sun.COM 		/* Save away the mapped address for the mailbox */
7849517SBill.Taylor@Sun.COM 		mblist->mbl_mbox[i].mb_mapaddr	= dma_cookie.dmac_laddress;
7859517SBill.Taylor@Sun.COM 
7869517SBill.Taylor@Sun.COM 		/* Make each entry point to the "next" and "prev" entries */
7879517SBill.Taylor@Sun.COM 		mblist->mbl_mbox[i].mb_next	= i+1;
7889517SBill.Taylor@Sun.COM 		mblist->mbl_mbox[i].mb_prev	= i-1;
7899517SBill.Taylor@Sun.COM 		mblist->mbl_mbox[i].mb_indx	= i;
7909517SBill.Taylor@Sun.COM 		mblist->mbl_num_alloc		= i + 1;
7919517SBill.Taylor@Sun.COM 	}
7929517SBill.Taylor@Sun.COM 
7939517SBill.Taylor@Sun.COM 	/* Make the "head" and "tail" entries point to each other */
7949517SBill.Taylor@Sun.COM 	mblist->mbl_mbox[mblist->mbl_head_indx].mb_prev =
7959517SBill.Taylor@Sun.COM 	    mblist->mbl_tail_indx;
7969517SBill.Taylor@Sun.COM 	mblist->mbl_mbox[mblist->mbl_tail_indx].mb_next =
7979517SBill.Taylor@Sun.COM 	    mblist->mbl_head_indx;
7989517SBill.Taylor@Sun.COM 
7999517SBill.Taylor@Sun.COM 	return (DDI_SUCCESS);
8009517SBill.Taylor@Sun.COM 
8019517SBill.Taylor@Sun.COM mboxlist_init_fail:
8029517SBill.Taylor@Sun.COM 	hermon_impl_mboxlist_fini(state, mblist);
8039517SBill.Taylor@Sun.COM 
8049517SBill.Taylor@Sun.COM 	return (DDI_FAILURE);
8059517SBill.Taylor@Sun.COM }
8069517SBill.Taylor@Sun.COM 
8079517SBill.Taylor@Sun.COM 
8089517SBill.Taylor@Sun.COM /*
8099517SBill.Taylor@Sun.COM  * hermon_impl_mboxlist_fini()
8109517SBill.Taylor@Sun.COM  *    Context: Only called from attach() and/or detach() path contexts
8119517SBill.Taylor@Sun.COM  */
8129517SBill.Taylor@Sun.COM static void
hermon_impl_mboxlist_fini(hermon_state_t * state,hermon_mboxlist_t * mblist)8139517SBill.Taylor@Sun.COM hermon_impl_mboxlist_fini(hermon_state_t *state, hermon_mboxlist_t *mblist)
8149517SBill.Taylor@Sun.COM {
8159517SBill.Taylor@Sun.COM 	hermon_rsrc_t	*rsrc;
8169517SBill.Taylor@Sun.COM 	int		i, status;
8179517SBill.Taylor@Sun.COM 
8189517SBill.Taylor@Sun.COM 	/* Release the resources for each of the mailbox list entries */
8199517SBill.Taylor@Sun.COM 	for (i = 0; i < mblist->mbl_num_alloc; i++) {
8209517SBill.Taylor@Sun.COM 		rsrc = mblist->mbl_mbox[i].mb_rsrcptr;
8219517SBill.Taylor@Sun.COM 
8229517SBill.Taylor@Sun.COM 		/*
8239517SBill.Taylor@Sun.COM 		 * First, unbind the DMA memory for the mailbox
8249517SBill.Taylor@Sun.COM 		 *
8259517SBill.Taylor@Sun.COM 		 * Note: The only way ddi_dma_unbind_handle() currently
8269517SBill.Taylor@Sun.COM 		 * can return an error is if the handle passed in is invalid.
8279517SBill.Taylor@Sun.COM 		 * Since this should never happen, we choose to return void
8289517SBill.Taylor@Sun.COM 		 * from this function!  If this does return an error,
8299517SBill.Taylor@Sun.COM 		 * however, then we print a warning message to the console.
8309517SBill.Taylor@Sun.COM 		 */
8319517SBill.Taylor@Sun.COM 		status = ddi_dma_unbind_handle(rsrc->hr_dmahdl);
8329517SBill.Taylor@Sun.COM 		if (status != DDI_SUCCESS) {
8339517SBill.Taylor@Sun.COM 			HERMON_WARNING(state, "failed to unbind DMA mapping");
8349517SBill.Taylor@Sun.COM 			return;
8359517SBill.Taylor@Sun.COM 		}
8369517SBill.Taylor@Sun.COM 
8379517SBill.Taylor@Sun.COM 		/* Next, free the mailbox resource */
8389517SBill.Taylor@Sun.COM 		hermon_rsrc_free(state, &rsrc);
8399517SBill.Taylor@Sun.COM 	}
8409517SBill.Taylor@Sun.COM 
8419517SBill.Taylor@Sun.COM 	/* Destroy the mailbox list mutex and cv */
8429517SBill.Taylor@Sun.COM 	mutex_destroy(&mblist->mbl_lock);
8439517SBill.Taylor@Sun.COM 	cv_destroy(&mblist->mbl_cv);
8449517SBill.Taylor@Sun.COM 
8459517SBill.Taylor@Sun.COM 	/* Free up the memory for tracking the mailbox list */
8469517SBill.Taylor@Sun.COM 	kmem_free(mblist->mbl_mbox, mblist->mbl_list_sz *
8479517SBill.Taylor@Sun.COM 	    sizeof (hermon_mbox_t));
8489517SBill.Taylor@Sun.COM }
8499517SBill.Taylor@Sun.COM 
8509517SBill.Taylor@Sun.COM 
8519517SBill.Taylor@Sun.COM /*
8529517SBill.Taylor@Sun.COM  * hermon_outstanding_cmd_alloc()
8539517SBill.Taylor@Sun.COM  *    Context: Can be called only from base context.
8549517SBill.Taylor@Sun.COM  */
8559517SBill.Taylor@Sun.COM static int
hermon_outstanding_cmd_alloc(hermon_state_t * state,hermon_cmd_t ** cmd_ptr,uint_t cmd_wait)8569517SBill.Taylor@Sun.COM hermon_outstanding_cmd_alloc(hermon_state_t *state, hermon_cmd_t **cmd_ptr,
8579517SBill.Taylor@Sun.COM     uint_t cmd_wait)
8589517SBill.Taylor@Sun.COM {
8599517SBill.Taylor@Sun.COM 	hermon_cmdlist_t	*cmd_list;
8609517SBill.Taylor@Sun.COM 	uint_t		next, prev, head;
8619517SBill.Taylor@Sun.COM 
8629517SBill.Taylor@Sun.COM 	cmd_list = &state->hs_cmd_list;
8639517SBill.Taylor@Sun.COM 	mutex_enter(&cmd_list->cml_lock);
8649517SBill.Taylor@Sun.COM 
8659517SBill.Taylor@Sun.COM 	/* Ensure that outstanding commands are supported */
8669517SBill.Taylor@Sun.COM 	ASSERT(cmd_list->cml_num_alloc != 0);
8679517SBill.Taylor@Sun.COM 
8689517SBill.Taylor@Sun.COM 	/*
8699517SBill.Taylor@Sun.COM 	 * If the outstanding command list is empty, then wait (if
8709517SBill.Taylor@Sun.COM 	 * appropriate in the current context).  Otherwise, grab the
8719517SBill.Taylor@Sun.COM 	 * next available command.
8729517SBill.Taylor@Sun.COM 	 */
8739517SBill.Taylor@Sun.COM 	while (cmd_list->cml_entries_free == 0) {
8749517SBill.Taylor@Sun.COM 		/* No free commands */
8759517SBill.Taylor@Sun.COM 		if (cmd_wait == HERMON_NOSLEEP) {
8769517SBill.Taylor@Sun.COM 			mutex_exit(&cmd_list->cml_lock);
8779517SBill.Taylor@Sun.COM 			return (HERMON_CMD_INSUFF_RSRC);
8789517SBill.Taylor@Sun.COM 		}
8799517SBill.Taylor@Sun.COM 
8809517SBill.Taylor@Sun.COM 		/*
8819517SBill.Taylor@Sun.COM 		 * Wait (on cv) for a command to become free.  Note: Just
8829517SBill.Taylor@Sun.COM 		 * as we do above in hermon_cmd_post(), we also have the
8839517SBill.Taylor@Sun.COM 		 * "__lock_lint" here to workaround warlock.  Warlock doesn't
8849517SBill.Taylor@Sun.COM 		 * know that other parts of the Hermon may occasionally call
8859517SBill.Taylor@Sun.COM 		 * this routine while holding their own locks, so it complains
8869517SBill.Taylor@Sun.COM 		 * about this cv_wait.  In reality, however, the rest of the
8879517SBill.Taylor@Sun.COM 		 * driver never calls this routine with a lock held unless
8889517SBill.Taylor@Sun.COM 		 * they pass HERMON_CMD_NOSLEEP.
8899517SBill.Taylor@Sun.COM 		 */
8909517SBill.Taylor@Sun.COM 		cmd_list->cml_waiters++;
8919517SBill.Taylor@Sun.COM #ifndef	__lock_lint
8929517SBill.Taylor@Sun.COM 		cv_wait(&cmd_list->cml_cv, &cmd_list->cml_lock);
8939517SBill.Taylor@Sun.COM #endif
8949517SBill.Taylor@Sun.COM 	}
8959517SBill.Taylor@Sun.COM 
8969517SBill.Taylor@Sun.COM 	/* Grab the next available command from the list */
8979517SBill.Taylor@Sun.COM 	head = cmd_list->cml_head_indx;
8989517SBill.Taylor@Sun.COM 	*cmd_ptr = &cmd_list->cml_cmd[head];
8999517SBill.Taylor@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(**cmd_ptr))
9009517SBill.Taylor@Sun.COM 	next = (*cmd_ptr)->cmd_next;
9019517SBill.Taylor@Sun.COM 	prev = (*cmd_ptr)->cmd_prev;
9029517SBill.Taylor@Sun.COM 	(*cmd_ptr)->cmd_status = HERMON_CMD_INVALID_STATUS;
9039517SBill.Taylor@Sun.COM 
9049517SBill.Taylor@Sun.COM 	/* Remove it from the command list */
9059517SBill.Taylor@Sun.COM 	cmd_list->cml_cmd[next].cmd_prev = prev;
9069517SBill.Taylor@Sun.COM 	cmd_list->cml_cmd[prev].cmd_next = next;
9079517SBill.Taylor@Sun.COM 	cmd_list->cml_head_indx		 = next;
9089517SBill.Taylor@Sun.COM 
9099517SBill.Taylor@Sun.COM 	/* Update the "free" count and return */
9109517SBill.Taylor@Sun.COM 	cmd_list->cml_entries_free--;
9119517SBill.Taylor@Sun.COM 
9129517SBill.Taylor@Sun.COM 	mutex_exit(&cmd_list->cml_lock);
9139517SBill.Taylor@Sun.COM 
9149517SBill.Taylor@Sun.COM 	return (HERMON_CMD_SUCCESS);
9159517SBill.Taylor@Sun.COM }
9169517SBill.Taylor@Sun.COM 
9179517SBill.Taylor@Sun.COM 
9189517SBill.Taylor@Sun.COM /*
9199517SBill.Taylor@Sun.COM  * hermon_outstanding_cmd_free()
9209517SBill.Taylor@Sun.COM  *    Context: Can be called only from base context.
9219517SBill.Taylor@Sun.COM  */
9229517SBill.Taylor@Sun.COM static void
hermon_outstanding_cmd_free(hermon_state_t * state,hermon_cmd_t ** cmd_ptr)9239517SBill.Taylor@Sun.COM hermon_outstanding_cmd_free(hermon_state_t *state, hermon_cmd_t **cmd_ptr)
9249517SBill.Taylor@Sun.COM {
9259517SBill.Taylor@Sun.COM 	hermon_cmdlist_t	*cmd_list;
9269517SBill.Taylor@Sun.COM 	uint_t		cmd_indx;
9279517SBill.Taylor@Sun.COM 
9289517SBill.Taylor@Sun.COM 	cmd_list = &state->hs_cmd_list;
9299517SBill.Taylor@Sun.COM 	mutex_enter(&cmd_list->cml_lock);
9309517SBill.Taylor@Sun.COM 
9319517SBill.Taylor@Sun.COM 	/* Pull the "index" from command entry */
9329517SBill.Taylor@Sun.COM 	cmd_indx = (*cmd_ptr)->cmd_indx;
9339517SBill.Taylor@Sun.COM 
9349517SBill.Taylor@Sun.COM 	/*
9359517SBill.Taylor@Sun.COM 	 * If outstanding command list is not empty, then insert the entry.
9369517SBill.Taylor@Sun.COM 	 * Otherwise, this is the only entry.  So update the pointers
9379517SBill.Taylor@Sun.COM 	 * appropriately.
9389517SBill.Taylor@Sun.COM 	 */
9399517SBill.Taylor@Sun.COM 	if (cmd_list->cml_entries_free++ != 0) {
9409517SBill.Taylor@Sun.COM 		/* Update the current command */
9419517SBill.Taylor@Sun.COM 		(*cmd_ptr)->cmd_next = cmd_list->cml_head_indx;
9429517SBill.Taylor@Sun.COM 		(*cmd_ptr)->cmd_prev = cmd_list->cml_tail_indx;
9439517SBill.Taylor@Sun.COM 
9449517SBill.Taylor@Sun.COM 		/* Update head and tail commands */
9459517SBill.Taylor@Sun.COM 		cmd_list->cml_cmd[cmd_list->cml_head_indx].cmd_prev = cmd_indx;
9469517SBill.Taylor@Sun.COM 		cmd_list->cml_cmd[cmd_list->cml_tail_indx].cmd_next = cmd_indx;
9479517SBill.Taylor@Sun.COM 
9489517SBill.Taylor@Sun.COM 		/* Update tail index */
9499517SBill.Taylor@Sun.COM 		cmd_list->cml_tail_indx = cmd_indx;
9509517SBill.Taylor@Sun.COM 
9519517SBill.Taylor@Sun.COM 	} else {
9529517SBill.Taylor@Sun.COM 		/* Update the current command */
9539517SBill.Taylor@Sun.COM 		(*cmd_ptr)->cmd_next = cmd_indx;
9549517SBill.Taylor@Sun.COM 		(*cmd_ptr)->cmd_prev = cmd_indx;
9559517SBill.Taylor@Sun.COM 
9569517SBill.Taylor@Sun.COM 		/* Update head and tail indexes */
9579517SBill.Taylor@Sun.COM 		cmd_list->cml_head_indx = cmd_indx;
9589517SBill.Taylor@Sun.COM 		cmd_list->cml_tail_indx = cmd_indx;
9599517SBill.Taylor@Sun.COM 	}
9609517SBill.Taylor@Sun.COM 
9619517SBill.Taylor@Sun.COM 	/* If there are threads waiting, signal one of them */
9629517SBill.Taylor@Sun.COM 	if (cmd_list->cml_waiters > 0) {
9639517SBill.Taylor@Sun.COM 		cmd_list->cml_waiters--;
9649517SBill.Taylor@Sun.COM 		cv_signal(&cmd_list->cml_cv);
9659517SBill.Taylor@Sun.COM 	}
9669517SBill.Taylor@Sun.COM 
9679517SBill.Taylor@Sun.COM 	/* Clear out the command entry pointer */
9689517SBill.Taylor@Sun.COM 	*cmd_ptr = NULL;
9699517SBill.Taylor@Sun.COM 
9709517SBill.Taylor@Sun.COM 	mutex_exit(&cmd_list->cml_lock);
9719517SBill.Taylor@Sun.COM }
9729517SBill.Taylor@Sun.COM 
9739517SBill.Taylor@Sun.COM 
9749517SBill.Taylor@Sun.COM /*
9759517SBill.Taylor@Sun.COM  * hermon_write_hcr()
9769517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
9779517SBill.Taylor@Sun.COM  */
9789517SBill.Taylor@Sun.COM static int
hermon_write_hcr(hermon_state_t * state,hermon_cmd_post_t * cmdpost,uint16_t token,int * hw_err)9799517SBill.Taylor@Sun.COM hermon_write_hcr(hermon_state_t *state, hermon_cmd_post_t *cmdpost,
9809517SBill.Taylor@Sun.COM     uint16_t token, int *hw_err)
9819517SBill.Taylor@Sun.COM {
9829517SBill.Taylor@Sun.COM 	hermon_hw_hcr_t	*hcr;
9839517SBill.Taylor@Sun.COM 	uint_t		status, count, countmax;
9849517SBill.Taylor@Sun.COM 	uint64_t	hcrreg;
9859517SBill.Taylor@Sun.COM 	uint64_t	togmask;
9869517SBill.Taylor@Sun.COM 	ddi_acc_handle_t cmdhdl = hermon_get_cmdhdl(state);
9879517SBill.Taylor@Sun.COM 	boolean_t	hw_error = B_FALSE;
9889517SBill.Taylor@Sun.COM 
9899517SBill.Taylor@Sun.COM 	/* initialize the FMA retry loop */
9909517SBill.Taylor@Sun.COM 	hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9919517SBill.Taylor@Sun.COM 
9929517SBill.Taylor@Sun.COM 	/*
9939517SBill.Taylor@Sun.COM 	 * Grab the "HCR access" lock if the driver is not in
9949517SBill.Taylor@Sun.COM 	 * fastreboot. In fastreboot, this function is called
9959517SBill.Taylor@Sun.COM 	 * with the single thread but in high interrupt context
9969517SBill.Taylor@Sun.COM 	 * (so that this mutex lock cannot be used).
9979517SBill.Taylor@Sun.COM 	 */
9989517SBill.Taylor@Sun.COM #ifdef __lock_lint
9999517SBill.Taylor@Sun.COM 	mutex_enter(&state->hs_cmd_regs.hcr_lock);
10009517SBill.Taylor@Sun.COM #else
10019517SBill.Taylor@Sun.COM 	if (!HERMON_IN_FASTREBOOT(state)) {
10029517SBill.Taylor@Sun.COM 		mutex_enter(&state->hs_cmd_regs.hcr_lock);
10039517SBill.Taylor@Sun.COM 	}
10049517SBill.Taylor@Sun.COM #endif
10059517SBill.Taylor@Sun.COM 	hcr = state->hs_cmd_regs.hcr;
10069517SBill.Taylor@Sun.COM 
10079517SBill.Taylor@Sun.COM 	/*
10089517SBill.Taylor@Sun.COM 	 * First, check the "go" bit to see if any previous hcr usage is
10099517SBill.Taylor@Sun.COM 	 * complete.  As long as it is set then we must continue to poll.
10109517SBill.Taylor@Sun.COM 	 */
10119517SBill.Taylor@Sun.COM 
10129517SBill.Taylor@Sun.COM 	countmax = state->hs_cfg_profile->cp_cmd_poll_max;
10139517SBill.Taylor@Sun.COM 	togmask = (state->hs_cmd_toggle & 0x01) << HERMON_HCR_CMD_T_SHFT;
10149517SBill.Taylor@Sun.COM 
10159517SBill.Taylor@Sun.COM 	/* the FMA retry loop starts. */
10169517SBill.Taylor@Sun.COM 	hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
10179517SBill.Taylor@Sun.COM 	    fm_test);
10189517SBill.Taylor@Sun.COM 
10199517SBill.Taylor@Sun.COM 	count	 = 0;
10209517SBill.Taylor@Sun.COM 	for (;;) {
10219517SBill.Taylor@Sun.COM 		hcrreg = ddi_get32(cmdhdl, &hcr->cmd);
10229517SBill.Taylor@Sun.COM 
10239517SBill.Taylor@Sun.COM 		/* If "go" bit is clear and toggle reset, then done */
10249517SBill.Taylor@Sun.COM 		if (((hcrreg & HERMON_HCR_CMD_GO_MASK) == 0) &&
10259517SBill.Taylor@Sun.COM 		    ((hcrreg & HERMON_HCR_CMD_T_MASK)  == togmask)) {
10269517SBill.Taylor@Sun.COM 			break;
10279517SBill.Taylor@Sun.COM 		}
10289517SBill.Taylor@Sun.COM 		/* Delay before polling the "go" bit again */
10299517SBill.Taylor@Sun.COM 		drv_usecwait(state->hs_cfg_profile->cp_cmd_poll_delay);
10309517SBill.Taylor@Sun.COM 
10319517SBill.Taylor@Sun.COM 		/*
10329517SBill.Taylor@Sun.COM 		 * If we poll more than the maximum number of times, then
10339517SBill.Taylor@Sun.COM 		 * return a "timeout" error.
10349517SBill.Taylor@Sun.COM 		 */
10359517SBill.Taylor@Sun.COM 		if (++count > countmax) {
10369517SBill.Taylor@Sun.COM #ifdef __lock_lint
10379517SBill.Taylor@Sun.COM 			mutex_exit(&state->hs_cmd_regs.hcr_lock);
10389517SBill.Taylor@Sun.COM #else
10399517SBill.Taylor@Sun.COM 			if (!HERMON_IN_FASTREBOOT(state)) {
10409517SBill.Taylor@Sun.COM 				mutex_exit(&state->hs_cmd_regs.hcr_lock);
10419517SBill.Taylor@Sun.COM 			}
10429517SBill.Taylor@Sun.COM #endif
10439517SBill.Taylor@Sun.COM 			cmn_err(CE_NOTE, "write_hcr: cannot start cmd");
10449517SBill.Taylor@Sun.COM 			return (HERMON_CMD_TIMEOUT_GOBIT);
10459517SBill.Taylor@Sun.COM 		}
10469517SBill.Taylor@Sun.COM 	}
10479517SBill.Taylor@Sun.COM 
10489517SBill.Taylor@Sun.COM 	/* the FMA retry loop ends. */
10499517SBill.Taylor@Sun.COM 	hermon_pio_end(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
10509517SBill.Taylor@Sun.COM 	    fm_test);
10519517SBill.Taylor@Sun.COM 
10529517SBill.Taylor@Sun.COM 	/* check if there is a transient error */
10539517SBill.Taylor@Sun.COM 	if (fm_loop_cnt != HCA_PIO_RETRY_CNT) {
10549517SBill.Taylor@Sun.COM 		hw_error = B_TRUE;
10559517SBill.Taylor@Sun.COM 	}
10569517SBill.Taylor@Sun.COM 
10579517SBill.Taylor@Sun.COM 	/* succeeded, so update the cmd counter for this cmd's completion */
10589517SBill.Taylor@Sun.COM 	state->hs_cmd_toggle++;
10599517SBill.Taylor@Sun.COM 	togmask = (state->hs_cmd_toggle & 0x01) << HERMON_HCR_CMD_T_SHFT;
10609517SBill.Taylor@Sun.COM 
10619517SBill.Taylor@Sun.COM 	/* the FMA retry loop starts. */
10629517SBill.Taylor@Sun.COM 	hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
10639517SBill.Taylor@Sun.COM 	    fm_test);
10649517SBill.Taylor@Sun.COM 
10659517SBill.Taylor@Sun.COM 	/* Write "inparam" as a 64-bit quantity */
10669517SBill.Taylor@Sun.COM 	ddi_put64(cmdhdl, (uint64_t *)(void *)&hcr->in_param0,
10679517SBill.Taylor@Sun.COM 	    cmdpost->cp_inparm);
10689517SBill.Taylor@Sun.COM 
10699517SBill.Taylor@Sun.COM 	/* Write "inmod" and 32-bits of "outparam" as 64-bit */
10709517SBill.Taylor@Sun.COM 	hcrreg = ((uint64_t)cmdpost->cp_inmod << 32);
10719517SBill.Taylor@Sun.COM 	hcrreg = hcrreg | (cmdpost->cp_outparm >> 32);
10729517SBill.Taylor@Sun.COM 
10739517SBill.Taylor@Sun.COM 	ddi_put64(cmdhdl, (uint64_t *)(void *)&hcr->input_modifier, hcrreg);
10749517SBill.Taylor@Sun.COM 
10759517SBill.Taylor@Sun.COM 	/* Write the other 32-bits of "outparam" and "token" as 64-bit */
10769517SBill.Taylor@Sun.COM 	hcrreg = (cmdpost->cp_outparm << 32);
10779517SBill.Taylor@Sun.COM 	hcrreg = hcrreg | ((uint32_t)token << HERMON_HCR_TOKEN_SHIFT);
10789517SBill.Taylor@Sun.COM 
10799517SBill.Taylor@Sun.COM 	ddi_put64(cmdhdl, (uint64_t *)(void *)&hcr->out_param1, hcrreg);
10809517SBill.Taylor@Sun.COM 
10819517SBill.Taylor@Sun.COM 	/* Then setup the final hcrreg to hit doorbell (i.e. "go" bit) */
10829517SBill.Taylor@Sun.COM 	hcrreg = HERMON_HCR_CMD_GO_MASK;
10839517SBill.Taylor@Sun.COM 	/* Then set the toggle bit for this command */
10849517SBill.Taylor@Sun.COM 	hcrreg |= (state->hs_cmd_toggle & 0x01) << HERMON_HCR_CMD_T_SHFT;
10859517SBill.Taylor@Sun.COM 	if (cmdpost->cp_flags == HERMON_CMD_SLEEP_NOSPIN) {
10869517SBill.Taylor@Sun.COM 		hcrreg = hcrreg | HERMON_HCR_CMD_E_MASK;
10879517SBill.Taylor@Sun.COM 	}
10889517SBill.Taylor@Sun.COM 	hcrreg = hcrreg | (cmdpost->cp_opmod << HERMON_HCR_CMD_OPMOD_SHFT);
10899517SBill.Taylor@Sun.COM 	hcrreg = hcrreg | (cmdpost->cp_opcode);
10909517SBill.Taylor@Sun.COM 
10919517SBill.Taylor@Sun.COM 	/* Write the doorbell to the HCR */
10929517SBill.Taylor@Sun.COM 	ddi_put32(cmdhdl, &hcr->cmd, hcrreg);
10939517SBill.Taylor@Sun.COM 
10949517SBill.Taylor@Sun.COM 	/* the FMA retry loop ends. */
10959517SBill.Taylor@Sun.COM 	hermon_pio_end(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
10969517SBill.Taylor@Sun.COM 	    fm_test);
10979517SBill.Taylor@Sun.COM 
10989517SBill.Taylor@Sun.COM 	/* check if there is a transient error */
10999517SBill.Taylor@Sun.COM 	if (fm_loop_cnt != HCA_PIO_RETRY_CNT) {
11009517SBill.Taylor@Sun.COM 		hw_error = B_TRUE;
11019517SBill.Taylor@Sun.COM 	}
11029517SBill.Taylor@Sun.COM 
11039517SBill.Taylor@Sun.COM 	/*
11049517SBill.Taylor@Sun.COM 	 * In the SPIN case we read the HCR and check the "go" bit.  For the
11059517SBill.Taylor@Sun.COM 	 * NOSPIN case we do not have to poll, we simply release the HCR lock
11069517SBill.Taylor@Sun.COM 	 * and return.
11079517SBill.Taylor@Sun.COM 	 */
11089517SBill.Taylor@Sun.COM 	if (cmdpost->cp_flags == HERMON_CMD_NOSLEEP_SPIN) {
11099517SBill.Taylor@Sun.COM 
11109517SBill.Taylor@Sun.COM 		countmax = (state->hs_cfg_profile->cp_cmd_poll_max << 4);
11119517SBill.Taylor@Sun.COM 
11129517SBill.Taylor@Sun.COM 		/* the FMA retry loop starts. */
11139517SBill.Taylor@Sun.COM 		hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt,
11149517SBill.Taylor@Sun.COM 		    fm_status, fm_test);
11159517SBill.Taylor@Sun.COM 
11169517SBill.Taylor@Sun.COM 		count	 = 0;
11179517SBill.Taylor@Sun.COM 		for (;;) {
11189517SBill.Taylor@Sun.COM 			hcrreg = ddi_get32(cmdhdl, &hcr->cmd);
11199517SBill.Taylor@Sun.COM 
11209517SBill.Taylor@Sun.COM 			/* If "go" bit is clear and toggle reset, then done */
11219517SBill.Taylor@Sun.COM 			if (((hcrreg & HERMON_HCR_CMD_GO_MASK) == 0) &&
11229517SBill.Taylor@Sun.COM 			    ((hcrreg & HERMON_HCR_CMD_T_MASK)  == togmask)) {
11239517SBill.Taylor@Sun.COM 				break;
11249517SBill.Taylor@Sun.COM 			}
11259517SBill.Taylor@Sun.COM 			/* Delay before polling the "go" bit again */
11269517SBill.Taylor@Sun.COM 			drv_usecwait(state->hs_cfg_profile->cp_cmd_poll_delay);
11279517SBill.Taylor@Sun.COM 
11289517SBill.Taylor@Sun.COM 			/*
11299517SBill.Taylor@Sun.COM 			 * If we poll more than the maximum number of times,
11309517SBill.Taylor@Sun.COM 			 * then return a "timeout" error.
11319517SBill.Taylor@Sun.COM 			 */
11329517SBill.Taylor@Sun.COM 			if (++count > countmax) {
11339517SBill.Taylor@Sun.COM #ifdef __lock_lint
11349517SBill.Taylor@Sun.COM 				mutex_exit(&state-> hs_cmd_regs.hcr_lock);
11359517SBill.Taylor@Sun.COM #else
11369517SBill.Taylor@Sun.COM 				if (!HERMON_IN_FASTREBOOT(state)) {
11379517SBill.Taylor@Sun.COM 					mutex_exit(&state->
11389517SBill.Taylor@Sun.COM 					    hs_cmd_regs.hcr_lock);
11399517SBill.Taylor@Sun.COM 				}
11409517SBill.Taylor@Sun.COM #endif
11419517SBill.Taylor@Sun.COM 				cmn_err(CE_NOTE,
11429517SBill.Taylor@Sun.COM 				    "write_hcr: cannot complete cmd");
11439517SBill.Taylor@Sun.COM 				return (HERMON_CMD_TIMEOUT_GOBIT);
11449517SBill.Taylor@Sun.COM 			}
11459517SBill.Taylor@Sun.COM 		}
11469517SBill.Taylor@Sun.COM 
11479517SBill.Taylor@Sun.COM 		/* Pull out the "status" bits from the HCR */
11489517SBill.Taylor@Sun.COM 		status = (hcrreg >> HERMON_HCR_CMD_STATUS_SHFT);
11499517SBill.Taylor@Sun.COM 
11509517SBill.Taylor@Sun.COM 		/*
11519517SBill.Taylor@Sun.COM 		 * Read the "outparam" value.  Note: we have to read "outparam"
11529517SBill.Taylor@Sun.COM 		 * as two separate 32-bit reads because the field in the HCR is
11539517SBill.Taylor@Sun.COM 		 * not 64-bit aligned.
11549517SBill.Taylor@Sun.COM 		 */
11559517SBill.Taylor@Sun.COM 		hcrreg = ddi_get32(cmdhdl, &hcr->out_param0);
11569517SBill.Taylor@Sun.COM 		cmdpost->cp_outparm = hcrreg << 32;
11579517SBill.Taylor@Sun.COM 		hcrreg = ddi_get32(cmdhdl, &hcr->out_param1);
11589517SBill.Taylor@Sun.COM 		cmdpost->cp_outparm |= hcrreg;
11599517SBill.Taylor@Sun.COM 
11609517SBill.Taylor@Sun.COM 		/* the FMA retry loop ends. */
11619517SBill.Taylor@Sun.COM 		hermon_pio_end(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
11629517SBill.Taylor@Sun.COM 		    fm_test);
11639517SBill.Taylor@Sun.COM 
11649517SBill.Taylor@Sun.COM 		/* check if there is a transient error */
11659517SBill.Taylor@Sun.COM 		if (fm_loop_cnt != HCA_PIO_RETRY_CNT) {
11669517SBill.Taylor@Sun.COM 			hw_error = B_TRUE;
11679517SBill.Taylor@Sun.COM 		}
11689517SBill.Taylor@Sun.COM 
11699517SBill.Taylor@Sun.COM 	/* END SPIN */
11709517SBill.Taylor@Sun.COM 	} else {		/* NOSPIN */
11719517SBill.Taylor@Sun.COM 		status = HERMON_CMD_SUCCESS;
11729517SBill.Taylor@Sun.COM 	}
11739517SBill.Taylor@Sun.COM 
11749517SBill.Taylor@Sun.COM 	/* Drop the "HCR access" lock */
11759517SBill.Taylor@Sun.COM #ifdef __lock_lint
11769517SBill.Taylor@Sun.COM 	mutex_exit(&state->hs_cmd_regs.hcr_lock);
11779517SBill.Taylor@Sun.COM #else
11789517SBill.Taylor@Sun.COM 	if (!HERMON_IN_FASTREBOOT(state)) {
11799517SBill.Taylor@Sun.COM 		mutex_exit(&state->hs_cmd_regs.hcr_lock);
11809517SBill.Taylor@Sun.COM 	}
11819517SBill.Taylor@Sun.COM #endif
11829517SBill.Taylor@Sun.COM 	if (hw_error == B_TRUE) {
11839517SBill.Taylor@Sun.COM 		*hw_err = HCA_PIO_TRANSIENT;
11849517SBill.Taylor@Sun.COM 	} else {
11859517SBill.Taylor@Sun.COM 		*hw_err = HCA_PIO_OK;
11869517SBill.Taylor@Sun.COM 	}
11879517SBill.Taylor@Sun.COM #ifdef FMA_TEST
11889517SBill.Taylor@Sun.COM 	if (hermon_test_num == -3) {
11899517SBill.Taylor@Sun.COM 		status = HERMON_CMD_INTERNAL_ERR;
11909517SBill.Taylor@Sun.COM 	}
11919517SBill.Taylor@Sun.COM #endif
11929517SBill.Taylor@Sun.COM 	return (status);
11939517SBill.Taylor@Sun.COM 
11949517SBill.Taylor@Sun.COM pio_error:
11959517SBill.Taylor@Sun.COM #ifdef __lock_lint
11969517SBill.Taylor@Sun.COM 	mutex_exit(&state->hs_cmd_regs.hcr_lock);
11979517SBill.Taylor@Sun.COM #else
11989517SBill.Taylor@Sun.COM 	if (!HERMON_IN_FASTREBOOT(state)) {
11999517SBill.Taylor@Sun.COM 		mutex_exit(&state->hs_cmd_regs.hcr_lock);
12009517SBill.Taylor@Sun.COM 	}
12019517SBill.Taylor@Sun.COM #endif
12029517SBill.Taylor@Sun.COM 	hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_NON_FATAL);
12039517SBill.Taylor@Sun.COM 	*hw_err = HCA_PIO_PERSISTENT;
12049517SBill.Taylor@Sun.COM 	return (HERMON_CMD_INVALID_STATUS);
12059517SBill.Taylor@Sun.COM }
12069517SBill.Taylor@Sun.COM 
12079517SBill.Taylor@Sun.COM 
12089517SBill.Taylor@Sun.COM /*
12099517SBill.Taylor@Sun.COM  * hermon_outstanding_cmdlist_init()
12109517SBill.Taylor@Sun.COM  *    Context: Only called from attach() path context
12119517SBill.Taylor@Sun.COM  */
12129517SBill.Taylor@Sun.COM int
hermon_outstanding_cmdlist_init(hermon_state_t * state)12139517SBill.Taylor@Sun.COM hermon_outstanding_cmdlist_init(hermon_state_t *state)
12149517SBill.Taylor@Sun.COM {
12159517SBill.Taylor@Sun.COM 	uint_t		num_outstanding_cmds, head, tail;
12169517SBill.Taylor@Sun.COM 	int		i;
12179517SBill.Taylor@Sun.COM 
12189517SBill.Taylor@Sun.COM 	/*
12199517SBill.Taylor@Sun.COM 	 * Determine the number of the outstanding commands supported
12209517SBill.Taylor@Sun.COM 	 * by the Hermon device (obtained from the QUERY_FW command).  Note:
12219517SBill.Taylor@Sun.COM 	 * Because we handle both SLEEP and NOSLEEP cases around the hermon HCR,
12229517SBill.Taylor@Sun.COM 	 * we know that when an interrupt comes in it will be next on the
12239517SBill.Taylor@Sun.COM 	 * command register, and will at most have to wait one commands time.
12249517SBill.Taylor@Sun.COM 	 * We do not have to reserve an outstanding command here for
12259517SBill.Taylor@Sun.COM 	 * interrupts.
12269517SBill.Taylor@Sun.COM 	 */
12279517SBill.Taylor@Sun.COM 	num_outstanding_cmds = (1 << state->hs_fw.log_max_cmd);
12289517SBill.Taylor@Sun.COM 
12299517SBill.Taylor@Sun.COM 	/* Initialize the outstanding command list */
12309517SBill.Taylor@Sun.COM 	state->hs_cmd_list.cml_list_sz	 = num_outstanding_cmds;
12319517SBill.Taylor@Sun.COM 	state->hs_cmd_list.cml_head_indx = 0;
12329517SBill.Taylor@Sun.COM 	state->hs_cmd_list.cml_tail_indx = state->hs_cmd_list.cml_list_sz - 1;
12339517SBill.Taylor@Sun.COM 	state->hs_cmd_list.cml_entries_free = state->hs_cmd_list.cml_list_sz;
12349517SBill.Taylor@Sun.COM 	state->hs_cmd_list.cml_waiters	 = 0;
12359517SBill.Taylor@Sun.COM 	state->hs_cmd_list.cml_num_alloc = 0;
12369517SBill.Taylor@Sun.COM 
12379517SBill.Taylor@Sun.COM 	/* Allocate the memory for the outstanding command list */
12389517SBill.Taylor@Sun.COM 	if (num_outstanding_cmds) {
12399517SBill.Taylor@Sun.COM 		state->hs_cmd_list.cml_cmd =
12409517SBill.Taylor@Sun.COM 		    kmem_zalloc(state->hs_cmd_list.cml_list_sz *
12419517SBill.Taylor@Sun.COM 		    sizeof (hermon_cmd_t), KM_SLEEP);
12429517SBill.Taylor@Sun.COM 	}
12439517SBill.Taylor@Sun.COM 	mutex_init(&state->hs_cmd_list.cml_lock, NULL, MUTEX_DRIVER,
12449517SBill.Taylor@Sun.COM 	    DDI_INTR_PRI(state->hs_intrmsi_pri));
12459517SBill.Taylor@Sun.COM 	cv_init(&state->hs_cmd_list.cml_cv, NULL, CV_DRIVER, NULL);
12469517SBill.Taylor@Sun.COM 
12479517SBill.Taylor@Sun.COM 	/* Initialize the individual outstanding command list entries */
12489517SBill.Taylor@Sun.COM 	for (i = 0; i < state->hs_cmd_list.cml_list_sz; i++) {
12499517SBill.Taylor@Sun.COM 		mutex_init(&state->hs_cmd_list.cml_cmd[i].cmd_comp_lock,
12509517SBill.Taylor@Sun.COM 		    NULL, MUTEX_DRIVER, DDI_INTR_PRI(state->hs_intrmsi_pri));
12519517SBill.Taylor@Sun.COM 		cv_init(&state->hs_cmd_list.cml_cmd[i].cmd_comp_cv, NULL,
12529517SBill.Taylor@Sun.COM 		    CV_DRIVER, NULL);
12539517SBill.Taylor@Sun.COM 
12549517SBill.Taylor@Sun.COM 		state->hs_cmd_list.cml_cmd[i].cmd_next	= i+1;
12559517SBill.Taylor@Sun.COM 		state->hs_cmd_list.cml_cmd[i].cmd_prev	= i-1;
12569517SBill.Taylor@Sun.COM 		state->hs_cmd_list.cml_cmd[i].cmd_indx	= i;
12579517SBill.Taylor@Sun.COM 		state->hs_cmd_list.cml_num_alloc	= i + 1;
12589517SBill.Taylor@Sun.COM 	}
12599517SBill.Taylor@Sun.COM 	if (num_outstanding_cmds) {
12609517SBill.Taylor@Sun.COM 		head = state->hs_cmd_list.cml_head_indx;
12619517SBill.Taylor@Sun.COM 		tail = state->hs_cmd_list.cml_tail_indx;
12629517SBill.Taylor@Sun.COM 		state->hs_cmd_list.cml_cmd[head].cmd_prev =
12639517SBill.Taylor@Sun.COM 		    state->hs_cmd_list.cml_tail_indx;
12649517SBill.Taylor@Sun.COM 		state->hs_cmd_list.cml_cmd[tail].cmd_next =
12659517SBill.Taylor@Sun.COM 		    state->hs_cmd_list.cml_head_indx;
12669517SBill.Taylor@Sun.COM 	}
12679517SBill.Taylor@Sun.COM 
12689517SBill.Taylor@Sun.COM 	return (DDI_SUCCESS);
12699517SBill.Taylor@Sun.COM }
12709517SBill.Taylor@Sun.COM 
12719517SBill.Taylor@Sun.COM 
12729517SBill.Taylor@Sun.COM /*
12739517SBill.Taylor@Sun.COM  * hermon_outstanding_cmdlist_fini()
12749517SBill.Taylor@Sun.COM  *    Context: Only called from attach() and/or detach() path contexts
12759517SBill.Taylor@Sun.COM  */
12769517SBill.Taylor@Sun.COM void
hermon_outstanding_cmdlist_fini(hermon_state_t * state)12779517SBill.Taylor@Sun.COM hermon_outstanding_cmdlist_fini(hermon_state_t *state)
12789517SBill.Taylor@Sun.COM {
12799517SBill.Taylor@Sun.COM 	int		i;
12809517SBill.Taylor@Sun.COM 
12819517SBill.Taylor@Sun.COM 	/* Destroy the outstanding command list entries */
12829517SBill.Taylor@Sun.COM 	for (i = 0; i < state->hs_cmd_list.cml_num_alloc; i++) {
12839517SBill.Taylor@Sun.COM 		mutex_destroy(&state->hs_cmd_list.cml_cmd[i].cmd_comp_lock);
12849517SBill.Taylor@Sun.COM 		cv_destroy(&state->hs_cmd_list.cml_cmd[i].cmd_comp_cv);
12859517SBill.Taylor@Sun.COM 	}
12869517SBill.Taylor@Sun.COM 
12879517SBill.Taylor@Sun.COM 	/* Destroy the lock (and cv) and free up memory for list */
12889517SBill.Taylor@Sun.COM 	mutex_destroy(&state->hs_cmd_list.cml_lock);
12899517SBill.Taylor@Sun.COM 	cv_destroy(&state->hs_cmd_list.cml_cv);
12909517SBill.Taylor@Sun.COM 	if (state->hs_cmd_list.cml_num_alloc) {
12919517SBill.Taylor@Sun.COM 		kmem_free(state->hs_cmd_list.cml_cmd,
12929517SBill.Taylor@Sun.COM 		    state->hs_cmd_list.cml_list_sz * sizeof (hermon_cmd_t));
12939517SBill.Taylor@Sun.COM 	}
12949517SBill.Taylor@Sun.COM }
12959517SBill.Taylor@Sun.COM 
12969517SBill.Taylor@Sun.COM 
12979517SBill.Taylor@Sun.COM /*
12989517SBill.Taylor@Sun.COM  * hermon_mbox_sync()
12999517SBill.Taylor@Sun.COM  */
13009517SBill.Taylor@Sun.COM static void
hermon_mbox_sync(hermon_mbox_t * mbox,uint_t offset,uint_t length,uint_t flag)13019517SBill.Taylor@Sun.COM hermon_mbox_sync(hermon_mbox_t *mbox, uint_t offset, uint_t length,
13029517SBill.Taylor@Sun.COM     uint_t flag)
13039517SBill.Taylor@Sun.COM {
13049517SBill.Taylor@Sun.COM 	ddi_dma_handle_t	dmahdl;
13059517SBill.Taylor@Sun.COM 	int			status;
13069517SBill.Taylor@Sun.COM 
13079517SBill.Taylor@Sun.COM 	/* Get the DMA handle from mailbox */
13089517SBill.Taylor@Sun.COM 	dmahdl = mbox->mb_rsrcptr->hr_dmahdl;
13099517SBill.Taylor@Sun.COM 
13109517SBill.Taylor@Sun.COM 	/* Calculate offset into mailbox */
13119517SBill.Taylor@Sun.COM 	status = ddi_dma_sync(dmahdl, (off_t)offset, (size_t)length, flag);
13129517SBill.Taylor@Sun.COM 	if (status != DDI_SUCCESS) {
13139517SBill.Taylor@Sun.COM 		return;
13149517SBill.Taylor@Sun.COM 	}
13159517SBill.Taylor@Sun.COM }
13169517SBill.Taylor@Sun.COM 
13179517SBill.Taylor@Sun.COM 
13189517SBill.Taylor@Sun.COM /*
13199517SBill.Taylor@Sun.COM  * hermon_init_hca_cmd_post()
13209517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
13219517SBill.Taylor@Sun.COM  *    (Currently called only from attach() path context)
13229517SBill.Taylor@Sun.COM  */
13239517SBill.Taylor@Sun.COM int
hermon_init_hca_cmd_post(hermon_state_t * state,hermon_hw_initqueryhca_t * inithca,uint_t sleepflag)13249517SBill.Taylor@Sun.COM hermon_init_hca_cmd_post(hermon_state_t *state,
13259517SBill.Taylor@Sun.COM     hermon_hw_initqueryhca_t *inithca, uint_t sleepflag)
13269517SBill.Taylor@Sun.COM {
13279517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
13289517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
13299517SBill.Taylor@Sun.COM 	uint64_t		data;
13309517SBill.Taylor@Sun.COM 	uint_t			size;
13319517SBill.Taylor@Sun.COM 	int			status, i;
13329517SBill.Taylor@Sun.COM 
13339517SBill.Taylor@Sun.COM 	/* Make sure we are called with the correct flag */
13349517SBill.Taylor@Sun.COM 	ASSERT(sleepflag == HERMON_CMD_NOSLEEP_SPIN);
13359517SBill.Taylor@Sun.COM 
13369517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
13379517SBill.Taylor@Sun.COM 
13389517SBill.Taylor@Sun.COM 	/* Get an "In" mailbox for the command */
13399517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
13409517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
13419517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
13429517SBill.Taylor@Sun.COM 		return (status);
13439517SBill.Taylor@Sun.COM 	}
13449517SBill.Taylor@Sun.COM 
13459517SBill.Taylor@Sun.COM 	/* Copy the Hermon "INIT_HCA" command into the mailbox */
13469517SBill.Taylor@Sun.COM 	size = sizeof (hermon_hw_initqueryhca_t);
13479517SBill.Taylor@Sun.COM 	for (i = 0; i < (size >> 3); i++) {
13489517SBill.Taylor@Sun.COM 		data = ((uint64_t *)inithca)[i];
13499517SBill.Taylor@Sun.COM 		ddi_put64(mbox_info.mbi_in->mb_acchdl,
13509517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
13519517SBill.Taylor@Sun.COM 	}
13529517SBill.Taylor@Sun.COM 
13539517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
13549517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
13559517SBill.Taylor@Sun.COM 
13569517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "INIT_HCA" command */
13579517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
13589517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
13599517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 0;
13609517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= INIT_HCA;
13619517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
13629517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
13639517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
13649517SBill.Taylor@Sun.COM 
13659517SBill.Taylor@Sun.COM 	/* Free the mailbox */
13669517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
13679517SBill.Taylor@Sun.COM 	return (status);
13689517SBill.Taylor@Sun.COM }
13699517SBill.Taylor@Sun.COM 
13709517SBill.Taylor@Sun.COM 
13719517SBill.Taylor@Sun.COM /*
13729517SBill.Taylor@Sun.COM  * hermon_close_hca_cmd_post()
13739517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
13749517SBill.Taylor@Sun.COM  *    (Currently called only from attach() and/or detach() path contexts)
13759517SBill.Taylor@Sun.COM  */
13769517SBill.Taylor@Sun.COM int
hermon_close_hca_cmd_post(hermon_state_t * state,uint_t sleepflag)13779517SBill.Taylor@Sun.COM hermon_close_hca_cmd_post(hermon_state_t *state, uint_t sleepflag)
13789517SBill.Taylor@Sun.COM {
13799517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
13809517SBill.Taylor@Sun.COM 	int			status;
13819517SBill.Taylor@Sun.COM 
13829517SBill.Taylor@Sun.COM 	/* Make sure we are called with the correct flag */
13839517SBill.Taylor@Sun.COM 	ASSERT(sleepflag == HERMON_CMD_NOSLEEP_SPIN);
13849517SBill.Taylor@Sun.COM 
13859517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
13869517SBill.Taylor@Sun.COM 
13879517SBill.Taylor@Sun.COM 
13889517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "CLOSE_HCA" command */
13899517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0;
13909517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
13919517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 0;
13929517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= CLOSE_HCA;
13939517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
13949517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
13959517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
13969517SBill.Taylor@Sun.COM 	return (status);
13979517SBill.Taylor@Sun.COM }
13989517SBill.Taylor@Sun.COM 
13999517SBill.Taylor@Sun.COM 
14009517SBill.Taylor@Sun.COM /*
14019517SBill.Taylor@Sun.COM  * hermon_set_port_cmd_post()
14029517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
14039517SBill.Taylor@Sun.COM  *    (Currently called only from attach() path context)
14049517SBill.Taylor@Sun.COM  */
14059517SBill.Taylor@Sun.COM int
hermon_set_port_cmd_post(hermon_state_t * state,hermon_hw_set_port_t * initport,uint_t port,uint_t sleepflag)14069517SBill.Taylor@Sun.COM hermon_set_port_cmd_post(hermon_state_t *state, hermon_hw_set_port_t *initport,
14079517SBill.Taylor@Sun.COM     uint_t port, uint_t sleepflag)
14089517SBill.Taylor@Sun.COM {
14099517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
14109517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
14119517SBill.Taylor@Sun.COM 	uint64_t		data;
14129517SBill.Taylor@Sun.COM 	uint_t			size;
14139517SBill.Taylor@Sun.COM 	int			status, i;
14149517SBill.Taylor@Sun.COM 
14159517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
14169517SBill.Taylor@Sun.COM 
14179517SBill.Taylor@Sun.COM 	/* Get an "In" mailbox for the command */
14189517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
14199517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
14209517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
14219517SBill.Taylor@Sun.COM 		return (status);
14229517SBill.Taylor@Sun.COM 	}
14239517SBill.Taylor@Sun.COM 
14249517SBill.Taylor@Sun.COM 	/* Copy the Hermon "INIT_PORT" command into the mailbox */
14259517SBill.Taylor@Sun.COM 	size = sizeof (hermon_hw_set_port_t);
14269517SBill.Taylor@Sun.COM 	for (i = 0; i < (size >> 3); i++) {
14279517SBill.Taylor@Sun.COM 		data = ((uint64_t *)initport)[i];
14289517SBill.Taylor@Sun.COM 		ddi_put64(mbox_info.mbi_in->mb_acchdl,
14299517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
14309517SBill.Taylor@Sun.COM 	}
14319517SBill.Taylor@Sun.COM 
14329517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
14339517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
14349517SBill.Taylor@Sun.COM 
14359517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "SET_PORT" command */
14369517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
14379517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
14389517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= port;
14399517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= SET_PORT;
14409517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
14419517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
14429517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
14439517SBill.Taylor@Sun.COM 
14449517SBill.Taylor@Sun.COM 	/* Free the mailbox */
14459517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
14469517SBill.Taylor@Sun.COM 	return (status);
14479517SBill.Taylor@Sun.COM }
14489517SBill.Taylor@Sun.COM 
14499517SBill.Taylor@Sun.COM 
14509517SBill.Taylor@Sun.COM /*
14519517SBill.Taylor@Sun.COM  * hermon_init_port_cmd_post()
14529517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
14539517SBill.Taylor@Sun.COM  *    (Currently called only from attach() and/or detach() path contexts)
14549517SBill.Taylor@Sun.COM  */
14559517SBill.Taylor@Sun.COM int
hermon_init_port_cmd_post(hermon_state_t * state,uint_t port,uint_t sleepflag)14569517SBill.Taylor@Sun.COM hermon_init_port_cmd_post(hermon_state_t *state, uint_t port, uint_t sleepflag)
14579517SBill.Taylor@Sun.COM {
14589517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
14599517SBill.Taylor@Sun.COM 	int			status;
14609517SBill.Taylor@Sun.COM 
14619517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
14629517SBill.Taylor@Sun.COM 
14639517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "INIT_PORT" command */
14649517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0;
14659517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
14669517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= port;
14679517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= INIT_PORT;
14689517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
14699517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
14709517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
14719517SBill.Taylor@Sun.COM 
14729517SBill.Taylor@Sun.COM 	return (status);
14739517SBill.Taylor@Sun.COM }
14749517SBill.Taylor@Sun.COM 
14759517SBill.Taylor@Sun.COM 
14769517SBill.Taylor@Sun.COM /*
14779517SBill.Taylor@Sun.COM  * hermon_close_port_cmd_post()
14789517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
14799517SBill.Taylor@Sun.COM  *    (Currently called only from attach() and/or detach() path contexts)
14809517SBill.Taylor@Sun.COM  */
14819517SBill.Taylor@Sun.COM int
hermon_close_port_cmd_post(hermon_state_t * state,uint_t port,uint_t sleepflag)14829517SBill.Taylor@Sun.COM hermon_close_port_cmd_post(hermon_state_t *state, uint_t port, uint_t sleepflag)
14839517SBill.Taylor@Sun.COM {
14849517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
14859517SBill.Taylor@Sun.COM 	int			status;
14869517SBill.Taylor@Sun.COM 
14879517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
14889517SBill.Taylor@Sun.COM 
14899517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "CLOSE_PORT" command */
14909517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0;
14919517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
14929517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= port;
14939517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= CLOSE_PORT;
14949517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
14959517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
14969517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
14979517SBill.Taylor@Sun.COM 	return (status);
14989517SBill.Taylor@Sun.COM }
14999517SBill.Taylor@Sun.COM 
15009517SBill.Taylor@Sun.COM 
15019517SBill.Taylor@Sun.COM /*
15029517SBill.Taylor@Sun.COM  * hermon_mod_stat_cfg_cmd_post()
15039517SBill.Taylor@Sun.COM  *    Context: Can be called only from attach() path
15049517SBill.Taylor@Sun.COM  *
15059517SBill.Taylor@Sun.COM  * This routine was initially implemented to enable SRQ. That's no longer needed
15069517SBill.Taylor@Sun.COM  * in hermon, and the code is conditionally compiled OUT, but left here because
15079517SBill.Taylor@Sun.COM  * there are other static configuration parameters we might one day want to set
15089517SBill.Taylor@Sun.COM  */
15099517SBill.Taylor@Sun.COM #ifdef HERMON_NO_MOD_STAT_CFG
15109517SBill.Taylor@Sun.COM int
hermon_mod_stat_cfg_cmd_post(hermon_state_t * state)15119517SBill.Taylor@Sun.COM hermon_mod_stat_cfg_cmd_post(hermon_state_t *state)
15129517SBill.Taylor@Sun.COM {
15139517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
15149517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
15159517SBill.Taylor@Sun.COM 	hermon_hw_mod_stat_cfg_t	*mod;
15169517SBill.Taylor@Sun.COM 	hermon_hw_msg_in_mod_t	inmod;
15179517SBill.Taylor@Sun.COM 	uint64_t		data;
15189517SBill.Taylor@Sun.COM 	uint_t			size;
15199517SBill.Taylor@Sun.COM 	int			status, i;
15209517SBill.Taylor@Sun.COM 
15219517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
15229517SBill.Taylor@Sun.COM 
15239517SBill.Taylor@Sun.COM 	/*
15249517SBill.Taylor@Sun.COM 	 * "MOD_STAT_CFG" needs an INMBOX parameter, to specify what operations
15259517SBill.Taylor@Sun.COM 	 * to do.  However, at the point in time that we call this command, the
15269517SBill.Taylor@Sun.COM 	 * DDR has not yet been initialized, and all INMBOX'es are located in
15279517SBill.Taylor@Sun.COM 	 * DDR.  Because we want to call MOD_STAT_CFG before QUERY_DEVLIM is
15289517SBill.Taylor@Sun.COM 	 * called, and thus call it before DDR is setup, we simply use an
15299517SBill.Taylor@Sun.COM 	 * OUTMBOX memory location here as our INMBOX parameter.
15309517SBill.Taylor@Sun.COM 	 */
15319517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_OUTMBOX;
15329517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, HERMON_NOSLEEP);
15339517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
15349517SBill.Taylor@Sun.COM 		return (status);
15359517SBill.Taylor@Sun.COM 	}
15369517SBill.Taylor@Sun.COM 
15379517SBill.Taylor@Sun.COM 	/*
15389517SBill.Taylor@Sun.COM 	 * Allocate on the heap our 'mod_stat_cfg' structure.  We want to
15399517SBill.Taylor@Sun.COM 	 * ideally move all of this on to the stack in the future, but this
15409517SBill.Taylor@Sun.COM 	 * works well for now.
15419517SBill.Taylor@Sun.COM 	 */
15429517SBill.Taylor@Sun.COM 	mod = (hermon_hw_mod_stat_cfg_t *)kmem_zalloc(
15439517SBill.Taylor@Sun.COM 	    sizeof (hermon_hw_mod_stat_cfg_t), KM_SLEEP);
15449517SBill.Taylor@Sun.COM 
15459517SBill.Taylor@Sun.COM 	/* Setup "MOD_STAT_CFG" settings */
15469517SBill.Taylor@Sun.COM 	mod->srq_m	= 1;
15479517SBill.Taylor@Sun.COM 	mod->srq	= state->hs_cfg_profile->cp_srq_enable;
15489517SBill.Taylor@Sun.COM 
15499517SBill.Taylor@Sun.COM 	if (mod->srq) {
15509517SBill.Taylor@Sun.COM 		/*  use DEV_LIMS num srq */
15519517SBill.Taylor@Sun.COM 		mod->log_max_srq = state->hs_cfg_profile->cp_log_num_srq;
15529517SBill.Taylor@Sun.COM 	} else {
15539517SBill.Taylor@Sun.COM 		mod->log_max_srq = 0;
15549517SBill.Taylor@Sun.COM 	}
15559517SBill.Taylor@Sun.COM 
15569517SBill.Taylor@Sun.COM 	/* Copy the "MOD_STAT_CFG" command into the "In" mailbox */
15579517SBill.Taylor@Sun.COM 	size = sizeof (hermon_hw_mod_stat_cfg_t);
15589517SBill.Taylor@Sun.COM 	for (i = 0; i < (size >> 3); i++) {
15599517SBill.Taylor@Sun.COM 		data = ((uint64_t *)mod)[i];
15609517SBill.Taylor@Sun.COM 		ddi_put64(mbox_info.mbi_in->mb_acchdl,
15619517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
15629517SBill.Taylor@Sun.COM 	}
15639517SBill.Taylor@Sun.COM 
15649517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
15659517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
15669517SBill.Taylor@Sun.COM 
15679517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "MOD_STAT_CFG" command */
15689517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_out->mb_mapaddr;
15699517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
15709517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 0;
15719517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MOD_STAT_CFG;
15729517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= HERMON_MOD_STAT_CFG_PTR;
15739517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
15749517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
15759517SBill.Taylor@Sun.COM 
15769517SBill.Taylor@Sun.COM 	/* Free "MOD_STAT_CFG" struct */
15779517SBill.Taylor@Sun.COM 	kmem_free(mod, sizeof (hermon_hw_mod_stat_cfg_t));
15789517SBill.Taylor@Sun.COM 
15799517SBill.Taylor@Sun.COM 	/* Free the mailbox */
15809517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
15819517SBill.Taylor@Sun.COM 	return (status);
15829517SBill.Taylor@Sun.COM }
15839517SBill.Taylor@Sun.COM #endif
15849517SBill.Taylor@Sun.COM 
15859517SBill.Taylor@Sun.COM 
15869517SBill.Taylor@Sun.COM /*
15879517SBill.Taylor@Sun.COM  * hermon_map_cmd_post()
1588*12965SWilliam.Taylor@Oracle.COM  *    Context: Can be called only from user or kernel context
15899517SBill.Taylor@Sun.COM  *
15909517SBill.Taylor@Sun.COM  * Generic routine to map FW, ICMA, and ICM.
15919517SBill.Taylor@Sun.COM  */
15929517SBill.Taylor@Sun.COM int
hermon_map_cmd_post(hermon_state_t * state,hermon_dma_info_t * dma,uint16_t opcode,ddi_dma_cookie_t cookie,uint_t ccount)15939517SBill.Taylor@Sun.COM hermon_map_cmd_post(hermon_state_t *state, hermon_dma_info_t *dma,
15949517SBill.Taylor@Sun.COM     uint16_t opcode, ddi_dma_cookie_t cookie, uint_t ccount)
15959517SBill.Taylor@Sun.COM {
15969517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
15979517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
15989517SBill.Taylor@Sun.COM 	hermon_hw_vpm_t		vpm;
15999517SBill.Taylor@Sun.COM 	uint64_t		data;
16009517SBill.Taylor@Sun.COM 	uint64_t		paddr, vaddr;
16019517SBill.Taylor@Sun.COM 	uint_t			size;
16029517SBill.Taylor@Sun.COM 	int			status, i, j, k = 0;
16039517SBill.Taylor@Sun.COM 	int			max_mailbox_size;
16049517SBill.Taylor@Sun.COM 	int			cookie_num_icm_pages;
16059517SBill.Taylor@Sun.COM 	int			num_vpm_entries;
16069517SBill.Taylor@Sun.COM 	int			log2_npages;
16079517SBill.Taylor@Sun.COM 	int			npages;
16089517SBill.Taylor@Sun.COM 
16099517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
16109517SBill.Taylor@Sun.COM 
16119517SBill.Taylor@Sun.COM 	/* Allocate an IN mailbox */
16129517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
16139517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, HERMON_SLEEP);
16149517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
16159517SBill.Taylor@Sun.COM 		return (status);
16169517SBill.Taylor@Sun.COM 	}
16179517SBill.Taylor@Sun.COM 
16189517SBill.Taylor@Sun.COM 	/* Initialize cmd parameters */
16199517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
16209517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= opcode;
16219517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
16229517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
16239517SBill.Taylor@Sun.COM 
16249517SBill.Taylor@Sun.COM 	/*
16259517SBill.Taylor@Sun.COM 	 * Allocate a list of VPM (Virtual Physical Mapping) structures.
16269517SBill.Taylor@Sun.COM 	 * A VPM encodes a power-of-2 number of DMA pages that have been
16279517SBill.Taylor@Sun.COM 	 * allocated and are passed in the dma_info. We need to break up
16289517SBill.Taylor@Sun.COM 	 * the DMA cookies that are in the dma_info into power-of-2 page
16299517SBill.Taylor@Sun.COM 	 * mappings. We also need to keep track of the number of VPMs we
16309517SBill.Taylor@Sun.COM 	 * have total, as it is used as the inmod for this command.
16319517SBill.Taylor@Sun.COM 	 */
16329517SBill.Taylor@Sun.COM 
16339517SBill.Taylor@Sun.COM 	/* Start with the ICM address passed and the first cookie */
16349517SBill.Taylor@Sun.COM 	vaddr  = dma->icmaddr;
16359517SBill.Taylor@Sun.COM 
16369517SBill.Taylor@Sun.COM 	/* Initialize the VPM count and the VPM struct */
16379517SBill.Taylor@Sun.COM 	num_vpm_entries = 0;
16389517SBill.Taylor@Sun.COM 	size = sizeof (hermon_hw_vpm_t);
16399517SBill.Taylor@Sun.COM 	bzero(&vpm, size);
16409517SBill.Taylor@Sun.COM 
16419517SBill.Taylor@Sun.COM 	/*
16429517SBill.Taylor@Sun.COM 	 * Establish a max mailbox size (in VPM entries). If we reach this,
16439517SBill.Taylor@Sun.COM 	 * we must post a MAP command, reinitialzie num_vpm_entries, and
16449517SBill.Taylor@Sun.COM 	 * continue.
16459517SBill.Taylor@Sun.COM 	 */
16469517SBill.Taylor@Sun.COM 	max_mailbox_size = HERMON_MBOX_SIZE / size;
16479517SBill.Taylor@Sun.COM 
16489517SBill.Taylor@Sun.COM 	/*
16499517SBill.Taylor@Sun.COM 	 * First, walk through the DMA cookies and build VPMs from them.
16509517SBill.Taylor@Sun.COM 	 */
16519517SBill.Taylor@Sun.COM 	while (ccount-- > 0) {
16529517SBill.Taylor@Sun.COM 
16539517SBill.Taylor@Sun.COM 		/* Determine the number of ICM pages in this cookie. */
16549517SBill.Taylor@Sun.COM 		cookie_num_icm_pages = cookie.dmac_size / HERMON_PAGESIZE;
16559517SBill.Taylor@Sun.COM 
16569517SBill.Taylor@Sun.COM 		/* Initialize this set of VPM's starting physical address. */
16579517SBill.Taylor@Sun.COM 		paddr = cookie.dmac_laddress;
16589517SBill.Taylor@Sun.COM 
16599517SBill.Taylor@Sun.COM 		/*
16609517SBill.Taylor@Sun.COM 		 * Now build a set of VPMs for this cookie's memory, breaking
16619517SBill.Taylor@Sun.COM 		 * up the cookies into multiple VPMs if necessary to achieve
16629517SBill.Taylor@Sun.COM 		 * the required power-of-2 number of pages per VPM. Once each
16639517SBill.Taylor@Sun.COM 		 * VPM is constructed, write it out to the mailbox memory.
16649517SBill.Taylor@Sun.COM 		 */
16659517SBill.Taylor@Sun.COM 		for (i = cookie_num_icm_pages; i > 0; i -= npages) {
16669517SBill.Taylor@Sun.COM 			log2_npages = highbit(i) - 1;
16679517SBill.Taylor@Sun.COM 			npages	    = (1 << log2_npages);
16689517SBill.Taylor@Sun.COM 			/* Ensure this chunk is aligned on it's own size */
16699517SBill.Taylor@Sun.COM 			while (((npages * HERMON_PAGESIZE - 1) & paddr) != 0) {
16709517SBill.Taylor@Sun.COM 				log2_npages--;
16719517SBill.Taylor@Sun.COM 				npages = (1 << log2_npages);
16729517SBill.Taylor@Sun.COM 			}
16739517SBill.Taylor@Sun.COM 			vpm.log2sz    = log2_npages;
16749517SBill.Taylor@Sun.COM 
16759517SBill.Taylor@Sun.COM 			vpm.paddr_l = (uint32_t)(paddr >> 12);
16769517SBill.Taylor@Sun.COM 			vpm.paddr_h = (uint32_t)(paddr >> 32);
16779517SBill.Taylor@Sun.COM 			/* Increment the paddr for the next VPM */
16789517SBill.Taylor@Sun.COM 			paddr += npages * HERMON_PAGESIZE;
16799517SBill.Taylor@Sun.COM 
16809517SBill.Taylor@Sun.COM 			if (opcode == MAP_ICM) {
16819517SBill.Taylor@Sun.COM 				vpm.vaddr_l = (uint32_t)(vaddr >> 12);
16829517SBill.Taylor@Sun.COM 				vpm.vaddr_h = (uint32_t)(vaddr >> 32);
16839517SBill.Taylor@Sun.COM 				/* Increment the ICM address for the next VPM */
16849517SBill.Taylor@Sun.COM 				vaddr += npages * HERMON_PAGESIZE;
16859517SBill.Taylor@Sun.COM 			}
16869517SBill.Taylor@Sun.COM 
16879517SBill.Taylor@Sun.COM 			/*
16889517SBill.Taylor@Sun.COM 			 * Copy this VPM into the "In" mailbox. Note we're
16899517SBill.Taylor@Sun.COM 			 * using 'k' as the offset from mb_addr for this cmd.
16909517SBill.Taylor@Sun.COM 			 */
16919517SBill.Taylor@Sun.COM 			for (j = 0; j < (size >> 3); j++, k++) {
16929517SBill.Taylor@Sun.COM 				data = ((uint64_t *)(void *)&vpm)[j];
16939517SBill.Taylor@Sun.COM 				ddi_put64(mbox_info.mbi_in->mb_acchdl,
16949517SBill.Taylor@Sun.COM 				    ((uint64_t *)mbox_info.mbi_in->mb_addr + k),
16959517SBill.Taylor@Sun.COM 				    data);
16969517SBill.Taylor@Sun.COM 			}
16979517SBill.Taylor@Sun.COM 
16989517SBill.Taylor@Sun.COM 			/*
16999517SBill.Taylor@Sun.COM 			 * Increment the number of VPM entries and check
17009517SBill.Taylor@Sun.COM 			 * against max mailbox size. If we have reached
17019517SBill.Taylor@Sun.COM 			 * the maximum mailbox size, post the map cmd.
17029517SBill.Taylor@Sun.COM 			 */
17039517SBill.Taylor@Sun.COM 			if (++num_vpm_entries == max_mailbox_size) {
17049517SBill.Taylor@Sun.COM 
17059517SBill.Taylor@Sun.COM 				/* Sync the mailbox for the device to read */
17069517SBill.Taylor@Sun.COM 				hermon_mbox_sync(mbox_info.mbi_in, 0, (size *
17079517SBill.Taylor@Sun.COM 				    num_vpm_entries), DDI_DMA_SYNC_FORDEV);
17089517SBill.Taylor@Sun.COM 
17099517SBill.Taylor@Sun.COM 				/* Setup and post the command */
17109517SBill.Taylor@Sun.COM 				cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
17119517SBill.Taylor@Sun.COM 				cmd.cp_inmod	= num_vpm_entries;
17129517SBill.Taylor@Sun.COM 				status = hermon_cmd_post(state, &cmd);
17139517SBill.Taylor@Sun.COM 				if (status != HERMON_CMD_SUCCESS) {
17149517SBill.Taylor@Sun.COM 					cmn_err(CE_NOTE, "hermon%d: %s cmd "
17159517SBill.Taylor@Sun.COM 					    "failed (0x%x)", state->hs_instance,
17169517SBill.Taylor@Sun.COM 					    opcode == MAP_FA ? "MAP_FA" :
17179517SBill.Taylor@Sun.COM 					    opcode == MAP_ICM ? "MAP_ICM" :
17189517SBill.Taylor@Sun.COM 					    opcode == MAP_ICM_AUX ? "MAP_ICMA" :
17199517SBill.Taylor@Sun.COM 					    "UNKNOWN", status);
17209517SBill.Taylor@Sun.COM 					goto map_fail;
17219517SBill.Taylor@Sun.COM 				}
17229517SBill.Taylor@Sun.COM 
17239517SBill.Taylor@Sun.COM 				/*
17249517SBill.Taylor@Sun.COM 				 * Reinitialize num_vpm_entries, and the
17259517SBill.Taylor@Sun.COM 				 * mb_addr offset
17269517SBill.Taylor@Sun.COM 				 */
17279517SBill.Taylor@Sun.COM 				num_vpm_entries = k = 0;
17289517SBill.Taylor@Sun.COM 			}
17299517SBill.Taylor@Sun.COM 		}
17309517SBill.Taylor@Sun.COM 
17319517SBill.Taylor@Sun.COM 		/* If count remains, move onto the next cookie */
17329517SBill.Taylor@Sun.COM 		if (ccount != 0) {
17339517SBill.Taylor@Sun.COM 			ddi_dma_nextcookie(dma->dma_hdl, &cookie);
17349517SBill.Taylor@Sun.COM 		}
17359517SBill.Taylor@Sun.COM 	}
17369517SBill.Taylor@Sun.COM 
17379517SBill.Taylor@Sun.COM 	if (num_vpm_entries) {
17389517SBill.Taylor@Sun.COM 
17399517SBill.Taylor@Sun.COM 		/* Sync the mailbox for the device to read */
17409517SBill.Taylor@Sun.COM 		hermon_mbox_sync(mbox_info.mbi_in, 0, (size * num_vpm_entries),
17419517SBill.Taylor@Sun.COM 		    DDI_DMA_SYNC_FORDEV);
17429517SBill.Taylor@Sun.COM 
17439517SBill.Taylor@Sun.COM 		/* Setup and post the command */
17449517SBill.Taylor@Sun.COM 		cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
17459517SBill.Taylor@Sun.COM 		cmd.cp_inmod	= num_vpm_entries;
17469517SBill.Taylor@Sun.COM 		status = hermon_cmd_post(state, &cmd);
17479517SBill.Taylor@Sun.COM 		if (status != HERMON_CMD_SUCCESS) {
17489517SBill.Taylor@Sun.COM 			cmn_err(CE_NOTE, "hermon%d: %s cmd "
17499517SBill.Taylor@Sun.COM 			    "failed (0x%x)", state->hs_instance,
17509517SBill.Taylor@Sun.COM 			    opcode == MAP_FA ? "MAP_FA" :
17519517SBill.Taylor@Sun.COM 			    opcode == MAP_ICM ? "MAP_ICM" :
17529517SBill.Taylor@Sun.COM 			    opcode == MAP_ICM_AUX ? "MAP_ICMA" :
17539517SBill.Taylor@Sun.COM 			    "UNKNOWN", status);
17549517SBill.Taylor@Sun.COM 			goto map_fail;
17559517SBill.Taylor@Sun.COM 		}
17569517SBill.Taylor@Sun.COM 	}
17579517SBill.Taylor@Sun.COM 
17589517SBill.Taylor@Sun.COM map_fail:
17599517SBill.Taylor@Sun.COM 	/* Free the mailbox */
17609517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
17619517SBill.Taylor@Sun.COM 	return (status);
17629517SBill.Taylor@Sun.COM }
17639517SBill.Taylor@Sun.COM 
17649517SBill.Taylor@Sun.COM 
17659517SBill.Taylor@Sun.COM /*
17669517SBill.Taylor@Sun.COM  * hermon_unmap_fa_cmd_post()
17679517SBill.Taylor@Sun.COM  *    Context: Can be called only from attach() path
17689517SBill.Taylor@Sun.COM  */
17699517SBill.Taylor@Sun.COM int
hermon_unmap_fa_cmd_post(hermon_state_t * state)17709517SBill.Taylor@Sun.COM hermon_unmap_fa_cmd_post(hermon_state_t *state)
17719517SBill.Taylor@Sun.COM {
17729517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
17739517SBill.Taylor@Sun.COM 	int			status;
17749517SBill.Taylor@Sun.COM 
17759517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
17769517SBill.Taylor@Sun.COM 
17779517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "UNMAP_FA" command */
17789517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0;
17799517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
17809517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 0;
17819517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= UNMAP_FA;
17829517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
17839517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
17849517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
17859517SBill.Taylor@Sun.COM 
17869517SBill.Taylor@Sun.COM 	return (status);
17879517SBill.Taylor@Sun.COM }
17889517SBill.Taylor@Sun.COM 
17899517SBill.Taylor@Sun.COM 
17909517SBill.Taylor@Sun.COM /*
17919517SBill.Taylor@Sun.COM  * hermon_run_fw_cmd_post()
17929517SBill.Taylor@Sun.COM  *    Context: Can be called only from attach() path
17939517SBill.Taylor@Sun.COM  */
17949517SBill.Taylor@Sun.COM int
hermon_run_fw_cmd_post(hermon_state_t * state)17959517SBill.Taylor@Sun.COM hermon_run_fw_cmd_post(hermon_state_t *state)
17969517SBill.Taylor@Sun.COM {
17979517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
17989517SBill.Taylor@Sun.COM 	int			status;
17999517SBill.Taylor@Sun.COM 
18009517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
18019517SBill.Taylor@Sun.COM 
18029517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "RUN_FW" command */
18039517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0;
18049517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
18059517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 0;
18069517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= RUN_FW;
18079517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
18089517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
18099517SBill.Taylor@Sun.COM 
18109517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
18119517SBill.Taylor@Sun.COM #ifdef FMA_TEST
18129517SBill.Taylor@Sun.COM 	if (hermon_test_num == -2) {
18139517SBill.Taylor@Sun.COM 		status = HERMON_CMD_BAD_NVMEM;
181410125SEiji.Ota@Sun.COM 		/*
181510125SEiji.Ota@Sun.COM 		 * No need of an ereport here since this case
181610125SEiji.Ota@Sun.COM 		 * is treated as a degradation later.
181710125SEiji.Ota@Sun.COM 		 */
18189517SBill.Taylor@Sun.COM 		HERMON_FMANOTE(state, HERMON_FMA_BADNVMEM);
18199517SBill.Taylor@Sun.COM 	}
18209517SBill.Taylor@Sun.COM #endif
18219517SBill.Taylor@Sun.COM 	return (status);
18229517SBill.Taylor@Sun.COM }
18239517SBill.Taylor@Sun.COM 
18249517SBill.Taylor@Sun.COM 
18259517SBill.Taylor@Sun.COM /*
18269517SBill.Taylor@Sun.COM  * hermon_set_icm_size_cmd_post()
18279517SBill.Taylor@Sun.COM  *    Context: Can be called only from attach() path
18289517SBill.Taylor@Sun.COM  */
18299517SBill.Taylor@Sun.COM int
hermon_set_icm_size_cmd_post(hermon_state_t * state)18309517SBill.Taylor@Sun.COM hermon_set_icm_size_cmd_post(hermon_state_t *state)
18319517SBill.Taylor@Sun.COM {
18329517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
18339517SBill.Taylor@Sun.COM 	int			status;
18349517SBill.Taylor@Sun.COM 
18359517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
18369517SBill.Taylor@Sun.COM 
18379517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "SET_ICM_SIZE" command */
18389517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= (uint64_t)state->hs_icm_sz;
18399517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
18409517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 0;
18419517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= SET_ICM_SIZE;
18429517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
18439517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
18449517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
18459517SBill.Taylor@Sun.COM 
18469517SBill.Taylor@Sun.COM 	/*
18479517SBill.Taylor@Sun.COM 	 * Aux ICM size in 4K pages returned in output param
18489517SBill.Taylor@Sun.COM 	 * convert it to bytes
18499517SBill.Taylor@Sun.COM 	 */
18509517SBill.Taylor@Sun.COM 	state->hs_icma_sz = (uint64_t)(cmd.cp_outparm << HERMON_PAGESHIFT);
18519517SBill.Taylor@Sun.COM 	return (status);
18529517SBill.Taylor@Sun.COM }
18539517SBill.Taylor@Sun.COM 
18549517SBill.Taylor@Sun.COM 
18559517SBill.Taylor@Sun.COM /*
18569517SBill.Taylor@Sun.COM  * hermon_unmap_icm_aux_cmd_post()
18579517SBill.Taylor@Sun.COM  *    Context: Can be called only from attach() path
18589517SBill.Taylor@Sun.COM  */
18599517SBill.Taylor@Sun.COM int
hermon_unmap_icm_aux_cmd_post(hermon_state_t * state)18609517SBill.Taylor@Sun.COM hermon_unmap_icm_aux_cmd_post(hermon_state_t *state)
18619517SBill.Taylor@Sun.COM {
18629517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
18639517SBill.Taylor@Sun.COM 	int			status;
18649517SBill.Taylor@Sun.COM 
18659517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
18669517SBill.Taylor@Sun.COM 
18679517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "UNMAP_ICM_AUX" command */
18689517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0;
18699517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
18709517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 0;
18719517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= UNMAP_ICM_AUX;
18729517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
18739517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
18749517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
18759517SBill.Taylor@Sun.COM 	return (status);
18769517SBill.Taylor@Sun.COM }
18779517SBill.Taylor@Sun.COM 
18789517SBill.Taylor@Sun.COM 
18799517SBill.Taylor@Sun.COM /*
18809517SBill.Taylor@Sun.COM  * hermon_unmap_icm_cmd_post()
18819517SBill.Taylor@Sun.COM  *    Context: Can be called from base or attach context
18829517SBill.Taylor@Sun.COM  */
18839517SBill.Taylor@Sun.COM int
hermon_unmap_icm_cmd_post(hermon_state_t * state,hermon_dma_info_t * dma_info)18849517SBill.Taylor@Sun.COM hermon_unmap_icm_cmd_post(hermon_state_t *state, hermon_dma_info_t *dma_info)
18859517SBill.Taylor@Sun.COM {
18869517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
18879517SBill.Taylor@Sun.COM 	uint64_t		addr;
18889517SBill.Taylor@Sun.COM 	uint32_t		npages;
18899517SBill.Taylor@Sun.COM 	int			status;
18909517SBill.Taylor@Sun.COM 
18919517SBill.Taylor@Sun.COM 	/*
18929517SBill.Taylor@Sun.COM 	 * Setup and post the Hermon "UNMAP_ICM" command. If a
18939517SBill.Taylor@Sun.COM 	 * hermon_dma_info_t was passed, we want to unmap a set
18949517SBill.Taylor@Sun.COM 	 * of pages. Otherwise, unmap all of ICM.
18959517SBill.Taylor@Sun.COM 	 */
18969517SBill.Taylor@Sun.COM 	if (dma_info != NULL) {
18979517SBill.Taylor@Sun.COM 		addr   = dma_info->icmaddr;
18989517SBill.Taylor@Sun.COM 		npages = dma_info->length / HERMON_PAGESIZE;
18999517SBill.Taylor@Sun.COM 	} else {
19009517SBill.Taylor@Sun.COM 		addr   = 0;
19019517SBill.Taylor@Sun.COM 		npages = state->hs_icm_sz / HERMON_PAGESIZE;
19029517SBill.Taylor@Sun.COM 	}
19039517SBill.Taylor@Sun.COM 
19049517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "UNMAP_ICM" command */
19059517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
19069517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= addr;
19079517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
19089517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= npages;
19099517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= UNMAP_ICM;
19109517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
19119517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
19129517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
19139517SBill.Taylor@Sun.COM 	return (status);
19149517SBill.Taylor@Sun.COM }
19159517SBill.Taylor@Sun.COM 
19169517SBill.Taylor@Sun.COM 
19179517SBill.Taylor@Sun.COM /*
19189517SBill.Taylor@Sun.COM  * hermon_mad_ifc_cmd_post()
19199517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
19209517SBill.Taylor@Sun.COM  */
19219517SBill.Taylor@Sun.COM int
hermon_mad_ifc_cmd_post(hermon_state_t * state,uint_t port,uint_t sleepflag,uint32_t * mad,uint32_t * resp)19229517SBill.Taylor@Sun.COM hermon_mad_ifc_cmd_post(hermon_state_t *state, uint_t port,
19239517SBill.Taylor@Sun.COM     uint_t sleepflag, uint32_t *mad, uint32_t *resp)
19249517SBill.Taylor@Sun.COM {
19259517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
19269517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
19279517SBill.Taylor@Sun.COM 	uint_t			size;
19289517SBill.Taylor@Sun.COM 	int			status;
19299517SBill.Taylor@Sun.COM 
19309517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
19319517SBill.Taylor@Sun.COM 
19329517SBill.Taylor@Sun.COM 	/* Get "In" and "Out" mailboxes for the command */
19339517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX | HERMON_ALLOC_OUTMBOX;
19349517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
19359517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
19369517SBill.Taylor@Sun.COM 		return (status);
19379517SBill.Taylor@Sun.COM 	}
19389517SBill.Taylor@Sun.COM 
19399517SBill.Taylor@Sun.COM 	/* Copy the request MAD into the "In" mailbox */
19409517SBill.Taylor@Sun.COM 	size = HERMON_CMD_MAD_IFC_SIZE;
19419517SBill.Taylor@Sun.COM 	bcopy(mad, mbox_info.mbi_in->mb_addr, size);
19429517SBill.Taylor@Sun.COM 
19439517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
19449517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
19459517SBill.Taylor@Sun.COM 
19469517SBill.Taylor@Sun.COM 	/* Setup the Hermon "MAD_IFC" command */
19479517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
19489517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
19499517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= port;
19509517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MAD_IFC;
19519517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= HERMON_CMD_MKEY_CHECK;  /* Enable MKey checking */
19529517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
19539517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
19549517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
19559517SBill.Taylor@Sun.COM 		goto mad_ifc_fail;
19569517SBill.Taylor@Sun.COM 	}
19579517SBill.Taylor@Sun.COM 
19589517SBill.Taylor@Sun.COM 	/* Sync the mailbox to read the results */
19599517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, 0, size, DDI_DMA_SYNC_FORCPU);
19609517SBill.Taylor@Sun.COM 
19619517SBill.Taylor@Sun.COM 	/* Copy the response MAD into "resp" */
19629517SBill.Taylor@Sun.COM 	bcopy(mbox_info.mbi_out->mb_addr, resp, size);
19639517SBill.Taylor@Sun.COM 
19649517SBill.Taylor@Sun.COM mad_ifc_fail:
19659517SBill.Taylor@Sun.COM 	/* Free the mailbox */
19669517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
19679517SBill.Taylor@Sun.COM 	return (status);
19689517SBill.Taylor@Sun.COM }
19699517SBill.Taylor@Sun.COM 
19709517SBill.Taylor@Sun.COM 
19719517SBill.Taylor@Sun.COM /*
19729517SBill.Taylor@Sun.COM  * hermon_getportinfo_cmd_post()
19739517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
19749517SBill.Taylor@Sun.COM  */
19759517SBill.Taylor@Sun.COM int
hermon_getportinfo_cmd_post(hermon_state_t * state,uint_t port,uint_t sleepflag,sm_portinfo_t * portinfo)19769517SBill.Taylor@Sun.COM hermon_getportinfo_cmd_post(hermon_state_t *state, uint_t port,
19779517SBill.Taylor@Sun.COM     uint_t sleepflag, sm_portinfo_t *portinfo)
19789517SBill.Taylor@Sun.COM {
19799517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
19809517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
19819517SBill.Taylor@Sun.COM 	uint32_t		*mbox;
19829517SBill.Taylor@Sun.COM 	uint_t			size;
19839517SBill.Taylor@Sun.COM 	int			status, i;
19849517SBill.Taylor@Sun.COM 
19859517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
19869517SBill.Taylor@Sun.COM 
19879517SBill.Taylor@Sun.COM 	/* Get "In" and "Out" mailboxes for the command */
19889517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX | HERMON_ALLOC_OUTMBOX;
19899517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
19909517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
19919517SBill.Taylor@Sun.COM 		return (status);
19929517SBill.Taylor@Sun.COM 	}
19939517SBill.Taylor@Sun.COM 
19949517SBill.Taylor@Sun.COM 	/* Build the GetPortInfo request MAD in the "In" mailbox */
19959517SBill.Taylor@Sun.COM 	size = HERMON_CMD_MAD_IFC_SIZE;
19969517SBill.Taylor@Sun.COM 	mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
19979517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], HERMON_CMD_MADHDR0);
19989517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], HERMON_CMD_MADHDR1);
19999517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], HERMON_CMD_MADHDR2);
20009517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], HERMON_CMD_MADHDR3);
20019517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], HERMON_CMD_PORTINFO);
20029517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[5], port);
20039517SBill.Taylor@Sun.COM 	for (i = 6; i < (size >> 2); i++) {
20049517SBill.Taylor@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[i], 0);
20059517SBill.Taylor@Sun.COM 	}
20069517SBill.Taylor@Sun.COM 
20079517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
20089517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
20099517SBill.Taylor@Sun.COM 
20109517SBill.Taylor@Sun.COM 	/* Setup the Hermon "MAD_IFC" command */
20119517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
20129517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
20139517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= port;
20149517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MAD_IFC;
20159517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
20169517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN; /* NO SLEEP */
20179517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
20189517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
20199517SBill.Taylor@Sun.COM 		goto getportinfo_fail;
20209517SBill.Taylor@Sun.COM 	}
20219517SBill.Taylor@Sun.COM 
20229517SBill.Taylor@Sun.COM 	/* Sync the mailbox to read the results */
20239517SBill.Taylor@Sun.COM 	size = sizeof (sm_portinfo_t);
20249517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
20259517SBill.Taylor@Sun.COM 	    size, DDI_DMA_SYNC_FORCPU);
20269517SBill.Taylor@Sun.COM 
20279517SBill.Taylor@Sun.COM 	/*
20289517SBill.Taylor@Sun.COM 	 * Copy GetPortInfo response MAD into "portinfo".  Do any endian
20299517SBill.Taylor@Sun.COM 	 * swapping that may be necessary to flip any of the "portinfo"
20309517SBill.Taylor@Sun.COM 	 * fields
20319517SBill.Taylor@Sun.COM 	 */
20329517SBill.Taylor@Sun.COM 	bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
20339517SBill.Taylor@Sun.COM 	    HERMON_CMD_MADDATA_OFFSET), portinfo, size);
20349891SRajkumar.Sivaprakasam@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*portinfo))
20359517SBill.Taylor@Sun.COM 	HERMON_GETPORTINFO_SWAP(portinfo);
20369517SBill.Taylor@Sun.COM 
20379517SBill.Taylor@Sun.COM getportinfo_fail:
20389517SBill.Taylor@Sun.COM 	/* Free the mailbox */
20399517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
20409517SBill.Taylor@Sun.COM 	return (status);
20419517SBill.Taylor@Sun.COM }
20429517SBill.Taylor@Sun.COM 
20439517SBill.Taylor@Sun.COM /*
204411190SRamaswamy.Tummala@Sun.COM  * hermon_is_ext_port_counters_supported()
204511190SRamaswamy.Tummala@Sun.COM  *
204611190SRamaswamy.Tummala@Sun.COM  * Determine weather extended port counters are supported or not by sending
204711190SRamaswamy.Tummala@Sun.COM  * ClassPortInfo perf mgmt class MAD.
204811190SRamaswamy.Tummala@Sun.COM  */
204911190SRamaswamy.Tummala@Sun.COM int
hermon_is_ext_port_counters_supported(hermon_state_t * state,uint_t port,uint_t sleepflag,int * ext_width_supported)205011190SRamaswamy.Tummala@Sun.COM hermon_is_ext_port_counters_supported(hermon_state_t *state, uint_t port,
205111190SRamaswamy.Tummala@Sun.COM     uint_t sleepflag, int *ext_width_supported)
205211190SRamaswamy.Tummala@Sun.COM {
205311190SRamaswamy.Tummala@Sun.COM 	hermon_mbox_info_t	mbox_info;
205411190SRamaswamy.Tummala@Sun.COM 	hermon_cmd_post_t	cmd;
205511190SRamaswamy.Tummala@Sun.COM 	uint64_t		data;
205611190SRamaswamy.Tummala@Sun.COM 	uint32_t		*mbox;
205711190SRamaswamy.Tummala@Sun.COM 	int			status;
205811190SRamaswamy.Tummala@Sun.COM 
205911190SRamaswamy.Tummala@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
206011190SRamaswamy.Tummala@Sun.COM 
206111190SRamaswamy.Tummala@Sun.COM 	/* Get "In" and "Out" mailboxes for the command */
206211190SRamaswamy.Tummala@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX | HERMON_ALLOC_OUTMBOX;
206311190SRamaswamy.Tummala@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
206411190SRamaswamy.Tummala@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
206511190SRamaswamy.Tummala@Sun.COM 		return (status);
206611190SRamaswamy.Tummala@Sun.COM 	}
206711190SRamaswamy.Tummala@Sun.COM 
206811190SRamaswamy.Tummala@Sun.COM 	/* Build the ClassPortInfo request MAD in the "In" mailbox */
206911190SRamaswamy.Tummala@Sun.COM 	mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
207011190SRamaswamy.Tummala@Sun.COM 
207111190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], HERMON_CMD_PERF_GET);
207211190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], HERMON_CMD_MADHDR1);
207311190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], HERMON_CMD_MADHDR2);
207411190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], HERMON_CMD_MADHDR3);
207511190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4],
207611190SRamaswamy.Tummala@Sun.COM 	    HERMON_CMD_CLASSPORTINFO);
207711190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[5], HERMON_CMD_PERFATTR);
207811190SRamaswamy.Tummala@Sun.COM 
207911190SRamaswamy.Tummala@Sun.COM 	/* Sync the mailbox for the device to read */
208011190SRamaswamy.Tummala@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, HERMON_CMD_MAD_IFC_SIZE,
208111190SRamaswamy.Tummala@Sun.COM 	    DDI_DMA_SYNC_FORDEV);
208211190SRamaswamy.Tummala@Sun.COM 
208311190SRamaswamy.Tummala@Sun.COM 	/* Setup the Hermon "MAD_IFC" command */
208411190SRamaswamy.Tummala@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
208511190SRamaswamy.Tummala@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
208611190SRamaswamy.Tummala@Sun.COM 	cmd.cp_inmod	= port;
208711190SRamaswamy.Tummala@Sun.COM 	cmd.cp_opcode	= MAD_IFC;
208811190SRamaswamy.Tummala@Sun.COM 	/* No MKey and BKey checking */
208911190SRamaswamy.Tummala@Sun.COM 	cmd.cp_opmod	= HERMON_CMD_MKEY_DONTCHECK | HERMON_CMD_BKEY_DONTCHECK;
209011190SRamaswamy.Tummala@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN; /* NO SLEEP */
209111190SRamaswamy.Tummala@Sun.COM 	status = hermon_cmd_post(state, &cmd);
209211190SRamaswamy.Tummala@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
209311190SRamaswamy.Tummala@Sun.COM 		goto fail;
209411190SRamaswamy.Tummala@Sun.COM 	}
209511190SRamaswamy.Tummala@Sun.COM 
209611190SRamaswamy.Tummala@Sun.COM 	/* Sync the mailbox to read the results */
209711190SRamaswamy.Tummala@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, 0, HERMON_CMD_MAD_IFC_SIZE,
209811190SRamaswamy.Tummala@Sun.COM 	    DDI_DMA_SYNC_FORCPU);
209911190SRamaswamy.Tummala@Sun.COM 
210011190SRamaswamy.Tummala@Sun.COM 	/*
210111190SRamaswamy.Tummala@Sun.COM 	 * We can discard the MAD header and the reserved area of the
210211190SRamaswamy.Tummala@Sun.COM 	 * perf mgmt class MAD
210311190SRamaswamy.Tummala@Sun.COM 	 */
210411190SRamaswamy.Tummala@Sun.COM 	data = ddi_get64(mbox_info.mbi_out->mb_acchdl,
210511190SRamaswamy.Tummala@Sun.COM 	    ((uint64_t *)mbox_info.mbi_out->mb_addr + 8));
210611190SRamaswamy.Tummala@Sun.COM 	*ext_width_supported = (data & (HERMON_IS_EXT_WIDTH_SUPPORTED |
210711190SRamaswamy.Tummala@Sun.COM 	    HERMON_IS_EXT_WIDTH_SUPPORTED_NOIETF)) ? 1 : 0;
210811190SRamaswamy.Tummala@Sun.COM 
210911190SRamaswamy.Tummala@Sun.COM fail:
211011190SRamaswamy.Tummala@Sun.COM 	/* Free the mailbox */
211111190SRamaswamy.Tummala@Sun.COM 	hermon_mbox_free(state, &mbox_info);
211211190SRamaswamy.Tummala@Sun.COM 	return (status);
211311190SRamaswamy.Tummala@Sun.COM }
211411190SRamaswamy.Tummala@Sun.COM 
211511190SRamaswamy.Tummala@Sun.COM /*
211611190SRamaswamy.Tummala@Sun.COM  * hermon_getextpefcntr_cmd_post()
211711190SRamaswamy.Tummala@Sun.COM  *
211811190SRamaswamy.Tummala@Sun.COM  * Read the extended performance counters of the specified port and
211911190SRamaswamy.Tummala@Sun.COM  * copy them into perfinfo.
212011190SRamaswamy.Tummala@Sun.COM  */
212111190SRamaswamy.Tummala@Sun.COM int
hermon_getextperfcntr_cmd_post(hermon_state_t * state,uint_t port,uint_t sleepflag,hermon_hw_sm_extperfcntr_t * perfinfo)212211190SRamaswamy.Tummala@Sun.COM hermon_getextperfcntr_cmd_post(hermon_state_t *state, uint_t port,
212311190SRamaswamy.Tummala@Sun.COM     uint_t sleepflag, hermon_hw_sm_extperfcntr_t *perfinfo)
212411190SRamaswamy.Tummala@Sun.COM {
212511190SRamaswamy.Tummala@Sun.COM 	hermon_mbox_info_t	mbox_info;
212611190SRamaswamy.Tummala@Sun.COM 	hermon_cmd_post_t	cmd;
212711190SRamaswamy.Tummala@Sun.COM 	uint64_t		data;
212811190SRamaswamy.Tummala@Sun.COM 	uint32_t		*mbox;
212911190SRamaswamy.Tummala@Sun.COM 	int			status, i;
213011190SRamaswamy.Tummala@Sun.COM 
213111190SRamaswamy.Tummala@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
213211190SRamaswamy.Tummala@Sun.COM 
213311190SRamaswamy.Tummala@Sun.COM 	/* Get "In" and "Out" mailboxes for the command */
213411190SRamaswamy.Tummala@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX | HERMON_ALLOC_OUTMBOX;
213511190SRamaswamy.Tummala@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
213611190SRamaswamy.Tummala@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
213711190SRamaswamy.Tummala@Sun.COM 		return (status);
213811190SRamaswamy.Tummala@Sun.COM 	}
213911190SRamaswamy.Tummala@Sun.COM 
214011190SRamaswamy.Tummala@Sun.COM 	/* Build PortCountersExtended request MAD in the "In" mailbox */
214111190SRamaswamy.Tummala@Sun.COM 	mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
214211190SRamaswamy.Tummala@Sun.COM 
214311190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], HERMON_CMD_PERF_GET);
214411190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], HERMON_CMD_MADHDR1);
214511190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], HERMON_CMD_MADHDR2);
214611190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], HERMON_CMD_MADHDR3);
214711190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4],
214811190SRamaswamy.Tummala@Sun.COM 	    HERMON_CMD_EXTPERFCNTRS);
214911190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[5], HERMON_CMD_PERFATTR);
215011190SRamaswamy.Tummala@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[16], (port << 16));
215111190SRamaswamy.Tummala@Sun.COM 
215211190SRamaswamy.Tummala@Sun.COM 	/* Sync the mailbox for the device to read */
215311190SRamaswamy.Tummala@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, HERMON_CMD_MAD_IFC_SIZE,
215411190SRamaswamy.Tummala@Sun.COM 	    DDI_DMA_SYNC_FORDEV);
215511190SRamaswamy.Tummala@Sun.COM 
215611190SRamaswamy.Tummala@Sun.COM 	/* Setup the Hermon "MAD_IFC" command */
215711190SRamaswamy.Tummala@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
215811190SRamaswamy.Tummala@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
215911190SRamaswamy.Tummala@Sun.COM 	cmd.cp_inmod	= port;
216011190SRamaswamy.Tummala@Sun.COM 	cmd.cp_opcode	= MAD_IFC;
216111190SRamaswamy.Tummala@Sun.COM 	/* No MKey and BKey checking */
216211190SRamaswamy.Tummala@Sun.COM 	cmd.cp_opmod	= HERMON_CMD_MKEY_DONTCHECK | HERMON_CMD_BKEY_DONTCHECK;
216311190SRamaswamy.Tummala@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN; /* NO SLEEP */
216411190SRamaswamy.Tummala@Sun.COM 	status = hermon_cmd_post(state, &cmd);
216511190SRamaswamy.Tummala@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
216611190SRamaswamy.Tummala@Sun.COM 		goto fail;
216711190SRamaswamy.Tummala@Sun.COM 	}
216811190SRamaswamy.Tummala@Sun.COM 
216911190SRamaswamy.Tummala@Sun.COM 	/* Sync the mailbox to read the results */
217011190SRamaswamy.Tummala@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, 0, HERMON_CMD_MAD_IFC_SIZE,
217111190SRamaswamy.Tummala@Sun.COM 	    DDI_DMA_SYNC_FORCPU);
217211190SRamaswamy.Tummala@Sun.COM 
217311190SRamaswamy.Tummala@Sun.COM 	/*
217411190SRamaswamy.Tummala@Sun.COM 	 * Copy Perfcounters into "perfinfo". We can discard the MAD
217511190SRamaswamy.Tummala@Sun.COM 	 * header and the reserved area of the perf mgmt class MAD.
217611190SRamaswamy.Tummala@Sun.COM 	 */
217711190SRamaswamy.Tummala@Sun.COM 	for (i = 0; i < (sizeof (hermon_hw_sm_extperfcntr_t) >> 3); i++) {
217811190SRamaswamy.Tummala@Sun.COM 		data = ddi_get64(mbox_info.mbi_out->mb_acchdl,
217911190SRamaswamy.Tummala@Sun.COM 		    ((uint64_t *)mbox_info.mbi_out->mb_addr + i + 8));
218011190SRamaswamy.Tummala@Sun.COM 		((uint64_t *)(void *)perfinfo)[i] = data;
218111190SRamaswamy.Tummala@Sun.COM 	}
218211190SRamaswamy.Tummala@Sun.COM 
218311190SRamaswamy.Tummala@Sun.COM fail:
218411190SRamaswamy.Tummala@Sun.COM 	/* Free the mailbox */
218511190SRamaswamy.Tummala@Sun.COM 	hermon_mbox_free(state, &mbox_info);
218611190SRamaswamy.Tummala@Sun.COM 	return (status);
218711190SRamaswamy.Tummala@Sun.COM }
218811190SRamaswamy.Tummala@Sun.COM 
218911190SRamaswamy.Tummala@Sun.COM /*
21909517SBill.Taylor@Sun.COM  * hermon_getpefcntr_cmd_post()
21919517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
21929879SRamaswamy.Tummala@Sun.COM  *
21939879SRamaswamy.Tummala@Sun.COM  * If reset is zero, read the performance counters of the specified port and
21949879SRamaswamy.Tummala@Sun.COM  * copy them into perfinfo.
21959879SRamaswamy.Tummala@Sun.COM  * If reset is non-zero reset the performance counters of the specified port.
21969517SBill.Taylor@Sun.COM  */
21979517SBill.Taylor@Sun.COM int
hermon_getperfcntr_cmd_post(hermon_state_t * state,uint_t port,uint_t sleepflag,hermon_hw_sm_perfcntr_t * perfinfo,int reset)21989517SBill.Taylor@Sun.COM hermon_getperfcntr_cmd_post(hermon_state_t *state, uint_t port,
21999879SRamaswamy.Tummala@Sun.COM     uint_t sleepflag, hermon_hw_sm_perfcntr_t *perfinfo, int reset)
22009517SBill.Taylor@Sun.COM {
22019517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
22029517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
22039517SBill.Taylor@Sun.COM 	uint64_t		data;
22049517SBill.Taylor@Sun.COM 	uint32_t		*mbox;
22059517SBill.Taylor@Sun.COM 	uint_t			size;
22069517SBill.Taylor@Sun.COM 	int			status, i;
22079517SBill.Taylor@Sun.COM 
22089517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
22099517SBill.Taylor@Sun.COM 
22109517SBill.Taylor@Sun.COM 	/* Get "In" and "Out" mailboxes for the command */
22119517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX | HERMON_ALLOC_OUTMBOX;
22129517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
22139517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
22149517SBill.Taylor@Sun.COM 		return (status);
22159517SBill.Taylor@Sun.COM 	}
22169517SBill.Taylor@Sun.COM 
22179517SBill.Taylor@Sun.COM 	/* Build the GetPortInfo request MAD in the "In" mailbox */
22189517SBill.Taylor@Sun.COM 	size = HERMON_CMD_MAD_IFC_SIZE;
22199517SBill.Taylor@Sun.COM 	mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
22209879SRamaswamy.Tummala@Sun.COM 
22219879SRamaswamy.Tummala@Sun.COM 	if (reset) {
22229879SRamaswamy.Tummala@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0],
22239879SRamaswamy.Tummala@Sun.COM 		    HERMON_CMD_PERF_SET);
22249879SRamaswamy.Tummala@Sun.COM 	} else {
22259879SRamaswamy.Tummala@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0],
22269879SRamaswamy.Tummala@Sun.COM 		    HERMON_CMD_PERF_GET);
22279879SRamaswamy.Tummala@Sun.COM 	}
22289517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], HERMON_CMD_MADHDR1);
22299517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], HERMON_CMD_MADHDR2);
22309517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], HERMON_CMD_MADHDR3);
22319517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], HERMON_CMD_PERFCNTRS);
22329517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[5], HERMON_CMD_PERFATTR);
22339879SRamaswamy.Tummala@Sun.COM 
22349879SRamaswamy.Tummala@Sun.COM 	if (reset) {
22359879SRamaswamy.Tummala@Sun.COM 		/* reset counters for XmitData, RcvData, XmitPkts, RcvPkts */
22369879SRamaswamy.Tummala@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[16],
22379879SRamaswamy.Tummala@Sun.COM 		    ((port << 16) | 0xf000));
22389879SRamaswamy.Tummala@Sun.COM 
22399879SRamaswamy.Tummala@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[22], 0);
22409879SRamaswamy.Tummala@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[23], 0);
22419879SRamaswamy.Tummala@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[24], 0);
22429879SRamaswamy.Tummala@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[25], 0);
22439879SRamaswamy.Tummala@Sun.COM 	} else
22449879SRamaswamy.Tummala@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[16], (port << 16));
22459517SBill.Taylor@Sun.COM 
22469517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
22479517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
22489517SBill.Taylor@Sun.COM 
22499517SBill.Taylor@Sun.COM 	/* Setup the Hermon "MAD_IFC" command */
22509517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
22519517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
22529517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= port;
22539517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MAD_IFC;
225411190SRamaswamy.Tummala@Sun.COM 	/* No MKey and BKey checking */
225511190SRamaswamy.Tummala@Sun.COM 	cmd.cp_opmod	= HERMON_CMD_MKEY_DONTCHECK | HERMON_CMD_BKEY_DONTCHECK;
22569517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN; /* NO SLEEP */
22579517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
22589517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
22599517SBill.Taylor@Sun.COM 		goto getperfinfo_fail;
22609517SBill.Taylor@Sun.COM 	}
22619517SBill.Taylor@Sun.COM 
22629517SBill.Taylor@Sun.COM 	/* Sync the mailbox to read the results */
22639517SBill.Taylor@Sun.COM 	size = HERMON_CMD_MAD_IFC_SIZE;
22649517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, 0, size, DDI_DMA_SYNC_FORCPU);
22659517SBill.Taylor@Sun.COM 
22669879SRamaswamy.Tummala@Sun.COM 	if (reset == 0) {
22679879SRamaswamy.Tummala@Sun.COM 		size = sizeof (hermon_hw_sm_perfcntr_t); /* for the copy */
22689879SRamaswamy.Tummala@Sun.COM 		/*
22699879SRamaswamy.Tummala@Sun.COM 		 * Copy Perfcounters into "perfinfo".  We can discard the MAD
22709879SRamaswamy.Tummala@Sun.COM 		 * header and the 8 Quadword reserved area of the PERM mgmt
22719879SRamaswamy.Tummala@Sun.COM 		 * class MAD
22729879SRamaswamy.Tummala@Sun.COM 		 */
22739879SRamaswamy.Tummala@Sun.COM 
22749879SRamaswamy.Tummala@Sun.COM 		for (i = 0; i < size >> 3; i++) {
22759879SRamaswamy.Tummala@Sun.COM 			data = ddi_get64(mbox_info.mbi_out->mb_acchdl,
22769879SRamaswamy.Tummala@Sun.COM 			    ((uint64_t *)mbox_info.mbi_out->mb_addr + i + 8));
22779879SRamaswamy.Tummala@Sun.COM 			((uint64_t *)(void *)perfinfo)[i] = data;
22789879SRamaswamy.Tummala@Sun.COM 		}
22799517SBill.Taylor@Sun.COM 	}
22809517SBill.Taylor@Sun.COM 
22819517SBill.Taylor@Sun.COM getperfinfo_fail:
22829517SBill.Taylor@Sun.COM 	/* Free the mailbox */
22839517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
22849517SBill.Taylor@Sun.COM 	return (status);
22859517SBill.Taylor@Sun.COM }
22869517SBill.Taylor@Sun.COM 
22879517SBill.Taylor@Sun.COM 
22889517SBill.Taylor@Sun.COM 
22899517SBill.Taylor@Sun.COM /*
22909517SBill.Taylor@Sun.COM  * hermon_getnodeinfo_cmd_post()
22919517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
22929517SBill.Taylor@Sun.COM  *    (Currently called only from attach() and detach() path contexts)
22939517SBill.Taylor@Sun.COM  */
22949517SBill.Taylor@Sun.COM int
hermon_getnodeinfo_cmd_post(hermon_state_t * state,uint_t sleepflag,sm_nodeinfo_t * nodeinfo)22959517SBill.Taylor@Sun.COM hermon_getnodeinfo_cmd_post(hermon_state_t *state, uint_t sleepflag,
22969517SBill.Taylor@Sun.COM     sm_nodeinfo_t *nodeinfo)
22979517SBill.Taylor@Sun.COM {
22989517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
22999517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
23009517SBill.Taylor@Sun.COM 	uint32_t		*mbox;
23019517SBill.Taylor@Sun.COM 	uint_t			size;
23029517SBill.Taylor@Sun.COM 	int			status, i;
23039517SBill.Taylor@Sun.COM 
23049517SBill.Taylor@Sun.COM 	/* Make sure we are called with the correct flag */
23059517SBill.Taylor@Sun.COM 	ASSERT(sleepflag == HERMON_CMD_NOSLEEP_SPIN);
23069517SBill.Taylor@Sun.COM 
23079517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
23089517SBill.Taylor@Sun.COM 
23099517SBill.Taylor@Sun.COM 	/* Get "In" and "Out" mailboxes for the command */
23109517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX | HERMON_ALLOC_OUTMBOX;
23119517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
23129517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
23139517SBill.Taylor@Sun.COM 		return (status);
23149517SBill.Taylor@Sun.COM 	}
23159517SBill.Taylor@Sun.COM 
23169517SBill.Taylor@Sun.COM 	/* Build the GetNodeInfo request MAD into the "In" mailbox */
23179517SBill.Taylor@Sun.COM 	size = HERMON_CMD_MAD_IFC_SIZE;
23189517SBill.Taylor@Sun.COM 	mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
23199517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], HERMON_CMD_MADHDR0);
23209517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], HERMON_CMD_MADHDR1);
23219517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], HERMON_CMD_MADHDR2);
23229517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], HERMON_CMD_MADHDR3);
23239517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], HERMON_CMD_NODEINFO);
23249517SBill.Taylor@Sun.COM 	for (i = 5; i < (size >> 2); i++) {
23259517SBill.Taylor@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[i], 0);
23269517SBill.Taylor@Sun.COM 	}
23279517SBill.Taylor@Sun.COM 
23289517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
23299517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
23309517SBill.Taylor@Sun.COM 
23319517SBill.Taylor@Sun.COM 	/* Setup the Hermon "MAD_IFC" command */
23329517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
23339517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
23349517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 1;  /* Get NodeInfo from port #1 */
23359517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MAD_IFC;
23369517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
23379517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
23389517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
23399517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
23409517SBill.Taylor@Sun.COM 		goto getnodeinfo_fail;
23419517SBill.Taylor@Sun.COM 	}
23429517SBill.Taylor@Sun.COM 
23439517SBill.Taylor@Sun.COM 	/* Sync the mailbox to read the results */
23449517SBill.Taylor@Sun.COM 	size = sizeof (sm_nodeinfo_t);
23459517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
23469517SBill.Taylor@Sun.COM 	    size, DDI_DMA_SYNC_FORCPU);
23479517SBill.Taylor@Sun.COM 
23489517SBill.Taylor@Sun.COM 	/*
23499517SBill.Taylor@Sun.COM 	 * Copy GetNodeInfo response MAD into "nodeinfo".  Do any endian
23509517SBill.Taylor@Sun.COM 	 * swapping that may be necessary to flip any of the "nodeinfo"
23519517SBill.Taylor@Sun.COM 	 * fields
23529517SBill.Taylor@Sun.COM 	 */
23539517SBill.Taylor@Sun.COM 	bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
23549517SBill.Taylor@Sun.COM 	    HERMON_CMD_MADDATA_OFFSET), nodeinfo, size);
23559891SRajkumar.Sivaprakasam@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*nodeinfo))
23569517SBill.Taylor@Sun.COM 	HERMON_GETNODEINFO_SWAP(nodeinfo);
23579517SBill.Taylor@Sun.COM 
23589517SBill.Taylor@Sun.COM getnodeinfo_fail:
23599517SBill.Taylor@Sun.COM 	/* Free the mailbox */
23609517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
23619517SBill.Taylor@Sun.COM 	return (status);
23629517SBill.Taylor@Sun.COM }
23639517SBill.Taylor@Sun.COM 
23649517SBill.Taylor@Sun.COM 
23659517SBill.Taylor@Sun.COM /*
23669517SBill.Taylor@Sun.COM  * hermon_getnodedesc_cmd_post()
23679517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
23689517SBill.Taylor@Sun.COM  *    (Currently called only from attach() and detach() path contexts)
23699517SBill.Taylor@Sun.COM  */
23709517SBill.Taylor@Sun.COM int
hermon_getnodedesc_cmd_post(hermon_state_t * state,uint_t sleepflag,sm_nodedesc_t * nodedesc)23719517SBill.Taylor@Sun.COM hermon_getnodedesc_cmd_post(hermon_state_t *state, uint_t sleepflag,
23729517SBill.Taylor@Sun.COM     sm_nodedesc_t *nodedesc)
23739517SBill.Taylor@Sun.COM {
23749517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
23759517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
23769517SBill.Taylor@Sun.COM 	uint32_t		*mbox;
23779517SBill.Taylor@Sun.COM 	uint_t			size;
23789517SBill.Taylor@Sun.COM 	int			status, i;
23799517SBill.Taylor@Sun.COM 
23809517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
23819517SBill.Taylor@Sun.COM 
23829517SBill.Taylor@Sun.COM 	/* Get "In" and "Out" mailboxes for the command */
23839517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX | HERMON_ALLOC_OUTMBOX;
23849517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
23859517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
23869517SBill.Taylor@Sun.COM 		return (status);
23879517SBill.Taylor@Sun.COM 	}
23889517SBill.Taylor@Sun.COM 
23899517SBill.Taylor@Sun.COM 	/* Build the GetNodeDesc request MAD into the "In" mailbox */
23909517SBill.Taylor@Sun.COM 	size = HERMON_CMD_MAD_IFC_SIZE;
23919517SBill.Taylor@Sun.COM 	mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
23929517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], HERMON_CMD_MADHDR0);
23939517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], HERMON_CMD_MADHDR1);
23949517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], HERMON_CMD_MADHDR2);
23959517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], HERMON_CMD_MADHDR3);
23969517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], HERMON_CMD_NODEDESC);
23979517SBill.Taylor@Sun.COM 	for (i = 5; i < (size >> 2); i++) {
23989517SBill.Taylor@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[i], 0);
23999517SBill.Taylor@Sun.COM 	}
24009517SBill.Taylor@Sun.COM 
24019517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
24029517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
24039517SBill.Taylor@Sun.COM 
24049517SBill.Taylor@Sun.COM 	/* Setup the Hermon "MAD_IFC" command */
24059517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
24069517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
24079517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 1;  /* Get NodeDesc from port #1 */
24089517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MAD_IFC;
24099517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
24109517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
24119517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
24129517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
24139517SBill.Taylor@Sun.COM 		goto getnodedesc_fail;
24149517SBill.Taylor@Sun.COM 	}
24159517SBill.Taylor@Sun.COM 
24169517SBill.Taylor@Sun.COM 	/* Sync the mailbox to read the results */
24179517SBill.Taylor@Sun.COM 	size = sizeof (sm_nodedesc_t);
24189517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
24199517SBill.Taylor@Sun.COM 	    size, DDI_DMA_SYNC_FORCPU);
24209517SBill.Taylor@Sun.COM 
24219517SBill.Taylor@Sun.COM 	/* Copy GetNodeDesc response MAD into "nodedesc" */
24229517SBill.Taylor@Sun.COM 	bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
24239517SBill.Taylor@Sun.COM 	    HERMON_CMD_MADDATA_OFFSET), nodedesc, size);
24249517SBill.Taylor@Sun.COM 
24259517SBill.Taylor@Sun.COM getnodedesc_fail:
24269517SBill.Taylor@Sun.COM 	/* Free the mailbox */
24279517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
24289517SBill.Taylor@Sun.COM 	return (status);
24299517SBill.Taylor@Sun.COM }
24309517SBill.Taylor@Sun.COM 
24319517SBill.Taylor@Sun.COM 
24329517SBill.Taylor@Sun.COM /*
24339517SBill.Taylor@Sun.COM  * hermon_getguidinfo_cmd_post()
24349517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
24359517SBill.Taylor@Sun.COM  */
24369517SBill.Taylor@Sun.COM int
hermon_getguidinfo_cmd_post(hermon_state_t * state,uint_t port,uint_t guidblock,uint_t sleepflag,sm_guidinfo_t * guidinfo)24379517SBill.Taylor@Sun.COM hermon_getguidinfo_cmd_post(hermon_state_t *state, uint_t port,
24389517SBill.Taylor@Sun.COM     uint_t guidblock, uint_t sleepflag, sm_guidinfo_t *guidinfo)
24399517SBill.Taylor@Sun.COM {
24409517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
24419517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
24429517SBill.Taylor@Sun.COM 	uint32_t		*mbox;
24439517SBill.Taylor@Sun.COM 	uint_t			size;
24449517SBill.Taylor@Sun.COM 	int			status, i;
24459517SBill.Taylor@Sun.COM 
24469517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
24479517SBill.Taylor@Sun.COM 
24489517SBill.Taylor@Sun.COM 	/* Get "In" and "Out" mailboxes for the command */
24499517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX | HERMON_ALLOC_OUTMBOX;
24509517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
24519517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
24529517SBill.Taylor@Sun.COM 		return (status);
24539517SBill.Taylor@Sun.COM 	}
24549517SBill.Taylor@Sun.COM 
24559517SBill.Taylor@Sun.COM 	/* Build the GetGUIDInfo request MAD into the "In" mailbox */
24569517SBill.Taylor@Sun.COM 	size = HERMON_CMD_MAD_IFC_SIZE;
24579517SBill.Taylor@Sun.COM 	mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
24589517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], HERMON_CMD_MADHDR0);
24599517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], HERMON_CMD_MADHDR1);
24609517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], HERMON_CMD_MADHDR2);
24619517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], HERMON_CMD_MADHDR3);
24629517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], HERMON_CMD_GUIDINFO);
24639517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[5], guidblock);
24649517SBill.Taylor@Sun.COM 	for (i = 6; i < (size >> 2); i++) {
24659517SBill.Taylor@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[i], 0);
24669517SBill.Taylor@Sun.COM 	}
24679517SBill.Taylor@Sun.COM 
24689517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
24699517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
24709517SBill.Taylor@Sun.COM 
24719517SBill.Taylor@Sun.COM 	/* Setup the Hermon "MAD_IFC" command */
24729517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
24739517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
24749517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= port;
24759517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MAD_IFC;
24769517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
24779517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
24789517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
24799517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
24809517SBill.Taylor@Sun.COM 		goto getguidinfo_fail;
24819517SBill.Taylor@Sun.COM 	}
24829517SBill.Taylor@Sun.COM 
24839517SBill.Taylor@Sun.COM 	/* Sync the mailbox to read the results */
24849517SBill.Taylor@Sun.COM 	size = sizeof (sm_guidinfo_t);
24859517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
24869517SBill.Taylor@Sun.COM 	    size, DDI_DMA_SYNC_FORCPU);
24879517SBill.Taylor@Sun.COM 
24889517SBill.Taylor@Sun.COM 	/*
24899517SBill.Taylor@Sun.COM 	 * Copy GetGUIDInfo response MAD into "guidinfo".  Do any endian
24909517SBill.Taylor@Sun.COM 	 * swapping that may be necessary to flip the "guidinfo" fields
24919517SBill.Taylor@Sun.COM 	 */
24929517SBill.Taylor@Sun.COM 	bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
24939517SBill.Taylor@Sun.COM 	    HERMON_CMD_MADDATA_OFFSET), guidinfo, size);
24949891SRajkumar.Sivaprakasam@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*guidinfo))
24959517SBill.Taylor@Sun.COM 	HERMON_GETGUIDINFO_SWAP(guidinfo);
24969517SBill.Taylor@Sun.COM 
24979517SBill.Taylor@Sun.COM getguidinfo_fail:
24989517SBill.Taylor@Sun.COM 	/* Free the mailbox */
24999517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
25009517SBill.Taylor@Sun.COM 	return (status);
25019517SBill.Taylor@Sun.COM }
25029517SBill.Taylor@Sun.COM 
25039517SBill.Taylor@Sun.COM 
25049517SBill.Taylor@Sun.COM /*
25059517SBill.Taylor@Sun.COM  * hermon_getpkeytable_cmd_post()
25069517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
25079517SBill.Taylor@Sun.COM  */
25089517SBill.Taylor@Sun.COM int
hermon_getpkeytable_cmd_post(hermon_state_t * state,uint_t port,uint_t pkeyblock,uint_t sleepflag,sm_pkey_table_t * pkeytable)25099517SBill.Taylor@Sun.COM hermon_getpkeytable_cmd_post(hermon_state_t *state, uint_t port,
25109517SBill.Taylor@Sun.COM     uint_t pkeyblock, uint_t sleepflag, sm_pkey_table_t *pkeytable)
25119517SBill.Taylor@Sun.COM {
25129517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
25139517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
25149517SBill.Taylor@Sun.COM 	uint32_t		*mbox;
25159517SBill.Taylor@Sun.COM 	uint_t			size;
25169517SBill.Taylor@Sun.COM 	int			status, i;
25179517SBill.Taylor@Sun.COM 
25189517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
25199517SBill.Taylor@Sun.COM 
25209517SBill.Taylor@Sun.COM 	/* Get "In" and "Out" mailboxes for the command */
25219517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX | HERMON_ALLOC_OUTMBOX;
25229517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
25239517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
25249517SBill.Taylor@Sun.COM 		return (status);
25259517SBill.Taylor@Sun.COM 	}
25269517SBill.Taylor@Sun.COM 
25279517SBill.Taylor@Sun.COM 	/* Build the GetPkeyTable request MAD into the "In" mailbox */
25289517SBill.Taylor@Sun.COM 	size = HERMON_CMD_MAD_IFC_SIZE;
25299517SBill.Taylor@Sun.COM 	mbox = (uint32_t *)mbox_info.mbi_in->mb_addr;
25309517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[0], HERMON_CMD_MADHDR0);
25319517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[1], HERMON_CMD_MADHDR1);
25329517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[2], HERMON_CMD_MADHDR2);
25339517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[3], HERMON_CMD_MADHDR3);
25349517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[4], HERMON_CMD_PKEYTBLE);
25359517SBill.Taylor@Sun.COM 	ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[5], pkeyblock);
25369517SBill.Taylor@Sun.COM 	for (i = 6; i < (size >> 2); i++) {
25379517SBill.Taylor@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl, &mbox[i], 0);
25389517SBill.Taylor@Sun.COM 	}
25399517SBill.Taylor@Sun.COM 
25409517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
25419517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
25429517SBill.Taylor@Sun.COM 
25439517SBill.Taylor@Sun.COM 	/* Setup the Hermon "MAD_IFC" command */
25449517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
25459517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
25469517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= port;
25479517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MAD_IFC;
25489517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= HERMON_CMD_MKEY_DONTCHECK;  /* No MKey checking */
25499517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
25509517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
25519517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
25529517SBill.Taylor@Sun.COM 		goto getpkeytable_fail;
25539517SBill.Taylor@Sun.COM 	}
25549517SBill.Taylor@Sun.COM 
25559517SBill.Taylor@Sun.COM 	/* Sync the mailbox to read the results */
25569517SBill.Taylor@Sun.COM 	size = sizeof (sm_pkey_table_t);
25579517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, HERMON_CMD_MADDATA_OFFSET,
25589517SBill.Taylor@Sun.COM 	    size, DDI_DMA_SYNC_FORCPU);
25599517SBill.Taylor@Sun.COM 
25609517SBill.Taylor@Sun.COM 	/*
25619517SBill.Taylor@Sun.COM 	 * Copy GetPKeyTable response MAD into "pkeytable".  Do any endian
25629517SBill.Taylor@Sun.COM 	 * swapping that may be necessary to flip the "pkeytable" fields
25639517SBill.Taylor@Sun.COM 	 */
25649517SBill.Taylor@Sun.COM 	bcopy((void *)((uintptr_t)mbox_info.mbi_out->mb_addr +
25659517SBill.Taylor@Sun.COM 	    HERMON_CMD_MADDATA_OFFSET), pkeytable, size);
25669891SRajkumar.Sivaprakasam@Sun.COM 	_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*pkeytable))
25679517SBill.Taylor@Sun.COM 	HERMON_GETPKEYTABLE_SWAP(pkeytable);
25689517SBill.Taylor@Sun.COM 
25699517SBill.Taylor@Sun.COM getpkeytable_fail:
25709517SBill.Taylor@Sun.COM 	/* Free the mailbox */
25719517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
25729517SBill.Taylor@Sun.COM 	return (status);
25739517SBill.Taylor@Sun.COM }
25749517SBill.Taylor@Sun.COM 
25759517SBill.Taylor@Sun.COM 
25769517SBill.Taylor@Sun.COM /*
25779517SBill.Taylor@Sun.COM  * hermon_write_mtt_cmd_post()
25789517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
25799517SBill.Taylor@Sun.COM  */
25809517SBill.Taylor@Sun.COM int
hermon_write_mtt_cmd_post(hermon_state_t * state,hermon_rsrc_t * mtt,uint64_t start_addr,uint_t nummtt,uint_t sleepflag)25819517SBill.Taylor@Sun.COM hermon_write_mtt_cmd_post(hermon_state_t *state, hermon_rsrc_t *mtt,
25829517SBill.Taylor@Sun.COM     uint64_t start_addr, uint_t nummtt, uint_t sleepflag)
25839517SBill.Taylor@Sun.COM {
25849517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
25859517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
25869517SBill.Taylor@Sun.COM 	uint64_t		data;
25879517SBill.Taylor@Sun.COM 	uint_t			size;
25889517SBill.Taylor@Sun.COM 	int			status;
25899517SBill.Taylor@Sun.COM 	int			i;
25909517SBill.Taylor@Sun.COM 
25919517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
25929517SBill.Taylor@Sun.COM 
25939517SBill.Taylor@Sun.COM 	/* Get an "In" mailbox for the command */
25949517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
25959517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
25969517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
25979517SBill.Taylor@Sun.COM 		return (status);
25989517SBill.Taylor@Sun.COM 	}
25999517SBill.Taylor@Sun.COM 
26009517SBill.Taylor@Sun.COM 	/*
26019517SBill.Taylor@Sun.COM 	 * The WRITE_MTT command input parameter contains the 64-bit addr of
26029517SBill.Taylor@Sun.COM 	 * the first target MTT, followed by 64 bits reserved, followed by an
26039517SBill.Taylor@Sun.COM 	 * array of MTT entries.
26049517SBill.Taylor@Sun.COM 	 *
26059517SBill.Taylor@Sun.COM 	 */
26069517SBill.Taylor@Sun.COM 	ddi_put64(mbox_info.mbi_in->mb_acchdl,
26079517SBill.Taylor@Sun.COM 	    ((uint64_t *)mbox_info.mbi_in->mb_addr),
26089517SBill.Taylor@Sun.COM 	    start_addr);
26099517SBill.Taylor@Sun.COM 
26109517SBill.Taylor@Sun.COM 	ddi_put64(mbox_info.mbi_in->mb_acchdl,
26119517SBill.Taylor@Sun.COM 	    ((uint64_t *)mbox_info.mbi_in->mb_addr + 1), 0x0);
26129517SBill.Taylor@Sun.COM 
26139517SBill.Taylor@Sun.COM 	for (i = 0; i < nummtt; i++) {
26149517SBill.Taylor@Sun.COM 		data = ((uint64_t *)mtt->hr_addr)[i];
26159517SBill.Taylor@Sun.COM 		ddi_put64(mbox_info.mbi_in->mb_acchdl,
26169517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_in->mb_addr + i + 2), data);
26179517SBill.Taylor@Sun.COM 	}
26189517SBill.Taylor@Sun.COM 
26199517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
26209517SBill.Taylor@Sun.COM 	size = (nummtt << HERMON_MTT_SIZE_SHIFT) + HERMON_CMD_WRITEMTT_RSVD_SZ;
26219517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
26229517SBill.Taylor@Sun.COM 
26239517SBill.Taylor@Sun.COM 	/* Setup and post Hermon "WRITE_MTT" command */
26249517SBill.Taylor@Sun.COM 	cmd.cp_inparm   = mbox_info.mbi_in->mb_mapaddr;
26259517SBill.Taylor@Sun.COM 	cmd.cp_outparm  = 0;
26269517SBill.Taylor@Sun.COM 	cmd.cp_inmod    = nummtt;
26279517SBill.Taylor@Sun.COM 	cmd.cp_opcode   = WRITE_MTT;
26289517SBill.Taylor@Sun.COM 	cmd.cp_opmod    = 0;
26299517SBill.Taylor@Sun.COM 	cmd.cp_flags    = sleepflag;
26309517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
26319517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
26329517SBill.Taylor@Sun.COM 		cmn_err(CE_CONT, "WRITE_MTT failed (0x%x)\n", status);
26339517SBill.Taylor@Sun.COM 	}
26349517SBill.Taylor@Sun.COM 
26359517SBill.Taylor@Sun.COM 	/* Free the mailbox */
26369517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
26379517SBill.Taylor@Sun.COM 	return (status);
26389517SBill.Taylor@Sun.COM }
26399517SBill.Taylor@Sun.COM 
26409517SBill.Taylor@Sun.COM 
26419517SBill.Taylor@Sun.COM /*
26429517SBill.Taylor@Sun.COM  * hermon_sync_tpt_cmd_post()
26439517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
26449517SBill.Taylor@Sun.COM  */
26459517SBill.Taylor@Sun.COM int
hermon_sync_tpt_cmd_post(hermon_state_t * state,uint_t sleepflag)26469517SBill.Taylor@Sun.COM hermon_sync_tpt_cmd_post(hermon_state_t *state, uint_t sleepflag)
26479517SBill.Taylor@Sun.COM {
26489517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
26499517SBill.Taylor@Sun.COM 	int			status;
26509517SBill.Taylor@Sun.COM 
26519517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
26529517SBill.Taylor@Sun.COM 
26539517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "SYNC_TPT" command */
26549517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0;
26559517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
26569517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 0;
26579517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= SYNC_TPT;
26589517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
26599517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
26609517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
26619517SBill.Taylor@Sun.COM 
26629517SBill.Taylor@Sun.COM 	return (status);
26639517SBill.Taylor@Sun.COM }
26649517SBill.Taylor@Sun.COM 
26659517SBill.Taylor@Sun.COM /*
26669517SBill.Taylor@Sun.COM  * hermon_map_eq_cmd_post()
26679517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
26689517SBill.Taylor@Sun.COM  *    (Currently called only from attach() and/or detach() path contexts)
26699517SBill.Taylor@Sun.COM  */
26709517SBill.Taylor@Sun.COM int
hermon_map_eq_cmd_post(hermon_state_t * state,uint_t map,uint_t eqcindx,uint64_t eqmapmask,uint_t sleepflag)26719517SBill.Taylor@Sun.COM hermon_map_eq_cmd_post(hermon_state_t *state, uint_t map, uint_t eqcindx,
26729517SBill.Taylor@Sun.COM     uint64_t eqmapmask, uint_t sleepflag)
26739517SBill.Taylor@Sun.COM {
26749517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
26759517SBill.Taylor@Sun.COM 	int			status;
26769517SBill.Taylor@Sun.COM 
26779517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
26789517SBill.Taylor@Sun.COM 
26799517SBill.Taylor@Sun.COM 	/* Setup and post Hermon "MAP_EQ" command */
26809517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= eqmapmask;
26819517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
26829517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= eqcindx;
26839517SBill.Taylor@Sun.COM 	if (map != HERMON_CMD_MAP_EQ_EVT_MAP) {
26849517SBill.Taylor@Sun.COM 		cmd.cp_inmod |= HERMON_CMD_UNMAP_EQ_MASK;
26859517SBill.Taylor@Sun.COM 	}
26869517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MAP_EQ;
26879517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
26889517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
26899517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
26909517SBill.Taylor@Sun.COM 	return (status);
26919517SBill.Taylor@Sun.COM }
26929517SBill.Taylor@Sun.COM 
26939517SBill.Taylor@Sun.COM 
26949517SBill.Taylor@Sun.COM /*
26959517SBill.Taylor@Sun.COM  * hermon_resize_cq_cmd_post()
26969517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
26979517SBill.Taylor@Sun.COM  */
26989517SBill.Taylor@Sun.COM int
hermon_resize_cq_cmd_post(hermon_state_t * state,hermon_hw_cqc_t * cqc,uint_t cqcindx,uint32_t * prod_indx,uint_t sleepflag)26999517SBill.Taylor@Sun.COM hermon_resize_cq_cmd_post(hermon_state_t *state, hermon_hw_cqc_t *cqc,
27009517SBill.Taylor@Sun.COM     uint_t cqcindx, uint32_t *prod_indx, uint_t sleepflag)
27019517SBill.Taylor@Sun.COM {
27029517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
27039517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
27049517SBill.Taylor@Sun.COM 	uint64_t		data;
27059517SBill.Taylor@Sun.COM 	uint_t			size;
27069517SBill.Taylor@Sun.COM 	int			status, i;
27079517SBill.Taylor@Sun.COM 
27089517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
27099517SBill.Taylor@Sun.COM 
27109517SBill.Taylor@Sun.COM 	/* Get an "In" mailbox for the command */
27119517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
27129517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
27139517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
27149517SBill.Taylor@Sun.COM 		return (status);
27159517SBill.Taylor@Sun.COM 	}
27169517SBill.Taylor@Sun.COM 
27179517SBill.Taylor@Sun.COM 	/* Copy the Hermon "MODIFY_CQ" command into mailbox */
27189517SBill.Taylor@Sun.COM 	size = sizeof (hermon_hw_cqc_t);
27199517SBill.Taylor@Sun.COM 	for (i = 0; i < (size >> 3); i++) {
27209517SBill.Taylor@Sun.COM 		data = ((uint64_t *)(void *)cqc)[i];
27219517SBill.Taylor@Sun.COM 		ddi_put64(mbox_info.mbi_in->mb_acchdl,
27229517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
27239517SBill.Taylor@Sun.COM 	}
27249517SBill.Taylor@Sun.COM 
27259517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
27269517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
27279517SBill.Taylor@Sun.COM 
27289517SBill.Taylor@Sun.COM 	/* Setup and post Hermon "MODIFY_CQ" command */
27299517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
27309517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;	/* resize cq */
27319517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= cqcindx;
27329517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MODIFY_CQ;
27339517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= RESIZE_CQ;
27349517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
27359517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
27369517SBill.Taylor@Sun.COM 
27379517SBill.Taylor@Sun.COM 	/*
27389517SBill.Taylor@Sun.COM 	 * New "producer index" is returned in the upper 32 bits of
27399517SBill.Taylor@Sun.COM 	 * command "outparam"
27409517SBill.Taylor@Sun.COM 	 */
27419517SBill.Taylor@Sun.COM 	*prod_indx = (cmd.cp_outparm >> 32);
27429517SBill.Taylor@Sun.COM 
27439517SBill.Taylor@Sun.COM 	/* Free the mailbox */
27449517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
27459517SBill.Taylor@Sun.COM 	return (status);
27469517SBill.Taylor@Sun.COM }
27479517SBill.Taylor@Sun.COM 
27489517SBill.Taylor@Sun.COM 
27499517SBill.Taylor@Sun.COM /*
27509517SBill.Taylor@Sun.COM  * hermon_modify_cq_cmd_post()
27519517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
27529517SBill.Taylor@Sun.COM  */
27539517SBill.Taylor@Sun.COM int
hermon_modify_cq_cmd_post(hermon_state_t * state,hermon_hw_cqc_t * cqc,uint_t cqcindx,uint_t opmod,uint_t sleepflag)27549517SBill.Taylor@Sun.COM hermon_modify_cq_cmd_post(hermon_state_t *state, hermon_hw_cqc_t *cqc,
27559517SBill.Taylor@Sun.COM     uint_t cqcindx, uint_t opmod, uint_t sleepflag)
27569517SBill.Taylor@Sun.COM {
27579517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
27589517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
27599517SBill.Taylor@Sun.COM 	uint64_t		data;
27609517SBill.Taylor@Sun.COM 	uint_t			size;
27619517SBill.Taylor@Sun.COM 	int			status, i;
27629517SBill.Taylor@Sun.COM 
27639517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
27649517SBill.Taylor@Sun.COM 
27659517SBill.Taylor@Sun.COM 	/* Get an "In" mailbox for the command */
27669517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
27679517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
27689517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
27699517SBill.Taylor@Sun.COM 		return (status);
27709517SBill.Taylor@Sun.COM 	}
27719517SBill.Taylor@Sun.COM 
27729517SBill.Taylor@Sun.COM 	/* Copy the Hermon "MODIFY_CQ" command into mailbox */
27739517SBill.Taylor@Sun.COM 	size = sizeof (hermon_hw_cqc_t);
27749517SBill.Taylor@Sun.COM 	for (i = 0; i < (size >> 3); i++) {
27759517SBill.Taylor@Sun.COM 		data = ((uint64_t *)(void *)cqc)[i];
27769517SBill.Taylor@Sun.COM 		ddi_put64(mbox_info.mbi_in->mb_acchdl,
27779517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
27789517SBill.Taylor@Sun.COM 	}
27799517SBill.Taylor@Sun.COM 
27809517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
27819517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
27829517SBill.Taylor@Sun.COM 
27839517SBill.Taylor@Sun.COM 	/* Setup and post Hermon "MODIFY_CQ" command */
27849517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
27859517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
27869517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= cqcindx;
27879517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MODIFY_CQ;
27889517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= (uint16_t)opmod;
27899517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
27909517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
27919517SBill.Taylor@Sun.COM 
27929517SBill.Taylor@Sun.COM 	/* Free the mailbox */
27939517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
27949517SBill.Taylor@Sun.COM 	return (status);
27959517SBill.Taylor@Sun.COM }
27969517SBill.Taylor@Sun.COM 
27979517SBill.Taylor@Sun.COM 
27989517SBill.Taylor@Sun.COM /*
27999517SBill.Taylor@Sun.COM  * hermon_cmn_qp_cmd_post()
28009517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
28019517SBill.Taylor@Sun.COM  *
28029517SBill.Taylor@Sun.COM  *    This is the common function for posting all the various types of
28039517SBill.Taylor@Sun.COM  *    QP state transition related Hermon commands.  Since some of the
28049517SBill.Taylor@Sun.COM  *    commands differ from the others in the number (and type) of arguments
28059517SBill.Taylor@Sun.COM  *    that each require, this routine does checks based on opcode type
28069517SBill.Taylor@Sun.COM  *    (explained in more detail below).
28079517SBill.Taylor@Sun.COM  *
28089517SBill.Taylor@Sun.COM  * Note: This common function should be used only with the following
28099517SBill.Taylor@Sun.COM  *    opcodes: RTS2SQD_QP, TOERR_QP, TORST_QP, RST2INIT_QP, INIT2INIT_QP,
28109517SBill.Taylor@Sun.COM  *    INIT2RTR_QP, RTR2RTS_QP, RTS2RTS_QP, SQD2RTS_QP, and SQERR2RTS_QP.
28119517SBill.Taylor@Sun.COM  */
28129517SBill.Taylor@Sun.COM int
hermon_cmn_qp_cmd_post(hermon_state_t * state,uint_t opcode,hermon_hw_qpc_t * qp,uint_t qpindx,uint32_t opmask,uint_t sleepflag)28139517SBill.Taylor@Sun.COM hermon_cmn_qp_cmd_post(hermon_state_t *state, uint_t opcode,
28149517SBill.Taylor@Sun.COM     hermon_hw_qpc_t *qp, uint_t qpindx, uint32_t opmask,
28159517SBill.Taylor@Sun.COM     uint_t sleepflag)
28169517SBill.Taylor@Sun.COM {
28179517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
28189517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
28199517SBill.Taylor@Sun.COM 	uint64_t		data, in_mapaddr, out_mapaddr;
28209517SBill.Taylor@Sun.COM 	uint_t			size, flags, opmod;
28219517SBill.Taylor@Sun.COM 	int			status, i;
28229517SBill.Taylor@Sun.COM 
28239517SBill.Taylor@Sun.COM 	/*
28249517SBill.Taylor@Sun.COM 	 * Use the specified opcode type to set the appropriate parameters.
28259517SBill.Taylor@Sun.COM 	 * Specifically, we need to set in_mapaddr, out_mapaddr, flags, and
28269517SBill.Taylor@Sun.COM 	 * opmod (as necessary).  Setting these parameters may also require
28279517SBill.Taylor@Sun.COM 	 * us to allocate an "In" or "Out" mailbox depending on the command
28289517SBill.Taylor@Sun.COM 	 * type.
28299517SBill.Taylor@Sun.COM 	 */
28309517SBill.Taylor@Sun.COM 
28319517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
28329517SBill.Taylor@Sun.COM 
28339517SBill.Taylor@Sun.COM 	if (opcode == RTS2SQD_QP) {
28349517SBill.Taylor@Sun.COM 		/*
28359517SBill.Taylor@Sun.COM 		 * Note: For RTS-to-SendQueueDrain state transitions we
28369517SBill.Taylor@Sun.COM 		 * always want to request the event generation from the
28379517SBill.Taylor@Sun.COM 		 * hardware.  Though we may not notify the consumer of the
28389517SBill.Taylor@Sun.COM 		 * drained event, the decision to forward (or not) is made
28399517SBill.Taylor@Sun.COM 		 * later in the SQD event handler.
28409517SBill.Taylor@Sun.COM 		 */
28419517SBill.Taylor@Sun.COM 		flags = HERMON_CMD_REQ_SQD_EVENT;
28429517SBill.Taylor@Sun.COM 
28439517SBill.Taylor@Sun.COM 		/*
28449517SBill.Taylor@Sun.COM 		 * The RTS2SQD_QP command uses no "In" or "Out" mailboxes (and
28459517SBill.Taylor@Sun.COM 		 * has no special opcode modifiers).
28469517SBill.Taylor@Sun.COM 		 */
28479517SBill.Taylor@Sun.COM 		in_mapaddr  = 0;
28489517SBill.Taylor@Sun.COM 		out_mapaddr = 0;
28499517SBill.Taylor@Sun.COM 		opmod = 0;
28509517SBill.Taylor@Sun.COM 
28519517SBill.Taylor@Sun.COM 	} else if (opcode == TOERR_QP) {
28529517SBill.Taylor@Sun.COM 		/*
28539517SBill.Taylor@Sun.COM 		 * The TOERR_QP command uses no "In" or "Out" mailboxes, has no
28549517SBill.Taylor@Sun.COM 		 * special opcode modifiers, and takes no special flags.
28559517SBill.Taylor@Sun.COM 		 */
28569517SBill.Taylor@Sun.COM 		in_mapaddr  = 0;
28579517SBill.Taylor@Sun.COM 		out_mapaddr = 0;
28589517SBill.Taylor@Sun.COM 		opmod = 0;
28599517SBill.Taylor@Sun.COM 		flags = 0;
28609517SBill.Taylor@Sun.COM 
28619517SBill.Taylor@Sun.COM 	} else if (opcode == TORST_QP) {
28629517SBill.Taylor@Sun.COM 		/*
28639517SBill.Taylor@Sun.COM 		 * The TORST_QP command could take an "Out" mailbox, but we do
28649517SBill.Taylor@Sun.COM 		 * not require it here.  It also does not takes any special
28659517SBill.Taylor@Sun.COM 		 * flags.  It does however, take a HERMON_CMD_DIRECT_TO_RESET
28669517SBill.Taylor@Sun.COM 		 * opcode modifier, which indicates that the transition to
28679517SBill.Taylor@Sun.COM 		 * reset should happen without first moving the QP through the
28689517SBill.Taylor@Sun.COM 		 * Error state (and, hence, without generating any unnecessary
28699517SBill.Taylor@Sun.COM 		 * "flushed-in-error" completions).
28709517SBill.Taylor@Sun.COM 		 */
28719517SBill.Taylor@Sun.COM 		in_mapaddr  = 0;
28729517SBill.Taylor@Sun.COM 		out_mapaddr = 0;
28739517SBill.Taylor@Sun.COM 		opmod = HERMON_CMD_DIRECT_TO_RESET | HERMON_CMD_NO_OUTMBOX;
28749517SBill.Taylor@Sun.COM 		flags = 0;
28759517SBill.Taylor@Sun.COM 
28769517SBill.Taylor@Sun.COM 	} else {
28779517SBill.Taylor@Sun.COM 		/*
28789517SBill.Taylor@Sun.COM 		 * All the other QP state transition commands (RST2INIT_QP,
28799517SBill.Taylor@Sun.COM 		 * INIT2INIT_QP, INIT2RTR_QP, RTR2RTS_QP, RTS2RTS_QP,
28809517SBill.Taylor@Sun.COM 		 * SQD2RTS_QP, and SQERR2RTS_QP) require an "In" mailbox.
28819517SBill.Taylor@Sun.COM 		 * None of these require any special flags or opcode modifiers.
28829517SBill.Taylor@Sun.COM 		 */
28839517SBill.Taylor@Sun.COM 		mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
28849517SBill.Taylor@Sun.COM 		status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
28859517SBill.Taylor@Sun.COM 		if (status != HERMON_CMD_SUCCESS) {
28869517SBill.Taylor@Sun.COM 			return (status);
28879517SBill.Taylor@Sun.COM 		}
28889517SBill.Taylor@Sun.COM 		in_mapaddr  = mbox_info.mbi_in->mb_mapaddr;
28899517SBill.Taylor@Sun.COM 		out_mapaddr = 0;
28909517SBill.Taylor@Sun.COM 		flags = 0;
28919517SBill.Taylor@Sun.COM 		opmod = 0;
28929517SBill.Taylor@Sun.COM 
28939517SBill.Taylor@Sun.COM 		/* Copy the Hermon command into the "In" mailbox */
28949517SBill.Taylor@Sun.COM 		size = sizeof (hermon_hw_qpc_t);
28959517SBill.Taylor@Sun.COM 		for (i = 0; i < (size >> 3); i++) {
28969517SBill.Taylor@Sun.COM 			data = ((uint64_t *)(void *)qp)[i];
28979517SBill.Taylor@Sun.COM 			ddi_put64(mbox_info.mbi_in->mb_acchdl,
28989517SBill.Taylor@Sun.COM 			    ((uint64_t *)mbox_info.mbi_in->mb_addr + i + 1),
28999517SBill.Taylor@Sun.COM 			    data);
29009517SBill.Taylor@Sun.COM 		}
29019517SBill.Taylor@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl,
29029517SBill.Taylor@Sun.COM 		    ((uint32_t *)mbox_info.mbi_in->mb_addr), opmask);
29039517SBill.Taylor@Sun.COM 
29049517SBill.Taylor@Sun.COM 		/*
29059517SBill.Taylor@Sun.COM 		 * Sync the mailbox for the device to read.  We have to add
29069517SBill.Taylor@Sun.COM 		 * eight bytes here to account for "opt_param_mask" and
29079517SBill.Taylor@Sun.COM 		 * proper alignment.
29089517SBill.Taylor@Sun.COM 		 */
29099517SBill.Taylor@Sun.COM 		hermon_mbox_sync(mbox_info.mbi_in, 0, size + 8,
29109517SBill.Taylor@Sun.COM 		    DDI_DMA_SYNC_FORDEV);
29119517SBill.Taylor@Sun.COM 	}
29129517SBill.Taylor@Sun.COM 
29139517SBill.Taylor@Sun.COM 	/* Setup and post Hermon QP state transition command */
29149517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= in_mapaddr;
29159517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= out_mapaddr;
29169517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= qpindx | flags;
29179517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= (uint16_t)opcode;
29189517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= (uint16_t)opmod;
29199517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
29209517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
29219517SBill.Taylor@Sun.COM 
29229517SBill.Taylor@Sun.COM 	/*
29239517SBill.Taylor@Sun.COM 	 * If we allocated a mailbox (either an "In" or an "Out") above,
29249517SBill.Taylor@Sun.COM 	 * then free it now before returning.
29259517SBill.Taylor@Sun.COM 	 */
29269517SBill.Taylor@Sun.COM 	if ((opcode != RTS2SQD_QP) && (opcode != TOERR_QP) &&
29279517SBill.Taylor@Sun.COM 	    (opcode != TORST_QP)) {
29289517SBill.Taylor@Sun.COM 		/* Free the mailbox */
29299517SBill.Taylor@Sun.COM 		hermon_mbox_free(state, &mbox_info);
29309517SBill.Taylor@Sun.COM 	}
29319517SBill.Taylor@Sun.COM 	return (status);
29329517SBill.Taylor@Sun.COM }
29339517SBill.Taylor@Sun.COM 
29349517SBill.Taylor@Sun.COM 
29359517SBill.Taylor@Sun.COM /*
29369517SBill.Taylor@Sun.COM  * hermon_cmn_query_cmd_post()
29379517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
29389517SBill.Taylor@Sun.COM  *
29399517SBill.Taylor@Sun.COM  *    This is the common function for posting all the various types of
29409517SBill.Taylor@Sun.COM  *    Hermon query commands.  All Hermon query commands require an "Out"
29419517SBill.Taylor@Sun.COM  *    mailbox to be allocated for the resulting queried data.
29429517SBill.Taylor@Sun.COM  *
29439517SBill.Taylor@Sun.COM  * Note: This common function should be used only with the following
29449517SBill.Taylor@Sun.COM  *    opcodes: QUERY_DEV_LIM, QUERY_FW, QUERY_DDR, QUERY_ADAPTER, QUERY_PORT
29459517SBill.Taylor@Sun.COM  *     QUERY_HCA, QUERY_MPT, QUERY_EQ, QUERY_CQ, and QUERY_QP.
2946*12965SWilliam.Taylor@Oracle.COM  *	With support of FCoIB, this also supports QUERY_FC.
29479517SBill.Taylor@Sun.COM  */
29489517SBill.Taylor@Sun.COM int
hermon_cmn_query_cmd_post(hermon_state_t * state,uint_t opcode,uint_t opmod,uint_t queryindx,void * query,uint_t size,uint_t sleepflag)29499517SBill.Taylor@Sun.COM hermon_cmn_query_cmd_post(hermon_state_t *state, uint_t opcode, uint_t opmod,
29509517SBill.Taylor@Sun.COM     uint_t queryindx, void *query, uint_t size, uint_t sleepflag)
29519517SBill.Taylor@Sun.COM {
29529517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
29539517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
29549517SBill.Taylor@Sun.COM 	uint64_t		data;
29559517SBill.Taylor@Sun.COM 	uint_t			offset;
29569517SBill.Taylor@Sun.COM 	int			status, i;
29579517SBill.Taylor@Sun.COM 
29589517SBill.Taylor@Sun.COM 	bzero(&cmd, sizeof (hermon_cmd_post_t));
29599517SBill.Taylor@Sun.COM 
29609517SBill.Taylor@Sun.COM 	/* Get an "Out" mailbox for the command */
29619517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_OUTMBOX;
29629517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
29639517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
29649517SBill.Taylor@Sun.COM 		return (status);
29659517SBill.Taylor@Sun.COM 	}
29669517SBill.Taylor@Sun.COM 
29679517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon query command */
29689517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0;
29699517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
29709517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= queryindx;
29719517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= (uint16_t)opcode;
29729517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= (uint16_t)opmod;
29739517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
29749517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
29759517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
29769517SBill.Taylor@Sun.COM 		goto cmn_query_fail;
29779517SBill.Taylor@Sun.COM 	}
29789517SBill.Taylor@Sun.COM 
29799517SBill.Taylor@Sun.COM 	/* Sync the mailbox to read the results */
29809517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, 0, size, DDI_DMA_SYNC_FORCPU);
29819517SBill.Taylor@Sun.COM 
29829517SBill.Taylor@Sun.COM 	/*
29839517SBill.Taylor@Sun.COM 	 * QUERY_QP is handled somewhat differently than the other query
29849517SBill.Taylor@Sun.COM 	 * commands.  For QUERY_QP, the actual queried data is offset into
29859517SBill.Taylor@Sun.COM 	 * the mailbox (by one 64-bit word).
29869517SBill.Taylor@Sun.COM 	 */
29879517SBill.Taylor@Sun.COM 	offset = (opcode == QUERY_QP) ? 1 : 0;
29889517SBill.Taylor@Sun.COM 
29899517SBill.Taylor@Sun.COM 	/* Copy query command results into "query" */
29909517SBill.Taylor@Sun.COM 	for (i = 0; i < (size >> 3); i++) {
29919517SBill.Taylor@Sun.COM 		data = ddi_get64(mbox_info.mbi_out->mb_acchdl,
29929517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_out->mb_addr + i + offset));
29939517SBill.Taylor@Sun.COM 		((uint64_t *)query)[i] = data;
29949517SBill.Taylor@Sun.COM 	}
29959517SBill.Taylor@Sun.COM 
29969517SBill.Taylor@Sun.COM cmn_query_fail:
29979517SBill.Taylor@Sun.COM 	/* Free the mailbox */
29989517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
29999517SBill.Taylor@Sun.COM 	return (status);
30009517SBill.Taylor@Sun.COM }
30019517SBill.Taylor@Sun.COM 
30029517SBill.Taylor@Sun.COM 
30039517SBill.Taylor@Sun.COM /*
30049517SBill.Taylor@Sun.COM  * hermon_cmn_ownership_cmd_post()
30059517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
30069517SBill.Taylor@Sun.COM  *
30079517SBill.Taylor@Sun.COM  *    This is the common function for posting all the various types of
30089517SBill.Taylor@Sun.COM  *    Hermon HW/SW resource ownership commands.  Since some of the commands
30099517SBill.Taylor@Sun.COM  *    differ from the others in the direction of ownership change (i.e.
30109517SBill.Taylor@Sun.COM  *    from HW ownership to SW, or vice versa), they differ in the type of
30119517SBill.Taylor@Sun.COM  *    mailbox and specific handling that each requires.  This routine does
30129517SBill.Taylor@Sun.COM  *    certain checks based on opcode type to determine the direction of
30139517SBill.Taylor@Sun.COM  *    the transition and to correctly handle the request.
30149517SBill.Taylor@Sun.COM  *
30159517SBill.Taylor@Sun.COM  * Note: This common function should be used only with the following
30169517SBill.Taylor@Sun.COM  *    opcodes: HW2SW_MPT, HW2SW_EQ, HW2SW_CQ, SW2HW_MPT, SW2HW_EQ, and
30179517SBill.Taylor@Sun.COM  *    SW2HW_CQ
30189517SBill.Taylor@Sun.COM  */
30199517SBill.Taylor@Sun.COM int
hermon_cmn_ownership_cmd_post(hermon_state_t * state,uint_t opcode,void * hwrsrc,uint_t size,uint_t hwrsrcindx,uint_t sleepflag)30209517SBill.Taylor@Sun.COM hermon_cmn_ownership_cmd_post(hermon_state_t *state, uint_t opcode,
30219517SBill.Taylor@Sun.COM     void *hwrsrc, uint_t size, uint_t hwrsrcindx, uint_t sleepflag)
30229517SBill.Taylor@Sun.COM {
30239517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
30249517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
30259517SBill.Taylor@Sun.COM 	uint64_t		data, in_mapaddr, out_mapaddr;
30269517SBill.Taylor@Sun.COM 	uint_t			direction, opmod;
30279517SBill.Taylor@Sun.COM 	int			status, i;
30289517SBill.Taylor@Sun.COM 
30299517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
30309517SBill.Taylor@Sun.COM 
30319517SBill.Taylor@Sun.COM 	/*
30329517SBill.Taylor@Sun.COM 	 * Determine the direction of the ownership transfer based on the
30339517SBill.Taylor@Sun.COM 	 * provided opcode
30349517SBill.Taylor@Sun.COM 	 */
30359517SBill.Taylor@Sun.COM 	if ((opcode == HW2SW_MPT) || (opcode == HW2SW_EQ) ||
30369517SBill.Taylor@Sun.COM 	    (opcode == HW2SW_CQ) || (opcode == HW2SW_SRQ)) {
30379517SBill.Taylor@Sun.COM 		direction = HERMON_CMD_RSRC_HW2SW;
30389517SBill.Taylor@Sun.COM 
30399517SBill.Taylor@Sun.COM 	} else if ((opcode == SW2HW_MPT) || (opcode == SW2HW_EQ) ||
30409517SBill.Taylor@Sun.COM 	    (opcode == SW2HW_CQ) || (opcode == SW2HW_SRQ)) {
30419517SBill.Taylor@Sun.COM 		direction = HERMON_CMD_RSRC_SW2HW;
30429517SBill.Taylor@Sun.COM 
30439517SBill.Taylor@Sun.COM 	} else {
30449517SBill.Taylor@Sun.COM 		return (HERMON_CMD_INVALID_STATUS);
30459517SBill.Taylor@Sun.COM 	}
30469517SBill.Taylor@Sun.COM 
30479517SBill.Taylor@Sun.COM 	/*
30489517SBill.Taylor@Sun.COM 	 * If hwrsrc is NULL then we do not allocate a mailbox.  This is used
30499517SBill.Taylor@Sun.COM 	 * in the case of memory deregister where the out mailbox is not
30509517SBill.Taylor@Sun.COM 	 * needed.  In the case of re-register, we do use the hwrsrc.
30519517SBill.Taylor@Sun.COM 	 *
30529517SBill.Taylor@Sun.COM 	 * Otherwise, If ownership transfer is going from hardware to software,
30539517SBill.Taylor@Sun.COM 	 * then allocate an "Out" mailbox.  This will be filled in later as a
30549517SBill.Taylor@Sun.COM 	 * result of the Hermon command.
30559517SBill.Taylor@Sun.COM 	 *
30569517SBill.Taylor@Sun.COM 	 * And if the ownership transfer is going from software to hardware,
30579517SBill.Taylor@Sun.COM 	 * then we need an "In" mailbox, and we need to fill it in and sync it
30589517SBill.Taylor@Sun.COM 	 * (if necessary).  Then the mailbox can be passed to the Hermon
30599517SBill.Taylor@Sun.COM 	 * firmware.
30609517SBill.Taylor@Sun.COM 	 *
30619517SBill.Taylor@Sun.COM 	 * For the HW2SW (dereg) case, we only use an out mbox if hwrsrc is !=
30629517SBill.Taylor@Sun.COM 	 * NULL.  This implies a re-reg, and the out mbox must be used.  If
30639517SBill.Taylor@Sun.COM 	 * hwrsrc is == NULL, then we can save some time and resources by not
30649517SBill.Taylor@Sun.COM 	 * using an out mbox at all.  We must set opmod to HERMON_CMD_DO_OUTMBOX
30659517SBill.Taylor@Sun.COM 	 * and HERMON_CMD_NO_OUTMBOX appropriately in this case.
30669517SBill.Taylor@Sun.COM 	 *
30679517SBill.Taylor@Sun.COM 	 * For the SW2HW (reg) case, no out mbox is possible.  We set opmod to
30689517SBill.Taylor@Sun.COM 	 * 0 anyway, but this field is not used in this case.
30699517SBill.Taylor@Sun.COM 	 */
30709517SBill.Taylor@Sun.COM 	if (direction == HERMON_CMD_RSRC_HW2SW) {
30719517SBill.Taylor@Sun.COM 		if (hwrsrc != NULL) {
30729517SBill.Taylor@Sun.COM 			mbox_info.mbi_alloc_flags = HERMON_ALLOC_OUTMBOX;
30739517SBill.Taylor@Sun.COM 			status = hermon_mbox_alloc(state, &mbox_info,
30749517SBill.Taylor@Sun.COM 			    sleepflag);
30759517SBill.Taylor@Sun.COM 			if (status != HERMON_CMD_SUCCESS) {
30769517SBill.Taylor@Sun.COM 				return (status);
30779517SBill.Taylor@Sun.COM 			}
30789517SBill.Taylor@Sun.COM 			in_mapaddr  = 0;
30799517SBill.Taylor@Sun.COM 			out_mapaddr = mbox_info.mbi_out->mb_mapaddr;
30809517SBill.Taylor@Sun.COM 			opmod = HERMON_CMD_DO_OUTMBOX;
30819517SBill.Taylor@Sun.COM 		} else {
30829517SBill.Taylor@Sun.COM 			in_mapaddr = 0;
30839517SBill.Taylor@Sun.COM 			out_mapaddr = 0;
30849517SBill.Taylor@Sun.COM 			opmod = HERMON_CMD_NO_OUTMBOX;
30859517SBill.Taylor@Sun.COM 		}
30869517SBill.Taylor@Sun.COM 	} else {  /* HERMON_CMD_RSRC_SW2HW */
30879517SBill.Taylor@Sun.COM 		mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
30889517SBill.Taylor@Sun.COM 		status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
30899517SBill.Taylor@Sun.COM 		if (status != HERMON_CMD_SUCCESS) {
30909517SBill.Taylor@Sun.COM 			return (status);
30919517SBill.Taylor@Sun.COM 		}
30929517SBill.Taylor@Sun.COM 
30939517SBill.Taylor@Sun.COM 		/* Copy the SW2HW ownership command into mailbox */
30949517SBill.Taylor@Sun.COM 		for (i = 0; i < (size >> 3); i++) {
30959517SBill.Taylor@Sun.COM 			data = ((uint64_t *)hwrsrc)[i];
30969517SBill.Taylor@Sun.COM 			ddi_put64(mbox_info.mbi_in->mb_acchdl,
30979517SBill.Taylor@Sun.COM 			    ((uint64_t *)mbox_info.mbi_in->mb_addr + i),
30989517SBill.Taylor@Sun.COM 			    data);
30999517SBill.Taylor@Sun.COM 		}
31009517SBill.Taylor@Sun.COM 
31019517SBill.Taylor@Sun.COM 		/* Sync the mailbox for the device to read */
31029517SBill.Taylor@Sun.COM 		hermon_mbox_sync(mbox_info.mbi_in, 0, size,
31039517SBill.Taylor@Sun.COM 		    DDI_DMA_SYNC_FORDEV);
31049517SBill.Taylor@Sun.COM 
31059517SBill.Taylor@Sun.COM 		in_mapaddr  = mbox_info.mbi_in->mb_mapaddr;
31069517SBill.Taylor@Sun.COM 		out_mapaddr = 0;
31079517SBill.Taylor@Sun.COM 		opmod = 0;
31089517SBill.Taylor@Sun.COM 	}
31099517SBill.Taylor@Sun.COM 
31109517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon ownership command */
31119517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= in_mapaddr;
31129517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= out_mapaddr;
31139517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= hwrsrcindx;
31149517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= (uint16_t)opcode;
31159517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= (uint16_t)opmod;
31169517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
31179517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
31189517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
31199517SBill.Taylor@Sun.COM 		goto cmn_ownership_fail;
31209517SBill.Taylor@Sun.COM 	}
31219517SBill.Taylor@Sun.COM 
31229517SBill.Taylor@Sun.COM 	/*
31239517SBill.Taylor@Sun.COM 	 * As mentioned above, for HW2SW ownership transfers we need to
31249517SBill.Taylor@Sun.COM 	 * sync (if necessary) and copy out the resulting data from the
31259517SBill.Taylor@Sun.COM 	 * "Out" mailbox" (assuming the above command was successful).
31269517SBill.Taylor@Sun.COM 	 */
31279517SBill.Taylor@Sun.COM 	if (direction == HERMON_CMD_RSRC_HW2SW && hwrsrc != NULL) {
31289517SBill.Taylor@Sun.COM 
31299517SBill.Taylor@Sun.COM 		/* Sync the mailbox to read the results */
31309517SBill.Taylor@Sun.COM 		hermon_mbox_sync(mbox_info.mbi_out, 0, size,
31319517SBill.Taylor@Sun.COM 		    DDI_DMA_SYNC_FORCPU);
31329517SBill.Taylor@Sun.COM 
31339517SBill.Taylor@Sun.COM 		/* Copy HW2SW ownership command results into "hwrsrc" */
31349517SBill.Taylor@Sun.COM 		for (i = 0; i < (size >> 3); i++) {
31359517SBill.Taylor@Sun.COM 			data = ddi_get64(mbox_info.mbi_out->mb_acchdl,
31369517SBill.Taylor@Sun.COM 			    ((uint64_t *)mbox_info.mbi_out->mb_addr + i));
31379517SBill.Taylor@Sun.COM 			((uint64_t *)hwrsrc)[i] = data;
31389517SBill.Taylor@Sun.COM 		}
31399517SBill.Taylor@Sun.COM 	}
31409517SBill.Taylor@Sun.COM 
31419517SBill.Taylor@Sun.COM cmn_ownership_fail:
31429517SBill.Taylor@Sun.COM 	if (hwrsrc != NULL) {
31439517SBill.Taylor@Sun.COM 		/* Free the mailbox */
31449517SBill.Taylor@Sun.COM 		hermon_mbox_free(state, &mbox_info);
31459517SBill.Taylor@Sun.COM 	}
31469517SBill.Taylor@Sun.COM 	return (status);
31479517SBill.Taylor@Sun.COM }
31489517SBill.Taylor@Sun.COM 
31499517SBill.Taylor@Sun.COM 
31509517SBill.Taylor@Sun.COM /*
31519517SBill.Taylor@Sun.COM  * hermon_conf_special_qp_cmd_post()
31529517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
31539517SBill.Taylor@Sun.COM  */
31549517SBill.Taylor@Sun.COM /*ARGSUSED*/
31559517SBill.Taylor@Sun.COM int
hermon_conf_special_qp_cmd_post(hermon_state_t * state,uint_t qpindx,uint_t qptype,uint_t sleepflag,uint_t opmod)31569517SBill.Taylor@Sun.COM hermon_conf_special_qp_cmd_post(hermon_state_t *state, uint_t qpindx,
31579517SBill.Taylor@Sun.COM     uint_t qptype, uint_t sleepflag, uint_t opmod)
31589517SBill.Taylor@Sun.COM {
31599517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
31609517SBill.Taylor@Sun.COM 	int			status;
31619517SBill.Taylor@Sun.COM 
31629517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
31639517SBill.Taylor@Sun.COM 
31649517SBill.Taylor@Sun.COM 	/* Setup and post Hermon "CONF_SPECIAL_QP" command */
31659517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0;
31669517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
31679517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= qpindx & 0x00FFFFF8;	/* mask off low 3 bits */
31689517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= CONF_SPECIAL_QP;
31699517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= (uint16_t)opmod;
31709517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
31719517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
31729517SBill.Taylor@Sun.COM 
31739517SBill.Taylor@Sun.COM 	return (status);
31749517SBill.Taylor@Sun.COM }
31759517SBill.Taylor@Sun.COM 
31769517SBill.Taylor@Sun.COM 
31779517SBill.Taylor@Sun.COM /*
3178*12965SWilliam.Taylor@Oracle.COM  * hermon_get_heart_beat_rq_cmd_post()
3179*12965SWilliam.Taylor@Oracle.COM  *    Context: Can be called only from kernel or interrupt context
3180*12965SWilliam.Taylor@Oracle.COM  */
3181*12965SWilliam.Taylor@Oracle.COM int
hermon_get_heart_beat_rq_cmd_post(hermon_state_t * state,uint_t qpindx,uint64_t * outparm)3182*12965SWilliam.Taylor@Oracle.COM hermon_get_heart_beat_rq_cmd_post(hermon_state_t *state, uint_t qpindx,
3183*12965SWilliam.Taylor@Oracle.COM     uint64_t *outparm)
3184*12965SWilliam.Taylor@Oracle.COM {
3185*12965SWilliam.Taylor@Oracle.COM 	hermon_cmd_post_t	cmd;
3186*12965SWilliam.Taylor@Oracle.COM 	int			status;
3187*12965SWilliam.Taylor@Oracle.COM 
3188*12965SWilliam.Taylor@Oracle.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
3189*12965SWilliam.Taylor@Oracle.COM 
3190*12965SWilliam.Taylor@Oracle.COM 	/* Setup and post the Hermon "HEART_BEAT_RQ" command */
3191*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_inparm	= 0;
3192*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_outparm	= 0;
3193*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_inmod	= qpindx;
3194*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_opcode	= HEART_BEAT_RQ;
3195*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_opmod	= 0;
3196*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
3197*12965SWilliam.Taylor@Oracle.COM 	status = hermon_cmd_post(state, &cmd);
3198*12965SWilliam.Taylor@Oracle.COM 
3199*12965SWilliam.Taylor@Oracle.COM 	/*
3200*12965SWilliam.Taylor@Oracle.COM 	 * Return immediate out param through argument pointer.
3201*12965SWilliam.Taylor@Oracle.COM 	 */
3202*12965SWilliam.Taylor@Oracle.COM 	*outparm = cmd.cp_outparm;
3203*12965SWilliam.Taylor@Oracle.COM 	return (status);
3204*12965SWilliam.Taylor@Oracle.COM }
3205*12965SWilliam.Taylor@Oracle.COM 
3206*12965SWilliam.Taylor@Oracle.COM 
3207*12965SWilliam.Taylor@Oracle.COM /*
32089517SBill.Taylor@Sun.COM  * hermon_mgid_hash_cmd_post()
32099517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
32109517SBill.Taylor@Sun.COM  */
32119517SBill.Taylor@Sun.COM int
hermon_mgid_hash_cmd_post(hermon_state_t * state,uint64_t mgid_h,uint64_t mgid_l,uint64_t * mgid_hash,uint_t sleepflag)32129517SBill.Taylor@Sun.COM hermon_mgid_hash_cmd_post(hermon_state_t *state, uint64_t mgid_h,
32139517SBill.Taylor@Sun.COM     uint64_t mgid_l, uint64_t *mgid_hash, uint_t sleepflag)
32149517SBill.Taylor@Sun.COM {
32159517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
32169517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
32179517SBill.Taylor@Sun.COM 	int			status;
32189517SBill.Taylor@Sun.COM 
32199517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
32209517SBill.Taylor@Sun.COM 
32219517SBill.Taylor@Sun.COM 	/* Get an "In" mailbox for the command */
32229517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
32239517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
32249517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
32259517SBill.Taylor@Sun.COM 		return (status);
32269517SBill.Taylor@Sun.COM 	}
32279517SBill.Taylor@Sun.COM 
32289517SBill.Taylor@Sun.COM 	/* Copy the Hermon "MGID_HASH" command into mailbox */
32299517SBill.Taylor@Sun.COM 	ddi_put64(mbox_info.mbi_in->mb_acchdl,
32309517SBill.Taylor@Sun.COM 	    ((uint64_t *)mbox_info.mbi_in->mb_addr + 0), mgid_h);
32319517SBill.Taylor@Sun.COM 	ddi_put64(mbox_info.mbi_in->mb_acchdl,
32329517SBill.Taylor@Sun.COM 	    ((uint64_t *)mbox_info.mbi_in->mb_addr + 1), mgid_l);
32339517SBill.Taylor@Sun.COM 
32349517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
32359517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, HERMON_CMD_MGIDHASH_SZ,
32369517SBill.Taylor@Sun.COM 	    DDI_DMA_SYNC_FORDEV);
32379517SBill.Taylor@Sun.COM 
32389517SBill.Taylor@Sun.COM 	/* Setup and post the Hermon "MGID_HASH" command */
32399517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
32409517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
32419517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 0;
32429517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MGID_HASH;
32439517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
32449517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
32459517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
32469517SBill.Taylor@Sun.COM 
32479517SBill.Taylor@Sun.COM 	/* MGID hash value is returned in command "outparam" */
32489517SBill.Taylor@Sun.COM 	*mgid_hash = cmd.cp_outparm;
32499517SBill.Taylor@Sun.COM 
32509517SBill.Taylor@Sun.COM 	/* Free the mailbox */
32519517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
32529517SBill.Taylor@Sun.COM 	return (status);
32539517SBill.Taylor@Sun.COM }
32549517SBill.Taylor@Sun.COM 
32559517SBill.Taylor@Sun.COM 
32569517SBill.Taylor@Sun.COM /*
32579517SBill.Taylor@Sun.COM  * hermon_read_mgm_cmd_post()
32589517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
32599517SBill.Taylor@Sun.COM  *
32609517SBill.Taylor@Sun.COM  * Note: It is assumed that the "mcg" parameter is actually a pointer to a
32619517SBill.Taylor@Sun.COM  *    "hermon_hw_mcg_t" struct and some number of "hermon_hw_mcg_qp_list_t"
32629517SBill.Taylor@Sun.COM  *    structs.  Combined size should be equal to result of HERMON_MCGMEM_SZ()
32639517SBill.Taylor@Sun.COM  *    macro.
32649517SBill.Taylor@Sun.COM  */
32659517SBill.Taylor@Sun.COM int
hermon_read_mgm_cmd_post(hermon_state_t * state,hermon_hw_mcg_t * mcg,uint_t mcgindx,uint_t sleepflag)32669517SBill.Taylor@Sun.COM hermon_read_mgm_cmd_post(hermon_state_t *state, hermon_hw_mcg_t *mcg,
32679517SBill.Taylor@Sun.COM     uint_t mcgindx, uint_t sleepflag)
32689517SBill.Taylor@Sun.COM {
32699517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
32709517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
32719517SBill.Taylor@Sun.COM 	uint64_t		data;
32729517SBill.Taylor@Sun.COM 	uint32_t		data32;
32739517SBill.Taylor@Sun.COM 	uint_t			size, hdrsz, qplistsz;
32749517SBill.Taylor@Sun.COM 	int			status, i;
32759517SBill.Taylor@Sun.COM 
32769517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
32779517SBill.Taylor@Sun.COM 
32789517SBill.Taylor@Sun.COM 	/* Get an "Out" mailbox for the results */
32799517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_OUTMBOX;
32809517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
32819517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
32829517SBill.Taylor@Sun.COM 		return (status);
32839517SBill.Taylor@Sun.COM 	}
32849517SBill.Taylor@Sun.COM 
32859517SBill.Taylor@Sun.COM 	/* Setup and post Hermon "READ_MGM" command */
32869517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0;
32879517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
32889517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= mcgindx;
32899517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= READ_MGM;
32909517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
32919517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
32929517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
32939517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
32949517SBill.Taylor@Sun.COM 		goto read_mgm_fail;
32959517SBill.Taylor@Sun.COM 	}
32969517SBill.Taylor@Sun.COM 
32979517SBill.Taylor@Sun.COM 	/* Sync the mailbox to read the results */
32989517SBill.Taylor@Sun.COM 	size = HERMON_MCGMEM_SZ(state);
32999517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, 0, size, DDI_DMA_SYNC_FORCPU);
33009517SBill.Taylor@Sun.COM 
33019517SBill.Taylor@Sun.COM 	/* Copy the READ_MGM command results into "mcg" */
33029517SBill.Taylor@Sun.COM 	hdrsz = sizeof (hermon_hw_mcg_t);
33039517SBill.Taylor@Sun.COM 	for (i = 0; i < (hdrsz >> 3); i++) {
33049517SBill.Taylor@Sun.COM 		data = ddi_get64(mbox_info.mbi_out->mb_acchdl,
33059517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_out->mb_addr + i));
33069517SBill.Taylor@Sun.COM 		((uint64_t *)mcg)[i] = data;
33079517SBill.Taylor@Sun.COM 	}
33089517SBill.Taylor@Sun.COM 	qplistsz = size - hdrsz;
33099517SBill.Taylor@Sun.COM 	for (i = 0; i < (qplistsz >> 2); i++) {
33109517SBill.Taylor@Sun.COM 		data32 = ddi_get32(mbox_info.mbi_out->mb_acchdl,
33119517SBill.Taylor@Sun.COM 		    ((uint32_t *)mbox_info.mbi_out->mb_addr + i + 8));
33129517SBill.Taylor@Sun.COM 		((uint32_t *)mcg)[i + 8] = data32;
33139517SBill.Taylor@Sun.COM 	}
33149517SBill.Taylor@Sun.COM 
33159517SBill.Taylor@Sun.COM read_mgm_fail:
33169517SBill.Taylor@Sun.COM 	/* Free the mailbox */
33179517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
33189517SBill.Taylor@Sun.COM 	return (status);
33199517SBill.Taylor@Sun.COM }
33209517SBill.Taylor@Sun.COM 
33219517SBill.Taylor@Sun.COM 
33229517SBill.Taylor@Sun.COM /*
33239517SBill.Taylor@Sun.COM  * hermon_write_mgm_cmd_post()
33249517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
33259517SBill.Taylor@Sun.COM  *
33269517SBill.Taylor@Sun.COM  * Note: It is assumed that the "mcg" parameter is actually a pointer to a
33279517SBill.Taylor@Sun.COM  *    "hermon_hw_mcg_t" struct and some number of "hermon_hw_mcg_qp_list_t"
33289517SBill.Taylor@Sun.COM  *    structs.  Combined size should be equal to result of HERMON_MCGMEM_SZ()
33299517SBill.Taylor@Sun.COM  *    macro.
33309517SBill.Taylor@Sun.COM  */
33319517SBill.Taylor@Sun.COM int
hermon_write_mgm_cmd_post(hermon_state_t * state,hermon_hw_mcg_t * mcg,uint_t mcgindx,uint_t sleepflag)33329517SBill.Taylor@Sun.COM hermon_write_mgm_cmd_post(hermon_state_t *state, hermon_hw_mcg_t *mcg,
33339517SBill.Taylor@Sun.COM     uint_t mcgindx, uint_t sleepflag)
33349517SBill.Taylor@Sun.COM {
33359517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
33369517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
33379517SBill.Taylor@Sun.COM 	uint64_t		data;
33389517SBill.Taylor@Sun.COM 	uint_t			size, hdrsz, qplistsz;
33399517SBill.Taylor@Sun.COM 	int			status, i;
33409517SBill.Taylor@Sun.COM 
33419517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
33429517SBill.Taylor@Sun.COM 
33439517SBill.Taylor@Sun.COM 	/* Get an "In" mailbox for the command */
33449517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
33459517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
33469517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
33479517SBill.Taylor@Sun.COM 		return (status);
33489517SBill.Taylor@Sun.COM 	}
33499517SBill.Taylor@Sun.COM 
33509517SBill.Taylor@Sun.COM 	/* Copy the Hermon "WRITE_MGM" command into mailbox */
33519517SBill.Taylor@Sun.COM 	size  = HERMON_MCGMEM_SZ(state);
33529517SBill.Taylor@Sun.COM 	hdrsz = sizeof (hermon_hw_mcg_t);
33539517SBill.Taylor@Sun.COM 	for (i = 0; i < (hdrsz >> 3); i++) {
33549517SBill.Taylor@Sun.COM 		data = ((uint64_t *)mcg)[i];
33559517SBill.Taylor@Sun.COM 		ddi_put64(mbox_info.mbi_in->mb_acchdl,
33569517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
33579517SBill.Taylor@Sun.COM 	}
33589517SBill.Taylor@Sun.COM 	qplistsz = size - hdrsz;
33599517SBill.Taylor@Sun.COM 	for (i = 0; i < (qplistsz >> 2); i++) {
33609517SBill.Taylor@Sun.COM 		data = ((uint32_t *)mcg)[i + 8];
33619517SBill.Taylor@Sun.COM 		ddi_put32(mbox_info.mbi_in->mb_acchdl,
33629517SBill.Taylor@Sun.COM 		    ((uint32_t *)mbox_info.mbi_in->mb_addr + i + 8), data);
33639517SBill.Taylor@Sun.COM 	}
33649517SBill.Taylor@Sun.COM 
33659517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
33669517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
33679517SBill.Taylor@Sun.COM 
33689517SBill.Taylor@Sun.COM 	/* Setup and post Hermon "WRITE_MGM" command */
33699517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
33709517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
33719517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= mcgindx;
33729517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= WRITE_MGM;
33739517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
33749517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
33759517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
33769517SBill.Taylor@Sun.COM 
33779517SBill.Taylor@Sun.COM 	/* Free the mailbox */
33789517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
33799517SBill.Taylor@Sun.COM 	return (status);
33809517SBill.Taylor@Sun.COM }
33819517SBill.Taylor@Sun.COM 
33829517SBill.Taylor@Sun.COM /*
33839517SBill.Taylor@Sun.COM  * hermon_resize_srq_cmd_post()
33849517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
33859517SBill.Taylor@Sun.COM  */
33869517SBill.Taylor@Sun.COM 
hermon_resize_srq_cmd_post(hermon_state_t * state,hermon_hw_srqc_t * srq,uint_t srqnum,uint_t sleepflag)33879517SBill.Taylor@Sun.COM int hermon_resize_srq_cmd_post(hermon_state_t *state, hermon_hw_srqc_t *srq,
33889517SBill.Taylor@Sun.COM     uint_t srqnum, uint_t sleepflag)
33899517SBill.Taylor@Sun.COM {
33909517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
33919517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
33929517SBill.Taylor@Sun.COM 	uint64_t		data;
33939517SBill.Taylor@Sun.COM 	uint_t			size;
33949517SBill.Taylor@Sun.COM 	int			status, i;
33959517SBill.Taylor@Sun.COM 
33969517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
33979517SBill.Taylor@Sun.COM 
33989517SBill.Taylor@Sun.COM 	/* Get an "In" mailbox for the command */
33999517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
34009517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
34019517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
34029517SBill.Taylor@Sun.COM 		return (status);
34039517SBill.Taylor@Sun.COM 	}
34049517SBill.Taylor@Sun.COM 
34059517SBill.Taylor@Sun.COM 	/* Copy the Hermon "RESIZE_SRQ" command into mailbox */
34069517SBill.Taylor@Sun.COM 	size = sizeof (hermon_hw_srqc_t);
34079517SBill.Taylor@Sun.COM 	for (i = 0; i < (size >> 3); i++) {
34089517SBill.Taylor@Sun.COM 		data = ((uint64_t *)(void *)srq)[i];
34099517SBill.Taylor@Sun.COM 		ddi_put64(mbox_info.mbi_in->mb_acchdl,
34109517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
34119517SBill.Taylor@Sun.COM 	}
34129517SBill.Taylor@Sun.COM 
34139517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
34149517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
34159517SBill.Taylor@Sun.COM 
34169517SBill.Taylor@Sun.COM 	/* Setup and post Hermon "RESIZE_SRQ" command */
34179517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
34189517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
34199517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= srqnum;
34209517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= RESIZE_SRQ;
34219517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
34229517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
34239517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
34249517SBill.Taylor@Sun.COM 
34259517SBill.Taylor@Sun.COM 	/* Free the mailbox */
34269517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
34279517SBill.Taylor@Sun.COM 	return (status);
34289517SBill.Taylor@Sun.COM }
34299517SBill.Taylor@Sun.COM /*
34309517SBill.Taylor@Sun.COM  * hermon_modify_mpt_cmd_post()
34319517SBill.Taylor@Sun.COM  *    Context: Can be called from interrupt or base context.
34329517SBill.Taylor@Sun.COM  */
34339517SBill.Taylor@Sun.COM int
hermon_modify_mpt_cmd_post(hermon_state_t * state,hermon_hw_dmpt_t * mpt,uint_t mptindx,uint_t flags,uint_t sleepflag)34349517SBill.Taylor@Sun.COM hermon_modify_mpt_cmd_post(hermon_state_t *state, hermon_hw_dmpt_t *mpt,
34359517SBill.Taylor@Sun.COM     uint_t mptindx, uint_t flags, uint_t sleepflag)
34369517SBill.Taylor@Sun.COM {
34379517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
34389517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
34399517SBill.Taylor@Sun.COM 	uint64_t		data;
34409517SBill.Taylor@Sun.COM 	uint_t			size;
34419517SBill.Taylor@Sun.COM 	int			status, i;
34429517SBill.Taylor@Sun.COM 
34439517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
34449517SBill.Taylor@Sun.COM 
34459517SBill.Taylor@Sun.COM 	/* Get an "In" mailbox for the command */
34469517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
34479517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
34489517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
34499517SBill.Taylor@Sun.COM 		return (status);
34509517SBill.Taylor@Sun.COM 	}
34519517SBill.Taylor@Sun.COM 
34529517SBill.Taylor@Sun.COM 	/* Copy the Hermon "MODIFY_MPT" command into mailbox */
34539517SBill.Taylor@Sun.COM 	size = sizeof (hermon_hw_dmpt_t);
34549517SBill.Taylor@Sun.COM 	for (i = 0; i < (size >> 3); i++) {
34559517SBill.Taylor@Sun.COM 		data = ((uint64_t *)mpt)[i];
34569517SBill.Taylor@Sun.COM 		ddi_put64(mbox_info.mbi_in->mb_acchdl,
34579517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
34589517SBill.Taylor@Sun.COM 	}
34599517SBill.Taylor@Sun.COM 
34609517SBill.Taylor@Sun.COM 	/* Sync the mailbox for the device to read */
34619517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
34629517SBill.Taylor@Sun.COM 
34639517SBill.Taylor@Sun.COM 	/* Setup and post Hermon "MODIFY_MPT" command */
34649517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
34659517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
34669517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= mptindx;
34679517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= MODIFY_MPT;
34689517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= (uint16_t)flags;
34699517SBill.Taylor@Sun.COM 	cmd.cp_flags	= sleepflag;
34709517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
34719517SBill.Taylor@Sun.COM 
34729517SBill.Taylor@Sun.COM 	/* Free the mailbox */
34739517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
34749517SBill.Taylor@Sun.COM 	return (status);
34759517SBill.Taylor@Sun.COM }
34769517SBill.Taylor@Sun.COM 
34779517SBill.Taylor@Sun.COM 
3478*12965SWilliam.Taylor@Oracle.COM /*
3479*12965SWilliam.Taylor@Oracle.COM  * hermon_config_fc_cmd_post()
3480*12965SWilliam.Taylor@Oracle.COM  *    	Context: Can be called from user or kernel context.
3481*12965SWilliam.Taylor@Oracle.COM  *	This can do either a basic config passing in
3482*12965SWilliam.Taylor@Oracle.COM  * 	*hermon_hw_config_fc_basic_s, or config the N_Port table.
3483*12965SWilliam.Taylor@Oracle.COM  *	passing in pointer to an array of 32-bit id's
3484*12965SWilliam.Taylor@Oracle.COM  *	Note that either one needs to be cast to void *
3485*12965SWilliam.Taylor@Oracle.COM  */
3486*12965SWilliam.Taylor@Oracle.COM int
hermon_config_fc_cmd_post(hermon_state_t * state,void * cfginfo,int enable,int selector,int n_ports,int portnum,uint_t sleepflag)3487*12965SWilliam.Taylor@Oracle.COM hermon_config_fc_cmd_post(hermon_state_t *state, void *cfginfo, int enable,
3488*12965SWilliam.Taylor@Oracle.COM     int selector, int n_ports, int portnum, uint_t sleepflag)
3489*12965SWilliam.Taylor@Oracle.COM {
3490*12965SWilliam.Taylor@Oracle.COM 	hermon_mbox_info_t	mbox_info;
3491*12965SWilliam.Taylor@Oracle.COM 	hermon_cmd_post_t	cmd;
3492*12965SWilliam.Taylor@Oracle.COM 	uint64_t		data;
3493*12965SWilliam.Taylor@Oracle.COM 	uint32_t		portid;
3494*12965SWilliam.Taylor@Oracle.COM 	uint_t			size;
3495*12965SWilliam.Taylor@Oracle.COM 	int			status, i;
3496*12965SWilliam.Taylor@Oracle.COM 
3497*12965SWilliam.Taylor@Oracle.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
3498*12965SWilliam.Taylor@Oracle.COM 
3499*12965SWilliam.Taylor@Oracle.COM 	/* Get an "In" mailbox for the command */
3500*12965SWilliam.Taylor@Oracle.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_INMBOX;
3501*12965SWilliam.Taylor@Oracle.COM 	status = hermon_mbox_alloc(state, &mbox_info, sleepflag);
3502*12965SWilliam.Taylor@Oracle.COM 	if (status != HERMON_CMD_SUCCESS) {
3503*12965SWilliam.Taylor@Oracle.COM 		return (status);
3504*12965SWilliam.Taylor@Oracle.COM 	}
3505*12965SWilliam.Taylor@Oracle.COM 
3506*12965SWilliam.Taylor@Oracle.COM 	/* Copy the appropriate info into mailbox */
3507*12965SWilliam.Taylor@Oracle.COM 	if (selector == HERMON_HW_FC_CONF_BASIC) {	/* basic info */
3508*12965SWilliam.Taylor@Oracle.COM 		size = sizeof (hermon_hw_config_fc_basic_t);
3509*12965SWilliam.Taylor@Oracle.COM 		for (i = 0; i < (size >> 3); i++) {
3510*12965SWilliam.Taylor@Oracle.COM 			data = ((uint64_t *)cfginfo)[i];
3511*12965SWilliam.Taylor@Oracle.COM 			ddi_put64(mbox_info.mbi_in->mb_acchdl,
3512*12965SWilliam.Taylor@Oracle.COM 			    ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
3513*12965SWilliam.Taylor@Oracle.COM 		}
3514*12965SWilliam.Taylor@Oracle.COM 	} else {					/* NPort config */
3515*12965SWilliam.Taylor@Oracle.COM 		ASSERT(selector == HERMON_HW_FC_CONF_NPORT);
3516*12965SWilliam.Taylor@Oracle.COM 		size = n_ports * sizeof (uint32_t);
3517*12965SWilliam.Taylor@Oracle.COM 		/*
3518*12965SWilliam.Taylor@Oracle.COM 		 * n_ports must == number queried from card
3519*12965SWilliam.Taylor@Oracle.COM 		 *
3520*12965SWilliam.Taylor@Oracle.COM 		 * passed in is an array but for little endian needs to
3521*12965SWilliam.Taylor@Oracle.COM 		 * be rearranged in the mbox
3522*12965SWilliam.Taylor@Oracle.COM 		 */
3523*12965SWilliam.Taylor@Oracle.COM 		for (i = 0; i < (size >> 3); i++) {
3524*12965SWilliam.Taylor@Oracle.COM 			portid = ((uint32_t *)cfginfo)[i * 2];
3525*12965SWilliam.Taylor@Oracle.COM 			data = (uint64_t)portid << 32;
3526*12965SWilliam.Taylor@Oracle.COM 			if (i * 2 < n_ports) {
3527*12965SWilliam.Taylor@Oracle.COM 				portid = ((uint32_t *)cfginfo)[i * 2 + 1];
3528*12965SWilliam.Taylor@Oracle.COM 				data |= portid;
3529*12965SWilliam.Taylor@Oracle.COM 			}
3530*12965SWilliam.Taylor@Oracle.COM 			ddi_put64(mbox_info.mbi_in->mb_acchdl,
3531*12965SWilliam.Taylor@Oracle.COM 			    ((uint64_t *)mbox_info.mbi_in->mb_addr + i), data);
3532*12965SWilliam.Taylor@Oracle.COM 		}
3533*12965SWilliam.Taylor@Oracle.COM 	}
3534*12965SWilliam.Taylor@Oracle.COM 
3535*12965SWilliam.Taylor@Oracle.COM 	/* Sync the mailbox for the device to read */
3536*12965SWilliam.Taylor@Oracle.COM 	hermon_mbox_sync(mbox_info.mbi_in, 0, size, DDI_DMA_SYNC_FORDEV);
3537*12965SWilliam.Taylor@Oracle.COM 
3538*12965SWilliam.Taylor@Oracle.COM 	/* Setup and post Hermon "CONFIG_FC" command */
3539*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_inparm	= mbox_info.mbi_in->mb_mapaddr;
3540*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_outparm	= 0;
3541*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_inmod	= (uint32_t)(selector | portnum);
3542*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_opcode	= CONFIG_FC;
3543*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_opmod	= (uint16_t)enable;
3544*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_flags	= sleepflag;
3545*12965SWilliam.Taylor@Oracle.COM 	status = hermon_cmd_post(state, &cmd);
3546*12965SWilliam.Taylor@Oracle.COM 
3547*12965SWilliam.Taylor@Oracle.COM 	/* Free the mailbox */
3548*12965SWilliam.Taylor@Oracle.COM 	hermon_mbox_free(state, &mbox_info);
3549*12965SWilliam.Taylor@Oracle.COM 	return (status);
3550*12965SWilliam.Taylor@Oracle.COM }
3551*12965SWilliam.Taylor@Oracle.COM 
3552*12965SWilliam.Taylor@Oracle.COM /*
3553*12965SWilliam.Taylor@Oracle.COM  * hermon_sense_port_post() - used to send protocol running on a port
3554*12965SWilliam.Taylor@Oracle.COM  *	Context: Can be called from interrupt or base context
3555*12965SWilliam.Taylor@Oracle.COM  */
3556*12965SWilliam.Taylor@Oracle.COM 
3557*12965SWilliam.Taylor@Oracle.COM int
hermon_sense_port_post(hermon_state_t * state,uint_t portnum,uint32_t * protocol)3558*12965SWilliam.Taylor@Oracle.COM hermon_sense_port_post(hermon_state_t *state, uint_t portnum,
3559*12965SWilliam.Taylor@Oracle.COM     uint32_t *protocol)
3560*12965SWilliam.Taylor@Oracle.COM {
3561*12965SWilliam.Taylor@Oracle.COM 	hermon_cmd_post_t	cmd;
3562*12965SWilliam.Taylor@Oracle.COM 	int			status;
3563*12965SWilliam.Taylor@Oracle.COM 
3564*12965SWilliam.Taylor@Oracle.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
3565*12965SWilliam.Taylor@Oracle.COM 
3566*12965SWilliam.Taylor@Oracle.COM 	/* Setup and post Hermon "CMD_NOP" command */
3567*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_inparm	= 0;
3568*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_outparm	= 0;
3569*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_inmod	= (uint32_t)portnum;
3570*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_opcode	= SENSE_PORT;
3571*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_opmod	= 0;
3572*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
3573*12965SWilliam.Taylor@Oracle.COM 	status = hermon_cmd_post(state, &cmd);
3574*12965SWilliam.Taylor@Oracle.COM 	if (status == HERMON_CMD_SUCCESS) *protocol = (uint32_t)cmd.cp_outparm;
3575*12965SWilliam.Taylor@Oracle.COM 	return (status);
3576*12965SWilliam.Taylor@Oracle.COM }
3577*12965SWilliam.Taylor@Oracle.COM 
3578*12965SWilliam.Taylor@Oracle.COM 
3579*12965SWilliam.Taylor@Oracle.COM /*
3580*12965SWilliam.Taylor@Oracle.COM  * CONFIG_INT_MOD - used to configure INTERRUPT moderation
3581*12965SWilliam.Taylor@Oracle.COM  *	if command fails, *health is invalid/undefined
3582*12965SWilliam.Taylor@Oracle.COM  */
3583*12965SWilliam.Taylor@Oracle.COM int
hermon_config_int_mod(hermon_state_t * state,uint_t min_delay,uint_t vector)3584*12965SWilliam.Taylor@Oracle.COM hermon_config_int_mod(hermon_state_t *state, uint_t min_delay, uint_t vector)
3585*12965SWilliam.Taylor@Oracle.COM {
3586*12965SWilliam.Taylor@Oracle.COM 	hermon_cmd_post_t	cmd;
3587*12965SWilliam.Taylor@Oracle.COM 	int			status;
3588*12965SWilliam.Taylor@Oracle.COM 	uint64_t		inparm = 0;
3589*12965SWilliam.Taylor@Oracle.COM 
3590*12965SWilliam.Taylor@Oracle.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
3591*12965SWilliam.Taylor@Oracle.COM 
3592*12965SWilliam.Taylor@Oracle.COM 	/* Setup and post Hermon "CONFIG_INT_MOD" command */
3593*12965SWilliam.Taylor@Oracle.COM 	inparm = (((uint64_t)min_delay & 0xFFFF) << 48) ||
3594*12965SWilliam.Taylor@Oracle.COM 	    (((uint64_t)vector & 0xFFFF) << 32);
3595*12965SWilliam.Taylor@Oracle.COM 
3596*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_inparm	= inparm;
3597*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_outparm	= 0;
3598*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_inmod	= 0;
3599*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_opcode	= CONFIG_INT_MOD;
3600*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_opmod	= 0;
3601*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
3602*12965SWilliam.Taylor@Oracle.COM 	status = hermon_cmd_post(state, &cmd);
3603*12965SWilliam.Taylor@Oracle.COM 	return (status);
3604*12965SWilliam.Taylor@Oracle.COM }
3605*12965SWilliam.Taylor@Oracle.COM 
3606*12965SWilliam.Taylor@Oracle.COM 
36079517SBill.Taylor@Sun.COM int
hermon_nop_post(hermon_state_t * state,uint_t interval,uint_t sleep)36089517SBill.Taylor@Sun.COM hermon_nop_post(hermon_state_t *state, uint_t interval, uint_t sleep)
36099517SBill.Taylor@Sun.COM {
36109517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
36119517SBill.Taylor@Sun.COM 	int			status;
36129517SBill.Taylor@Sun.COM 
36139517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
36149517SBill.Taylor@Sun.COM 
36159517SBill.Taylor@Sun.COM 	/* Setup and post Hermon "CMD_NOP" command */
36169517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0;
36179517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
36189517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= interval;
36199517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= CMD_NOP;
36209517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
36219517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_SLEEP_NOSPIN;
36229517SBill.Taylor@Sun.COM 	if (sleep) cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
36239517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
36249517SBill.Taylor@Sun.COM 	return (status);
36259517SBill.Taylor@Sun.COM }
36269517SBill.Taylor@Sun.COM 
36279517SBill.Taylor@Sun.COM int
hermon_hw_health_check(hermon_state_t * state,int * health)3628*12965SWilliam.Taylor@Oracle.COM hermon_hw_health_check(hermon_state_t *state, int *health)
3629*12965SWilliam.Taylor@Oracle.COM {
3630*12965SWilliam.Taylor@Oracle.COM 	hermon_cmd_post_t	cmd;
3631*12965SWilliam.Taylor@Oracle.COM 	int			status;
3632*12965SWilliam.Taylor@Oracle.COM 
3633*12965SWilliam.Taylor@Oracle.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
3634*12965SWilliam.Taylor@Oracle.COM 
3635*12965SWilliam.Taylor@Oracle.COM 	/* Setup and post Hermon "CMD_NOP" command */
3636*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_inparm	= 0;
3637*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_outparm	= 0;
3638*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_inmod	= 0;
3639*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_opcode	= HW_HEALTH_CHECK;
3640*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_opmod	= 0;
3641*12965SWilliam.Taylor@Oracle.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
3642*12965SWilliam.Taylor@Oracle.COM 	status = hermon_cmd_post(state, &cmd);
3643*12965SWilliam.Taylor@Oracle.COM 	*health = (int)cmd.cp_outparm;
3644*12965SWilliam.Taylor@Oracle.COM 	return (status);
3645*12965SWilliam.Taylor@Oracle.COM }
3646*12965SWilliam.Taylor@Oracle.COM 
3647*12965SWilliam.Taylor@Oracle.COM int
hermon_setdebug_post(hermon_state_t * state)36489517SBill.Taylor@Sun.COM hermon_setdebug_post(hermon_state_t *state)
36499517SBill.Taylor@Sun.COM {
36509517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
36519517SBill.Taylor@Sun.COM 	int			status;
36529517SBill.Taylor@Sun.COM 
36539517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
36549517SBill.Taylor@Sun.COM 
36559517SBill.Taylor@Sun.COM 	/* Setup and post Hermon "CMD_NOP" command */
36569517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= 0xFFFFFFFFFFFFFFFF;
36579517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= 0;
36589517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 0;
36599517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= SET_DEBUG_MSG;
36609517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
36619517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
36629517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
36639517SBill.Taylor@Sun.COM 	return (status);
36649517SBill.Taylor@Sun.COM }
36659517SBill.Taylor@Sun.COM 
36669517SBill.Taylor@Sun.COM 
36679517SBill.Taylor@Sun.COM int
hermon_read_mtt_cmd_post(hermon_state_t * state,uint64_t mtt_addr,hermon_hw_mtt_t * mtt)36689517SBill.Taylor@Sun.COM hermon_read_mtt_cmd_post(hermon_state_t *state, uint64_t mtt_addr,
36699517SBill.Taylor@Sun.COM 	hermon_hw_mtt_t *mtt)
36709517SBill.Taylor@Sun.COM {
36719517SBill.Taylor@Sun.COM 
36729517SBill.Taylor@Sun.COM 	hermon_cmd_post_t	cmd;
36739517SBill.Taylor@Sun.COM 	hermon_mbox_info_t	mbox_info;
36749517SBill.Taylor@Sun.COM 	int			i, status;
36759517SBill.Taylor@Sun.COM 	uint_t			size;
36769517SBill.Taylor@Sun.COM 	uint64_t		data;
36779517SBill.Taylor@Sun.COM 
36789517SBill.Taylor@Sun.COM 	bzero((void *)&cmd, sizeof (hermon_cmd_post_t));
36799517SBill.Taylor@Sun.COM 
36809517SBill.Taylor@Sun.COM 	/* Get an "Out" mailbox for the command */
36819517SBill.Taylor@Sun.COM 	mbox_info.mbi_alloc_flags = HERMON_ALLOC_OUTMBOX;
36829517SBill.Taylor@Sun.COM 	status = hermon_mbox_alloc(state, &mbox_info, HERMON_CMD_SLEEP_NOSPIN);
36839517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
36849517SBill.Taylor@Sun.COM 		return (status);
36859517SBill.Taylor@Sun.COM 	}
36869517SBill.Taylor@Sun.COM 
36879517SBill.Taylor@Sun.COM 	/* Setup and post the "READ_MTT" command */
36889517SBill.Taylor@Sun.COM 	cmd.cp_inparm	= mtt_addr;
36899517SBill.Taylor@Sun.COM 	cmd.cp_outparm	= mbox_info.mbi_out->mb_mapaddr;
36909517SBill.Taylor@Sun.COM 	cmd.cp_inmod	= 1;
36919517SBill.Taylor@Sun.COM 	cmd.cp_opcode	= READ_MTT;
36929517SBill.Taylor@Sun.COM 	cmd.cp_opmod	= 0;
36939517SBill.Taylor@Sun.COM 	cmd.cp_flags	= HERMON_CMD_NOSLEEP_SPIN;
36949517SBill.Taylor@Sun.COM 	status = hermon_cmd_post(state, &cmd);
36959517SBill.Taylor@Sun.COM 	if (status != HERMON_CMD_SUCCESS) {
36969517SBill.Taylor@Sun.COM 		return (status);
36979517SBill.Taylor@Sun.COM 	}
36989517SBill.Taylor@Sun.COM 
36999517SBill.Taylor@Sun.COM 	/* Sync the mailbox to read the results */
37009517SBill.Taylor@Sun.COM 	size = sizeof (hermon_hw_mtt_t);
37019517SBill.Taylor@Sun.COM 	hermon_mbox_sync(mbox_info.mbi_out, 0, size, DDI_DMA_SYNC_FORCPU);
37029517SBill.Taylor@Sun.COM 
37039517SBill.Taylor@Sun.COM 	/* Copy mtt read out */
37049517SBill.Taylor@Sun.COM 	for (i = 0; i < (size >> 3); i++) {
37059517SBill.Taylor@Sun.COM 		data = ddi_get64(mbox_info.mbi_out->mb_acchdl,
37069517SBill.Taylor@Sun.COM 		    ((uint64_t *)mbox_info.mbi_out->mb_addr + i));
37079517SBill.Taylor@Sun.COM 		((uint64_t *)(void *)mtt)[i] = data;
37089517SBill.Taylor@Sun.COM 	}
37099517SBill.Taylor@Sun.COM 
37109517SBill.Taylor@Sun.COM 	/* Free the mailbox */
37119517SBill.Taylor@Sun.COM 	hermon_mbox_free(state, &mbox_info);
37129517SBill.Taylor@Sun.COM 	return (status);
37139517SBill.Taylor@Sun.COM }
3714