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 <sound/info.h> 23 24 #ifdef CONFIG_PROC_FS 25 26 static int snd_opl4_mem_proc_open(struct snd_info_entry *entry, 27 unsigned short mode, void **file_private_data) 28 { 29 struct snd_opl4 *opl4 = entry->private_data; 30 31 mutex_lock(&opl4->access_mutex); 32 if (opl4->memory_access) { 33 mutex_unlock(&opl4->access_mutex); 34 return -EBUSY; 35 } 36 opl4->memory_access++; 37 mutex_unlock(&opl4->access_mutex); 38 return 0; 39 } 40 41 static int snd_opl4_mem_proc_release(struct snd_info_entry *entry, 42 unsigned short mode, void *file_private_data) 43 { 44 struct snd_opl4 *opl4 = entry->private_data; 45 46 mutex_lock(&opl4->access_mutex); 47 opl4->memory_access--; 48 mutex_unlock(&opl4->access_mutex); 49 return 0; 50 } 51 52 static ssize_t snd_opl4_mem_proc_read(struct snd_info_entry *entry, 53 void *file_private_data, 54 struct file *file, char __user *_buf, 55 size_t count, loff_t pos) 56 { 57 struct snd_opl4 *opl4 = entry->private_data; 58 char* buf; 59 60 buf = vmalloc(count); 61 if (!buf) 62 return -ENOMEM; 63 snd_opl4_read_memory(opl4, buf, pos, count); 64 if (copy_to_user(_buf, buf, count)) { 65 vfree(buf); 66 return -EFAULT; 67 } 68 vfree(buf); 69 return count; 70 } 71 72 static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry, 73 void *file_private_data, 74 struct file *file, 75 const char __user *_buf, 76 size_t count, loff_t pos) 77 { 78 struct snd_opl4 *opl4 = entry->private_data; 79 char *buf; 80 81 buf = vmalloc(count); 82 if (!buf) 83 return -ENOMEM; 84 if (copy_from_user(buf, _buf, count)) { 85 vfree(buf); 86 return -EFAULT; 87 } 88 snd_opl4_write_memory(opl4, buf, pos, count); 89 vfree(buf); 90 return count; 91 } 92 93 static struct snd_info_entry_ops snd_opl4_mem_proc_ops = { 94 .open = snd_opl4_mem_proc_open, 95 .release = snd_opl4_mem_proc_release, 96 .read = snd_opl4_mem_proc_read, 97 .write = snd_opl4_mem_proc_write, 98 }; 99 100 int snd_opl4_create_proc(struct snd_opl4 *opl4) 101 { 102 struct snd_info_entry *entry; 103 104 entry = snd_info_create_card_entry(opl4->card, "opl4-mem", opl4->card->proc_root); 105 if (entry) { 106 if (opl4->hardware < OPL3_HW_OPL4_ML) { 107 /* OPL4 can access 4 MB external ROM/SRAM */ 108 entry->mode |= S_IWUSR; 109 entry->size = 4 * 1024 * 1024; 110 } else { 111 /* OPL4-ML has 1 MB internal ROM */ 112 entry->size = 1 * 1024 * 1024; 113 } 114 entry->content = SNDRV_INFO_CONTENT_DATA; 115 entry->c.ops = &snd_opl4_mem_proc_ops; 116 entry->module = THIS_MODULE; 117 entry->private_data = opl4; 118 if (snd_info_register(entry) < 0) { 119 snd_info_free_entry(entry); 120 entry = NULL; 121 } 122 } 123 opl4->proc_entry = entry; 124 return 0; 125 } 126 127 void snd_opl4_free_proc(struct snd_opl4 *opl4) 128 { 129 snd_info_free_entry(opl4->proc_entry); 130 } 131 132 #endif /* CONFIG_PROC_FS */ 133