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