diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/isa/gus/gus_irq.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'sound/isa/gus/gus_irq.c')
-rw-r--r-- | sound/isa/gus/gus_irq.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c new file mode 100644 index 000000000000..1e2a15eb8106 --- /dev/null +++ b/sound/isa/gus/gus_irq.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * Routine for IRQ handling from GF1/InterWave chip | ||
3 | * Copyright (c) by Jaroslav Kysela <perex@suse.cz> | ||
4 | * | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <sound/driver.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/info.h> | ||
25 | #include <sound/gus.h> | ||
26 | |||
27 | #ifdef CONFIG_SND_DEBUG | ||
28 | #define STAT_ADD(x) ((x)++) | ||
29 | #else | ||
30 | #define STAT_ADD(x) while (0) { ; } | ||
31 | #endif | ||
32 | |||
33 | irqreturn_t snd_gus_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
34 | { | ||
35 | snd_gus_card_t * gus = dev_id; | ||
36 | unsigned char status; | ||
37 | int loop = 100; | ||
38 | int handled = 0; | ||
39 | |||
40 | __again: | ||
41 | status = inb(gus->gf1.reg_irqstat); | ||
42 | if (status == 0) | ||
43 | return IRQ_RETVAL(handled); | ||
44 | handled = 1; | ||
45 | // snd_printk("IRQ: status = 0x%x\n", status); | ||
46 | if (status & 0x02) { | ||
47 | STAT_ADD(gus->gf1.interrupt_stat_midi_in); | ||
48 | gus->gf1.interrupt_handler_midi_in(gus); | ||
49 | } | ||
50 | if (status & 0x01) { | ||
51 | STAT_ADD(gus->gf1.interrupt_stat_midi_out); | ||
52 | gus->gf1.interrupt_handler_midi_out(gus); | ||
53 | } | ||
54 | if (status & (0x20 | 0x40)) { | ||
55 | unsigned int already, _current_; | ||
56 | unsigned char voice_status, voice; | ||
57 | snd_gus_voice_t *pvoice; | ||
58 | |||
59 | already = 0; | ||
60 | while (((voice_status = snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ)) & 0xc0) != 0xc0) { | ||
61 | voice = voice_status & 0x1f; | ||
62 | _current_ = 1 << voice; | ||
63 | if (already & _current_) | ||
64 | continue; /* multi request */ | ||
65 | already |= _current_; /* mark request */ | ||
66 | #if 0 | ||
67 | printk("voice = %i, voice_status = 0x%x, voice_verify = %i\n", voice, voice_status, inb(GUSP(gus, GF1PAGE))); | ||
68 | #endif | ||
69 | pvoice = &gus->gf1.voices[voice]; | ||
70 | if (pvoice->use) { | ||
71 | if (!(voice_status & 0x80)) { /* voice position IRQ */ | ||
72 | STAT_ADD(pvoice->interrupt_stat_wave); | ||
73 | pvoice->handler_wave(gus, pvoice); | ||
74 | } | ||
75 | if (!(voice_status & 0x40)) { /* volume ramp IRQ */ | ||
76 | STAT_ADD(pvoice->interrupt_stat_volume); | ||
77 | pvoice->handler_volume(gus, pvoice); | ||
78 | } | ||
79 | } else { | ||
80 | STAT_ADD(gus->gf1.interrupt_stat_voice_lost); | ||
81 | snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); | ||
82 | snd_gf1_i_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | if (status & 0x04) { | ||
87 | STAT_ADD(gus->gf1.interrupt_stat_timer1); | ||
88 | gus->gf1.interrupt_handler_timer1(gus); | ||
89 | } | ||
90 | if (status & 0x08) { | ||
91 | STAT_ADD(gus->gf1.interrupt_stat_timer2); | ||
92 | gus->gf1.interrupt_handler_timer2(gus); | ||
93 | } | ||
94 | if (status & 0x80) { | ||
95 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL) & 0x40) { | ||
96 | STAT_ADD(gus->gf1.interrupt_stat_dma_write); | ||
97 | gus->gf1.interrupt_handler_dma_write(gus); | ||
98 | } | ||
99 | if (snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL) & 0x40) { | ||
100 | STAT_ADD(gus->gf1.interrupt_stat_dma_read); | ||
101 | gus->gf1.interrupt_handler_dma_read(gus); | ||
102 | } | ||
103 | } | ||
104 | if (--loop > 0) | ||
105 | goto __again; | ||
106 | return IRQ_NONE; | ||
107 | } | ||
108 | |||
109 | #ifdef CONFIG_SND_DEBUG | ||
110 | static void snd_gus_irq_info_read(snd_info_entry_t *entry, | ||
111 | snd_info_buffer_t * buffer) | ||
112 | { | ||
113 | snd_gus_card_t *gus; | ||
114 | snd_gus_voice_t *pvoice; | ||
115 | int idx; | ||
116 | |||
117 | gus = entry->private_data; | ||
118 | snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out); | ||
119 | snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in); | ||
120 | snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1); | ||
121 | snd_iprintf(buffer, "timer2 = %u\n", gus->gf1.interrupt_stat_timer2); | ||
122 | snd_iprintf(buffer, "dma write = %u\n", gus->gf1.interrupt_stat_dma_write); | ||
123 | snd_iprintf(buffer, "dma read = %u\n", gus->gf1.interrupt_stat_dma_read); | ||
124 | snd_iprintf(buffer, "voice lost = %u\n", gus->gf1.interrupt_stat_voice_lost); | ||
125 | for (idx = 0; idx < 32; idx++) { | ||
126 | pvoice = &gus->gf1.voices[idx]; | ||
127 | snd_iprintf(buffer, "voice %i: wave = %u, volume = %u\n", | ||
128 | idx, | ||
129 | pvoice->interrupt_stat_wave, | ||
130 | pvoice->interrupt_stat_volume); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | void snd_gus_irq_profile_init(snd_gus_card_t *gus) | ||
135 | { | ||
136 | snd_info_entry_t *entry; | ||
137 | |||
138 | if (! snd_card_proc_new(gus->card, "gusirq", &entry)) | ||
139 | snd_info_set_text_ops(entry, gus, 1024, snd_gus_irq_info_read); | ||
140 | } | ||
141 | |||
142 | #endif | ||