xref: /openbmc/linux/sound/isa/gus/gus_dram.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
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