1 /* 2 * Functions for the OPL4 proc file 3 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20 #include "opl4_local.h" 21 #include <linux/vmalloc.h> 22 #include <linux/export.h> 23 #include <sound/info.h> 24 25 #ifdef CONFIG_PROC_FS 26 27 static int snd_opl4_mem_proc_open(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 if (opl4->memory_access) { 34 mutex_unlock(&opl4->access_mutex); 35 return -EBUSY; 36 } 37 opl4->memory_access++; 38 mutex_unlock(&opl4->access_mutex); 39 return 0; 40 } 41 42 static int snd_opl4_mem_proc_release(struct snd_info_entry *entry, 43 unsigned short mode, void *file_private_data) 44 { 45 struct snd_opl4 *opl4 = entry->private_data; 46 47 mutex_lock(&opl4->access_mutex); 48 opl4->memory_access--; 49 mutex_unlock(&opl4->access_mutex); 50 return 0; 51 } 52 53 static ssize_t snd_opl4_mem_proc_read(struct snd_info_entry *entry, 54 void *file_private_data, 55 struct file *file, char __user *_buf, 56 size_t count, loff_t pos) 57 { 58 struct snd_opl4 *opl4 = entry->private_data; 59 char* buf; 60 61 buf = vmalloc(count); 62 if (!buf) 63 return -ENOMEM; 64 snd_opl4_read_memory(opl4, buf, pos, count); 65 if (copy_to_user(_buf, buf, count)) { 66 vfree(buf); 67 return -EFAULT; 68 } 69 vfree(buf); 70 return count; 71 } 72 73 static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry, 74 void *file_private_data, 75 struct file *file, 76 const char __user *_buf, 77 size_t count, loff_t pos) 78 { 79 struct snd_opl4 *opl4 = entry->private_data; 80 char *buf; 81 82 buf = vmalloc(count); 83 if (!buf) 84 return -ENOMEM; 85 if (copy_from_user(buf, _buf, count)) { 86 vfree(buf); 87 return -EFAULT; 88 } 89 snd_opl4_write_memory(opl4, buf, pos, count); 90 vfree(buf); 91 return count; 92 } 93 94 static struct snd_info_entry_ops snd_opl4_mem_proc_ops = { 95 .open = snd_opl4_mem_proc_open, 96 .release = snd_opl4_mem_proc_release, 97 .read = snd_opl4_mem_proc_read, 98 .write = snd_opl4_mem_proc_write, 99 }; 100 101 int snd_opl4_create_proc(struct snd_opl4 *opl4) 102 { 103 struct snd_info_entry *entry; 104 105 entry = snd_info_create_card_entry(opl4->card, "opl4-mem", opl4->card->proc_root); 106 if (entry) { 107 if (opl4->hardware < OPL3_HW_OPL4_ML) { 108 /* OPL4 can access 4 MB external ROM/SRAM */ 109 entry->mode |= S_IWUSR; 110 entry->size = 4 * 1024 * 1024; 111 } else { 112 /* OPL4-ML has 1 MB internal ROM */ 113 entry->size = 1 * 1024 * 1024; 114 } 115 entry->content = SNDRV_INFO_CONTENT_DATA; 116 entry->c.ops = &snd_opl4_mem_proc_ops; 117 entry->module = THIS_MODULE; 118 entry->private_data = opl4; 119 if (snd_info_register(entry) < 0) { 120 snd_info_free_entry(entry); 121 entry = NULL; 122 } 123 } 124 opl4->proc_entry = entry; 125 return 0; 126 } 127 128 void snd_opl4_free_proc(struct snd_opl4 *opl4) 129 { 130 snd_info_free_entry(opl4->proc_entry); 131 } 132 133 #endif /* CONFIG_PROC_FS */ 134