1a9643ea8Slogwang /*- 2*22ce4affSfengbojiang * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*22ce4affSfengbojiang * 4a9643ea8Slogwang * Copyright (c) 1997 Doug Rabson 5a9643ea8Slogwang * All rights reserved. 6a9643ea8Slogwang * 7a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without 8a9643ea8Slogwang * modification, are permitted provided that the following conditions 9a9643ea8Slogwang * are met: 10a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright 11a9643ea8Slogwang * notice, this list of conditions and the following disclaimer. 12a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright 13a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in the 14a9643ea8Slogwang * documentation and/or other materials provided with the distribution. 15a9643ea8Slogwang * 16a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17a9643ea8Slogwang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18a9643ea8Slogwang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19a9643ea8Slogwang * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20a9643ea8Slogwang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21a9643ea8Slogwang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22a9643ea8Slogwang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23a9643ea8Slogwang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24a9643ea8Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25a9643ea8Slogwang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26a9643ea8Slogwang * SUCH DAMAGE. 27a9643ea8Slogwang * 28a9643ea8Slogwang * $FreeBSD$ 29a9643ea8Slogwang */ 30a9643ea8Slogwang 31a9643ea8Slogwang #ifndef _SYS_MODULE_H_ 32a9643ea8Slogwang #define _SYS_MODULE_H_ 33a9643ea8Slogwang 34a9643ea8Slogwang /* 35a9643ea8Slogwang * Module metadata types 36a9643ea8Slogwang */ 37a9643ea8Slogwang #define MDT_DEPEND 1 /* argument is a module name */ 38a9643ea8Slogwang #define MDT_MODULE 2 /* module declaration */ 39a9643ea8Slogwang #define MDT_VERSION 3 /* module version(s) */ 40a9643ea8Slogwang #define MDT_PNP_INFO 4 /* Plug and play hints record */ 41a9643ea8Slogwang 42a9643ea8Slogwang #define MDT_STRUCT_VERSION 1 /* version of metadata structure */ 43a9643ea8Slogwang #define MDT_SETNAME "modmetadata_set" 44a9643ea8Slogwang 45a9643ea8Slogwang typedef enum modeventtype { 46a9643ea8Slogwang MOD_LOAD, 47a9643ea8Slogwang MOD_UNLOAD, 48a9643ea8Slogwang MOD_SHUTDOWN, 49a9643ea8Slogwang MOD_QUIESCE 50a9643ea8Slogwang } modeventtype_t; 51a9643ea8Slogwang 52a9643ea8Slogwang typedef struct module *module_t; 53a9643ea8Slogwang typedef int (*modeventhand_t)(module_t, int /* modeventtype_t */, void *); 54a9643ea8Slogwang 55a9643ea8Slogwang /* 56a9643ea8Slogwang * Struct for registering modules statically via SYSINIT. 57a9643ea8Slogwang */ 58a9643ea8Slogwang typedef struct moduledata { 59a9643ea8Slogwang const char *name; /* module name */ 60a9643ea8Slogwang modeventhand_t evhand; /* event handler */ 61a9643ea8Slogwang void *priv; /* extra data */ 62a9643ea8Slogwang } moduledata_t; 63a9643ea8Slogwang 64a9643ea8Slogwang /* 65a9643ea8Slogwang * A module can use this to report module specific data to the user via 66a9643ea8Slogwang * kldstat(2). 67a9643ea8Slogwang */ 68a9643ea8Slogwang typedef union modspecific { 69a9643ea8Slogwang int intval; 70a9643ea8Slogwang u_int uintval; 71a9643ea8Slogwang long longval; 72a9643ea8Slogwang u_long ulongval; 73a9643ea8Slogwang } modspecific_t; 74a9643ea8Slogwang 75a9643ea8Slogwang /* 76a9643ea8Slogwang * Module dependency declaration 77a9643ea8Slogwang */ 78a9643ea8Slogwang struct mod_depend { 79a9643ea8Slogwang int md_ver_minimum; 80a9643ea8Slogwang int md_ver_preferred; 81a9643ea8Slogwang int md_ver_maximum; 82a9643ea8Slogwang }; 83a9643ea8Slogwang 84a9643ea8Slogwang /* 85a9643ea8Slogwang * Module version declaration 86a9643ea8Slogwang */ 87a9643ea8Slogwang struct mod_version { 88a9643ea8Slogwang int mv_version; 89a9643ea8Slogwang }; 90a9643ea8Slogwang 91a9643ea8Slogwang struct mod_metadata { 92a9643ea8Slogwang int md_version; /* structure version MDTV_* */ 93a9643ea8Slogwang int md_type; /* type of entry MDT_* */ 94a9643ea8Slogwang const void *md_data; /* specific data */ 95a9643ea8Slogwang const char *md_cval; /* common string label */ 96a9643ea8Slogwang }; 97a9643ea8Slogwang 98a9643ea8Slogwang struct mod_pnp_match_info 99a9643ea8Slogwang { 100a9643ea8Slogwang const char *descr; /* Description of the table */ 101a9643ea8Slogwang const char *bus; /* Name of the bus for this table */ 102a9643ea8Slogwang const void *table; /* Pointer to pnp table */ 103a9643ea8Slogwang int entry_len; /* Length of each entry in the table (may be */ 104a9643ea8Slogwang /* longer than descr describes). */ 105a9643ea8Slogwang int num_entry; /* Number of entries in the table */ 106a9643ea8Slogwang }; 107a9643ea8Slogwang #ifdef _KERNEL 108a9643ea8Slogwang 109a9643ea8Slogwang #include <sys/linker_set.h> 110a9643ea8Slogwang 111*22ce4affSfengbojiang #define MODULE_METADATA_CONCAT(uniquifier) _mod_metadata##uniquifier 112a9643ea8Slogwang #define MODULE_METADATA(uniquifier, type, data, cval) \ 113*22ce4affSfengbojiang static struct mod_metadata MODULE_METADATA_CONCAT(uniquifier) = { \ 114a9643ea8Slogwang MDT_STRUCT_VERSION, \ 115a9643ea8Slogwang type, \ 116a9643ea8Slogwang data, \ 117a9643ea8Slogwang cval \ 118a9643ea8Slogwang }; \ 119*22ce4affSfengbojiang DATA_SET(modmetadata_set, MODULE_METADATA_CONCAT(uniquifier)) 120a9643ea8Slogwang 121a9643ea8Slogwang #define MODULE_DEPEND(module, mdepend, vmin, vpref, vmax) \ 122a9643ea8Slogwang static struct mod_depend _##module##_depend_on_##mdepend \ 123a9643ea8Slogwang __section(".data") = { \ 124a9643ea8Slogwang vmin, \ 125a9643ea8Slogwang vpref, \ 126a9643ea8Slogwang vmax \ 127a9643ea8Slogwang }; \ 128a9643ea8Slogwang MODULE_METADATA(_md_##module##_on_##mdepend, MDT_DEPEND, \ 129a9643ea8Slogwang &_##module##_depend_on_##mdepend, #mdepend) 130a9643ea8Slogwang 131a9643ea8Slogwang /* 132a9643ea8Slogwang * Every kernel has a 'kernel' module with the version set to 133a9643ea8Slogwang * __FreeBSD_version. We embed a MODULE_DEPEND() inside every module 134a9643ea8Slogwang * that depends on the 'kernel' module. It uses the current value of 135a9643ea8Slogwang * __FreeBSD_version as the minimum and preferred versions. For the 136a9643ea8Slogwang * maximum version it rounds the version up to the end of its branch 137a9643ea8Slogwang * (i.e. M99999 for M.x). This allows a module built on M.x to work 138a9643ea8Slogwang * on M.y systems where y >= x, but fail on M.z systems where z < x. 139a9643ea8Slogwang */ 140a9643ea8Slogwang #define MODULE_KERNEL_MAXVER (roundup(__FreeBSD_version, 100000) - 1) 141a9643ea8Slogwang 142a9643ea8Slogwang #define DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, maxver) \ 143a9643ea8Slogwang MODULE_DEPEND(name, kernel, __FreeBSD_version, \ 144a9643ea8Slogwang __FreeBSD_version, maxver); \ 145*22ce4affSfengbojiang MODULE_METADATA(_md_##name, MDT_MODULE, &data, __XSTRING(name));\ 146a9643ea8Slogwang SYSINIT(name##module, sub, order, module_register_init, &data); \ 147a9643ea8Slogwang struct __hack 148a9643ea8Slogwang 149*22ce4affSfengbojiang #ifdef KLD_TIED 150*22ce4affSfengbojiang #define DECLARE_MODULE(name, data, sub, order) \ 151*22ce4affSfengbojiang DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, __FreeBSD_version) 152*22ce4affSfengbojiang #else 153a9643ea8Slogwang #define DECLARE_MODULE(name, data, sub, order) \ 154a9643ea8Slogwang DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, MODULE_KERNEL_MAXVER) 155*22ce4affSfengbojiang #endif 156a9643ea8Slogwang 157a9643ea8Slogwang /* 158a9643ea8Slogwang * The module declared with DECLARE_MODULE_TIED can only be loaded 159a9643ea8Slogwang * into the kernel with exactly the same __FreeBSD_version. 160a9643ea8Slogwang * 161a9643ea8Slogwang * Use it for modules that use kernel interfaces that are not stable 162a9643ea8Slogwang * even on STABLE/X branches. 163a9643ea8Slogwang */ 164a9643ea8Slogwang #define DECLARE_MODULE_TIED(name, data, sub, order) \ 165a9643ea8Slogwang DECLARE_MODULE_WITH_MAXVER(name, data, sub, order, __FreeBSD_version) 166a9643ea8Slogwang 167*22ce4affSfengbojiang #define MODULE_VERSION_CONCAT(module, version) _##module##_version 168a9643ea8Slogwang #define MODULE_VERSION(module, version) \ 169*22ce4affSfengbojiang static struct mod_version MODULE_VERSION_CONCAT(module, version)\ 170a9643ea8Slogwang __section(".data") = { \ 171a9643ea8Slogwang version \ 172a9643ea8Slogwang }; \ 173*22ce4affSfengbojiang MODULE_METADATA(MODULE_VERSION_CONCAT(module, version), MDT_VERSION,\ 174*22ce4affSfengbojiang &MODULE_VERSION_CONCAT(module, version), __XSTRING(module)) 175a9643ea8Slogwang 176a9643ea8Slogwang /** 177a9643ea8Slogwang * Generic macros to create pnp info hints that modules may export 178a9643ea8Slogwang * to allow external tools to parse their internal device tables 179a9643ea8Slogwang * to make an informed guess about what driver(s) to load. 180a9643ea8Slogwang */ 181*22ce4affSfengbojiang #define MODULE_PNP_INFO(d, b, unique, t, n) \ 182a9643ea8Slogwang static const struct mod_pnp_match_info _module_pnp_##b##_##unique = { \ 183a9643ea8Slogwang .descr = d, \ 184a9643ea8Slogwang .bus = #b, \ 185a9643ea8Slogwang .table = t, \ 186*22ce4affSfengbojiang .entry_len = sizeof((t)[0]), \ 187a9643ea8Slogwang .num_entry = n \ 188a9643ea8Slogwang }; \ 189a9643ea8Slogwang MODULE_METADATA(_md_##b##_pnpinfo_##unique, MDT_PNP_INFO, \ 190a9643ea8Slogwang &_module_pnp_##b##_##unique, #b); 191a9643ea8Slogwang /** 192a9643ea8Slogwang * descr is a string that describes each entry in the table. The general 193*22ce4affSfengbojiang * form is the grammar (TYPE:pnp_name[/pnp_name];)* 194a9643ea8Slogwang * where TYPE is one of the following: 195a9643ea8Slogwang * U8 uint8_t element 196a9643ea8Slogwang * V8 like U8 and 0xff means match any 197a9643ea8Slogwang * G16 uint16_t element, any value >= matches 198a9643ea8Slogwang * L16 uint16_t element, any value <= matches 199a9643ea8Slogwang * M16 uint16_t element, mask of which of the following fields to use. 200a9643ea8Slogwang * U16 uint16_t element 201a9643ea8Slogwang * V16 like U16 and 0xffff means match any 202a9643ea8Slogwang * U32 uint32_t element 203a9643ea8Slogwang * V32 like U32 and 0xffffffff means match any 204a9643ea8Slogwang * W32 Two 16-bit values with first pnp_name in LSW and second in MSW. 205a9643ea8Slogwang * Z pointer to a string to match exactly 206*22ce4affSfengbojiang * D pointer to a string to human readable description for device 207a9643ea8Slogwang * P A pointer that should be ignored 208a9643ea8Slogwang * E EISA PNP Identifier (in binary, but bus publishes string) 209*22ce4affSfengbojiang * T Key for whole table. pnp_name=value. must be last, if present. 210a9643ea8Slogwang * 211a9643ea8Slogwang * The pnp_name "#" is reserved for other fields that should be ignored. 212*22ce4affSfengbojiang * Otherwise pnp_name must match the name from the parent device's pnpinfo 213*22ce4affSfengbojiang * output. The second pnp_name is used for the W32 type. 214a9643ea8Slogwang */ 215a9643ea8Slogwang 216a9643ea8Slogwang extern struct sx modules_sx; 217a9643ea8Slogwang 218a9643ea8Slogwang #define MOD_XLOCK sx_xlock(&modules_sx) 219a9643ea8Slogwang #define MOD_SLOCK sx_slock(&modules_sx) 220a9643ea8Slogwang #define MOD_XUNLOCK sx_xunlock(&modules_sx) 221a9643ea8Slogwang #define MOD_SUNLOCK sx_sunlock(&modules_sx) 222a9643ea8Slogwang #define MOD_LOCK_ASSERT sx_assert(&modules_sx, SX_LOCKED) 223a9643ea8Slogwang #define MOD_XLOCK_ASSERT sx_assert(&modules_sx, SX_XLOCKED) 224a9643ea8Slogwang 225a9643ea8Slogwang struct linker_file; 226a9643ea8Slogwang 227a9643ea8Slogwang void module_register_init(const void *); 228a9643ea8Slogwang int module_register(const struct moduledata *, struct linker_file *); 229a9643ea8Slogwang module_t module_lookupbyname(const char *); 230a9643ea8Slogwang module_t module_lookupbyid(int); 231a9643ea8Slogwang int module_quiesce(module_t); 232a9643ea8Slogwang void module_reference(module_t); 233a9643ea8Slogwang void module_release(module_t); 234a9643ea8Slogwang int module_unload(module_t); 235a9643ea8Slogwang int module_getid(module_t); 236a9643ea8Slogwang module_t module_getfnext(module_t); 237a9643ea8Slogwang const char * module_getname(module_t); 238a9643ea8Slogwang void module_setspecific(module_t, modspecific_t *); 239a9643ea8Slogwang struct linker_file *module_file(module_t); 240a9643ea8Slogwang 241a9643ea8Slogwang #ifdef MOD_DEBUG 242a9643ea8Slogwang extern int mod_debug; 243a9643ea8Slogwang #define MOD_DEBUG_REFS 1 244a9643ea8Slogwang 245a9643ea8Slogwang #define MOD_DPF(cat, args) do { \ 246a9643ea8Slogwang if (mod_debug & MOD_DEBUG_##cat) \ 247*22ce4affSfengbojiang printf args; \ 248a9643ea8Slogwang } while (0) 249a9643ea8Slogwang 250a9643ea8Slogwang #else /* !MOD_DEBUG */ 251a9643ea8Slogwang 252a9643ea8Slogwang #define MOD_DPF(cat, args) 253a9643ea8Slogwang #endif 254a9643ea8Slogwang #endif /* _KERNEL */ 255a9643ea8Slogwang 256a9643ea8Slogwang #define MAXMODNAME 32 257a9643ea8Slogwang 258a9643ea8Slogwang struct module_stat { 259a9643ea8Slogwang int version; /* set to sizeof(struct module_stat) */ 260a9643ea8Slogwang char name[MAXMODNAME]; 261a9643ea8Slogwang int refs; 262a9643ea8Slogwang int id; 263a9643ea8Slogwang modspecific_t data; 264a9643ea8Slogwang }; 265a9643ea8Slogwang 266a9643ea8Slogwang #ifndef _KERNEL 267a9643ea8Slogwang 268a9643ea8Slogwang #include <sys/cdefs.h> 269a9643ea8Slogwang 270a9643ea8Slogwang __BEGIN_DECLS 271a9643ea8Slogwang int modnext(int _modid); 272a9643ea8Slogwang int modfnext(int _modid); 273a9643ea8Slogwang int modstat(int _modid, struct module_stat *_stat); 274a9643ea8Slogwang int modfind(const char *_name); 275a9643ea8Slogwang __END_DECLS 276a9643ea8Slogwang 277a9643ea8Slogwang #endif 278a9643ea8Slogwang 279a9643ea8Slogwang #endif /* !_SYS_MODULE_H_ */ 280