125537Sdfr/*-
225537Sdfr * Copyright (c) 1997 Doug Rabson
325537Sdfr * All rights reserved.
425537Sdfr *
525537Sdfr * Redistribution and use in source and binary forms, with or without
625537Sdfr * modification, are permitted provided that the following conditions
725537Sdfr * are met:
825537Sdfr * 1. Redistributions of source code must retain the above copyright
925537Sdfr *    notice, this list of conditions and the following disclaimer.
1025537Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1125537Sdfr *    notice, this list of conditions and the following disclaimer in the
1225537Sdfr *    documentation and/or other materials provided with the distribution.
1325537Sdfr *
1425537Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1525537Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1625537Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1725537Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1825537Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1925537Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2025537Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2125537Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2225537Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2325537Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2425537Sdfr * SUCH DAMAGE.
2525537Sdfr *
2650477Speter * $FreeBSD$
2725537Sdfr */
2825537Sdfr
2925537Sdfr#ifndef _SYS_MODULE_H_
3025537Sdfr#define _SYS_MODULE_H_
3125537Sdfr
3259751Speter/*
3359751Speter * Module metadata types
3459751Speter */
3559751Speter#define	MDT_DEPEND	1		/* argument is a module name */
3659751Speter#define	MDT_MODULE	2		/* module declaration */
3759751Speter#define	MDT_VERSION	3		/* module version(s) */
3859751Speter
3959751Speter#define	MDT_STRUCT_VERSION	1	/* version of metadata structure */
4059751Speter#define	MDT_SETNAME	"modmetadata_set"
4159751Speter
4241153Swollmantypedef enum modeventtype {
4391472Sarr	MOD_LOAD,
4491472Sarr	MOD_UNLOAD,
45132117Sphk	MOD_SHUTDOWN,
46132117Sphk	MOD_QUIESCE
4725537Sdfr} modeventtype_t;
4825537Sdfr
4991472Sarrtypedef struct module *module_t;
5091472Sarrtypedef int (*modeventhand_t)(module_t, int /* modeventtype_t */, void *);
5125537Sdfr
5225537Sdfr/*
5325537Sdfr * Struct for registering modules statically via SYSINIT.
5425537Sdfr */
5525537Sdfrtypedef struct moduledata {
5691472Sarr	const char	*name;		/* module name */
5791472Sarr	modeventhand_t  evhand;		/* event handler */
5891472Sarr	void		*priv;		/* extra data */
5925537Sdfr} moduledata_t;
6025537Sdfr
6142435Sdfr/*
6291472Sarr * A module can use this to report module specific data to the user via
6391472Sarr * kldstat(2).
6442435Sdfr */
6542435Sdfrtypedef union modspecific {
6691472Sarr	int	intval;
6791472Sarr	u_int	uintval;
6891472Sarr	long	longval;
6991472Sarr	u_long	ulongval;
7042435Sdfr} modspecific_t;
7142435Sdfr
7259751Speter/*
7359751Speter * Module dependency declarartion
7459751Speter */
7559751Speterstruct mod_depend {
7691472Sarr	int	md_ver_minimum;
7791472Sarr	int	md_ver_preferred;
7891472Sarr	int	md_ver_maximum;
7959751Speter};
8059751Speter
8159751Speter/*
8259751Speter * Module version declaration
8359751Speter */
8459751Speterstruct mod_version {
8591472Sarr	int	mv_version;
8659751Speter};
8759751Speter
8859751Speterstruct mod_metadata {
8991472Sarr	int		md_version;	/* structure version MDTV_* */
9091472Sarr	int		md_type;	/* type of entry MDT_* */
9191472Sarr	void		*md_data;	/* specific data */
9291472Sarr	const char	*md_cval;	/* common string label */
9359751Speter};
9459751Speter
9591472Sarr#ifdef	_KERNEL
9640137Speter
9759751Speter#include <sys/linker_set.h>
9859751Speter
9991472Sarr#define	MODULE_METADATA(uniquifier, type, data, cval)			\
10091472Sarr	static struct mod_metadata _mod_metadata##uniquifier = {	\
10191472Sarr		MDT_STRUCT_VERSION,					\
10291472Sarr		type,							\
10391472Sarr		data,							\
10491472Sarr		cval							\
10591472Sarr	};								\
10691472Sarr	DATA_SET(modmetadata_set, _mod_metadata##uniquifier)
10759751Speter
10891472Sarr#define	MODULE_DEPEND(module, mdepend, vmin, vpref, vmax)		\
10991472Sarr	static struct mod_depend _##module##_depend_on_##mdepend = {	\
11091472Sarr		vmin,							\
11191472Sarr		vpref,							\
11291472Sarr		vmax							\
11391472Sarr	};								\
11491472Sarr	MODULE_METADATA(_md_##module##_on_##mdepend, MDT_DEPEND,	\
11591472Sarr	    &_##module##_depend_on_##mdepend, #mdepend)
11659751Speter
117176252Sjhb/*
118176252Sjhb * Every kernel has a 'kernel' module with the version set to
119176252Sjhb * __FreeBSD_version.  We embed a MODULE_DEPEND() inside every module
120176252Sjhb * that depends on the 'kernel' module.  It uses the current value of
121176252Sjhb * __FreeBSD_version as the minimum and preferred versions.  For the
122176252Sjhb * maximum version it rounds the version up to the end of its branch
123176252Sjhb * (i.e. M99999 for M.x).  This allows a module built on M.x to work
124176252Sjhb * on M.y systems where y >= x, but fail on M.z systems where z < x.
125176252Sjhb */
126176252Sjhb#define	MODULE_KERNEL_MAXVER	(roundup(__FreeBSD_version, 100000) - 1)
127176252Sjhb
128213716Skib#define	DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, maxver)	\
129176252Sjhb	MODULE_DEPEND(name, kernel, __FreeBSD_version,			\
130213716Skib	    __FreeBSD_version, maxver);			\
13191472Sarr	MODULE_METADATA(_md_##name, MDT_MODULE, &data, #name);		\
132177253Srwatson	SYSINIT(name##module, sub, order, module_register_init, &data);	\
13391472Sarr	struct __hack
13425537Sdfr
135213716Skib#define	DECLARE_MODULE(name, data, sub, order)				\
136213716Skib	DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, MODULE_KERNEL_MAXVER)
137213716Skib
138213716Skib/*
139213716Skib * The module declared with DECLARE_MODULE_TIED can only be loaded
140213716Skib * into the kernel with exactly the same __FreeBSD_version.
141213716Skib *
142213716Skib * Use it for modules that use kernel interfaces that are not stable
143213716Skib * even on STABLE/X branches.
144213716Skib */
145213716Skib#define	DECLARE_MODULE_TIED(name, data, sub, order)				\
146213716Skib	DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, __FreeBSD_version)
147213716Skib
14891472Sarr#define	MODULE_VERSION(module, version)					\
14991472Sarr	static struct mod_version _##module##_version = {		\
15091472Sarr		version							\
15191472Sarr	};								\
15291472Sarr	MODULE_METADATA(_##module##_version, MDT_VERSION,		\
15391472Sarr	    &_##module##_version, #module)
15459751Speter
15592547Sarrextern struct sx modules_sx;
15692547Sarr
15792547Sarr#define	MOD_XLOCK	sx_xlock(&modules_sx)
15892547Sarr#define	MOD_SLOCK	sx_slock(&modules_sx)
15992547Sarr#define	MOD_XUNLOCK	sx_xunlock(&modules_sx)
16092547Sarr#define	MOD_SUNLOCK	sx_sunlock(&modules_sx)
16192547Sarr#define	MOD_LOCK_ASSERT	sx_assert(&modules_sx, SX_LOCKED)
16292547Sarr#define	MOD_XLOCK_ASSERT	sx_assert(&modules_sx, SX_XLOCKED)
16392547Sarr
16446693Speterstruct linker_file;
16525537Sdfr
16691472Sarrvoid	module_register_init(const void *);
16791472Sarrint	module_register(const struct moduledata *, struct linker_file *);
16891472Sarrmodule_t	module_lookupbyname(const char *);
16991472Sarrmodule_t	module_lookupbyid(int);
170185635Sjhbint	module_quiesce(module_t);
17191472Sarrvoid	module_reference(module_t);
17291472Sarrvoid	module_release(module_t);
173185635Sjhbint	module_unload(module_t);
17491472Sarrint	module_getid(module_t);
17591472Sarrmodule_t	module_getfnext(module_t);
176185635Sjhbconst char *	module_getname(module_t);
17791472Sarrvoid	module_setspecific(module_t, modspecific_t *);
178157818Sjhbstruct linker_file *module_file(module_t);
17925537Sdfr
18091472Sarr#ifdef	MOD_DEBUG
18125537Sdfrextern int mod_debug;
18291472Sarr#define	MOD_DEBUG_REFS	1
18325537Sdfr
18491520Sobrien#define	MOD_DPF(cat, args) do {						\
18591472Sarr	if (mod_debug & MOD_DEBUG_##cat)				\
18691472Sarr		printf(args);						\
18791472Sarr} while (0)
18825537Sdfr
18991472Sarr#else	/* !MOD_DEBUG */
19025537Sdfr
19191472Sarr#define	MOD_DPF(cat, args)
19225537Sdfr#endif
19391472Sarr#endif	/* _KERNEL */
19425537Sdfr
19591472Sarr#define	MAXMODNAME	32
19625537Sdfr
19725537Sdfrstruct module_stat {
19891472Sarr	int		version;	/* set to sizeof(struct module_stat) */
19991472Sarr	char		name[MAXMODNAME];
20091472Sarr	int		refs;
20191472Sarr	int		id;
20291472Sarr	modspecific_t	data;
20325537Sdfr};
20425537Sdfr
20555205Speter#ifndef _KERNEL
20625537Sdfr
20725537Sdfr#include <sys/cdefs.h>
20825537Sdfr
20925537Sdfr__BEGIN_DECLS
21083248Sddint	modnext(int _modid);
21183248Sddint	modfnext(int _modid);
21291472Sarrint	modstat(int _modid, struct module_stat *_stat);
21383248Sddint	modfind(const char *_name);
21425537Sdfr__END_DECLS
21525537Sdfr
21625537Sdfr#endif
21725537Sdfr
21825537Sdfr#endif	/* !_SYS_MODULE_H_ */
219