mapper.c revision 1.2
11.2Skamil/*	$NetBSD: mapper.c,v 1.2 2020/01/30 07:58:33 kamil Exp $	*/
21.1Skamil
31.1Skamil/*-
41.1Skamil * Copyright (c) 2019 The NetBSD Foundation, Inc.
51.1Skamil * All rights reserved.
61.1Skamil *
71.1Skamil * Redistribution and use in source and binary forms, with or without
81.1Skamil * modification, are permitted provided that the following conditions
91.1Skamil * are met:
101.1Skamil * 1. Redistributions of source code must retain the above copyright
111.1Skamil *    notice, this list of conditions and the following disclaimer.
121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright
131.1Skamil *    notice, this list of conditions and the following disclaimer in the
141.1Skamil *    documentation and/or other materials provided with the distribution.
151.1Skamil *
161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Skamil * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Skamil * POSSIBILITY OF SUCH DAMAGE.
271.1Skamil */
281.1Skamil
291.1Skamil#include <sys/cdefs.h>
301.2Skamil__KERNEL_RCSID(0, "$NetBSD: mapper.c,v 1.2 2020/01/30 07:58:33 kamil Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/conf.h>
341.1Skamil#include <sys/device.h>
351.1Skamil#include <sys/kernel.h>
361.1Skamil#include <sys/kmem.h>
371.1Skamil#include <sys/module.h>
381.1Skamil#include <sys/systm.h>
391.1Skamil
401.1Skamil#include <uvm/uvm.h>
411.1Skamil
421.1Skamil/*
431.1Skamil * Creating a device /dev/mapper for demonstration.
441.1Skamil * To use this device you need to do:
451.2Skamil * 	mknod /dev/mapper c 351 0
461.1Skamil *
471.1Skamil */
481.1Skamil
491.1Skamildev_type_open(mapper_open);
501.1Skamildev_type_close(mapper_close);
511.1Skamildev_type_mmap(mapper_mmap);
521.1Skamil
531.1Skamilstatic struct cdevsw mapper_cdevsw = {
541.1Skamil	.d_open = mapper_open,
551.1Skamil	.d_close = mapper_close,
561.1Skamil	.d_read = noread,
571.1Skamil	.d_write = nowrite,
581.1Skamil	.d_ioctl = noioctl,
591.1Skamil	.d_stop = nostop,
601.1Skamil	.d_tty = notty,
611.1Skamil	.d_poll = nopoll,
621.1Skamil	.d_mmap = mapper_mmap,
631.1Skamil	.d_kqfilter = nokqfilter,
641.1Skamil	.d_discard = nodiscard,
651.1Skamil	.d_flag = D_OTHER
661.1Skamil};
671.1Skamil
681.1Skamilstruct mapper_softc {
691.1Skamil	int refcnt;
701.1Skamil	char *buffer;
711.1Skamil};
721.1Skamil
731.1Skamilstatic struct mapper_softc sc;
741.1Skamil
751.1Skamilint
761.1Skamilmapper_open(dev_t self __unused, int flag __unused, int mode __unused,
771.1Skamil           struct lwp *l __unused)
781.1Skamil{
791.1Skamil	if (sc.refcnt > 0)
801.1Skamil		return EBUSY;
811.1Skamil	++sc.refcnt;
821.1Skamil	sc.buffer = kmem_zalloc(PAGE_SIZE, KM_SLEEP);
831.1Skamil	snprintf(sc.buffer, PAGE_SIZE, "Hey There!");
841.1Skamil	return 0;
851.1Skamil}
861.1Skamil
871.1Skamilint
881.1Skamilmapper_close(dev_t self __unused, int flag __unused, int mode __unused,
891.1Skamil            struct lwp *l __unused)
901.1Skamil{
911.1Skamil	kmem_free(sc.buffer, PAGE_SIZE);
921.1Skamil	--sc.refcnt;
931.1Skamil	return 0;
941.1Skamil}
951.1Skamil
961.1Skamil/*
971.1Skamil * Here, pmap_extract() is used to extract the mapping from the specified
981.1Skamil * physical map for the provided virtual address, where pmap_kernel() points
991.1Skamil * to the kernel pmap.
1001.1Skamil */
1011.1Skamil
1021.1Skamilpaddr_t
1031.1Skamilmapper_mmap(dev_t dev, off_t off, int prot)
1041.1Skamil{
1051.1Skamil	paddr_t pa;
1061.1Skamil
1071.1Skamil	if (off & PAGE_MASK)
1081.1Skamil		return (paddr_t)-1;
1091.1Skamil	if (prot != VM_PROT_READ)
1101.1Skamil		return (paddr_t)-1;
1111.1Skamil	if (pmap_extract(pmap_kernel(), (vaddr_t)sc.buffer, &pa))
1121.1Skamil		return (paddr_t)atop(pa);
1131.1Skamil
1141.1Skamil	return (paddr_t)-1;
1151.1Skamil}
1161.1Skamil
1171.1SkamilMODULE(MODULE_CLASS_MISC, mapper, NULL);
1181.1Skamil
1191.1Skamilstatic int
1201.1Skamilmapper_modcmd(modcmd_t cmd, void *arg __unused)
1211.1Skamil{
1221.1Skamil	/* The major should be verified and changed if needed to avoid
1231.1Skamil	 * conflicts with other devices. */
1241.2Skamil	int cmajor = 351, bmajor = -1;
1251.1Skamil
1261.1Skamil	switch (cmd) {
1271.1Skamil	case MODULE_CMD_INIT:
1281.1Skamil		if (devsw_attach("mapper", NULL, &bmajor, &mapper_cdevsw,
1291.1Skamil					&cmajor))
1301.1Skamil			return ENXIO;
1311.1Skamil		return 0;
1321.1Skamil	case MODULE_CMD_FINI:
1331.1Skamil		if (sc.refcnt > 0)
1341.1Skamil			return EBUSY;
1351.1Skamil		devsw_detach(NULL, &mapper_cdevsw);
1361.1Skamil		return 0;
1371.1Skamil	default:
1381.1Skamil		return ENOTTY;
1391.1Skamil	}
1401.1Skamil	return 0;
1411.1Skamil}
142