diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:27:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:27:49 +0000 |
commit | ace9429bb58fd418f0c81d4c2835699bddf6bde6 (patch) | |
tree | b2d64bc10158fdd5497876388cd68142ca374ed3 /sound/isa/gus/gus_dram.c | |
parent | Initial commit. (diff) | |
download | linux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.tar.xz linux-ace9429bb58fd418f0c81d4c2835699bddf6bde6.zip |
Adding upstream version 6.6.15.upstream/6.6.15
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sound/isa/gus/gus_dram.c')
-rw-r--r-- | sound/isa/gus/gus_dram.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/sound/isa/gus/gus_dram.c b/sound/isa/gus/gus_dram.c new file mode 100644 index 0000000000..5cebc0119d --- /dev/null +++ b/sound/isa/gus/gus_dram.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) by Jaroslav Kysela <perex@perex.cz> + * DRAM access routines + */ + +#include <linux/time.h> +#include <sound/core.h> +#include <sound/gus.h> +#include <sound/info.h> + + +static int snd_gus_dram_poke(struct snd_gus_card *gus, char __user *_buffer, + unsigned int address, unsigned int size) +{ + unsigned long flags; + unsigned int size1, size2; + char buffer[256], *pbuffer; + + while (size > 0) { + size1 = size > sizeof(buffer) ? sizeof(buffer) : size; + if (copy_from_user(buffer, _buffer, size1)) + return -EFAULT; + if (gus->interwave) { + spin_lock_irqsave(&gus->reg_lock, flags); + snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); + snd_gf1_dram_addr(gus, address); + outsb(GUSP(gus, DRAM), buffer, size1); + spin_unlock_irqrestore(&gus->reg_lock, flags); + address += size1; + } else { + pbuffer = buffer; + size2 = size1; + while (size2--) + snd_gf1_poke(gus, address++, *pbuffer++); + } + size -= size1; + _buffer += size1; + } + return 0; +} + + +int snd_gus_dram_write(struct snd_gus_card *gus, char __user *buffer, + unsigned int address, unsigned int size) +{ + return snd_gus_dram_poke(gus, buffer, address, size); +} + +static int snd_gus_dram_peek(struct snd_gus_card *gus, char __user *_buffer, + unsigned int address, unsigned int size, + int rom) +{ + unsigned long flags; + unsigned int size1, size2; + char buffer[256], *pbuffer; + + while (size > 0) { + size1 = size > sizeof(buffer) ? sizeof(buffer) : size; + if (gus->interwave) { + spin_lock_irqsave(&gus->reg_lock, flags); + snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, rom ? 0x03 : 0x01); + snd_gf1_dram_addr(gus, address); + insb(GUSP(gus, DRAM), buffer, size1); + snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01); + spin_unlock_irqrestore(&gus->reg_lock, flags); + address += size1; + } else { + pbuffer = buffer; + size2 = size1; + while (size2--) + *pbuffer++ = snd_gf1_peek(gus, address++); + } + if (copy_to_user(_buffer, buffer, size1)) + return -EFAULT; + size -= size1; + _buffer += size1; + } + return 0; +} + +int snd_gus_dram_read(struct snd_gus_card *gus, char __user *buffer, + unsigned int address, unsigned int size, + int rom) +{ + return snd_gus_dram_peek(gus, buffer, address, size, rom); +} |