xref: /netbsd/sys/modules/examples/mapper/mapper.c (revision 1c575f78)
1*1c575f78Sriastradh /*	$NetBSD: mapper.c,v 1.4 2020/09/06 02:18:53 riastradh Exp $	*/
2370a60c3Skamil 
3370a60c3Skamil /*-
4370a60c3Skamil  * Copyright (c) 2019 The NetBSD Foundation, Inc.
5370a60c3Skamil  * All rights reserved.
6370a60c3Skamil  *
7370a60c3Skamil  * Redistribution and use in source and binary forms, with or without
8370a60c3Skamil  * modification, are permitted provided that the following conditions
9370a60c3Skamil  * are met:
10370a60c3Skamil  * 1. Redistributions of source code must retain the above copyright
11370a60c3Skamil  *    notice, this list of conditions and the following disclaimer.
12370a60c3Skamil  * 2. Redistributions in binary form must reproduce the above copyright
13370a60c3Skamil  *    notice, this list of conditions and the following disclaimer in the
14370a60c3Skamil  *    documentation and/or other materials provided with the distribution.
15370a60c3Skamil  *
16370a60c3Skamil  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17370a60c3Skamil  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18370a60c3Skamil  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19370a60c3Skamil  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20370a60c3Skamil  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21370a60c3Skamil  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22370a60c3Skamil  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23370a60c3Skamil  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24370a60c3Skamil  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25370a60c3Skamil  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26370a60c3Skamil  * POSSIBILITY OF SUCH DAMAGE.
27370a60c3Skamil  */
28370a60c3Skamil 
29370a60c3Skamil #include <sys/cdefs.h>
30*1c575f78Sriastradh __KERNEL_RCSID(0, "$NetBSD: mapper.c,v 1.4 2020/09/06 02:18:53 riastradh Exp $");
31370a60c3Skamil 
32370a60c3Skamil #include <sys/param.h>
33370a60c3Skamil #include <sys/conf.h>
34370a60c3Skamil #include <sys/device.h>
35370a60c3Skamil #include <sys/kernel.h>
36370a60c3Skamil #include <sys/kmem.h>
37370a60c3Skamil #include <sys/module.h>
38370a60c3Skamil #include <sys/systm.h>
39370a60c3Skamil 
40*1c575f78Sriastradh #include <uvm/uvm_extern.h>
41*1c575f78Sriastradh 
42370a60c3Skamil /*
43370a60c3Skamil  * Creating a device /dev/mapper for demonstration.
44370a60c3Skamil  * To use this device you need to do:
45e56e9450Skamil  * 	mknod /dev/mapper c 351 0
46370a60c3Skamil  *
47370a60c3Skamil  */
48370a60c3Skamil 
49370a60c3Skamil dev_type_open(mapper_open);
50370a60c3Skamil dev_type_close(mapper_close);
51370a60c3Skamil dev_type_mmap(mapper_mmap);
52370a60c3Skamil 
53370a60c3Skamil static struct cdevsw mapper_cdevsw = {
54370a60c3Skamil 	.d_open = mapper_open,
55370a60c3Skamil 	.d_close = mapper_close,
56370a60c3Skamil 	.d_read = noread,
57370a60c3Skamil 	.d_write = nowrite,
58370a60c3Skamil 	.d_ioctl = noioctl,
59370a60c3Skamil 	.d_stop = nostop,
60370a60c3Skamil 	.d_tty = notty,
61370a60c3Skamil 	.d_poll = nopoll,
62370a60c3Skamil 	.d_mmap = mapper_mmap,
63370a60c3Skamil 	.d_kqfilter = nokqfilter,
64370a60c3Skamil 	.d_discard = nodiscard,
65370a60c3Skamil 	.d_flag = D_OTHER
66370a60c3Skamil };
67370a60c3Skamil 
68370a60c3Skamil struct mapper_softc {
69370a60c3Skamil 	int refcnt;
70370a60c3Skamil 	char *buffer;
71370a60c3Skamil };
72370a60c3Skamil 
73370a60c3Skamil static struct mapper_softc sc;
74370a60c3Skamil 
75370a60c3Skamil int
mapper_open(dev_t self __unused,int flag __unused,int mode __unused,struct lwp * l __unused)76370a60c3Skamil mapper_open(dev_t self __unused, int flag __unused, int mode __unused,
77370a60c3Skamil            struct lwp *l __unused)
78370a60c3Skamil {
79370a60c3Skamil 	if (sc.refcnt > 0)
80370a60c3Skamil 		return EBUSY;
81370a60c3Skamil 	++sc.refcnt;
82370a60c3Skamil 	sc.buffer = kmem_zalloc(PAGE_SIZE, KM_SLEEP);
83370a60c3Skamil 	snprintf(sc.buffer, PAGE_SIZE, "Hey There!");
84370a60c3Skamil 	return 0;
85370a60c3Skamil }
86370a60c3Skamil 
87370a60c3Skamil int
mapper_close(dev_t self __unused,int flag __unused,int mode __unused,struct lwp * l __unused)88370a60c3Skamil mapper_close(dev_t self __unused, int flag __unused, int mode __unused,
89370a60c3Skamil             struct lwp *l __unused)
90370a60c3Skamil {
91370a60c3Skamil 	kmem_free(sc.buffer, PAGE_SIZE);
92370a60c3Skamil 	--sc.refcnt;
93370a60c3Skamil 	return 0;
94370a60c3Skamil }
95370a60c3Skamil 
96370a60c3Skamil /*
97370a60c3Skamil  * Here, pmap_extract() is used to extract the mapping from the specified
98370a60c3Skamil  * physical map for the provided virtual address, where pmap_kernel() points
99370a60c3Skamil  * to the kernel pmap.
100370a60c3Skamil  */
101370a60c3Skamil 
102370a60c3Skamil paddr_t
mapper_mmap(dev_t dev,off_t off,int prot)103370a60c3Skamil mapper_mmap(dev_t dev, off_t off, int prot)
104370a60c3Skamil {
105370a60c3Skamil 	paddr_t pa;
106370a60c3Skamil 
107370a60c3Skamil 	if (off & PAGE_MASK)
108370a60c3Skamil 		return (paddr_t)-1;
109370a60c3Skamil 	if (prot != VM_PROT_READ)
110370a60c3Skamil 		return (paddr_t)-1;
111370a60c3Skamil 	if (pmap_extract(pmap_kernel(), (vaddr_t)sc.buffer, &pa))
112370a60c3Skamil 		return (paddr_t)atop(pa);
113370a60c3Skamil 
114370a60c3Skamil 	return (paddr_t)-1;
115370a60c3Skamil }
116370a60c3Skamil 
117370a60c3Skamil MODULE(MODULE_CLASS_MISC, mapper, NULL);
118370a60c3Skamil 
119370a60c3Skamil static int
mapper_modcmd(modcmd_t cmd,void * arg __unused)120370a60c3Skamil mapper_modcmd(modcmd_t cmd, void *arg __unused)
121370a60c3Skamil {
122370a60c3Skamil 	/* The major should be verified and changed if needed to avoid
123370a60c3Skamil 	 * conflicts with other devices. */
124e56e9450Skamil 	int cmajor = 351, bmajor = -1;
125370a60c3Skamil 
126370a60c3Skamil 	switch (cmd) {
127370a60c3Skamil 	case MODULE_CMD_INIT:
128370a60c3Skamil 		if (devsw_attach("mapper", NULL, &bmajor, &mapper_cdevsw,
129370a60c3Skamil 					&cmajor))
130370a60c3Skamil 			return ENXIO;
131370a60c3Skamil 		return 0;
132370a60c3Skamil 	case MODULE_CMD_FINI:
133370a60c3Skamil 		if (sc.refcnt > 0)
134370a60c3Skamil 			return EBUSY;
135370a60c3Skamil 		devsw_detach(NULL, &mapper_cdevsw);
136370a60c3Skamil 		return 0;
137370a60c3Skamil 	default:
138370a60c3Skamil 		return ENOTTY;
139370a60c3Skamil 	}
140370a60c3Skamil 	return 0;
141370a60c3Skamil }
142