Linux Audio

Check our new training course

Loading...
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Functions for the OPL4 proc file
  4 * 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}