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