xnbu.c revision 551bc2a66868b5cb5be6b70ab9f55515e77a39a9
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The contents of this file are subject to the terms of the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Common Development and Distribution License (the "License").
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You may not use this file except in compliance with the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * or http://www.opensolaris.org/os/licensing.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When distributing Covered Code, include this CDDL HEADER in each
843e19887f64dde75055cf8842fc4db2171eff45johnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If applicable, add the following below this CDDL HEADER, with the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * fields enclosed by brackets "[]" replaced with your own identifying
843e19887f64dde75055cf8842fc4db2171eff45johnlev * information: Portions Copyright [yyyy] [name of copyright owner]
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER END
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Use is subject to license terms.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#pragma ident "%Z%%M% %I% %E% SMI"
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Xen inter-domain backend - GLDv3 driver edition.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * A traditional GLDv3 driver used to communicate with a guest
843e19887f64dde75055cf8842fc4db2171eff45johnlev * domain. This driver is typically plumbed underneath the IP stack
843e19887f64dde75055cf8842fc4db2171eff45johnlev * or a software ethernet bridge.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include "xnb.h"
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/sunddi.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/conf.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/modctl.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/strsubr.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/dlpi.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/pattr.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/mac.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/mac_ether.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <xen/sys/xendev.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Required driver entry points for GLDv3 */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xnbu_m_start(void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xnbu_m_stop(void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xnbu_m_set_mac_addr(void *, const uint8_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xnbu_m_set_multicast(void *, boolean_t, const uint8_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xnbu_m_set_promiscuous(void *, boolean_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int xnbu_m_stat(void *, uint_t, uint64_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xnbu_m_blank(void *, time_t, uint_t);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void xnbu_m_resources(void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic boolean_t xnbu_m_getcapab(void *, mac_capab_t, void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic mblk_t *xnbu_m_send(void *, mblk_t *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevtypedef struct xnbu {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_handle_t u_mh;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_resource_handle_t u_rx_handle;
843e19887f64dde75055cf8842fc4db2171eff45johnlev boolean_t u_need_sched;
843e19887f64dde75055cf8842fc4db2171eff45johnlev} xnbu_t;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic mac_callbacks_t xnb_callbacks = {
843e19887f64dde75055cf8842fc4db2171eff45johnlev MC_RESOURCES | MC_GETCAPAB,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_m_stat,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_m_start,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_m_stop,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_m_set_promiscuous,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_m_set_multicast,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_m_set_mac_addr,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_m_send,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_m_resources,
843e19887f64dde75055cf8842fc4db2171eff45johnlev NULL,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_m_getcapab
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_to_host(xnb_t *xnbp, mblk_t *mp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj xnbu_t *xnbup = xnbp->xnb_flavour_data;
843e19887f64dde75055cf8842fc4db2171eff45johnlev boolean_t sched = B_FALSE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(mp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_rx(xnbup->u_mh, xnbup->u_rx_handle, mp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_enter(&xnbp->xnb_tx_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If a transmit attempt failed because we ran out of ring
843e19887f64dde75055cf8842fc4db2171eff45johnlev * space and there is now some space, re-enable the transmit
843e19887f64dde75055cf8842fc4db2171eff45johnlev * path.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xnbup->u_need_sched &&
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj RING_HAS_UNCONSUMED_REQUESTS(&xnbp->xnb_rx_ring)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev sched = B_TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbup->u_need_sched = B_FALSE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_exit(&xnbp->xnb_tx_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (sched)
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_tx_update(xnbup->u_mh);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic mblk_t *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_cksum_from_peer(xnb_t *xnbp, mblk_t *mp, uint16_t flags)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Take a conservative approach - if the checksum is blank
843e19887f64dde75055cf8842fc4db2171eff45johnlev * then we fill it in.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If the consumer of the packet is IP then we might actually
843e19887f64dde75055cf8842fc4db2171eff45johnlev * only need fill it in if the data is not validated, but how
843e19887f64dde75055cf8842fc4db2171eff45johnlev * do we know who might end up with the packet?
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((flags & NETTXF_csum_blank) != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The checksum is blank. We must fill it in here.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev mp = xnb_process_cksum_flags(xnbp, mp, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Because we calculated the checksum ourselves we
843e19887f64dde75055cf8842fc4db2171eff45johnlev * know that it must be good, so we assert this.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
d4071fd381732cbdb28722bca7eb075e11755e6edme flags |= NETTXF_data_validated;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((flags & NETTXF_data_validated) != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The checksum is asserted valid.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The hardware checksum offload specification says
843e19887f64dde75055cf8842fc4db2171eff45johnlev * that we must provide the actual checksum as well as
843e19887f64dde75055cf8842fc4db2171eff45johnlev * an assertion that it is valid, but the protocol
843e19887f64dde75055cf8842fc4db2171eff45johnlev * stack doesn't actually use it so we don't bother.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If it was necessary we could grovel in the packet
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to find it.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) hcksum_assoc(mp, NULL, NULL, 0, 0, 0, 0,
843e19887f64dde75055cf8842fc4db2171eff45johnlev HCK_FULLCKSUM | HCK_FULLCKSUM_OK, KM_NOSLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (mp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic uint16_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_cksum_to_peer(xnb_t *xnbp, mblk_t *mp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev uint16_t r = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj if (xnbp->xnb_cksum_offload) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev uint32_t pflags;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev hcksum_retrieve(mp, NULL, NULL, NULL, NULL,
843e19887f64dde75055cf8842fc4db2171eff45johnlev NULL, NULL, &pflags);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If the protocol stack has requested checksum
843e19887f64dde75055cf8842fc4db2171eff45johnlev * offload, inform the peer that we have not
843e19887f64dde75055cf8842fc4db2171eff45johnlev * calculated the checksum.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((pflags & HCK_FULLCKSUM) != 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev r |= NETRXF_csum_blank;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (r);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_connected(xnb_t *xnbp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj xnbu_t *xnbup = xnbp->xnb_flavour_data;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_link_update(xnbup->u_mh, LINK_STATE_UP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We are able to send packets now - bring them on.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_tx_update(xnbup->u_mh);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_disconnected(xnb_t *xnbp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj xnbu_t *xnbup = xnbp->xnb_flavour_data;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_link_update(xnbup->u_mh, LINK_STATE_DOWN);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic boolean_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_hotplug(xnb_t *xnbp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (B_TRUE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic mblk_t *
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_m_send(void *arg, mblk_t *mp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnb_t *xnbp = arg;
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj xnbu_t *xnbup = xnbp->xnb_flavour_data;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mp = xnb_copy_to_peer(arg, mp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* XXPV dme: playing with need_sched without txlock? */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If we consumed all of the mblk_t's offered, perhaps we need
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to indicate that we can accept more. Otherwise we are full
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and need to wait for space.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mp == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If a previous transmit attempt failed because the ring
843e19887f64dde75055cf8842fc4db2171eff45johnlev * was full, try again now.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xnbup->u_need_sched) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbup->u_need_sched = B_FALSE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_tx_update(xnbup->u_mh);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbup->u_need_sched = B_TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (mp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xnbu_m_set_mac_addr() -- set the physical network address on the board
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* ARGSUSED */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_m_set_mac_addr(void *arg, const uint8_t *macaddr)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnb_t *xnbp = arg;
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj xnbu_t *xnbup = xnbp->xnb_flavour_data;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj bcopy(macaddr, xnbp->xnb_mac_addr, ETHERADDRL);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mac_unicst_update(xnbup->u_mh, xnbp->xnb_mac_addr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xnbu_m_set_multicast() -- set (enable) or disable a multicast address
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_m_set_multicast(void *arg, boolean_t add, const uint8_t *mca)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We always accept all packets from the peer, so nothing to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * do for enable or disable.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xnbu_m_set_promiscuous() -- set or reset promiscuous mode on the board
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* ARGSUSED */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_m_set_promiscuous(void *arg, boolean_t on)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We always accept all packets from the peer, so nothing to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * do for enable or disable.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xnbu_m_start() -- start the board receiving and enable interrupts.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_m_start(void *arg)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xnbu_m_stop() - disable hardware
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_m_stop(void *arg)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_m_stat(void *arg, uint_t stat, uint64_t *val)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnb_t *xnbp = arg;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_enter(&xnbp->xnb_tx_lock);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_enter(&xnbp->xnb_rx_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define map_stat(q, r) \
843e19887f64dde75055cf8842fc4db2171eff45johnlev case (MAC_STAT_##q): \
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj *val = xnbp->xnb_stat_##r; \
843e19887f64dde75055cf8842fc4db2171eff45johnlev break
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev switch (stat) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev map_stat(IPACKETS, ipackets);
843e19887f64dde75055cf8842fc4db2171eff45johnlev map_stat(OPACKETS, opackets);
843e19887f64dde75055cf8842fc4db2171eff45johnlev map_stat(RBYTES, rbytes);
843e19887f64dde75055cf8842fc4db2171eff45johnlev map_stat(OBYTES, obytes);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev default:
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_exit(&xnbp->xnb_rx_lock);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_exit(&xnbp->xnb_tx_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ENOTSUP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#undef map_stat
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_exit(&xnbp->xnb_rx_lock);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_exit(&xnbp->xnb_tx_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_m_blank(void *arg, time_t ticks, uint_t count)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * XXPV dme: blanking is not currently implemented.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_m_resources(void *arg)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnb_t *xnbp = arg;
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj xnbu_t *xnbup = xnbp->xnb_flavour_data;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_rx_fifo_t mrf;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mrf.mrf_type = MAC_RX_FIFO;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mrf.mrf_blank = xnbu_m_blank;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mrf.mrf_arg = (void *)xnbp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mrf.mrf_normal_blank_time = 128; /* XXPV dme: see xnbu_m_blank() */
843e19887f64dde75055cf8842fc4db2171eff45johnlev mrf.mrf_normal_pkt_count = 8; /* XXPV dme: see xnbu_m_blank() */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbup->u_rx_handle = mac_resource_add(xnbup->u_mh,
843e19887f64dde75055cf8842fc4db2171eff45johnlev (mac_resource_t *)&mrf);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic boolean_t
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnb_t *xnbp = arg;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev switch (cap) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev case MAC_CAPAB_HCKSUM: {
843e19887f64dde75055cf8842fc4db2171eff45johnlev uint32_t *capab = cap_data;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj if (xnbp->xnb_cksum_offload)
568a765b090ca47ac51e3db4143a65f9358495bfdme *capab = HCKSUM_INET_PARTIAL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev else
843e19887f64dde75055cf8842fc4db2171eff45johnlev *capab = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev case MAC_CAPAB_POLL:
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Just return B_TRUE. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev default:
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (B_FALSE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (B_TRUE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev static xnb_flavour_t flavour = {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_to_host, xnbu_connected, xnbu_disconnected, xnbu_hotplug,
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_cksum_from_peer, xnbu_cksum_to_peer,
843e19887f64dde75055cf8842fc4db2171eff45johnlev };
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbu_t *xnbup;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnb_t *xnbp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_register_t *mr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev switch (cmd) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev case DDI_ATTACH:
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev case DDI_RESUME:
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev default:
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbup = kmem_zalloc(sizeof (*xnbup), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((mr = mac_alloc(MAC_VERSION)) == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(xnbup, sizeof (*xnbup));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xnb_attach(dip, &flavour, xnbup) != DDI_SUCCESS) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_free(mr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(xnbup, sizeof (*xnbup));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbp = ddi_get_driver_private(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(xnbp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mr->m_dip = dip;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mr->m_driver = xnbp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Initialize pointers to device specific functions which will be
843e19887f64dde75055cf8842fc4db2171eff45johnlev * used by the generic layer.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev mr->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mr->m_src_addr = xnbp->xnb_mac_addr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mr->m_callbacks = &xnb_callbacks;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mr->m_min_sdu = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mr->m_max_sdu = XNBMAXPKT;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj (void) memset(xnbp->xnb_mac_addr, 0xff, ETHERADDRL);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj xnbp->xnb_mac_addr[0] &= 0xfe;
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnbup->u_need_sched = B_FALSE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Register ourselves with the GLDv3 interface.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = mac_register(mr, &xnbup->u_mh);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_free(mr);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnb_detach(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(xnbup, sizeof (*xnbup));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_link_update(xnbup->u_mh, LINK_STATE_DOWN);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*ARGSUSED*/
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxnbu_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnb_t *xnbp = ddi_get_driver_private(dip);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj xnbu_t *xnbup = xnbp->xnb_flavour_data;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev switch (cmd) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev case DDI_DETACH:
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev case DDI_SUSPEND:
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev default:
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(xnbp != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(xnbup != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_enter(&xnbp->xnb_tx_lock);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_enter(&xnbp->xnb_rx_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj if (!xnbp->xnb_detachable || xnbp->xnb_connected ||
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj (xnbp->xnb_rx_buf_count > 0)) {
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_exit(&xnbp->xnb_rx_lock);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_exit(&xnbp->xnb_tx_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_exit(&xnbp->xnb_rx_lock);
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj mutex_exit(&xnbp->xnb_tx_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Attempt to unregister the mac.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((xnbup->u_mh != NULL) && (mac_unregister(xnbup->u_mh) != 0))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_FAILURE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(xnbup, sizeof (*xnbup));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnb_detach(dip);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (DDI_SUCCESS);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevDDI_DEFINE_STREAM_OPS(ops, nulldev, nulldev, xnbu_attach, xnbu_detach,
843e19887f64dde75055cf8842fc4db2171eff45johnlev nodev, NULL, D_MP, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic struct modldrv modldrv = {
843e19887f64dde75055cf8842fc4db2171eff45johnlev &mod_driverops, "xnbu driver %I%", &ops
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic struct modlinkage modlinkage = {
843e19887f64dde75055cf8842fc4db2171eff45johnlev MODREV_1, &modldrv, NULL
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlev_init(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev int i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_init_ops(&ops, "xnbu");
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev i = mod_install(&modlinkage);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i != DDI_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_fini_ops(&ops);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (i);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlev_fini(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev int i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev i = mod_remove(&modlinkage);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i == DDI_SUCCESS)
843e19887f64dde75055cf8842fc4db2171eff45johnlev mac_fini_ops(&ops);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (i);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlev_info(struct modinfo *modinfop)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (mod_info(&modlinkage, modinfop));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}