cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

emu10k1_patch.c (5549B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Patch transfer callback for Emu10k1
      4 *
      5 *  Copyright (C) 2000 Takashi iwai <tiwai@suse.de>
      6 */
      7/*
      8 * All the code for loading in a patch.  There is very little that is
      9 * chip specific here.  Just the actual writing to the board.
     10 */
     11
     12#include "emu10k1_synth_local.h"
     13
     14/*
     15 */
     16#define BLANK_LOOP_START	4
     17#define BLANK_LOOP_END		8
     18#define BLANK_LOOP_SIZE		12
     19#define BLANK_HEAD_SIZE		32
     20
     21/*
     22 * allocate a sample block and copy data from userspace
     23 */
     24int
     25snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
     26		       struct snd_util_memhdr *hdr,
     27		       const void __user *data, long count)
     28{
     29	int offset;
     30	int truesize, size, blocksize;
     31	__maybe_unused int loopsize;
     32	int loopend, sampleend;
     33	unsigned int start_addr;
     34	struct snd_emu10k1 *emu;
     35
     36	emu = rec->hw;
     37	if (snd_BUG_ON(!sp || !hdr))
     38		return -EINVAL;
     39
     40	if (sp->v.size == 0) {
     41		dev_dbg(emu->card->dev,
     42			"emu: rom font for sample %d\n", sp->v.sample);
     43		return 0;
     44	}
     45
     46	/* recalculate address offset */
     47	sp->v.end -= sp->v.start;
     48	sp->v.loopstart -= sp->v.start;
     49	sp->v.loopend -= sp->v.start;
     50	sp->v.start = 0;
     51
     52	/* some samples have invalid data.  the addresses are corrected in voice info */
     53	sampleend = sp->v.end;
     54	if (sampleend > sp->v.size)
     55		sampleend = sp->v.size;
     56	loopend = sp->v.loopend;
     57	if (loopend > sampleend)
     58		loopend = sampleend;
     59
     60	/* be sure loop points start < end */
     61	if (sp->v.loopstart >= sp->v.loopend)
     62		swap(sp->v.loopstart, sp->v.loopend);
     63
     64	/* compute true data size to be loaded */
     65	truesize = sp->v.size + BLANK_HEAD_SIZE;
     66	loopsize = 0;
     67#if 0 /* not supported */
     68	if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
     69		loopsize = sp->v.loopend - sp->v.loopstart;
     70	truesize += loopsize;
     71#endif
     72	if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
     73		truesize += BLANK_LOOP_SIZE;
     74
     75	/* try to allocate a memory block */
     76	blocksize = truesize;
     77	if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
     78		blocksize *= 2;
     79	sp->block = snd_emu10k1_synth_alloc(emu, blocksize);
     80	if (sp->block == NULL) {
     81		dev_dbg(emu->card->dev,
     82			"synth malloc failed (size=%d)\n", blocksize);
     83		/* not ENOMEM (for compatibility with OSS) */
     84		return -ENOSPC;
     85	}
     86	/* set the total size */
     87	sp->v.truesize = blocksize;
     88
     89	/* write blank samples at head */
     90	offset = 0;
     91	size = BLANK_HEAD_SIZE;
     92	if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
     93		size *= 2;
     94	if (offset + size > blocksize)
     95		return -EINVAL;
     96	snd_emu10k1_synth_bzero(emu, sp->block, offset, size);
     97	offset += size;
     98
     99	/* copy start->loopend */
    100	size = loopend;
    101	if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
    102		size *= 2;
    103	if (offset + size > blocksize)
    104		return -EINVAL;
    105	if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
    106		snd_emu10k1_synth_free(emu, sp->block);
    107		sp->block = NULL;
    108		return -EFAULT;
    109	}
    110	offset += size;
    111	data += size;
    112
    113#if 0 /* not supported yet */
    114	/* handle reverse (or bidirectional) loop */
    115	if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)) {
    116		/* copy loop in reverse */
    117		if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
    118			int woffset;
    119			unsigned short *wblock = (unsigned short*)block;
    120			woffset = offset / 2;
    121			if (offset + loopsize * 2 > blocksize)
    122				return -EINVAL;
    123			for (i = 0; i < loopsize; i++)
    124				wblock[woffset + i] = wblock[woffset - i -1];
    125			offset += loopsize * 2;
    126		} else {
    127			if (offset + loopsize > blocksize)
    128				return -EINVAL;
    129			for (i = 0; i < loopsize; i++)
    130				block[offset + i] = block[offset - i -1];
    131			offset += loopsize;
    132		}
    133
    134		/* modify loop pointers */
    135		if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
    136			sp->v.loopend += loopsize;
    137		} else {
    138			sp->v.loopstart += loopsize;
    139			sp->v.loopend += loopsize;
    140		}
    141		/* add sample pointer */
    142		sp->v.end += loopsize;
    143	}
    144#endif
    145
    146	/* loopend -> sample end */
    147	size = sp->v.size - loopend;
    148	if (size < 0)
    149		return -EINVAL;
    150	if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
    151		size *= 2;
    152	if (snd_emu10k1_synth_copy_from_user(emu, sp->block, offset, data, size)) {
    153		snd_emu10k1_synth_free(emu, sp->block);
    154		sp->block = NULL;
    155		return -EFAULT;
    156	}
    157	offset += size;
    158
    159	/* clear rest of samples (if any) */
    160	if (offset < blocksize)
    161		snd_emu10k1_synth_bzero(emu, sp->block, offset, blocksize - offset);
    162
    163	if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
    164		/* if no blank loop is attached in the sample, add it */
    165		if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
    166			sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
    167			sp->v.loopend = sp->v.end + BLANK_LOOP_END;
    168		}
    169	}
    170
    171#if 0 /* not supported yet */
    172	if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_UNSIGNED) {
    173		/* unsigned -> signed */
    174		if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS)) {
    175			unsigned short *wblock = (unsigned short*)block;
    176			for (i = 0; i < truesize; i++)
    177				wblock[i] ^= 0x8000;
    178		} else {
    179			for (i = 0; i < truesize; i++)
    180				block[i] ^= 0x80;
    181		}
    182	}
    183#endif
    184
    185	/* recalculate offset */
    186	start_addr = BLANK_HEAD_SIZE * 2;
    187	if (! (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS))
    188		start_addr >>= 1;
    189	sp->v.start += start_addr;
    190	sp->v.end += start_addr;
    191	sp->v.loopstart += start_addr;
    192	sp->v.loopend += start_addr;
    193
    194	return 0;
    195}
    196
    197/*
    198 * free a sample block
    199 */
    200int
    201snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
    202			struct snd_util_memhdr *hdr)
    203{
    204	struct snd_emu10k1 *emu;
    205
    206	emu = rec->hw;
    207	if (snd_BUG_ON(!sp || !hdr))
    208		return -EINVAL;
    209
    210	if (sp->block) {
    211		snd_emu10k1_synth_free(emu, sp->block);
    212		sp->block = NULL;
    213	}
    214	return 0;
    215}
    216