subr_autoconf.c revision 180610
1/*-
2 * Copyright (c) 1992, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This software was developed by the Computer Systems Engineering group
6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7 * contributed to Berkeley.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *	@(#)subr_autoconf.c	8.1 (Berkeley) 6/10/93
34 *
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/kern/subr_autoconf.c 180610 2008-07-19 12:12:54Z rwatson $");
39
40#include "opt_ddb.h"
41
42#include <sys/param.h>
43#include <sys/kernel.h>
44#include <sys/lock.h>
45#include <sys/mutex.h>
46#include <sys/systm.h>
47
48/*
49 * Autoconfiguration subroutines.
50 */
51
52/*
53 * "Interrupt driven config" functions.
54 */
55static TAILQ_HEAD(, intr_config_hook) intr_config_hook_list =
56	TAILQ_HEAD_INITIALIZER(intr_config_hook_list);
57static struct mtx intr_config_hook_lock;
58MTX_SYSINIT(intr_config_hook, &intr_config_hook_lock, "intr config", MTX_DEF);
59
60/* ARGSUSED */
61static void run_interrupt_driven_config_hooks(void *dummy);
62
63static void
64run_interrupt_driven_config_hooks(dummy)
65	void *dummy;
66{
67	struct intr_config_hook *hook_entry, *next_entry;
68
69	mtx_lock(&intr_config_hook_lock);
70	TAILQ_FOREACH_SAFE(hook_entry, &intr_config_hook_list, ich_links,
71	    next_entry) {
72		mtx_unlock(&intr_config_hook_lock);
73		(*hook_entry->ich_func)(hook_entry->ich_arg);
74		mtx_lock(&intr_config_hook_lock);
75	}
76
77	while (!TAILQ_EMPTY(&intr_config_hook_list)) {
78		msleep(&intr_config_hook_list, &intr_config_hook_lock, PCONFIG,
79		    "conifhk", 0);
80	}
81	mtx_unlock(&intr_config_hook_lock);
82}
83SYSINIT(intr_config_hooks, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_FIRST,
84	run_interrupt_driven_config_hooks, NULL);
85
86/*
87 * Register a hook that will be called after "cold"
88 * autoconfiguration is complete and interrupts can
89 * be used to complete initialization.
90 */
91int
92config_intrhook_establish(hook)
93	struct intr_config_hook *hook;
94{
95	struct intr_config_hook *hook_entry;
96
97	mtx_lock(&intr_config_hook_lock);
98	TAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links)
99		if (hook_entry == hook)
100			break;
101	if (hook_entry != NULL) {
102		mtx_unlock(&intr_config_hook_lock);
103		printf("config_intrhook_establish: establishing an "
104		       "already established hook.\n");
105		return (1);
106	}
107	TAILQ_INSERT_TAIL(&intr_config_hook_list, hook, ich_links);
108	mtx_unlock(&intr_config_hook_lock);
109	if (cold == 0)
110		/* XXX Sufficient for modules loaded after initial config??? */
111		run_interrupt_driven_config_hooks(NULL);
112	return (0);
113}
114
115void
116config_intrhook_disestablish(hook)
117	struct intr_config_hook *hook;
118{
119	struct intr_config_hook *hook_entry;
120
121	mtx_lock(&intr_config_hook_lock);
122	TAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links)
123		if (hook_entry == hook)
124			break;
125	if (hook_entry == NULL)
126		panic("config_intrhook_disestablish: disestablishing an "
127		      "unestablished hook");
128
129	TAILQ_REMOVE(&intr_config_hook_list, hook, ich_links);
130
131	/* Wakeup anyone watching the list */
132	wakeup(&intr_config_hook_list);
133	mtx_unlock(&intr_config_hook_lock);
134}
135
136#ifdef DDB
137#include <ddb/ddb.h>
138#include <sys/linker.h>
139
140DB_SHOW_COMMAND(conifhk, db_show_conifhk)
141{
142	struct intr_config_hook *hook_entry;
143	char namebuf[64];
144	long offset;
145
146	TAILQ_FOREACH(hook_entry, &intr_config_hook_list, ich_links) {
147		if (linker_ddb_search_symbol_name(
148		    (caddr_t)hook_entry->ich_func, namebuf, sizeof(namebuf),
149		    &offset) == 0) {
150			db_printf("hook: %p at %s+%#lx arg: %p\n",
151			    hook_entry->ich_func, namebuf, offset,
152			    hook_entry->ich_arg);
153		} else {
154			db_printf("hook: %p at ??+?? arg %p\n",
155			    hook_entry->ich_func, hook_entry->ich_arg);
156		}
157	}
158}
159#endif /* DDB */
160