678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * CDDL HEADER START
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * The contents of this file are subject to the terms of the
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Common Development and Distribution License (the "License").
678453a8ed49104d8adad58f3ba591bdc39883e8speer * You may not use this file except in compliance with the License.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
678453a8ed49104d8adad58f3ba591bdc39883e8speer * or http://www.opensolaris.org/os/licensing.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * See the License for the specific language governing permissions
678453a8ed49104d8adad58f3ba591bdc39883e8speer * and limitations under the License.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * When distributing Covered Code, include this CDDL HEADER in each
678453a8ed49104d8adad58f3ba591bdc39883e8speer * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * If applicable, add the following below this CDDL HEADER, with the
678453a8ed49104d8adad58f3ba591bdc39883e8speer * fields enclosed by brackets "[]" replaced with your own identifying
678453a8ed49104d8adad58f3ba591bdc39883e8speer * information: Portions Copyright [yyyy] [name of copyright owner]
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * CDDL HEADER END
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Use is subject to license terms.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_intr.c
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * This file manages the interrupts for a hybrid I/O (hio) device.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * In the future, it may manage interrupts for all Neptune-based
678453a8ed49104d8adad58f3ba591bdc39883e8speer * devices.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer#include <sys/nxge/nxge_impl.h>
678453a8ed49104d8adad58f3ba591bdc39883e8speer#include <sys/nxge/nxge_hio.h>
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * External prototypes
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/* The following function may be found in nxge_[t|r]xdma.c */
678453a8ed49104d8adad58f3ba591bdc39883e8speerextern uint_t nxge_tx_intr(void *, void *);
678453a8ed49104d8adad58f3ba591bdc39883e8speerextern uint_t nxge_rx_intr(void *, void *);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Local prototypes
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speerstatic int nxge_intr_vec_find(nxge_t *, vpc_type_t, int);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_intr_add
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Add <channel>'s interrupt.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Arguments:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge
678453a8ed49104d8adad58f3ba591bdc39883e8speer * type Tx or Rx
678453a8ed49104d8adad58f3ba591bdc39883e8speer * channel The channel whose interrupt we want to add.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Notes:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Add here means: add a handler, enable, & arm the interrupt.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Context:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Service domain
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_status_t
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_intr_add(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_t *nxge,
678453a8ed49104d8adad58f3ba591bdc39883e8speer vpc_type_t type,
678453a8ed49104d8adad58f3ba591bdc39883e8speer int channel)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_intr_t *interrupts; /* The global interrupt data. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldg_t *group; /* The logical device group data. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldv_t *ldvp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer uint_t *inthandler; /* A parameter to ddi_intr_add_handler */
678453a8ed49104d8adad58f3ba591bdc39883e8speer int vector;
678453a8ed49104d8adad58f3ba591bdc39883e8speer int status1, status2;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer char c = (type == VP_BOUND_TX ? 'T' : 'R');
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_intr_add"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((vector = nxge_intr_vec_find(nxge, type, channel)) == -1) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_intr_add(%cDC %d): vector not found", c, channel));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer ldvp = &nxge->ldgvp->ldvp[vector];
678453a8ed49104d8adad58f3ba591bdc39883e8speer group = ldvp->ldgp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (group->nldvs == 1) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer inthandler = (uint_t *)group->ldvp->ldv_intr_handler;
678453a8ed49104d8adad58f3ba591bdc39883e8speer } else if (group->nldvs > 1) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer inthandler = (uint_t *)group->sys_intr_handler;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts = (nxge_intr_t *)&nxge->nxge_intr_type;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer status1 = DDI_SUCCESS;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((status2 = ddi_intr_add_handler(interrupts->htable[vector],
678453a8ed49104d8adad58f3ba591bdc39883e8speer (ddi_intr_handler_t *)inthandler, group->ldvp, nxge))
678453a8ed49104d8adad58f3ba591bdc39883e8speer != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_intr_add(%cDC %d): "
678453a8ed49104d8adad58f3ba591bdc39883e8speer "ddi_intr_add_handler(%d) returned %s",
678453a8ed49104d8adad58f3ba591bdc39883e8speer c, channel, vector, nxge_ddi_perror(status2)));
678453a8ed49104d8adad58f3ba591bdc39883e8speer status1 += status2;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_added++;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Enable the interrupt. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((status2 = ddi_intr_enable(interrupts->htable[vector]))
678453a8ed49104d8adad58f3ba591bdc39883e8speer != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_intr_add(%cDC %d): "
678453a8ed49104d8adad58f3ba591bdc39883e8speer "ddi_intr_enable(%d) returned %s",
678453a8ed49104d8adad58f3ba591bdc39883e8speer c, channel, vector, nxge_ddi_perror(status2)));
678453a8ed49104d8adad58f3ba591bdc39883e8speer status1 += status2;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (status1 == DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_enabled = B_TRUE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Finally, arm the interrupt. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (group->nldvs == 1) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxge);
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) npi_intr_ldg_mgmt_set(handle, group->ldg,
678453a8ed49104d8adad58f3ba591bdc39883e8speer B_TRUE, group->ldg_timer);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_intr_add"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_OK);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_intr_remove
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Remove <channel>'s interrupt.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Arguments:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge
678453a8ed49104d8adad58f3ba591bdc39883e8speer * type Tx or Rx
678453a8ed49104d8adad58f3ba591bdc39883e8speer * channel The channel whose interrupt we want to remove.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Notes:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Remove here means: disarm, disable, & remove the handler.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Context:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Service domain
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_status_t
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_intr_remove(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_t *nxge,
678453a8ed49104d8adad58f3ba591bdc39883e8speer vpc_type_t type,
678453a8ed49104d8adad58f3ba591bdc39883e8speer int channel)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_intr_t *interrupts; /* The global interrupt data. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldg_t *group; /* The logical device group data. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldv_t *ldvp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer int vector;
678453a8ed49104d8adad58f3ba591bdc39883e8speer int status1, status2;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer char c = (type == VP_BOUND_TX ? 'T' : 'R');
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_intr_remove"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((vector = nxge_intr_vec_find(nxge, type, channel)) == -1) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_intr_remove(%cDC %d): vector not found", c, channel));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer ldvp = &nxge->ldgvp->ldvp[vector];
678453a8ed49104d8adad58f3ba591bdc39883e8speer group = ldvp->ldgp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Disarm the interrupt. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (group->nldvs == 1) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxge);
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->arm = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) npi_intr_ldg_mgmt_set(handle, group->ldg,
678453a8ed49104d8adad58f3ba591bdc39883e8speer B_TRUE, group->ldg_timer);
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->arm = B_TRUE; /* HIOXXX There IS a better way */
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts = (nxge_intr_t *)&nxge->nxge_intr_type;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer status1 = DDI_SUCCESS;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Disable the interrupt. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((status2 = ddi_intr_disable(interrupts->htable[vector]))
678453a8ed49104d8adad58f3ba591bdc39883e8speer != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_intr_remove(%cDC %d)"
678453a8ed49104d8adad58f3ba591bdc39883e8speer ": ddi_intr_disable(%d) returned %s",
678453a8ed49104d8adad58f3ba591bdc39883e8speer c, channel, vector, nxge_ddi_perror(status2)));
678453a8ed49104d8adad58f3ba591bdc39883e8speer status1 += status2;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Remove the interrupt handler. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((status2 = ddi_intr_remove_handler(interrupts->htable[vector]))
678453a8ed49104d8adad58f3ba591bdc39883e8speer != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL, "nxge_intr_remove(%cDC %d)"
678453a8ed49104d8adad58f3ba591bdc39883e8speer ": ddi_intr_remove_handler(%d) returned %s",
678453a8ed49104d8adad58f3ba591bdc39883e8speer c, channel, vector, nxge_ddi_perror(status2)));
678453a8ed49104d8adad58f3ba591bdc39883e8speer status1 += status2;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (status1 == DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_added--;
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (interrupts->intr_added == 0)
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_enabled = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_intr_remove"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_OK);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_intr_vec_find
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Find the interrupt vector associated with <channel>.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Arguments:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge
678453a8ed49104d8adad58f3ba591bdc39883e8speer * type Tx or Rx
678453a8ed49104d8adad58f3ba591bdc39883e8speer * channel The channel whose vector we want to find.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Notes:
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Context:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Service domain
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speerstatic
678453a8ed49104d8adad58f3ba591bdc39883e8speerint
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_intr_vec_find(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_t *nxge,
678453a8ed49104d8adad58f3ba591bdc39883e8speer vpc_type_t type,
678453a8ed49104d8adad58f3ba591bdc39883e8speer int channel)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hw_pt_cfg_t *hardware;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldgv_t *ldgvp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldv_t *ldvp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer int first, limit, vector;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "==> nxge_intr_vec_find(%cDC %d)",
678453a8ed49104d8adad58f3ba591bdc39883e8speer type == VP_BOUND_TX ? 'T' : 'R', channel));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (nxge->ldgvp == 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_vec_find(%cDC %d): ldgvp == 0",
678453a8ed49104d8adad58f3ba591bdc39883e8speer type == VP_BOUND_TX ? 'T' : 'R', channel));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (-1);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware = &nxge->pt_config.hw_config;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer first = hardware->ldg_chn_start;
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (type == VP_BOUND_TX) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer first += 8; /* HIOXXX N2/NIU hack */
678453a8ed49104d8adad58f3ba591bdc39883e8speer limit = first + hardware->tdc.count;
678453a8ed49104d8adad58f3ba591bdc39883e8speer } else {
678453a8ed49104d8adad58f3ba591bdc39883e8speer limit = first + hardware->max_rdcs;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer ldgvp = nxge->ldgvp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer for (vector = first; vector < limit; vector++) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer ldvp = &ldgvp->ldvp[vector];
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (ldvp->channel == channel)
678453a8ed49104d8adad58f3ba591bdc39883e8speer break;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (vector == limit) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (-1);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_intr_vec_find"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (vector);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * ---------------------------------------------------------------------
678453a8ed49104d8adad58f3ba591bdc39883e8speer * HIO-specific interrupt functions.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * ---------------------------------------------------------------------
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_hio_intr_add
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Add <channel>'s interrupt.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Arguments:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge
678453a8ed49104d8adad58f3ba591bdc39883e8speer * type Tx or Rx
678453a8ed49104d8adad58f3ba591bdc39883e8speer * channel The channel whose interrupt we want to remove.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Notes:
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Context:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Guest domain
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_status_t
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_hio_intr_add(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_t *nxge,
678453a8ed49104d8adad58f3ba591bdc39883e8speer vpc_type_t type,
678453a8ed49104d8adad58f3ba591bdc39883e8speer int channel)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hio_dc_t *dc; /* The relevant DMA channel data structure. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_intr_t *interrupts; /* The global interrupt data. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldg_t *group; /* The logical device group data. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer uint_t *inthandler; /* A parameter to ddi_intr_add_handler */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer int vector; /* A shorthand variable */
678453a8ed49104d8adad58f3ba591bdc39883e8speer int ddi_status; /* The response to ddi_intr_add_handler */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer char c = (type == VP_BOUND_TX ? 'T' : 'R');
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "==> nxge_hio_intr_add(%cDC %d)", c, channel));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (nxge->ldgvp == 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_add(%cDC %d): ldgvp == 0", c, channel));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((dc = nxge_grp_dc_find(nxge, type, channel)) == 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_add: find(%s, %d) failed", c, channel));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* 'nxge_intr_type' is a bad name for this data structure. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts = (nxge_intr_t *)&nxge->nxge_intr_type;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Set <vector> here to make the following code easier to read. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer vector = dc->ldg.vector;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer group = &nxge->ldgvp->ldgp[vector];
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (group->nldvs == 1) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer inthandler = (uint_t *)group->ldvp->ldv_intr_handler;
678453a8ed49104d8adad58f3ba591bdc39883e8speer } else if (group->nldvs > 1) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer inthandler = (uint_t *)group->sys_intr_handler;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((ddi_status = ddi_intr_add_handler(interrupts->htable[vector],
678453a8ed49104d8adad58f3ba591bdc39883e8speer (ddi_intr_handler_t *)inthandler, group->ldvp, nxge))
678453a8ed49104d8adad58f3ba591bdc39883e8speer != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_add(%cDC %d): "
678453a8ed49104d8adad58f3ba591bdc39883e8speer "ddi_intr_add_handler(%d) returned %s",
678453a8ed49104d8adad58f3ba591bdc39883e8speer c, channel, vector, nxge_ddi_perror(ddi_status)));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_added++;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Enable the interrupt. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((ddi_status = ddi_intr_enable(interrupts->htable[vector]))
678453a8ed49104d8adad58f3ba591bdc39883e8speer != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_add(%cDC %d): "
678453a8ed49104d8adad58f3ba591bdc39883e8speer "ddi_intr_enable(%d) returned %s",
678453a8ed49104d8adad58f3ba591bdc39883e8speer c, channel, vector, nxge_ddi_perror(ddi_status)));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_enabled = B_TRUE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
e759c33a51f9bc8c2bbf4f37e5ea7e7de77d8edcMichael Speer /*
e759c33a51f9bc8c2bbf4f37e5ea7e7de77d8edcMichael Speer * Note: RDC interrupts will be armed in nxge_m_start(). This
e759c33a51f9bc8c2bbf4f37e5ea7e7de77d8edcMichael Speer * prevents us from getting an interrupt before we are ready
e759c33a51f9bc8c2bbf4f37e5ea7e7de77d8edcMichael Speer * to process packets.
e759c33a51f9bc8c2bbf4f37e5ea7e7de77d8edcMichael Speer */
e759c33a51f9bc8c2bbf4f37e5ea7e7de77d8edcMichael Speer if (type == VP_BOUND_TX) {
e759c33a51f9bc8c2bbf4f37e5ea7e7de77d8edcMichael Speer nxge_hio_ldgimgn(nxge, group);
e759c33a51f9bc8c2bbf4f37e5ea7e7de77d8edcMichael Speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer dc->interrupting = B_TRUE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_intr_add"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_OK);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_hio_intr_remove
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Remove <channel>'s interrupt.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Arguments:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge
678453a8ed49104d8adad58f3ba591bdc39883e8speer * type Tx or Rx
678453a8ed49104d8adad58f3ba591bdc39883e8speer * channel The channel whose interrupt we want to remove.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Notes:
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Context:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Guest domain
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_status_t
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_hio_intr_remove(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_t *nxge,
678453a8ed49104d8adad58f3ba591bdc39883e8speer vpc_type_t type,
678453a8ed49104d8adad58f3ba591bdc39883e8speer int channel)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hio_dc_t *dc; /* The relevant DMA channel data structure. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_intr_t *interrupts; /* The global interrupt data. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldg_t *group; /* The logical device group data. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer int vector; /* A shorthand variable */
678453a8ed49104d8adad58f3ba591bdc39883e8speer int status1, status2;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer char c = (type == VP_BOUND_TX ? 'T' : 'R');
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "==> nxge_hio_intr_remove(%cDC %d)", c, channel));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (nxge->ldgvp == 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_remove(%cDC %d): ldgvp == 0", c, channel));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((dc = nxge_grp_dc_find(nxge, type, channel)) == 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_remove(%cDC %d): DC FIND failed",
678453a8ed49104d8adad58f3ba591bdc39883e8speer c, channel));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (dc->interrupting == B_FALSE) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_remove(%cDC %d): interrupting == FALSE",
678453a8ed49104d8adad58f3ba591bdc39883e8speer c, channel));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_OK);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* 'nxge_intr_type' is a bad name for this data structure. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts = (nxge_intr_t *)&nxge->nxge_intr_type;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Set <vector> here to make the following code easier to read. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer vector = dc->ldg.vector;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer group = &nxge->ldgvp->ldgp[vector];
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Disarm the interrupt. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->arm = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hio_ldgimgn(nxge, group);
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->arm = B_TRUE; /* HIOXXX There IS a better way */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer status1 = DDI_SUCCESS;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Disable the interrupt. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((status2 = ddi_intr_disable(interrupts->htable[vector]))
678453a8ed49104d8adad58f3ba591bdc39883e8speer != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_remove(%cDC %d): "
678453a8ed49104d8adad58f3ba591bdc39883e8speer "ddi_intr_disable(%d) returned %s",
678453a8ed49104d8adad58f3ba591bdc39883e8speer c, channel, vector, nxge_ddi_perror(status2)));
678453a8ed49104d8adad58f3ba591bdc39883e8speer status1 += status2;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Remove the interrupt handler. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((status2 = ddi_intr_remove_handler(interrupts->htable[vector]))
678453a8ed49104d8adad58f3ba591bdc39883e8speer != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_remove(%cDC %d): "
678453a8ed49104d8adad58f3ba591bdc39883e8speer "ddi_intr_remove_handle(%d) returned %s",
678453a8ed49104d8adad58f3ba591bdc39883e8speer c, channel, vector, nxge_ddi_perror(status2)));
678453a8ed49104d8adad58f3ba591bdc39883e8speer status1 += status2;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (status1 == DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer dc->interrupting = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_added--;
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (interrupts->intr_added == 0)
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_enabled = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_intr_remove"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_OK);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_hio_intr_init
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Initialize interrupts in a guest domain.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Arguments:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Notes:
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Context:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Guest domain
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_status_t
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_hio_intr_init(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_t *nxge)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer int *prop_val;
678453a8ed49104d8adad58f3ba591bdc39883e8speer uint_t prop_len;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_intr_t *interrupts;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer int intr_type, behavior;
678453a8ed49104d8adad58f3ba591bdc39883e8speer int nintrs, navail, nactual;
678453a8ed49104d8adad58f3ba591bdc39883e8speer int inum = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer int ddi_status = DDI_SUCCESS;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hw_pt_cfg_t *hardware = &nxge->pt_config.hw_config;
678453a8ed49104d8adad58f3ba591bdc39883e8speer int i;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_intr_init"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Look up the "interrupts" property. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((ddi_prop_lookup_int_array(DDI_DEV_T_ANY, nxge->dip, 0,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "interrupts", &prop_val, &prop_len)) != DDI_PROP_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "==> nxge_hio_intr_init(obp): no 'interrupts' property"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * For each device assigned, the content of each interrupts
678453a8ed49104d8adad58f3ba591bdc39883e8speer * property is its logical device group.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Assignment of interrupts property is in the the following
678453a8ed49104d8adad58f3ba591bdc39883e8speer * order:
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * two receive channels
678453a8ed49104d8adad58f3ba591bdc39883e8speer * two transmit channels
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer for (i = 0; i < prop_len; i++) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware->ldg[i] = prop_val[i];
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "==> nxge_hio_intr_init(obp): F%d: interrupt #%d, ldg %d",
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge->function_num, i, hardware->ldg[i]));
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer ddi_prop_free(prop_val);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware->max_grpids = prop_len;
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware->max_ldgs = prop_len;
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware->ldg_chn_start = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* ----------------------------------------------------- */
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts = (nxge_intr_t *)&nxge->nxge_intr_type;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_registered = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_enabled = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->start_inum = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer ddi_status = ddi_intr_get_supported_types(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge->dip, &interrupts->intr_types);
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (ddi_status != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "ddi_intr_get_supported_types() returned 0x%x, "
678453a8ed49104d8adad58f3ba591bdc39883e8speer "types = 0x%x", ddi_status, interrupts->intr_types));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, HIO_CTL, "ddi_intr_get_supported_types() "
678453a8ed49104d8adad58f3ba591bdc39883e8speer "returned 0x%x, types = 0x%x", ddi_status, interrupts->intr_types));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* HIOXXX hack */
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_type = DDI_INTR_TYPE_FIXED;
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* HIOXXX hack */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer intr_type = interrupts->intr_type;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer ddi_status = ddi_intr_get_navail(nxge->dip, intr_type, &navail);
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (ddi_status != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "ddi_intr_get_navail() returned %s, navail: %d",
678453a8ed49104d8adad58f3ba591bdc39883e8speer ddi_status == DDI_FAILURE ? "DDI_FAILURE" :
678453a8ed49104d8adad58f3ba591bdc39883e8speer "DDI_INTR_NOTFOUND", navail));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_init: number of available interrupts: %d", navail));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer ddi_status = ddi_intr_get_nintrs(nxge->dip, intr_type, &nintrs);
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (ddi_status != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "ddi_intr_get_nintrs() returned %s, nintrs: %d",
678453a8ed49104d8adad58f3ba591bdc39883e8speer ddi_status == DDI_FAILURE ? "DDI_FAILURE" :
678453a8ed49104d8adad58f3ba591bdc39883e8speer "DDI_INTR_NOTFOUND", nintrs));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_init: number of interrupts: %d", nintrs));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_size = navail * sizeof (ddi_intr_handle_t);
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->htable = kmem_alloc(interrupts->intr_size, KM_SLEEP);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * When <behavior> is set to DDI_INTR_ALLOC_STRICT,
678453a8ed49104d8adad58f3ba591bdc39883e8speer * ddi_intr_alloc() succeeds if and only if <navail>
678453a8ed49104d8adad58f3ba591bdc39883e8speer * interrupts are are allocated. Otherwise, it fails.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer behavior = ((intr_type == DDI_INTR_TYPE_FIXED) ?
678453a8ed49104d8adad58f3ba591bdc39883e8speer DDI_INTR_ALLOC_STRICT : DDI_INTR_ALLOC_NORMAL);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer ddi_status = ddi_intr_alloc(nxge->dip, interrupts->htable, intr_type,
678453a8ed49104d8adad58f3ba591bdc39883e8speer inum, navail, &nactual, behavior);
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (ddi_status != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "ddi_intr_alloc() returned 0x%x%, "
678453a8ed49104d8adad58f3ba591bdc39883e8speer "number allocated: %d", ddi_status, nactual));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_ERROR);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_init: number of interrupts allocated: %d", nactual));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* <ninterrupts> is a dead variable: we may as well use it. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware->ninterrupts = nactual;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* FOI: Get the interrupt priority. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((ddi_status = ddi_intr_get_pri(interrupts->htable[0],
678453a8ed49104d8adad58f3ba591bdc39883e8speer (uint_t *)&interrupts->pri)) != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer " ddi_intr_get_pri() failed: %d", ddi_status));
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_init: interrupt priority: %d", interrupts->pri));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* FOI: Get our interrupt capability flags. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((ddi_status = ddi_intr_get_cap(interrupts->htable[0],
678453a8ed49104d8adad58f3ba591bdc39883e8speer &interrupts->intr_cap)) != DDI_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "ddi_intr_get_cap() failed: %d", ddi_status));
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nxge_hio_intr_init: interrupt capabilities: %d",
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_cap));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_registered = B_TRUE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_intr_init"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (NXGE_OK);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_hio_intr_uninit
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Uninitialize interrupts in a guest domain.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Arguments:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Notes:
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Context:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Guest domain
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speervoid
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_hio_intr_uninit(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_t *nxge)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hw_pt_cfg_t *hardware;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_intr_t *interrupts;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldgv_t *control;
678453a8ed49104d8adad58f3ba591bdc39883e8speer int i;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_intr_uninit"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* ----------------------------------------------------- */
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts = (nxge_intr_t *)&nxge->nxge_intr_type;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * If necessary, disable any currently active interrupts.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (interrupts->intr_enabled) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_grp_set_t *set;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_grp_t *group;
678453a8ed49104d8adad58f3ba591bdc39883e8speer int channel;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer set = &nxge->tx_set;
678453a8ed49104d8adad58f3ba591bdc39883e8speer group = set->group[0]; /* Assumption: only one group! */
678453a8ed49104d8adad58f3ba591bdc39883e8speer for (channel = 0; channel < NXGE_MAX_TDCS; channel++) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((1 << channel) & group->map) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) nxge_hio_intr_remove(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge, VP_BOUND_TX, channel);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer set = &nxge->rx_set;
678453a8ed49104d8adad58f3ba591bdc39883e8speer group = set->group[0]; /* Assumption: only one group! */
678453a8ed49104d8adad58f3ba591bdc39883e8speer for (channel = 0; channel < NXGE_MAX_RDCS; channel++) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((1 << channel) & group->map) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) nxge_hio_intr_remove(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge, VP_BOUND_RX, channel);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Free all of our allocated interrupts.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware = &nxge->pt_config.hw_config;
678453a8ed49104d8adad58f3ba591bdc39883e8speer for (i = 0; i < hardware->ninterrupts; i++) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (interrupts->htable[i])
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) ddi_intr_free(interrupts->htable[i]);
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->htable[i] = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer interrupts->intr_registered = B_FALSE;
48056c53c7a3d65cab2626a67418401d97b58c1aMichael Speer KMEM_FREE(interrupts->htable, interrupts->intr_size);
48056c53c7a3d65cab2626a67418401d97b58c1aMichael Speer interrupts->htable = NULL;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
9d5b8bc52bffb83a81625224a3b60481b39a6ba9Michael Speer if (nxge->ldgvp == NULL)
9d5b8bc52bffb83a81625224a3b60481b39a6ba9Michael Speer goto nxge_hio_intr_uninit_exit;
9d5b8bc52bffb83a81625224a3b60481b39a6ba9Michael Speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer control = nxge->ldgvp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (control->ldgp) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer KMEM_FREE(control->ldgp,
678453a8ed49104d8adad58f3ba591bdc39883e8speer sizeof (nxge_ldg_t) * NXGE_INT_MAX_LDGS);
678453a8ed49104d8adad58f3ba591bdc39883e8speer control->ldgp = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (control->ldvp) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer KMEM_FREE(control->ldvp,
678453a8ed49104d8adad58f3ba591bdc39883e8speer sizeof (nxge_ldv_t) * NXGE_INT_MAX_LDS);
678453a8ed49104d8adad58f3ba591bdc39883e8speer control->ldvp = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
48056c53c7a3d65cab2626a67418401d97b58c1aMichael Speer KMEM_FREE(control, sizeof (nxge_ldgv_t));
48056c53c7a3d65cab2626a67418401d97b58c1aMichael Speer nxge->ldgvp = NULL;
48056c53c7a3d65cab2626a67418401d97b58c1aMichael Speer
9d5b8bc52bffb83a81625224a3b60481b39a6ba9Michael Speernxge_hio_intr_uninit_exit:
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_intr_uninit"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_hio_tdsv_add
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Add a transmit device interrupt.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Arguments:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge
678453a8ed49104d8adad58f3ba591bdc39883e8speer * dc The TDC whose interrupt we're adding
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Notes:
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Context:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Guest domain
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speerstatic
678453a8ed49104d8adad58f3ba591bdc39883e8speerhv_rv_t
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_hio_tdsv_add(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_t *nxge,
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hio_dc_t *dc)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hw_pt_cfg_t *hardware = &nxge->pt_config.hw_config;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxhv_dc_fp_t *tx = &nhd->hio.tx;
678453a8ed49104d8adad58f3ba591bdc39883e8speer hv_rv_t hv_rv;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (tx->getinfo == 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nx_hio_tdsv_add: tx->getinfo absent"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (EINVAL);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Get the dma channel information.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer hv_rv = (*tx->getinfo)(dc->cookie, dc->page, &dc->ldg.index,
678453a8ed49104d8adad58f3ba591bdc39883e8speer &dc->ldg.ldsv);
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (hv_rv != 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nx_hio_tdsv_add: tx->getinfo failed: %ld", hv_rv));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (EIO);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nx_hio_tdsv_add: VRgroup = %d, LDSV = %d",
678453a8ed49104d8adad58f3ba591bdc39883e8speer (int)dc->ldg.index, (int)dc->ldg.ldsv));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (hardware->tdc.count == 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware->tdc.start = dc->channel;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware->tdc.count++;
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware->tdc.owned++;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * In version 1.0 of the hybrid I/O driver, there
678453a8ed49104d8adad58f3ba591bdc39883e8speer * are eight interrupt vectors per VR.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Vectors 0 - 3 are reserved for RDCs.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Vectors 4 - 7 are reserved for TDCs.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer dc->ldg.vector = (dc->ldg.ldsv % 2) + HIO_INTR_BLOCK_SIZE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer // Version 1.0 hack only!
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (0);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_hio_rdsv_add
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Add a transmit device interrupt.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Arguments:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge
678453a8ed49104d8adad58f3ba591bdc39883e8speer * dc The RDC whose interrupt we're adding
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Notes:
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Context:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Guest domain
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speerstatic
678453a8ed49104d8adad58f3ba591bdc39883e8speerhv_rv_t
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_hio_rdsv_add(
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_t *nxge,
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hio_dc_t *dc)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hio_data_t *nhd = (nxge_hio_data_t *)nxge->nxge_hw_p->hio;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_hw_pt_cfg_t *hardware = &nxge->pt_config.hw_config;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxhv_dc_fp_t *rx = &nhd->hio.rx;
678453a8ed49104d8adad58f3ba591bdc39883e8speer hv_rv_t hv_rv;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (rx->getinfo == 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nx_hio_tdsv_add: rx->getinfo absent"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (EINVAL);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Get DMA channel information.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer hv_rv = (*rx->getinfo)(dc->cookie, dc->page, &dc->ldg.index,
678453a8ed49104d8adad58f3ba591bdc39883e8speer &dc->ldg.ldsv);
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (hv_rv != 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_ERROR_MSG((nxge, NXGE_ERR_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nx_hio_tdsv_add: rx->getinfo failed: %ld", hv_rv));
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (EIO);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL,
678453a8ed49104d8adad58f3ba591bdc39883e8speer "nx_hio_rdsv_add: VRgroup = %d, LDSV = %d",
678453a8ed49104d8adad58f3ba591bdc39883e8speer (int)dc->ldg.index, (int)dc->ldg.ldsv));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (hardware->max_rdcs == 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware->start_rdc = dc->channel;
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware->def_rdc = dc->channel;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer hardware->max_rdcs++;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * In version 1.0 of the hybrid I/O driver, there
678453a8ed49104d8adad58f3ba591bdc39883e8speer * are eight interrupt vectors per VR.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Vectors 0 - 3 are reserved for RDCs.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer dc->ldg.vector = (dc->ldg.ldsv % 2);
678453a8ed49104d8adad58f3ba591bdc39883e8speer // Version 1.0 hack only!
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (0);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_hio_ldsv_add
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Add a transmit or receive interrupt.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Arguments:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge
678453a8ed49104d8adad58f3ba591bdc39883e8speer * dc The DMA channel whose interrupt we're adding
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Notes:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Guest domains can only add interrupts for DMA channels.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * They cannot access the MAC, MIF, or SYSERR interrupts.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Context:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Guest domain
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerint
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyernxge_hio_ldsv_add(nxge_t *nxge, nxge_hio_dc_t *dc)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldgv_t *control;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldg_t *group;
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldv_t *device;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (dc->type == VP_BOUND_TX) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_ldsv_add(TDC %d)",
678453a8ed49104d8adad58f3ba591bdc39883e8speer dc->channel));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (nxge_hio_tdsv_add(nxge, dc) != 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return (EIO);
678453a8ed49104d8adad58f3ba591bdc39883e8speer } else {
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "==> nxge_hio_ldsv_add(RDC %d)",
678453a8ed49104d8adad58f3ba591bdc39883e8speer dc->channel));
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (nxge_hio_rdsv_add(nxge, dc) != 0)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return (EIO);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer dc->ldg.map |= (1 << dc->ldg.ldsv);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer control = nxge->ldgvp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (control == NULL) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer control = KMEM_ZALLOC(sizeof (nxge_ldgv_t), KM_SLEEP);
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge->ldgvp = control;
678453a8ed49104d8adad58f3ba591bdc39883e8speer control->maxldgs = 1;
678453a8ed49104d8adad58f3ba591bdc39883e8speer control->maxldvs = 1;
678453a8ed49104d8adad58f3ba591bdc39883e8speer control->ldgp = KMEM_ZALLOC(
678453a8ed49104d8adad58f3ba591bdc39883e8speer sizeof (nxge_ldg_t) * NXGE_INT_MAX_LDGS, KM_SLEEP);
678453a8ed49104d8adad58f3ba591bdc39883e8speer control->ldvp = KMEM_ZALLOC(
678453a8ed49104d8adad58f3ba591bdc39883e8speer sizeof (nxge_ldv_t) * NXGE_INT_MAX_LDS, KM_SLEEP);
678453a8ed49104d8adad58f3ba591bdc39883e8speer } else {
678453a8ed49104d8adad58f3ba591bdc39883e8speer control->maxldgs++;
678453a8ed49104d8adad58f3ba591bdc39883e8speer control->maxldvs++;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Initialize the logical device group data structure first.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer group = &control->ldgp[dc->ldg.vector];
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) memset(group, 0, sizeof (*group));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * <hw_config.ldg> is a copy of the "interrupts" property.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->ldg = nxge->pt_config.hw_config.ldg[dc->ldg.vector];
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->vldg_index = (uint8_t)dc->ldg.index;
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Since <vldg_index> is a dead variable, I'm reusing
678453a8ed49104d8adad58f3ba591bdc39883e8speer * it in Hybrid I/O to calculate the offset into the
678453a8ed49104d8adad58f3ba591bdc39883e8speer * virtual PIO_LDSV space.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->arm = B_TRUE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->ldg_timer = NXGE_TIMER_LDG;
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->func = nxge->function_num;
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->vector = dc->ldg.vector;
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * <intdata> appears to be a dead variable.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Though it is not used anywhere in the driver,
678453a8ed49104d8adad58f3ba591bdc39883e8speer * we'll set it anyway.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->intdata = SID_DATA(group->func, group->vector);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->sys_intr_handler = nxge_intr; /* HIOXXX Does this work? */
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->nxgep = nxge;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Initialize the logical device state vector next.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer device = &control->ldvp[dc->ldg.ldsv];
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->ldg_assigned = group->ldg;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->ldv = dc->ldg.ldsv;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (dc->type == VP_BOUND_TX) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->is_txdma = B_TRUE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->is_rxdma = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->ldv_intr_handler = nxge_tx_intr;
678453a8ed49104d8adad58f3ba591bdc39883e8speer } else {
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->is_rxdma = B_TRUE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->is_txdma = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->ldv_intr_handler = nxge_rx_intr;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->is_mif = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->is_mac = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->is_syserr = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->use_timer = B_FALSE; /* Set to B_TRUE for syserr only. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->channel = dc->channel;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->vdma_index = dc->page;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->func = nxge->function_num;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->ldgp = group;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->ldv_flags = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->ldv_ldf_masks = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer device->nxgep = nxge;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * This code seems to imply a strict 1-to-1 correspondence.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->nldvs++;
678453a8ed49104d8adad58f3ba591bdc39883e8speer group->ldvp = device;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer control->nldvs++;
678453a8ed49104d8adad58f3ba591bdc39883e8speer control->ldg_intrs++;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_DEBUG_MSG((nxge, HIO_CTL, "<== nxge_hio_ldsv_add"));
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (0);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge_hio_ldsv_im
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Manage a VLDG's interrupts.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Arguments:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * nxge
678453a8ed49104d8adad58f3ba591bdc39883e8speer * group The VLDG to manage
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Notes:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * There are 8 sets of 4 64-bit registers per VR, 1 per LDG.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * That sums to 256 bytes of virtual PIO_LDSV space.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * VLDG0 starts at offset 0,
678453a8ed49104d8adad58f3ba591bdc39883e8speer * VLDG1 starts at offset 32, etc.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Each set consists of 4 registers:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Logical Device State Vector 0. LDSV0
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Logical Device State Vector 1. LDSV1
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Logical Device State Vector 2. LDSV2
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Logical Device Group Interrupt Management. LDGIMGN
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * The first three (LDSVx) are read-only. The 4th register is the
678453a8ed49104d8adad58f3ba591bdc39883e8speer * LDGIMGN, the LDG Interrupt Management register, which is used to
678453a8ed49104d8adad58f3ba591bdc39883e8speer * arm the LDG, or set its timer.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * The offset to write to is calculated as follows:
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * 0x2000 + (VLDG << 4) + offset, where:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * VDLG is the virtual group, i.e., index of the LDG.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * offset is the offset (alignment 8) of the register
678453a8ed49104d8adad58f3ba591bdc39883e8speer * to read or write.
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * So, for example, if we wanted to arm the first TDC of VRx, we would
678453a8ed49104d8adad58f3ba591bdc39883e8speer * calculate the address as:
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * 0x2000 + (0 << 4) + 0x18 = 0x18
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Context:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * Guest domain
678453a8ed49104d8adad58f3ba591bdc39883e8speer *
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speervoid
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_hio_ldsv_im(
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Read any register in the PIO_LDSV space. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_t *nxge,
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldg_t *group,
678453a8ed49104d8adad58f3ba591bdc39883e8speer pio_ld_op_t op,
678453a8ed49104d8adad58f3ba591bdc39883e8speer uint64_t *value)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer uint64_t offset = VLDG_OFFSET;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer offset += group->vldg_index << VLDG_SLL; /* bits 7:5 */
678453a8ed49104d8adad58f3ba591bdc39883e8speer offset += (op * sizeof (uint64_t)); /* 0, 8, 16, 24 */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_REG_RD64(nxge->npi_handle, offset, value);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speervoid
678453a8ed49104d8adad58f3ba591bdc39883e8speernxge_hio_ldgimgn(
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Write the PIO_LDGIMGN register. */
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_t *nxge,
678453a8ed49104d8adad58f3ba591bdc39883e8speer nxge_ldg_t *group)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer uint64_t offset = VLDG_OFFSET;
678453a8ed49104d8adad58f3ba591bdc39883e8speer ldgimgm_t mgm;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer offset += group->vldg_index << VLDG_SLL; /* bits 7:5 */
678453a8ed49104d8adad58f3ba591bdc39883e8speer offset += (PIO_LDGIMGN * sizeof (uint64_t)); /* 24 */
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer mgm.value = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (group->arm) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer mgm.bits.ldw.arm = 1;
678453a8ed49104d8adad58f3ba591bdc39883e8speer mgm.bits.ldw.timer = group->ldg_timer;
678453a8ed49104d8adad58f3ba591bdc39883e8speer } else {
678453a8ed49104d8adad58f3ba591bdc39883e8speer mgm.bits.ldw.arm = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer mgm.bits.ldw.timer = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer NXGE_REG_WR64(nxge->npi_handle, offset, mgm.value);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}