113 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Functions for the OPL4 proc file4 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>5 */6 7#include "opl4_local.h"8#include <linux/vmalloc.h>9#include <linux/export.h>10#include <sound/info.h>11 12static int snd_opl4_mem_proc_open(struct snd_info_entry *entry,13 unsigned short mode, void **file_private_data)14{15 struct snd_opl4 *opl4 = entry->private_data;16 17 mutex_lock(&opl4->access_mutex);18 if (opl4->memory_access) {19 mutex_unlock(&opl4->access_mutex);20 return -EBUSY;21 }22 opl4->memory_access++;23 mutex_unlock(&opl4->access_mutex);24 return 0;25}26 27static int snd_opl4_mem_proc_release(struct snd_info_entry *entry,28 unsigned short mode, void *file_private_data)29{30 struct snd_opl4 *opl4 = entry->private_data;31 32 mutex_lock(&opl4->access_mutex);33 opl4->memory_access--;34 mutex_unlock(&opl4->access_mutex);35 return 0;36}37 38static ssize_t snd_opl4_mem_proc_read(struct snd_info_entry *entry,39 void *file_private_data,40 struct file *file, char __user *_buf,41 size_t count, loff_t pos)42{43 struct snd_opl4 *opl4 = entry->private_data;44 char* buf;45 46 buf = vmalloc(count);47 if (!buf)48 return -ENOMEM;49 snd_opl4_read_memory(opl4, buf, pos, count);50 if (copy_to_user(_buf, buf, count)) {51 vfree(buf);52 return -EFAULT;53 }54 vfree(buf);55 return count;56}57 58static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry,59 void *file_private_data,60 struct file *file,61 const char __user *_buf,62 size_t count, loff_t pos)63{64 struct snd_opl4 *opl4 = entry->private_data;65 char *buf;66 67 buf = vmalloc(count);68 if (!buf)69 return -ENOMEM;70 if (copy_from_user(buf, _buf, count)) {71 vfree(buf);72 return -EFAULT;73 }74 snd_opl4_write_memory(opl4, buf, pos, count);75 vfree(buf);76 return count;77}78 79static const struct snd_info_entry_ops snd_opl4_mem_proc_ops = {80 .open = snd_opl4_mem_proc_open,81 .release = snd_opl4_mem_proc_release,82 .read = snd_opl4_mem_proc_read,83 .write = snd_opl4_mem_proc_write,84};85 86int snd_opl4_create_proc(struct snd_opl4 *opl4)87{88 struct snd_info_entry *entry;89 90 entry = snd_info_create_card_entry(opl4->card, "opl4-mem", opl4->card->proc_root);91 if (entry) {92 if (opl4->hardware < OPL3_HW_OPL4_ML) {93 /* OPL4 can access 4 MB external ROM/SRAM */94 entry->mode |= 0200;95 entry->size = 4 * 1024 * 1024;96 } else {97 /* OPL4-ML has 1 MB internal ROM */98 entry->size = 1 * 1024 * 1024;99 }100 entry->content = SNDRV_INFO_CONTENT_DATA;101 entry->c.ops = &snd_opl4_mem_proc_ops;102 entry->module = THIS_MODULE;103 entry->private_data = opl4;104 }105 opl4->proc_entry = entry;106 return 0;107}108 109void snd_opl4_free_proc(struct snd_opl4 *opl4)110{111 snd_info_free_entry(opl4->proc_entry);112}113