linux/sound/drivers/opl4/opl4_proc.c
<<
>>
Prefs
   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}
 113