18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * arch/um/drivers/mmapper_kern.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * BRIEF MODULE DESCRIPTION
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (C) 2000 RidgeRun, Inc.
88c2ecf20Sopenharmony_ci * Author: RidgeRun, Inc.
98c2ecf20Sopenharmony_ci *         Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/stddef.h>
148c2ecf20Sopenharmony_ci#include <linux/types.h>
158c2ecf20Sopenharmony_ci#include <linux/fs.h>
168c2ecf20Sopenharmony_ci#include <linux/init.h>
178c2ecf20Sopenharmony_ci#include <linux/miscdevice.h>
188c2ecf20Sopenharmony_ci#include <linux/module.h>
198c2ecf20Sopenharmony_ci#include <linux/mm.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
228c2ecf20Sopenharmony_ci#include <mem_user.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/* These are set in mmapper_init, which is called at boot time */
258c2ecf20Sopenharmony_cistatic unsigned long mmapper_size;
268c2ecf20Sopenharmony_cistatic unsigned long p_buf;
278c2ecf20Sopenharmony_cistatic char *v_buf;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic ssize_t mmapper_read(struct file *file, char __user *buf, size_t count,
308c2ecf20Sopenharmony_ci			    loff_t *ppos)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	return simple_read_from_buffer(buf, count, ppos, v_buf, mmapper_size);
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic ssize_t mmapper_write(struct file *file, const char __user *buf,
368c2ecf20Sopenharmony_ci			     size_t count, loff_t *ppos)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	if (*ppos > mmapper_size)
398c2ecf20Sopenharmony_ci		return -EINVAL;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	return simple_write_to_buffer(v_buf, mmapper_size, ppos, buf, count);
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic long mmapper_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	return -ENOIOCTLCMD;
478c2ecf20Sopenharmony_ci}
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic int mmapper_mmap(struct file *file, struct vm_area_struct *vma)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	int ret = -EINVAL;
528c2ecf20Sopenharmony_ci	int size;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	if (vma->vm_pgoff != 0)
558c2ecf20Sopenharmony_ci		goto out;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	size = vma->vm_end - vma->vm_start;
588c2ecf20Sopenharmony_ci	if (size > mmapper_size)
598c2ecf20Sopenharmony_ci		return -EFAULT;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	/*
628c2ecf20Sopenharmony_ci	 * XXX A comment above remap_pfn_range says it should only be
638c2ecf20Sopenharmony_ci	 * called when the mm semaphore is held
648c2ecf20Sopenharmony_ci	 */
658c2ecf20Sopenharmony_ci	if (remap_pfn_range(vma, vma->vm_start, p_buf >> PAGE_SHIFT, size,
668c2ecf20Sopenharmony_ci			    vma->vm_page_prot))
678c2ecf20Sopenharmony_ci		goto out;
688c2ecf20Sopenharmony_ci	ret = 0;
698c2ecf20Sopenharmony_ciout:
708c2ecf20Sopenharmony_ci	return ret;
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cistatic int mmapper_open(struct inode *inode, struct file *file)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	return 0;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic int mmapper_release(struct inode *inode, struct file *file)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	return 0;
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cistatic const struct file_operations mmapper_fops = {
848c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
858c2ecf20Sopenharmony_ci	.read		= mmapper_read,
868c2ecf20Sopenharmony_ci	.write		= mmapper_write,
878c2ecf20Sopenharmony_ci	.unlocked_ioctl	= mmapper_ioctl,
888c2ecf20Sopenharmony_ci	.mmap		= mmapper_mmap,
898c2ecf20Sopenharmony_ci	.open		= mmapper_open,
908c2ecf20Sopenharmony_ci	.release	= mmapper_release,
918c2ecf20Sopenharmony_ci	.llseek		= default_llseek,
928c2ecf20Sopenharmony_ci};
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci/*
958c2ecf20Sopenharmony_ci * No locking needed - only used (and modified) by below initcall and exitcall.
968c2ecf20Sopenharmony_ci */
978c2ecf20Sopenharmony_cistatic struct miscdevice mmapper_dev = {
988c2ecf20Sopenharmony_ci	.minor		= MISC_DYNAMIC_MINOR,
998c2ecf20Sopenharmony_ci	.name		= "mmapper",
1008c2ecf20Sopenharmony_ci	.fops		= &mmapper_fops
1018c2ecf20Sopenharmony_ci};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic int __init mmapper_init(void)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	int err;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	printk(KERN_INFO "Mapper v0.1\n");
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	v_buf = (char *) find_iomem("mmapper", &mmapper_size);
1108c2ecf20Sopenharmony_ci	if (mmapper_size == 0) {
1118c2ecf20Sopenharmony_ci		printk(KERN_ERR "mmapper_init - find_iomem failed\n");
1128c2ecf20Sopenharmony_ci		return -ENODEV;
1138c2ecf20Sopenharmony_ci	}
1148c2ecf20Sopenharmony_ci	p_buf = __pa(v_buf);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	err = misc_register(&mmapper_dev);
1178c2ecf20Sopenharmony_ci	if (err) {
1188c2ecf20Sopenharmony_ci		printk(KERN_ERR "mmapper - misc_register failed, err = %d\n",
1198c2ecf20Sopenharmony_ci		       err);
1208c2ecf20Sopenharmony_ci		return err;
1218c2ecf20Sopenharmony_ci	}
1228c2ecf20Sopenharmony_ci	return 0;
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistatic void mmapper_exit(void)
1268c2ecf20Sopenharmony_ci{
1278c2ecf20Sopenharmony_ci	misc_deregister(&mmapper_dev);
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cimodule_init(mmapper_init);
1318c2ecf20Sopenharmony_cimodule_exit(mmapper_exit);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ciMODULE_AUTHOR("Greg Lonnon <glonnon@ridgerun.com>");
1348c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("DSPLinux simulator mmapper driver");
1358c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
136