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