root/sound/isa/gus/gus_irq.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_gus_interrupt
  2. snd_gus_irq_info_read
  3. snd_gus_irq_profile_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Routine for IRQ handling from GF1/InterWave chip
   4  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   5  */
   6 
   7 #include <sound/core.h>
   8 #include <sound/info.h>
   9 #include <sound/gus.h>
  10 
  11 #ifdef CONFIG_SND_DEBUG
  12 #define STAT_ADD(x)     ((x)++)
  13 #else
  14 #define STAT_ADD(x)     while (0) { ; }
  15 #endif
  16 
  17 irqreturn_t snd_gus_interrupt(int irq, void *dev_id)
  18 {
  19         struct snd_gus_card * gus = dev_id;
  20         unsigned char status;
  21         int loop = 100;
  22         int handled = 0;
  23 
  24 __again:
  25         status = inb(gus->gf1.reg_irqstat);
  26         if (status == 0)
  27                 return IRQ_RETVAL(handled);
  28         handled = 1;
  29         /* snd_printk(KERN_DEBUG "IRQ: status = 0x%x\n", status); */
  30         if (status & 0x02) {
  31                 STAT_ADD(gus->gf1.interrupt_stat_midi_in);
  32                 if (gus->gf1.interrupt_handler_midi_in)
  33                         gus->gf1.interrupt_handler_midi_in(gus);
  34         }
  35         if (status & 0x01) {
  36                 STAT_ADD(gus->gf1.interrupt_stat_midi_out);
  37                 if (gus->gf1.interrupt_handler_midi_out)
  38                         gus->gf1.interrupt_handler_midi_out(gus);
  39         }
  40         if (status & (0x20 | 0x40)) {
  41                 unsigned int already, _current_;
  42                 unsigned char voice_status, voice;
  43                 struct snd_gus_voice *pvoice;
  44 
  45                 already = 0;
  46                 while (((voice_status = snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ)) & 0xc0) != 0xc0) {
  47                         voice = voice_status & 0x1f;
  48                         _current_ = 1 << voice;
  49                         if (already & _current_)
  50                                 continue;       /* multi request */
  51                         already |= _current_;   /* mark request */
  52 #if 0
  53                         printk(KERN_DEBUG "voice = %i, voice_status = 0x%x, "
  54                                "voice_verify = %i\n",
  55                                voice, voice_status, inb(GUSP(gus, GF1PAGE)));
  56 #endif
  57                         pvoice = &gus->gf1.voices[voice]; 
  58                         if (pvoice->use) {
  59                                 if (!(voice_status & 0x80)) {   /* voice position IRQ */
  60                                         STAT_ADD(pvoice->interrupt_stat_wave);
  61                                         pvoice->handler_wave(gus, pvoice);
  62                                 }
  63                                 if (!(voice_status & 0x40)) {   /* volume ramp IRQ */
  64                                         STAT_ADD(pvoice->interrupt_stat_volume);
  65                                         pvoice->handler_volume(gus, pvoice);
  66                                 }
  67                         } else {
  68                                 STAT_ADD(gus->gf1.interrupt_stat_voice_lost);
  69                                 snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
  70                                 snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
  71                         }
  72                 }
  73         }
  74         if (status & 0x04) {
  75                 STAT_ADD(gus->gf1.interrupt_stat_timer1);
  76                 if (gus->gf1.interrupt_handler_timer1)
  77                         gus->gf1.interrupt_handler_timer1(gus);
  78         }
  79         if (status & 0x08) {
  80                 STAT_ADD(gus->gf1.interrupt_stat_timer2);
  81                 if (gus->gf1.interrupt_handler_timer2)
  82                         gus->gf1.interrupt_handler_timer2(gus);
  83         }
  84         if (status & 0x80) {
  85                 if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) {
  86                         STAT_ADD(gus->gf1.interrupt_stat_dma_write);
  87                         if (gus->gf1.interrupt_handler_dma_write)
  88                                 gus->gf1.interrupt_handler_dma_write(gus);
  89                 }
  90                 if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) {
  91                         STAT_ADD(gus->gf1.interrupt_stat_dma_read);
  92                         if (gus->gf1.interrupt_handler_dma_read)
  93                                 gus->gf1.interrupt_handler_dma_read(gus);
  94                 }
  95         }
  96         if (--loop > 0)
  97                 goto __again;
  98         return IRQ_NONE;
  99 }
 100 
 101 #ifdef CONFIG_SND_DEBUG
 102 static void snd_gus_irq_info_read(struct snd_info_entry *entry, 
 103                                   struct snd_info_buffer *buffer)
 104 {
 105         struct snd_gus_card *gus;
 106         struct snd_gus_voice *pvoice;
 107         int idx;
 108 
 109         gus = entry->private_data;
 110         snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out);
 111         snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in);
 112         snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1);
 113         snd_iprintf(buffer, "timer2 = %u\n", gus->gf1.interrupt_stat_timer2);
 114         snd_iprintf(buffer, "dma write = %u\n", gus->gf1.interrupt_stat_dma_write);
 115         snd_iprintf(buffer, "dma read = %u\n", gus->gf1.interrupt_stat_dma_read);
 116         snd_iprintf(buffer, "voice lost = %u\n", gus->gf1.interrupt_stat_voice_lost);
 117         for (idx = 0; idx < 32; idx++) {
 118                 pvoice = &gus->gf1.voices[idx];
 119                 snd_iprintf(buffer, "voice %i: wave = %u, volume = %u\n",
 120                                         idx,
 121                                         pvoice->interrupt_stat_wave,
 122                                         pvoice->interrupt_stat_volume);
 123         }
 124 }
 125 
 126 void snd_gus_irq_profile_init(struct snd_gus_card *gus)
 127 {
 128         snd_card_ro_proc_new(gus->card, "gusirq", gus, snd_gus_irq_info_read);
 129 }
 130 
 131 #endif

/* [<][>][^][v][top][bottom][index][help] */