0001
0002
0003
0004
0005
0006
0007 #include <sound/core.h>
0008 #include <sound/info.h>
0009 #include <sound/gus.h>
0010
0011 #ifdef CONFIG_SND_DEBUG
0012 #define STAT_ADD(x) ((x)++)
0013 #else
0014 #define STAT_ADD(x) while (0) { ; }
0015 #endif
0016
0017 irqreturn_t snd_gus_interrupt(int irq, void *dev_id)
0018 {
0019 struct snd_gus_card * gus = dev_id;
0020 unsigned char status;
0021 int loop = 100;
0022 int handled = 0;
0023
0024 __again:
0025 status = inb(gus->gf1.reg_irqstat);
0026 if (status == 0)
0027 return IRQ_RETVAL(handled);
0028 handled = 1;
0029
0030 if (status & 0x02) {
0031 STAT_ADD(gus->gf1.interrupt_stat_midi_in);
0032 if (gus->gf1.interrupt_handler_midi_in)
0033 gus->gf1.interrupt_handler_midi_in(gus);
0034 }
0035 if (status & 0x01) {
0036 STAT_ADD(gus->gf1.interrupt_stat_midi_out);
0037 if (gus->gf1.interrupt_handler_midi_out)
0038 gus->gf1.interrupt_handler_midi_out(gus);
0039 }
0040 if (status & (0x20 | 0x40)) {
0041 unsigned int already, _current_;
0042 unsigned char voice_status, voice;
0043 struct snd_gus_voice *pvoice;
0044
0045 already = 0;
0046 while (((voice_status = snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ)) & 0xc0) != 0xc0) {
0047 voice = voice_status & 0x1f;
0048 _current_ = 1 << voice;
0049 if (already & _current_)
0050 continue;
0051 already |= _current_;
0052 #if 0
0053 printk(KERN_DEBUG "voice = %i, voice_status = 0x%x, "
0054 "voice_verify = %i\n",
0055 voice, voice_status, inb(GUSP(gus, GF1PAGE)));
0056 #endif
0057 pvoice = &gus->gf1.voices[voice];
0058 if (pvoice->use) {
0059 if (!(voice_status & 0x80)) {
0060 STAT_ADD(pvoice->interrupt_stat_wave);
0061 pvoice->handler_wave(gus, pvoice);
0062 }
0063 if (!(voice_status & 0x40)) {
0064 STAT_ADD(pvoice->interrupt_stat_volume);
0065 pvoice->handler_volume(gus, pvoice);
0066 }
0067 } else {
0068 STAT_ADD(gus->gf1.interrupt_stat_voice_lost);
0069 snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
0070 snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
0071 }
0072 }
0073 }
0074 if (status & 0x04) {
0075 STAT_ADD(gus->gf1.interrupt_stat_timer1);
0076 if (gus->gf1.interrupt_handler_timer1)
0077 gus->gf1.interrupt_handler_timer1(gus);
0078 }
0079 if (status & 0x08) {
0080 STAT_ADD(gus->gf1.interrupt_stat_timer2);
0081 if (gus->gf1.interrupt_handler_timer2)
0082 gus->gf1.interrupt_handler_timer2(gus);
0083 }
0084 if (status & 0x80) {
0085 if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) {
0086 STAT_ADD(gus->gf1.interrupt_stat_dma_write);
0087 if (gus->gf1.interrupt_handler_dma_write)
0088 gus->gf1.interrupt_handler_dma_write(gus);
0089 }
0090 if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) {
0091 STAT_ADD(gus->gf1.interrupt_stat_dma_read);
0092 if (gus->gf1.interrupt_handler_dma_read)
0093 gus->gf1.interrupt_handler_dma_read(gus);
0094 }
0095 }
0096 if (--loop > 0)
0097 goto __again;
0098 return IRQ_NONE;
0099 }
0100
0101 #ifdef CONFIG_SND_DEBUG
0102 static void snd_gus_irq_info_read(struct snd_info_entry *entry,
0103 struct snd_info_buffer *buffer)
0104 {
0105 struct snd_gus_card *gus;
0106 struct snd_gus_voice *pvoice;
0107 int idx;
0108
0109 gus = entry->private_data;
0110 snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out);
0111 snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in);
0112 snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1);
0113 snd_iprintf(buffer, "timer2 = %u\n", gus->gf1.interrupt_stat_timer2);
0114 snd_iprintf(buffer, "dma write = %u\n", gus->gf1.interrupt_stat_dma_write);
0115 snd_iprintf(buffer, "dma read = %u\n", gus->gf1.interrupt_stat_dma_read);
0116 snd_iprintf(buffer, "voice lost = %u\n", gus->gf1.interrupt_stat_voice_lost);
0117 for (idx = 0; idx < 32; idx++) {
0118 pvoice = &gus->gf1.voices[idx];
0119 snd_iprintf(buffer, "voice %i: wave = %u, volume = %u\n",
0120 idx,
0121 pvoice->interrupt_stat_wave,
0122 pvoice->interrupt_stat_volume);
0123 }
0124 }
0125
0126 void snd_gus_irq_profile_init(struct snd_gus_card *gus)
0127 {
0128 snd_card_ro_proc_new(gus->card, "gusirq", gus, snd_gus_irq_info_read);
0129 }
0130
0131 #endif