Diff markup
1 /* 1 /*
2 * Routine for IRQ handling from GF1/InterWav 2 * Routine for IRQ handling from GF1/InterWave chip
3 * Copyright (c) by Jaroslav Kysela <perex@pe 3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4 * 4 *
5 * 5 *
6 * This program is free software; you can re 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Pub 7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either vers 8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. 9 * (at your option) any later version.
10 * 10 *
11 * This program is distributed in the hope t 11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even th 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICUL 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more detai 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GN 16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * 19 *
20 */ 20 */
21 21
22 #include <sound/core.h> 22 #include <sound/core.h>
23 #include <sound/info.h> 23 #include <sound/info.h>
24 #include <sound/gus.h> 24 #include <sound/gus.h>
25 25
26 #ifdef CONFIG_SND_DEBUG 26 #ifdef CONFIG_SND_DEBUG
27 #define STAT_ADD(x) ((x)++) 27 #define STAT_ADD(x) ((x)++)
28 #else 28 #else
29 #define STAT_ADD(x) while (0) { ; } 29 #define STAT_ADD(x) while (0) { ; }
30 #endif 30 #endif
31 31
32 irqreturn_t snd_gus_interrupt(int irq, void *d 32 irqreturn_t snd_gus_interrupt(int irq, void *dev_id)
33 { 33 {
34 struct snd_gus_card * gus = dev_id; 34 struct snd_gus_card * gus = dev_id;
35 unsigned char status; 35 unsigned char status;
36 int loop = 100; 36 int loop = 100;
37 int handled = 0; 37 int handled = 0;
38 38
39 __again: 39 __again:
40 status = inb(gus->gf1.reg_irqstat); 40 status = inb(gus->gf1.reg_irqstat);
41 if (status == 0) 41 if (status == 0)
42 return IRQ_RETVAL(handled); 42 return IRQ_RETVAL(handled);
43 handled = 1; 43 handled = 1;
44 // snd_printk("IRQ: status = 0x%x\n", 44 // snd_printk("IRQ: status = 0x%x\n", status);
45 if (status & 0x02) { 45 if (status & 0x02) {
46 STAT_ADD(gus->gf1.interrupt_st 46 STAT_ADD(gus->gf1.interrupt_stat_midi_in);
47 if (gus->gf1.interrupt_handler 47 if (gus->gf1.interrupt_handler_midi_in)
48 gus->gf1.interrupt_han 48 gus->gf1.interrupt_handler_midi_in(gus);
49 } 49 }
50 if (status & 0x01) { 50 if (status & 0x01) {
51 STAT_ADD(gus->gf1.interrupt_st 51 STAT_ADD(gus->gf1.interrupt_stat_midi_out);
52 if (gus->gf1.interrupt_handler 52 if (gus->gf1.interrupt_handler_midi_out)
53 gus->gf1.interrupt_han 53 gus->gf1.interrupt_handler_midi_out(gus);
54 } 54 }
55 if (status & (0x20 | 0x40)) { 55 if (status & (0x20 | 0x40)) {
56 unsigned int already, _current 56 unsigned int already, _current_;
57 unsigned char voice_status, vo 57 unsigned char voice_status, voice;
58 struct snd_gus_voice *pvoice; 58 struct snd_gus_voice *pvoice;
59 59
60 already = 0; 60 already = 0;
61 while (((voice_status = snd_gf 61 while (((voice_status = snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ)) & 0xc0) != 0xc0) {
62 voice = voice_status & 62 voice = voice_status & 0x1f;
63 _current_ = 1 << voice 63 _current_ = 1 << voice;
64 if (already & _current 64 if (already & _current_)
65 continue; 65 continue; /* multi request */
66 already |= _current_; 66 already |= _current_; /* mark request */
67 #if 0 67 #if 0
68 printk("voice = %i, vo 68 printk("voice = %i, voice_status = 0x%x, voice_verify = %i\n", voice, voice_status, inb(GUSP(gus, GF1PAGE)));
69 #endif 69 #endif
70 pvoice = &gus->gf1.voi 70 pvoice = &gus->gf1.voices[voice];
71 if (pvoice->use) { 71 if (pvoice->use) {
72 if (!(voice_st 72 if (!(voice_status & 0x80)) { /* voice position IRQ */
73 STAT_A 73 STAT_ADD(pvoice->interrupt_stat_wave);
74 pvoice 74 pvoice->handler_wave(gus, pvoice);
75 } 75 }
76 if (!(voice_st 76 if (!(voice_status & 0x40)) { /* volume ramp IRQ */
77 STAT_A 77 STAT_ADD(pvoice->interrupt_stat_volume);
78 pvoice 78 pvoice->handler_volume(gus, pvoice);
79 } 79 }
80 } else { 80 } else {
81 STAT_ADD(gus-> 81 STAT_ADD(gus->gf1.interrupt_stat_voice_lost);
82 snd_gf1_i_ctrl 82 snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL);
83 snd_gf1_i_ctrl 83 snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
84 } 84 }
85 } 85 }
86 } 86 }
87 if (status & 0x04) { 87 if (status & 0x04) {
88 STAT_ADD(gus->gf1.interrupt_st 88 STAT_ADD(gus->gf1.interrupt_stat_timer1);
89 if (gus->gf1.interrupt_handler 89 if (gus->gf1.interrupt_handler_timer1)
90 gus->gf1.interrupt_han 90 gus->gf1.interrupt_handler_timer1(gus);
91 } 91 }
92 if (status & 0x08) { 92 if (status & 0x08) {
93 STAT_ADD(gus->gf1.interrupt_st 93 STAT_ADD(gus->gf1.interrupt_stat_timer2);
94 if (gus->gf1.interrupt_handler 94 if (gus->gf1.interrupt_handler_timer2)
95 gus->gf1.interrupt_han 95 gus->gf1.interrupt_handler_timer2(gus);
96 } 96 }
97 if (status & 0x80) { 97 if (status & 0x80) {
98 if (snd_gf1_i_look8(gus, SNDRV 98 if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) {
99 STAT_ADD(gus->gf1.inte 99 STAT_ADD(gus->gf1.interrupt_stat_dma_write);
100 if (gus->gf1.interrupt 100 if (gus->gf1.interrupt_handler_dma_write)
101 gus->gf1.inter 101 gus->gf1.interrupt_handler_dma_write(gus);
102 } 102 }
103 if (snd_gf1_i_look8(gus, SNDRV 103 if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) {
104 STAT_ADD(gus->gf1.inte 104 STAT_ADD(gus->gf1.interrupt_stat_dma_read);
105 if (gus->gf1.interrupt 105 if (gus->gf1.interrupt_handler_dma_read)
106 gus->gf1.inter 106 gus->gf1.interrupt_handler_dma_read(gus);
107 } 107 }
108 } 108 }
109 if (--loop > 0) 109 if (--loop > 0)
110 goto __again; 110 goto __again;
111 return IRQ_NONE; 111 return IRQ_NONE;
112 } 112 }
113 113
114 #ifdef CONFIG_SND_DEBUG 114 #ifdef CONFIG_SND_DEBUG
115 static void snd_gus_irq_info_read(struct snd_i 115 static void snd_gus_irq_info_read(struct snd_info_entry *entry,
116 struct snd_i 116 struct snd_info_buffer *buffer)
117 { 117 {
118 struct snd_gus_card *gus; 118 struct snd_gus_card *gus;
119 struct snd_gus_voice *pvoice; 119 struct snd_gus_voice *pvoice;
120 int idx; 120 int idx;
121 121
122 gus = entry->private_data; 122 gus = entry->private_data;
123 snd_iprintf(buffer, "midi out = %u\n", 123 snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out);
124 snd_iprintf(buffer, "midi in = %u\n", 124 snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in);
125 snd_iprintf(buffer, "timer1 = %u\n", g 125 snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1);
126 snd_iprintf(buffer, "timer2 = %u\n", g 126 snd_iprintf(buffer, "timer2 = %u\n", gus->gf1.interrupt_stat_timer2);
127 snd_iprintf(buffer, "dma write = %u\n" 127 snd_iprintf(buffer, "dma write = %u\n", gus->gf1.interrupt_stat_dma_write);
128 snd_iprintf(buffer, "dma read = %u\n", 128 snd_iprintf(buffer, "dma read = %u\n", gus->gf1.interrupt_stat_dma_read);
129 snd_iprintf(buffer, "voice lost = %u\n 129 snd_iprintf(buffer, "voice lost = %u\n", gus->gf1.interrupt_stat_voice_lost);
130 for (idx = 0; idx < 32; idx++) { 130 for (idx = 0; idx < 32; idx++) {
131 pvoice = &gus->gf1.voices[idx] 131 pvoice = &gus->gf1.voices[idx];
132 snd_iprintf(buffer, "voice %i: 132 snd_iprintf(buffer, "voice %i: wave = %u, volume = %u\n",
133 idx, 133 idx,
134 pvoice 134 pvoice->interrupt_stat_wave,
135 pvoice 135 pvoice->interrupt_stat_volume);
136 } 136 }
137 } 137 }
138 138
139 void snd_gus_irq_profile_init(struct snd_gus_c 139 void snd_gus_irq_profile_init(struct snd_gus_card *gus)
140 { 140 {
141 struct snd_info_entry *entry; 141 struct snd_info_entry *entry;
142 142
143 if (! snd_card_proc_new(gus->card, "gu 143 if (! snd_card_proc_new(gus->card, "gusirq", &entry))
144 snd_info_set_text_ops(entry, g 144 snd_info_set_text_ops(entry, gus, snd_gus_irq_info_read);
145 } 145 }
146 146
147 #endif 147 #endif
148 148
|
This page was automatically generated by the
LXR engine.
|