This source file includes following definitions.
- snd_emu8000_open_dma
- snd_emu8000_close_dma
- read_word
- snd_emu8000_write_wait
- write_word
- snd_emu8000_sample_new
- snd_emu8000_sample_free
- snd_emu8000_sample_reset
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 #include "emu8000_local.h"
  10 
  11 #include <linux/sched/signal.h>
  12 #include <linux/uaccess.h>
  13 #include <linux/moduleparam.h>
  14 
  15 static int emu8000_reset_addr;
  16 module_param(emu8000_reset_addr, int, 0444);
  17 MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)");
  18 
  19 
  20 
  21 
  22 
  23 static int
  24 snd_emu8000_open_dma(struct snd_emu8000 *emu, int write)
  25 {
  26         int i;
  27 
  28         
  29         for (i = 0; i < EMU8000_DRAM_VOICES; i++) {
  30                 snd_emux_lock_voice(emu->emu, i);
  31                 snd_emu8000_dma_chan(emu, i, write);
  32         }
  33 
  34         
  35         EMU8000_VTFT_WRITE(emu, 30, 0);
  36         EMU8000_PSST_WRITE(emu, 30, 0x1d8);
  37         EMU8000_CSL_WRITE(emu, 30, 0x1e0);
  38         EMU8000_CCCA_WRITE(emu, 30, 0x1d8);
  39         EMU8000_VTFT_WRITE(emu, 31, 0);
  40         EMU8000_PSST_WRITE(emu, 31, 0x1d8);
  41         EMU8000_CSL_WRITE(emu, 31, 0x1e0);
  42         EMU8000_CCCA_WRITE(emu, 31, 0x1d8);
  43 
  44         return 0;
  45 }
  46 
  47 
  48 
  49 
  50 static void
  51 snd_emu8000_close_dma(struct snd_emu8000 *emu)
  52 {
  53         int i;
  54 
  55         for (i = 0; i < EMU8000_DRAM_VOICES; i++) {
  56                 snd_emu8000_dma_chan(emu, i, EMU8000_RAM_CLOSE);
  57                 snd_emux_unlock_voice(emu->emu, i);
  58         }
  59 }
  60 
  61 
  62 
  63 
  64 #define BLANK_LOOP_START        4
  65 #define BLANK_LOOP_END          8
  66 #define BLANK_LOOP_SIZE         12
  67 #define BLANK_HEAD_SIZE         48
  68 
  69 
  70 
  71 
  72 
  73 static unsigned short
  74 read_word(const void __user *buf, int offset, int mode)
  75 {
  76         unsigned short c;
  77         if (mode & SNDRV_SFNT_SAMPLE_8BITS) {
  78                 unsigned char cc;
  79                 get_user(cc, (unsigned char __user *)buf + offset);
  80                 c = cc << 8; 
  81         } else {
  82 #ifdef SNDRV_LITTLE_ENDIAN
  83                 get_user(c, (unsigned short __user *)buf + offset);
  84 #else
  85                 unsigned short cc;
  86                 get_user(cc, (unsigned short __user *)buf + offset);
  87                 c = swab16(cc);
  88 #endif
  89         }
  90         if (mode & SNDRV_SFNT_SAMPLE_UNSIGNED)
  91                 c ^= 0x8000; 
  92         return c;
  93 }
  94 
  95 
  96 
  97 static void
  98 snd_emu8000_write_wait(struct snd_emu8000 *emu)
  99 {
 100         while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
 101                 schedule_timeout_interruptible(1);
 102                 if (signal_pending(current))
 103                         break;
 104         }
 105 }
 106 
 107 
 108 
 109 
 110 
 111 
 112 
 113 
 114 
 115 
 116 
 117 
 118 
 119 static inline void
 120 write_word(struct snd_emu8000 *emu, int *offset, unsigned short data)
 121 {
 122         if (emu8000_reset_addr) {
 123                 if (emu8000_reset_addr > 1)
 124                         snd_emu8000_write_wait(emu);
 125                 EMU8000_SMALW_WRITE(emu, *offset);
 126         }
 127         EMU8000_SMLD_WRITE(emu, data);
 128         *offset += 1;
 129 }
 130 
 131 
 132 
 133 
 134 
 135 int
 136 snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
 137                        struct snd_util_memhdr *hdr,
 138                        const void __user *data, long count)
 139 {
 140         int  i;
 141         int  rc;
 142         int  offset;
 143         int  truesize;
 144         int  dram_offset, dram_start;
 145         struct snd_emu8000 *emu;
 146 
 147         emu = rec->hw;
 148         if (snd_BUG_ON(!sp))
 149                 return -EINVAL;
 150 
 151         if (sp->v.size == 0)
 152                 return 0;
 153 
 154         
 155         if (sp->v.loopstart > sp->v.loopend)
 156                 swap(sp->v.loopstart, sp->v.loopend);
 157 
 158         
 159         truesize = sp->v.size;
 160         if (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP))
 161                 truesize += sp->v.loopend - sp->v.loopstart;
 162         if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK)
 163                 truesize += BLANK_LOOP_SIZE;
 164 
 165         sp->block = snd_util_mem_alloc(hdr, truesize * 2);
 166         if (sp->block == NULL) {
 167                 
 168                 
 169                 return -ENOSPC;
 170         }
 171 
 172         if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_8BITS) {
 173                 if (!access_ok(data, sp->v.size))
 174                         return -EFAULT;
 175         } else {
 176                 if (!access_ok(data, sp->v.size * 2))
 177                         return -EFAULT;
 178         }
 179 
 180         
 181         sp->v.end -= sp->v.start;
 182         sp->v.loopstart -= sp->v.start;
 183         sp->v.loopend -= sp->v.start;
 184         sp->v.start = 0;
 185 
 186         
 187         dram_offset = EMU8000_DRAM_OFFSET + (sp->block->offset >> 1);
 188         dram_start = dram_offset;
 189 
 190         
 191         sp->v.truesize = truesize * 2; 
 192 
 193         snd_emux_terminate_all(emu->emu);
 194         if ((rc = snd_emu8000_open_dma(emu, EMU8000_RAM_WRITE)) != 0)
 195                 return rc;
 196 
 197         
 198         snd_emu8000_write_wait(emu);
 199         EMU8000_SMALW_WRITE(emu, dram_offset);
 200 
 201         
 202 
 203 #if 0
 204         
 205         if (! sp->block->offset) {
 206                 for (i = 0; i < BLANK_HEAD_SIZE; i++) {
 207                         write_word(emu, &dram_offset, 0);
 208                 }
 209         }
 210 #endif
 211 
 212         offset = 0;
 213         for (i = 0; i < sp->v.size; i++) {
 214                 unsigned short s;
 215 
 216                 s = read_word(data, offset, sp->v.mode_flags);
 217                 offset++;
 218                 write_word(emu, &dram_offset, s);
 219 
 220                 
 221 
 222 
 223                 cond_resched();
 224 
 225                 if (i == sp->v.loopend &&
 226                     (sp->v.mode_flags & (SNDRV_SFNT_SAMPLE_BIDIR_LOOP|SNDRV_SFNT_SAMPLE_REVERSE_LOOP)))
 227                 {
 228                         int looplen = sp->v.loopend - sp->v.loopstart;
 229                         int k;
 230 
 231                         
 232                         for (k = 1; k <= looplen; k++) {
 233                                 s = read_word(data, offset - k, sp->v.mode_flags);
 234                                 write_word(emu, &dram_offset, s);
 235                         }
 236                         if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_BIDIR_LOOP) {
 237                                 sp->v.loopend += looplen;
 238                         } else {
 239                                 sp->v.loopstart += looplen;
 240                                 sp->v.loopend += looplen;
 241                         }
 242                         sp->v.end += looplen;
 243                 }
 244         }
 245 
 246         
 247         if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_NO_BLANK) {
 248                 for (i = 0; i < BLANK_LOOP_SIZE; i++) {
 249                         write_word(emu, &dram_offset, 0);
 250                 }
 251                 if (sp->v.mode_flags & SNDRV_SFNT_SAMPLE_SINGLESHOT) {
 252                         sp->v.loopstart = sp->v.end + BLANK_LOOP_START;
 253                         sp->v.loopend = sp->v.end + BLANK_LOOP_END;
 254                 }
 255         }
 256 
 257         
 258         sp->v.start += dram_start;
 259         sp->v.end += dram_start;
 260         sp->v.loopstart += dram_start;
 261         sp->v.loopend += dram_start;
 262 
 263         snd_emu8000_close_dma(emu);
 264         snd_emu8000_init_fm(emu);
 265 
 266         return 0;
 267 }
 268 
 269 
 270 
 271 
 272 int
 273 snd_emu8000_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
 274                         struct snd_util_memhdr *hdr)
 275 {
 276         if (sp->block) {
 277                 snd_util_mem_free(hdr, sp->block);
 278                 sp->block = NULL;
 279         }
 280         return 0;
 281 }
 282 
 283 
 284 
 285 
 286 
 287 void
 288 snd_emu8000_sample_reset(struct snd_emux *rec)
 289 {
 290         snd_emux_terminate_all(rec);
 291 }