1 /* 2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz> 3 * DRAM access routines 4 * 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22 #include <sound/driver.h> 23 #include <linux/time.h> 24 #include <sound/core.h> 25 #include <sound/gus.h> 26 #include <sound/info.h> 27 28 29 static int snd_gus_dram_poke(struct snd_gus_card *gus, char __user *_buffer, 30 unsigned int address, unsigned int size) 31 { 32 unsigned long flags; 33 unsigned int size1, size2; 34 char buffer[256], *pbuffer; 35 36 while (size > 0) { 37 size1 = size > sizeof(buffer) ? sizeof(buffer) : size; 38 if (copy_from_user(buffer, _buffer, size1)) 39 return -EFAULT; 40 if (gus->interwave) { 41 spin_lock_irqsave(&gus->reg_lock, flags); 42 snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); 43 snd_gf1_dram_addr(gus, address); 44 outsb(GUSP(gus, DRAM), buffer, size1); 45 spin_unlock_irqrestore(&gus->reg_lock, flags); 46 address += size1; 47 } else { 48 pbuffer = buffer; 49 size2 = size1; 50 while (size2--) 51 snd_gf1_poke(gus, address++, *pbuffer++); 52 } 53 size -= size1; 54 _buffer += size1; 55 } 56 return 0; 57 } 58 59 60 int snd_gus_dram_write(struct snd_gus_card *gus, char __user *buffer, 61 unsigned int address, unsigned int size) 62 { 63 return snd_gus_dram_poke(gus, buffer, address, size); 64 } 65 66 static int snd_gus_dram_peek(struct snd_gus_card *gus, char __user *_buffer, 67 unsigned int address, unsigned int size, 68 int rom) 69 { 70 unsigned long flags; 71 unsigned int size1, size2; 72 char buffer[256], *pbuffer; 73 74 while (size > 0) { 75 size1 = size > sizeof(buffer) ? sizeof(buffer) : size; 76 if (gus->interwave) { 77 spin_lock_irqsave(&gus->reg_lock, flags); 78 snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, rom ? 0x03 : 0x01); 79 snd_gf1_dram_addr(gus, address); 80 insb(GUSP(gus, DRAM), buffer, size1); 81 snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); 82 spin_unlock_irqrestore(&gus->reg_lock, flags); 83 address += size1; 84 } else { 85 pbuffer = buffer; 86 size2 = size1; 87 while (size2--) 88 *pbuffer++ = snd_gf1_peek(gus, address++); 89 } 90 if (copy_to_user(_buffer, buffer, size1)) 91 return -EFAULT; 92 size -= size1; 93 _buffer += size1; 94 } 95 return 0; 96 } 97 98 int snd_gus_dram_read(struct snd_gus_card *gus, char __user *buffer, 99 unsigned int address, unsigned int size, 100 int rom) 101 { 102 return snd_gus_dram_peek(gus, buffer, address, size, rom); 103 } 104