bus_func.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License, Version 1.0 only
2N/A * (the "License"). You may not use this file except in compliance
2N/A * with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A#include <sys/conf.h>
2N/A#include <sys/sysmacros.h>
2N/A#include <sys/async.h>
2N/A
2N/Astatic bus_func_desc_t *bfd_list = NULL; /* list of busfunc descriptors */
2N/Akmutex_t bfd_lock; /* lock protecting bfd_list */
2N/A
2N/A/*
2N/A * Register a new bus function. We expect this function to be called from a
2N/A * driver attach or detach routine, so we can safely perform a sleeping
2N/A * allocation here. We just insert the new element at the head of the list.
2N/A * For more information on bus_func semantics, refer to sun4u/sys/async.h.
2N/A */
2N/Avoid
2N/Abus_func_register(int type, busfunc_t func, void *arg)
2N/A{
2N/A bus_func_desc_t *bfd = kmem_alloc(sizeof (bus_func_desc_t), KM_SLEEP);
2N/A
2N/A bfd->bf_type = type;
2N/A bfd->bf_func = func;
2N/A bfd->bf_arg = arg;
2N/A
2N/A mutex_enter(&bfd_lock);
2N/A bfd->bf_next = bfd_list;
2N/A bfd_list = bfd;
2N/A mutex_exit(&bfd_lock);
2N/A}
2N/A
2N/A/*
2N/A * Unregister the specified bus function. We only delete an element that
2N/A * exactly matches the specified (type, func, arg) tuple. We expect this
2N/A * function to only be called from driver detach context.
2N/A */
2N/Avoid
2N/Abus_func_unregister(int type, busfunc_t func, void *arg)
2N/A{
2N/A bus_func_desc_t *bfd, **pp;
2N/A
2N/A mutex_enter(&bfd_lock);
2N/A pp = &bfd_list;
2N/A
2N/A for (bfd = bfd_list; bfd != NULL; bfd = bfd->bf_next) {
2N/A if (bfd->bf_type == type && bfd->bf_func == func &&
2N/A bfd->bf_arg == arg) {
2N/A *pp = bfd->bf_next;
2N/A break;
2N/A }
2N/A pp = &bfd->bf_next;
2N/A }
2N/A
2N/A mutex_exit(&bfd_lock);
2N/A
2N/A if (bfd != NULL)
2N/A kmem_free(bfd, sizeof (bus_func_desc_t));
2N/A}
2N/A
2N/A/*
2N/A * Invoke the registered bus functions of the specified type. We return the
2N/A * maximum of the result values (e.g. BF_FATAL if any call returned BF_FATAL).
2N/A * This function assumes that (1) the BF_* constants are defined so that the
2N/A * most fatal error has the highest numerical value, and (2) that the bf_func
2N/A * callbacks obey the rules described in async.h.
2N/A */
2N/Auint_t
2N/Abus_func_invoke(int type)
2N/A{
2N/A bus_func_desc_t *bfd;
2N/A uint_t err = BF_NONE;
2N/A
2N/A mutex_enter(&bfd_lock);
2N/A
2N/A for (bfd = bfd_list; bfd != NULL; bfd = bfd->bf_next) {
2N/A if (bfd->bf_type == type) {
2N/A uint_t status = bfd->bf_func(bfd->bf_arg);
2N/A err = MAX(err, status);
2N/A }
2N/A }
2N/A
2N/A mutex_exit(&bfd_lock);
2N/A return (err);
2N/A}
2N/A