1*1a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
3c1017a4cSJaroslav Kysela * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
41da177e4SLinus Torvalds * DRAM access routines
51da177e4SLinus Torvalds */
61da177e4SLinus Torvalds
71da177e4SLinus Torvalds #include <linux/time.h>
81da177e4SLinus Torvalds #include <sound/core.h>
91da177e4SLinus Torvalds #include <sound/gus.h>
101da177e4SLinus Torvalds #include <sound/info.h>
111da177e4SLinus Torvalds
121da177e4SLinus Torvalds
snd_gus_dram_poke(struct snd_gus_card * gus,char __user * _buffer,unsigned int address,unsigned int size)135e2da206STakashi Iwai static int snd_gus_dram_poke(struct snd_gus_card *gus, char __user *_buffer,
141da177e4SLinus Torvalds unsigned int address, unsigned int size)
151da177e4SLinus Torvalds {
161da177e4SLinus Torvalds unsigned long flags;
171da177e4SLinus Torvalds unsigned int size1, size2;
181da177e4SLinus Torvalds char buffer[256], *pbuffer;
191da177e4SLinus Torvalds
201da177e4SLinus Torvalds while (size > 0) {
211da177e4SLinus Torvalds size1 = size > sizeof(buffer) ? sizeof(buffer) : size;
221da177e4SLinus Torvalds if (copy_from_user(buffer, _buffer, size1))
231da177e4SLinus Torvalds return -EFAULT;
241da177e4SLinus Torvalds if (gus->interwave) {
251da177e4SLinus Torvalds spin_lock_irqsave(&gus->reg_lock, flags);
261da177e4SLinus Torvalds snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
271da177e4SLinus Torvalds snd_gf1_dram_addr(gus, address);
281da177e4SLinus Torvalds outsb(GUSP(gus, DRAM), buffer, size1);
291da177e4SLinus Torvalds spin_unlock_irqrestore(&gus->reg_lock, flags);
301da177e4SLinus Torvalds address += size1;
311da177e4SLinus Torvalds } else {
321da177e4SLinus Torvalds pbuffer = buffer;
331da177e4SLinus Torvalds size2 = size1;
341da177e4SLinus Torvalds while (size2--)
351da177e4SLinus Torvalds snd_gf1_poke(gus, address++, *pbuffer++);
361da177e4SLinus Torvalds }
371da177e4SLinus Torvalds size -= size1;
381da177e4SLinus Torvalds _buffer += size1;
391da177e4SLinus Torvalds }
401da177e4SLinus Torvalds return 0;
411da177e4SLinus Torvalds }
421da177e4SLinus Torvalds
431da177e4SLinus Torvalds
snd_gus_dram_write(struct snd_gus_card * gus,char __user * buffer,unsigned int address,unsigned int size)445e2da206STakashi Iwai int snd_gus_dram_write(struct snd_gus_card *gus, char __user *buffer,
451da177e4SLinus Torvalds unsigned int address, unsigned int size)
461da177e4SLinus Torvalds {
471da177e4SLinus Torvalds return snd_gus_dram_poke(gus, buffer, address, size);
481da177e4SLinus Torvalds }
491da177e4SLinus Torvalds
snd_gus_dram_peek(struct snd_gus_card * gus,char __user * _buffer,unsigned int address,unsigned int size,int rom)505e2da206STakashi Iwai static int snd_gus_dram_peek(struct snd_gus_card *gus, char __user *_buffer,
511da177e4SLinus Torvalds unsigned int address, unsigned int size,
521da177e4SLinus Torvalds int rom)
531da177e4SLinus Torvalds {
541da177e4SLinus Torvalds unsigned long flags;
551da177e4SLinus Torvalds unsigned int size1, size2;
561da177e4SLinus Torvalds char buffer[256], *pbuffer;
571da177e4SLinus Torvalds
581da177e4SLinus Torvalds while (size > 0) {
591da177e4SLinus Torvalds size1 = size > sizeof(buffer) ? sizeof(buffer) : size;
601da177e4SLinus Torvalds if (gus->interwave) {
611da177e4SLinus Torvalds spin_lock_irqsave(&gus->reg_lock, flags);
621da177e4SLinus Torvalds snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, rom ? 0x03 : 0x01);
631da177e4SLinus Torvalds snd_gf1_dram_addr(gus, address);
641da177e4SLinus Torvalds insb(GUSP(gus, DRAM), buffer, size1);
651da177e4SLinus Torvalds snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
661da177e4SLinus Torvalds spin_unlock_irqrestore(&gus->reg_lock, flags);
671da177e4SLinus Torvalds address += size1;
681da177e4SLinus Torvalds } else {
691da177e4SLinus Torvalds pbuffer = buffer;
701da177e4SLinus Torvalds size2 = size1;
711da177e4SLinus Torvalds while (size2--)
721da177e4SLinus Torvalds *pbuffer++ = snd_gf1_peek(gus, address++);
731da177e4SLinus Torvalds }
741da177e4SLinus Torvalds if (copy_to_user(_buffer, buffer, size1))
751da177e4SLinus Torvalds return -EFAULT;
761da177e4SLinus Torvalds size -= size1;
771da177e4SLinus Torvalds _buffer += size1;
781da177e4SLinus Torvalds }
791da177e4SLinus Torvalds return 0;
801da177e4SLinus Torvalds }
811da177e4SLinus Torvalds
snd_gus_dram_read(struct snd_gus_card * gus,char __user * buffer,unsigned int address,unsigned int size,int rom)825e2da206STakashi Iwai int snd_gus_dram_read(struct snd_gus_card *gus, char __user *buffer,
831da177e4SLinus Torvalds unsigned int address, unsigned int size,
841da177e4SLinus Torvalds int rom)
851da177e4SLinus Torvalds {
861da177e4SLinus Torvalds return snd_gus_dram_peek(gus, buffer, address, size, rom);
871da177e4SLinus Torvalds }
88