vserver 1.9.3
[linux-2.6.git] / sound / isa / wavefront / wavefront_fx.c
1 /*
2  *  Copyright (c) 1998-2002 by Paul Davis <pbd@op.net>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17  */
18
19 #include <sound/driver.h>
20 #include <asm/io.h>
21 #include <linux/init.h>
22 #include <linux/time.h>
23 #include <linux/wait.h>
24 #include <sound/core.h>
25 #include <sound/snd_wavefront.h>
26 #include <sound/initval.h>
27
28 /* Control bits for the Load Control Register
29  */
30
31 #define FX_LSB_TRANSFER 0x01    /* transfer after DSP LSB byte written */
32 #define FX_MSB_TRANSFER 0x02    /* transfer after DSP MSB byte written */
33 #define FX_AUTO_INCR    0x04    /* auto-increment DSP address after transfer */
34
35 /* weird stuff, derived from port I/O tracing with dosemu */
36
37 unsigned char page_zero[] __initdata = {
38 0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00,
39 0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00,
40 0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00,
41 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x19,
50 0x01, 0x1a, 0x01, 0x20, 0x01, 0x40, 0x01, 0x17, 0x00, 0x00, 0x01,
51 0x80, 0x01, 0x20, 0x00, 0x10, 0x01, 0xa0, 0x03, 0xd1, 0x00, 0x00,
52 0x01, 0xf2, 0x02, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf4, 0x02,
53 0xe0, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17,
54 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x00, 0x00,
55 0x40, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x60, 0x00, 0x00,
56 0x00, 0x92, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb3, 0x02,
57 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x40,
58 0x00, 0x80, 0x00, 0xf5, 0x00, 0x20, 0x00, 0x70, 0x00, 0xa0, 0x02,
59 0x11, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
60 0x02, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x17, 0x00, 0x1b, 0x00,
61 0x1d, 0x02, 0xdf
62 };
63
64 unsigned char page_one[] __initdata = {
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
66 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00,
67 0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01,
68 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x02, 0x60,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x80, 0x00,
78 0x00, 0x02, 0xfb, 0x02, 0xa0, 0x00, 0x00, 0x00, 0x1b, 0x02, 0xd7,
79 0x00, 0x00, 0x02, 0xf7, 0x03, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00,
80 0x1c, 0x03, 0x3c, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x00, 0x03, 0xc0,
81 0x00, 0x00, 0x03, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5d, 0x00,
82 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x03, 0xc0,
83 0x00, 0x00, 0x03, 0x9e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03,
84 0xbe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
86 0xdb, 0x00, 0x00, 0x02, 0xdb, 0x00, 0x00, 0x02, 0xe0, 0x00, 0x00,
87 0x02, 0xfb, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x40, 0x02, 0xfb, 0x02,
88 0x60, 0x00, 0x1b
89 };
90
91 unsigned char page_two[] __initdata = {
92 0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4,
93 0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x07,
98 0x05, 0x05, 0x05, 0x04, 0x07, 0x05, 0x04, 0x07, 0x05, 0x44, 0x46,
99 0x44, 0x46, 0x46, 0x07, 0x05, 0x44, 0x46, 0x05, 0x46, 0x05, 0x46,
100 0x05, 0x46, 0x05, 0x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07,
101 0x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07, 0x44, 0x05, 0x05,
102 0x05, 0x44, 0x05, 0x05, 0x05, 0x46, 0x05, 0x46, 0x05, 0x46, 0x05,
103 0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44
104 };
105
106 unsigned char page_three[] __initdata = {
107 0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06,
108 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
113 0xc0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00,
114 0x60, 0x00, 0x70, 0x00, 0x40, 0x00, 0x40, 0x00, 0x42, 0x00, 0x40,
115 0x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
116 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
117 0x00, 0x42, 0x00, 0x40, 0x00, 0x42, 0x00, 0x02, 0x00, 0x02, 0x00,
118 0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40
119 };
120
121 unsigned char page_four[] __initdata = {
122 0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02,
123 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
128 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
129 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, 0x00,
130 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60,
131 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00,
132 0x20, 0x00, 0x22, 0x02, 0x22, 0x02, 0x20, 0x00, 0x60, 0x00, 0x22,
133 0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01
134 };
135
136 unsigned char page_six[] __initdata = {
137 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00,
138 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e,
139 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00,
140 0x16, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1c, 0x00,
141 0x00, 0x1e, 0x00, 0x00, 0x20, 0x00, 0x00, 0x22, 0x00, 0x00, 0x24,
142 0x00, 0x00, 0x26, 0x00, 0x00, 0x28, 0x00, 0x00, 0x2a, 0x00, 0x00,
143 0x2c, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x30, 0x00, 0x00, 0x32, 0x00,
144 0x00, 0x34, 0x00, 0x00, 0x36, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3a,
145 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x40, 0x00, 0x00,
146 0x42, 0x03, 0x00, 0x44, 0x01, 0x00, 0x46, 0x0a, 0x21, 0x48, 0x0d,
147 0x23, 0x4a, 0x23, 0x1b, 0x4c, 0x37, 0x8f, 0x4e, 0x45, 0x77, 0x50,
148 0x52, 0xe2, 0x52, 0x1c, 0x92, 0x54, 0x1c, 0x52, 0x56, 0x07, 0x00,
149 0x58, 0x2f, 0xc6, 0x5a, 0x0b, 0x00, 0x5c, 0x30, 0x06, 0x5e, 0x17,
150 0x00, 0x60, 0x3d, 0xda, 0x62, 0x29, 0x00, 0x64, 0x3e, 0x41, 0x66,
151 0x39, 0x00, 0x68, 0x4c, 0x48, 0x6a, 0x49, 0x00, 0x6c, 0x4c, 0x6c,
152 0x6e, 0x11, 0xd2, 0x70, 0x16, 0x0c, 0x72, 0x00, 0x00, 0x74, 0x00,
153 0x80, 0x76, 0x0f, 0x00, 0x78, 0x00, 0x80, 0x7a, 0x13, 0x00, 0x7c,
154 0x80, 0x00, 0x7e, 0x80, 0x80
155 };
156
157 unsigned char page_seven[] __initdata = {
158 0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
160 0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f,
161 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff,
172 0x0f, 0xff, 0x0f, 0xff, 0x02, 0xe9, 0x06, 0x8c, 0x06, 0x8c, 0x0f,
173 0xff, 0x1a, 0x75, 0x0d, 0x8b, 0x04, 0xe9, 0x0b, 0x16, 0x1a, 0x38,
174 0x0d, 0xc8, 0x04, 0x6f, 0x0b, 0x91, 0x0f, 0xff, 0x06, 0x40, 0x06,
175 0x40, 0x02, 0x8f, 0x0f, 0xff, 0x06, 0x62, 0x06, 0x62, 0x02, 0x7b,
176 0x0f, 0xff, 0x06, 0x97, 0x06, 0x97, 0x02, 0x52, 0x0f, 0xff, 0x06,
177 0xf6, 0x06, 0xf6, 0x02, 0x19, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55,
178 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x14,
179 0xda, 0x0d, 0x93, 0x04, 0xda, 0x05, 0x93, 0x14, 0xda, 0x0d, 0x93,
180 0x04, 0xda, 0x05, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x02, 0x00
182 };
183
184 unsigned char page_zero_v2[] __initdata = {
185 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
194 };
195
196 unsigned char page_one_v2[] __initdata = {
197 0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
206 };
207
208 unsigned char page_two_v2[] __initdata = {
209 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213 0x00, 0x00, 0x00, 0x00
214 };
215 unsigned char page_three_v2[] __initdata = {
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00
221 };
222 unsigned char page_four_v2[] __initdata = {
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227 0x00, 0x00, 0x00, 0x00
228 };
229
230 unsigned char page_seven_v2[] __initdata = {
231 0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
240 };
241
242 unsigned char mod_v2[] __initdata = {
243 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02,
244 0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05,
245 0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0,
246 0x20, 0xb1, 0x20, 0xb2, 0x20, 0xb3, 0x20, 0xb4, 0x20, 0xb5, 0x20,
247 0xb6, 0x20, 0xb7, 0x20, 0xf0, 0x20, 0xf1, 0x20, 0xf2, 0x20, 0xf3,
248 0x20, 0xf4, 0x20, 0xf5, 0x20, 0xf6, 0x20, 0xf7, 0x20, 0x10, 0xff,
249 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x14, 0xff, 0x15, 0xff, 0x16,
250 0xff, 0x17, 0xff, 0x20, 0xff, 0x21, 0xff, 0x22, 0xff, 0x23, 0xff,
251 0x24, 0xff, 0x25, 0xff, 0x26, 0xff, 0x27, 0xff, 0x30, 0x00, 0x31,
252 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00,
253 0x37, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44,
254 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x50, 0x00, 0x51, 0x00,
255 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57,
256 0x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00,
257 0x65, 0x00, 0x66, 0x00, 0x67, 0x00, 0x70, 0xc0, 0x71, 0xc0, 0x72,
258 0xc0, 0x73, 0xc0, 0x74, 0xc0, 0x75, 0xc0, 0x76, 0xc0, 0x77, 0xc0,
259 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85,
260 0x00, 0x86, 0x00, 0x87, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00,
261 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0xa0,
262 0x00, 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa5, 0x00,
263 0xa6, 0x00, 0xa7, 0x00, 0xc0, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
264 0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xd0, 0x00,
265 0xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6,
266 0x00, 0xd7, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe2, 0x00, 0xe3, 0x00,
267 0xe4, 0x00, 0xe5, 0x00, 0xe6, 0x00, 0xe7, 0x00, 0x01, 0x00, 0x02,
268 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03,
269 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01,
270 0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01
271 };
272 unsigned char coefficients[] __initdata = {
273 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03,
274 0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49,
275 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01,
276 0x40, 0x02, 0x40, 0x01, 0x41, 0x02, 0x60, 0x07, 0x40, 0x00, 0x00,
277 0x07, 0x41, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, 0x07, 0x4a, 0x00,
278 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x4a, 0x01, 0x20, 0x07, 0x47,
279 0x00, 0x00, 0x07, 0x4a, 0x00, 0x00, 0x07, 0x7c, 0x00, 0x00, 0x07,
280 0x7e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x07, 0x7c, 0x00, 0x00,
281 0x07, 0x7e, 0x00, 0x00, 0x07, 0x44, 0x00, 0x00, 0x00, 0x44, 0x01,
282 0x00, 0x07, 0x44, 0x00, 0x00, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43,
283 0x00, 0x00, 0x00, 0x42, 0x01, 0x1a, 0x00, 0x43, 0x01, 0x20, 0x07,
284 0x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00,
285 0x07, 0x41, 0x00, 0x00, 0x01, 0x40, 0x02, 0x40, 0x01, 0x41, 0x02,
286 0x60, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x44,
287 0x0f, 0xff, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07,
288 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x51, 0x06, 0x40,
289 0x07, 0x50, 0x06, 0x40, 0x07, 0x4f, 0x03, 0x81, 0x07, 0x53, 0x1a,
290 0x76, 0x07, 0x54, 0x0d, 0x8b, 0x07, 0x55, 0x04, 0xe9, 0x07, 0x56,
291 0x0b, 0x17, 0x07, 0x57, 0x1a, 0x38, 0x07, 0x58, 0x0d, 0xc9, 0x07,
292 0x59, 0x04, 0x6f, 0x07, 0x5a, 0x0b, 0x91, 0x07, 0x73, 0x14, 0xda,
293 0x07, 0x74, 0x0d, 0x93, 0x07, 0x75, 0x04, 0xd9, 0x07, 0x76, 0x05,
294 0x93, 0x07, 0x77, 0x14, 0xda, 0x07, 0x78, 0x0d, 0x93, 0x07, 0x79,
295 0x04, 0xd9, 0x07, 0x7a, 0x05, 0x93, 0x07, 0x5e, 0x03, 0x68, 0x07,
296 0x5c, 0x04, 0x31, 0x07, 0x5d, 0x04, 0x31, 0x07, 0x62, 0x03, 0x52,
297 0x07, 0x60, 0x04, 0x76, 0x07, 0x61, 0x04, 0x76, 0x07, 0x66, 0x03,
298 0x2e, 0x07, 0x64, 0x04, 0xda, 0x07, 0x65, 0x04, 0xda, 0x07, 0x6a,
299 0x02, 0xf6, 0x07, 0x68, 0x05, 0x62, 0x07, 0x69, 0x05, 0x62, 0x06,
300 0x46, 0x0a, 0x22, 0x06, 0x48, 0x0d, 0x24, 0x06, 0x6e, 0x11, 0xd3,
301 0x06, 0x70, 0x15, 0xcb, 0x06, 0x52, 0x20, 0x93, 0x06, 0x54, 0x20,
302 0x54, 0x06, 0x4a, 0x27, 0x1d, 0x06, 0x58, 0x2f, 0xc8, 0x06, 0x5c,
303 0x30, 0x07, 0x06, 0x4c, 0x37, 0x90, 0x06, 0x60, 0x3d, 0xdb, 0x06,
304 0x64, 0x3e, 0x42, 0x06, 0x4e, 0x45, 0x78, 0x06, 0x68, 0x4c, 0x48,
305 0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02,
306 0xba
307 };
308 unsigned char coefficients2[] __initdata = {
309 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f,
310 0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d,
311 0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07,
312 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00,
313 0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00
314 };
315 unsigned char coefficients3[] __initdata = {
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00,
317 0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc,
318 0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01,
319 0x47, 0x01, 0x47, 0x01, 0x70, 0x01, 0x70, 0x01, 0x99, 0x01, 0x99,
320 0x01, 0xc2, 0x01, 0xc2, 0x01, 0xeb, 0x01, 0xeb, 0x02, 0x14, 0x02,
321 0x14, 0x02, 0x3d, 0x02, 0x3d, 0x02, 0x66, 0x02, 0x66, 0x02, 0x8f,
322 0x02, 0x8f, 0x02, 0xb8, 0x02, 0xb8, 0x02, 0xe1, 0x02, 0xe1, 0x03,
323 0x0a, 0x03, 0x0a, 0x03, 0x33, 0x03, 0x33, 0x03, 0x5c, 0x03, 0x5c,
324 0x03, 0x85, 0x03, 0x85, 0x03, 0xae, 0x03, 0xae, 0x03, 0xd7, 0x03,
325 0xd7, 0x04, 0x00, 0x04, 0x00, 0x04, 0x28, 0x04, 0x28, 0x04, 0x51,
326 0x04, 0x51, 0x04, 0x7a, 0x04, 0x7a, 0x04, 0xa3, 0x04, 0xa3, 0x04,
327 0xcc, 0x04, 0xcc, 0x04, 0xf5, 0x04, 0xf5, 0x05, 0x1e, 0x05, 0x1e,
328 0x05, 0x47, 0x05, 0x47, 0x05, 0x70, 0x05, 0x70, 0x05, 0x99, 0x05,
329 0x99, 0x05, 0xc2, 0x05, 0xc2, 0x05, 0xeb, 0x05, 0xeb, 0x06, 0x14,
330 0x06, 0x14, 0x06, 0x3d, 0x06, 0x3d, 0x06, 0x66, 0x06, 0x66, 0x06,
331 0x8f, 0x06, 0x8f, 0x06, 0xb8, 0x06, 0xb8, 0x06, 0xe1, 0x06, 0xe1,
332 0x07, 0x0a, 0x07, 0x0a, 0x07, 0x33, 0x07, 0x33, 0x07, 0x5c, 0x07,
333 0x5c, 0x07, 0x85, 0x07, 0x85, 0x07, 0xae, 0x07, 0xae, 0x07, 0xd7,
334 0x07, 0xd7, 0x08, 0x00, 0x08, 0x00, 0x08, 0x28, 0x08, 0x28, 0x08,
335 0x51, 0x08, 0x51, 0x08, 0x7a, 0x08, 0x7a, 0x08, 0xa3, 0x08, 0xa3,
336 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xf5, 0x08, 0xf5, 0x09, 0x1e, 0x09,
337 0x1e, 0x09, 0x47, 0x09, 0x47, 0x09, 0x70, 0x09, 0x70, 0x09, 0x99,
338 0x09, 0x99, 0x09, 0xc2, 0x09, 0xc2, 0x09, 0xeb, 0x09, 0xeb, 0x0a,
339 0x14, 0x0a, 0x14, 0x0a, 0x3d, 0x0a, 0x3d, 0x0a, 0x66, 0x0a, 0x66,
340 0x0a, 0x8f, 0x0a, 0x8f, 0x0a, 0xb8, 0x0a, 0xb8, 0x0a, 0xe1, 0x0a,
341 0xe1, 0x0b, 0x0a, 0x0b, 0x0a, 0x0b, 0x33, 0x0b, 0x33, 0x0b, 0x5c,
342 0x0b, 0x5c, 0x0b, 0x85, 0x0b, 0x85, 0x0b, 0xae, 0x0b, 0xae, 0x0b,
343 0xd7, 0x0b, 0xd7, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x28, 0x0c, 0x28,
344 0x0c, 0x51, 0x0c, 0x51, 0x0c, 0x7a, 0x0c, 0x7a, 0x0c, 0xa3, 0x0c,
345 0xa3, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xf5, 0x0c, 0xf5, 0x0d, 0x1e,
346 0x0d, 0x1e, 0x0d, 0x47, 0x0d, 0x47, 0x0d, 0x70, 0x0d, 0x70, 0x0d,
347 0x99, 0x0d, 0x99, 0x0d, 0xc2, 0x0d, 0xc2, 0x0d, 0xeb, 0x0d, 0xeb,
348 0x0e, 0x14, 0x0e, 0x14, 0x0e, 0x3d, 0x0e, 0x3d, 0x0e, 0x66, 0x0e,
349 0x66, 0x0e, 0x8f, 0x0e, 0x8f, 0x0e, 0xb8, 0x0e, 0xb8, 0x0e, 0xe1,
350 0x0e, 0xe1, 0x0f, 0x0a, 0x0f, 0x0a, 0x0f, 0x33, 0x0f, 0x33, 0x0f,
351 0x5c, 0x0f, 0x5c, 0x0f, 0x85, 0x0f, 0x85, 0x0f, 0xae, 0x0f, 0xae,
352 0x0f, 0xd7, 0x0f, 0xd7, 0x0f, 0xff, 0x0f, 0xff
353 };
354
355 static int
356 wavefront_fx_idle (snd_wavefront_t *dev)
357
358 {
359         int i;
360         unsigned int x = 0x80;
361
362         for (i = 0; i < 1000; i++) {
363                 x = inb (dev->fx_status);
364                 if ((x & 0x80) == 0) {
365                         break;
366                 }
367         }
368
369         if (x & 0x80) {
370                 snd_printk ("FX device never idle.\n");
371                 return 0;
372         }
373
374         return (1);
375 }
376
377 static void
378 wavefront_fx_mute (snd_wavefront_t *dev, int onoff)
379
380 {
381         if (!wavefront_fx_idle(dev)) {
382                 return;
383         }
384
385         outb (onoff ? 0x02 : 0x00, dev->fx_op);
386 }
387
388 static int
389 wavefront_fx_memset (snd_wavefront_t *dev,
390                      int page,
391                      int addr,
392                      int cnt,
393                      unsigned short *data)
394 {
395         if (page < 0 || page > 7) {
396                 snd_printk ("FX memset: "
397                         "page must be >= 0 and <= 7\n");
398                 return -(EINVAL);
399         }
400
401         if (addr < 0 || addr > 0x7f) {
402                 snd_printk ("FX memset: "
403                         "addr must be >= 0 and <= 7f\n");
404                 return -(EINVAL);
405         }
406
407         if (cnt == 1) {
408
409                 outb (FX_LSB_TRANSFER, dev->fx_lcr);
410                 outb (page, dev->fx_dsp_page);
411                 outb (addr, dev->fx_dsp_addr);
412                 outb ((data[0] >> 8), dev->fx_dsp_msb);
413                 outb ((data[0] & 0xff), dev->fx_dsp_lsb);
414
415                 snd_printk ("FX: addr %d:%x set to 0x%x\n",
416                         page, addr, data[0]);
417
418         } else {
419                 int i;
420
421                 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
422                 outb (page, dev->fx_dsp_page);
423                 outb (addr, dev->fx_dsp_addr);
424
425                 for (i = 0; i < cnt; i++) {
426                         outb ((data[i] >> 8), dev->fx_dsp_msb);
427                         outb ((data[i] & 0xff), dev->fx_dsp_lsb);
428                         if (!wavefront_fx_idle (dev)) {
429                                 break;
430                         }
431                 }
432
433                 if (i != cnt) {
434                         snd_printk ("FX memset "
435                                     "(0x%x, 0x%x, 0x%lx, %d) incomplete\n",
436                                     page, addr, (unsigned long) data, cnt);
437                         return -(EIO);
438                 }
439         }
440
441         return 0;
442 }
443
444 int
445 snd_wavefront_fx_detect (snd_wavefront_t *dev)
446
447 {
448         /* This is a crude check, but its the best one I have for now.
449            Certainly on the Maui and the Tropez, wavefront_fx_idle() will
450            report "never idle", which suggests that this test should
451            work OK.
452         */
453
454         if (inb (dev->fx_status) & 0x80) {
455                 snd_printk ("Hmm, probably a Maui or Tropez.\n");
456                 return -1;
457         }
458
459         return 0;
460 }
461
462 int
463 snd_wavefront_fx_open (snd_hwdep_t *hw, struct file *file)
464
465 {
466         if (!try_module_get(hw->card->module))
467                 return -EFAULT;
468         file->private_data = hw;
469         return 0;
470 }
471
472 int 
473 snd_wavefront_fx_release (snd_hwdep_t *hw, struct file *file)
474
475 {
476         module_put(hw->card->module);
477         return 0;
478 }
479
480 int
481 snd_wavefront_fx_ioctl (snd_hwdep_t *sdev, struct file *file,
482                         unsigned int cmd, unsigned long arg)
483
484 {
485         snd_card_t *card;
486         snd_wavefront_card_t *acard;
487         snd_wavefront_t *dev;
488         wavefront_fx_info r;
489         unsigned short *page_data = NULL;
490         unsigned short *pd;
491         int err = 0;
492
493         snd_assert(sdev->card != NULL, return -ENODEV);
494         
495         card = sdev->card;
496
497         snd_assert(card->private_data != NULL, return -ENODEV);
498
499         acard = card->private_data;
500         dev = &acard->wavefront;
501
502         if (copy_from_user (&r, (void __user *)arg, sizeof (wavefront_fx_info)))
503                 return -EFAULT;
504
505         switch (r.request) {
506         case WFFX_MUTE:
507                 wavefront_fx_mute (dev, r.data[0]);
508                 return -EIO;
509
510         case WFFX_MEMSET:
511                 if (r.data[2] <= 0) {
512                         snd_printk ("cannot write "
513                                 "<= 0 bytes to FX\n");
514                         return -EIO;
515                 } else if (r.data[2] == 1) {
516                         pd = (unsigned short *) &r.data[3];
517                 } else {
518                         if (r.data[2] > 256) {
519                                 snd_printk ("cannot write "
520                                             "> 512 bytes to FX\n");
521                                 return -EIO;
522                         }
523                         page_data = kmalloc(r.data[2] * sizeof(short), GFP_KERNEL);
524                         if (!page_data)
525                                 return -ENOMEM;
526                         if (copy_from_user (page_data,
527                                             (unsigned char __user *) r.data[3],
528                                             r.data[2] * sizeof(short))) {
529                                 kfree(page_data);
530                                 return -EFAULT;
531                         }
532                         pd = page_data;
533                 }
534
535                 err = wavefront_fx_memset (dev,
536                              r.data[0], /* page */
537                              r.data[1], /* addr */
538                              r.data[2], /* cnt */
539                              pd);
540                 if (page_data)
541                         kfree(page_data);
542                 break;
543
544         default:
545                 snd_printk ("FX: ioctl %d not yet supported\n",
546                             r.request);
547                 return -ENOTTY;
548         }
549         return err;
550 }
551
552 /* YSS225 initialization.
553
554    This code was developed using DOSEMU. The Turtle Beach SETUPSND
555    utility was run with I/O tracing in DOSEMU enabled, and a reconstruction
556    of the port I/O done, using the Yamaha faxback document as a guide
557    to add more logic to the code. Its really pretty weird.
558
559    There was an alternative approach of just dumping the whole I/O
560    sequence as a series of port/value pairs and a simple loop
561    that output it. However, I hope that eventually I'll get more
562    control over what this code does, and so I tried to stick with
563    a somewhat "algorithmic" approach.
564 */
565
566
567 int __init
568 snd_wavefront_fx_start (snd_wavefront_t *dev)
569
570 {
571         unsigned int i, j;
572
573         /* Set all bits for all channels on the MOD unit to zero */
574         /* XXX But why do this twice ? */
575
576         for (j = 0; j < 2; j++) {
577                 for (i = 0x10; i <= 0xff; i++) {
578             
579                         if (!wavefront_fx_idle (dev)) {
580                                 return (-1);
581                         }
582             
583                         outb (i, dev->fx_mod_addr);
584                         outb (0x0, dev->fx_mod_data);
585                 }
586         }
587
588         if (!wavefront_fx_idle (dev)) return (-1);
589         outb (0x02, dev->fx_op);                        /* mute on */
590
591         if (!wavefront_fx_idle (dev)) return (-1);
592         outb (0x07, dev->fx_dsp_page);
593         outb (0x44, dev->fx_dsp_addr);
594         outb (0x00, dev->fx_dsp_msb);
595         outb (0x00, dev->fx_dsp_lsb);
596         if (!wavefront_fx_idle (dev)) return (-1);
597         outb (0x07, dev->fx_dsp_page);
598         outb (0x42, dev->fx_dsp_addr);
599         outb (0x00, dev->fx_dsp_msb);
600         outb (0x00, dev->fx_dsp_lsb);
601         if (!wavefront_fx_idle (dev)) return (-1);
602         outb (0x07, dev->fx_dsp_page);
603         outb (0x43, dev->fx_dsp_addr);
604         outb (0x00, dev->fx_dsp_msb);
605         outb (0x00, dev->fx_dsp_lsb);
606         if (!wavefront_fx_idle (dev)) return (-1);
607         outb (0x07, dev->fx_dsp_page);
608         outb (0x7c, dev->fx_dsp_addr);
609         outb (0x00, dev->fx_dsp_msb);
610         outb (0x00, dev->fx_dsp_lsb);
611         if (!wavefront_fx_idle (dev)) return (-1);
612         outb (0x07, dev->fx_dsp_page);
613         outb (0x7e, dev->fx_dsp_addr);
614         outb (0x00, dev->fx_dsp_msb);
615         outb (0x00, dev->fx_dsp_lsb);
616         if (!wavefront_fx_idle (dev)) return (-1);
617         outb (0x07, dev->fx_dsp_page);
618         outb (0x46, dev->fx_dsp_addr);
619         outb (0x00, dev->fx_dsp_msb);
620         outb (0x00, dev->fx_dsp_lsb);
621         if (!wavefront_fx_idle (dev)) return (-1);
622         outb (0x07, dev->fx_dsp_page);
623         outb (0x49, dev->fx_dsp_addr);
624         outb (0x00, dev->fx_dsp_msb);
625         outb (0x00, dev->fx_dsp_lsb);
626         if (!wavefront_fx_idle (dev)) return (-1);
627         outb (0x07, dev->fx_dsp_page);
628         outb (0x47, dev->fx_dsp_addr);
629         outb (0x00, dev->fx_dsp_msb);
630         outb (0x00, dev->fx_dsp_lsb);
631         if (!wavefront_fx_idle (dev)) return (-1);
632         outb (0x07, dev->fx_dsp_page);
633         outb (0x4a, dev->fx_dsp_addr);
634         outb (0x00, dev->fx_dsp_msb);
635         outb (0x00, dev->fx_dsp_lsb);
636
637         /* either because of stupidity by TB's programmers, or because it
638            actually does something, rezero the MOD page.
639         */
640         for (i = 0x10; i <= 0xff; i++) {
641         
642                 if (!wavefront_fx_idle (dev)) {
643                         return (-1);
644                 }
645         
646                 outb (i, dev->fx_mod_addr);
647                 outb (0x0, dev->fx_mod_data);
648         }
649         /* load page zero */
650
651         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
652         outb (0x00, dev->fx_dsp_page);
653         outb (0x00, dev->fx_dsp_addr);
654
655         for (i = 0; i < sizeof (page_zero); i += 2) {
656                 outb (page_zero[i], dev->fx_dsp_msb);
657                 outb (page_zero[i+1], dev->fx_dsp_lsb);
658                 if (!wavefront_fx_idle (dev)) return (-1);
659         }
660
661         /* Now load page one */
662
663         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
664         outb (0x01, dev->fx_dsp_page);
665         outb (0x00, dev->fx_dsp_addr);
666
667         for (i = 0; i < sizeof (page_one); i += 2) {
668                 outb (page_one[i], dev->fx_dsp_msb);
669                 outb (page_one[i+1], dev->fx_dsp_lsb);
670                 if (!wavefront_fx_idle (dev)) return (-1);
671         }
672     
673         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
674         outb (0x02, dev->fx_dsp_page);
675         outb (0x00, dev->fx_dsp_addr);
676
677         for (i = 0; i < sizeof (page_two); i++) {
678                 outb (page_two[i], dev->fx_dsp_lsb);
679                 if (!wavefront_fx_idle (dev)) return (-1);
680         }
681     
682         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
683         outb (0x03, dev->fx_dsp_page);
684         outb (0x00, dev->fx_dsp_addr);
685
686         for (i = 0; i < sizeof (page_three); i++) {
687                 outb (page_three[i], dev->fx_dsp_lsb);
688                 if (!wavefront_fx_idle (dev)) return (-1);
689         }
690     
691         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
692         outb (0x04, dev->fx_dsp_page);
693         outb (0x00, dev->fx_dsp_addr);
694
695         for (i = 0; i < sizeof (page_four); i++) {
696                 outb (page_four[i], dev->fx_dsp_lsb);
697                 if (!wavefront_fx_idle (dev)) return (-1);
698         }
699
700         /* Load memory area (page six) */
701     
702         outb (FX_LSB_TRANSFER, dev->fx_lcr); 
703         outb (0x06, dev->fx_dsp_page); 
704
705         for (i = 0; i < sizeof (page_six); i += 3) {
706                 outb (page_six[i], dev->fx_dsp_addr);
707                 outb (page_six[i+1], dev->fx_dsp_msb);
708                 outb (page_six[i+2], dev->fx_dsp_lsb);
709                 if (!wavefront_fx_idle (dev)) return (-1);
710         }
711     
712         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
713         outb (0x07, dev->fx_dsp_page);
714         outb (0x00, dev->fx_dsp_addr);
715
716         for (i = 0; i < sizeof (page_seven); i += 2) {
717                 outb (page_seven[i], dev->fx_dsp_msb);
718                 outb (page_seven[i+1], dev->fx_dsp_lsb);
719                 if (!wavefront_fx_idle (dev)) return (-1);
720         }
721
722         /* Now setup the MOD area. We do this algorithmically in order to
723            save a little data space. It could be done in the same fashion
724            as the "pages".
725         */
726
727         for (i = 0x00; i <= 0x0f; i++) {
728                 outb (0x01, dev->fx_mod_addr);
729                 outb (i, dev->fx_mod_data);
730                 if (!wavefront_fx_idle (dev)) return (-1);
731                 outb (0x02, dev->fx_mod_addr);
732                 outb (0x00, dev->fx_mod_data);
733                 if (!wavefront_fx_idle (dev)) return (-1);
734         }
735
736         for (i = 0xb0; i <= 0xbf; i++) {
737                 outb (i, dev->fx_mod_addr);
738                 outb (0x20, dev->fx_mod_data);
739                 if (!wavefront_fx_idle (dev)) return (-1);
740         }
741
742         for (i = 0xf0; i <= 0xff; i++) {
743                 outb (i, dev->fx_mod_addr);
744                 outb (0x20, dev->fx_mod_data);
745                 if (!wavefront_fx_idle (dev)) return (-1);
746         }
747
748         for (i = 0x10; i <= 0x1d; i++) {
749                 outb (i, dev->fx_mod_addr);
750                 outb (0xff, dev->fx_mod_data);
751                 if (!wavefront_fx_idle (dev)) return (-1);
752         }
753
754         outb (0x1e, dev->fx_mod_addr);
755         outb (0x40, dev->fx_mod_data);
756         if (!wavefront_fx_idle (dev)) return (-1);
757
758         for (i = 0x1f; i <= 0x2d; i++) {
759                 outb (i, dev->fx_mod_addr);
760                 outb (0xff, dev->fx_mod_data);
761                 if (!wavefront_fx_idle (dev)) return (-1);
762         }
763
764         outb (0x2e, dev->fx_mod_addr);
765         outb (0x00, dev->fx_mod_data);
766         if (!wavefront_fx_idle (dev)) return (-1);
767
768         for (i = 0x2f; i <= 0x3e; i++) {
769                 outb (i, dev->fx_mod_addr);
770                 outb (0x00, dev->fx_mod_data);
771                 if (!wavefront_fx_idle (dev)) return (-1);
772         }
773
774         outb (0x3f, dev->fx_mod_addr);
775         outb (0x20, dev->fx_mod_data);
776         if (!wavefront_fx_idle (dev)) return (-1);
777
778         for (i = 0x40; i <= 0x4d; i++) {
779                 outb (i, dev->fx_mod_addr);
780                 outb (0x00, dev->fx_mod_data);
781                 if (!wavefront_fx_idle (dev)) return (-1);
782         }
783
784         outb (0x4e, dev->fx_mod_addr);
785         outb (0x0e, dev->fx_mod_data);
786         if (!wavefront_fx_idle (dev)) return (-1);
787         outb (0x4f, dev->fx_mod_addr);
788         outb (0x0e, dev->fx_mod_data);
789         if (!wavefront_fx_idle (dev)) return (-1);
790
791
792         for (i = 0x50; i <= 0x6b; i++) {
793                 outb (i, dev->fx_mod_addr);
794                 outb (0x00, dev->fx_mod_data);
795                 if (!wavefront_fx_idle (dev)) return (-1);
796         }
797
798         outb (0x6c, dev->fx_mod_addr);
799         outb (0x40, dev->fx_mod_data);
800         if (!wavefront_fx_idle (dev)) return (-1);
801
802         outb (0x6d, dev->fx_mod_addr);
803         outb (0x00, dev->fx_mod_data);
804         if (!wavefront_fx_idle (dev)) return (-1);
805
806         outb (0x6e, dev->fx_mod_addr);
807         outb (0x40, dev->fx_mod_data);
808         if (!wavefront_fx_idle (dev)) return (-1);
809
810         outb (0x6f, dev->fx_mod_addr);
811         outb (0x40, dev->fx_mod_data);
812         if (!wavefront_fx_idle (dev)) return (-1);
813
814         for (i = 0x70; i <= 0x7f; i++) {
815                 outb (i, dev->fx_mod_addr);
816                 outb (0xc0, dev->fx_mod_data);
817                 if (!wavefront_fx_idle (dev)) return (-1);
818         }
819     
820         for (i = 0x80; i <= 0xaf; i++) {
821                 outb (i, dev->fx_mod_addr);
822                 outb (0x00, dev->fx_mod_data);
823                 if (!wavefront_fx_idle (dev)) return (-1);
824         }
825
826         for (i = 0xc0; i <= 0xdd; i++) {
827                 outb (i, dev->fx_mod_addr);
828                 outb (0x00, dev->fx_mod_data);
829                 if (!wavefront_fx_idle (dev)) return (-1);
830         }
831
832         outb (0xde, dev->fx_mod_addr);
833         outb (0x10, dev->fx_mod_data);
834         if (!wavefront_fx_idle (dev)) return (-1);
835         outb (0xdf, dev->fx_mod_addr);
836         outb (0x10, dev->fx_mod_data);
837         if (!wavefront_fx_idle (dev)) return (-1);
838
839         for (i = 0xe0; i <= 0xef; i++) {
840                 outb (i, dev->fx_mod_addr);
841                 outb (0x00, dev->fx_mod_data);
842                 if (!wavefront_fx_idle (dev)) return (-1);
843         }
844
845         for (i = 0x00; i <= 0x0f; i++) {
846                 outb (0x01, dev->fx_mod_addr);
847                 outb (i, dev->fx_mod_data);
848                 outb (0x02, dev->fx_mod_addr);
849                 outb (0x01, dev->fx_mod_data);
850                 if (!wavefront_fx_idle (dev)) return (-1);
851         }
852
853         outb (0x02, dev->fx_op); /* mute on */
854
855         /* Now set the coefficients and so forth for the programs above */
856
857         for (i = 0; i < sizeof (coefficients); i += 4) {
858                 outb (coefficients[i], dev->fx_dsp_page);
859                 outb (coefficients[i+1], dev->fx_dsp_addr);
860                 outb (coefficients[i+2], dev->fx_dsp_msb);
861                 outb (coefficients[i+3], dev->fx_dsp_lsb);
862                 if (!wavefront_fx_idle (dev)) return (-1);
863         }
864
865         /* Some settings (?) that are too small to bundle into loops */
866
867         if (!wavefront_fx_idle (dev)) return (-1);
868         outb (0x1e, dev->fx_mod_addr);
869         outb (0x14, dev->fx_mod_data);
870         if (!wavefront_fx_idle (dev)) return (-1);
871         outb (0xde, dev->fx_mod_addr);
872         outb (0x20, dev->fx_mod_data);
873         if (!wavefront_fx_idle (dev)) return (-1);
874         outb (0xdf, dev->fx_mod_addr);
875         outb (0x20, dev->fx_mod_data);
876     
877         /* some more coefficients */
878
879         if (!wavefront_fx_idle (dev)) return (-1);
880         outb (0x06, dev->fx_dsp_page);
881         outb (0x78, dev->fx_dsp_addr);
882         outb (0x00, dev->fx_dsp_msb);
883         outb (0x40, dev->fx_dsp_lsb);
884         if (!wavefront_fx_idle (dev)) return (-1);
885         outb (0x07, dev->fx_dsp_page);
886         outb (0x03, dev->fx_dsp_addr);
887         outb (0x0f, dev->fx_dsp_msb);
888         outb (0xff, dev->fx_dsp_lsb);
889         if (!wavefront_fx_idle (dev)) return (-1);
890         outb (0x07, dev->fx_dsp_page);
891         outb (0x0b, dev->fx_dsp_addr);
892         outb (0x0f, dev->fx_dsp_msb);
893         outb (0xff, dev->fx_dsp_lsb);
894         if (!wavefront_fx_idle (dev)) return (-1);
895         outb (0x07, dev->fx_dsp_page);
896         outb (0x02, dev->fx_dsp_addr);
897         outb (0x00, dev->fx_dsp_msb);
898         outb (0x00, dev->fx_dsp_lsb);
899         if (!wavefront_fx_idle (dev)) return (-1);
900         outb (0x07, dev->fx_dsp_page);
901         outb (0x0a, dev->fx_dsp_addr);
902         outb (0x00, dev->fx_dsp_msb);
903         outb (0x00, dev->fx_dsp_lsb);
904         if (!wavefront_fx_idle (dev)) return (-1);
905         outb (0x07, dev->fx_dsp_page);
906         outb (0x46, dev->fx_dsp_addr);
907         outb (0x00, dev->fx_dsp_msb);
908         outb (0x00, dev->fx_dsp_lsb);
909         if (!wavefront_fx_idle (dev)) return (-1);
910         outb (0x07, dev->fx_dsp_page);
911         outb (0x49, dev->fx_dsp_addr);
912         outb (0x00, dev->fx_dsp_msb);
913         outb (0x00, dev->fx_dsp_lsb);
914     
915         /* Now, for some strange reason, lets reload every page
916            and all the coefficients over again. I have *NO* idea
917            why this is done. I do know that no sound is produced
918            is this phase is omitted.
919         */
920
921         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
922         outb (0x00, dev->fx_dsp_page);  
923         outb (0x10, dev->fx_dsp_addr);
924
925         for (i = 0; i < sizeof (page_zero_v2); i += 2) {
926                 outb (page_zero_v2[i], dev->fx_dsp_msb);
927                 outb (page_zero_v2[i+1], dev->fx_dsp_lsb);
928                 if (!wavefront_fx_idle (dev)) return (-1);
929         }
930     
931         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
932         outb (0x01, dev->fx_dsp_page);
933         outb (0x10, dev->fx_dsp_addr);
934
935         for (i = 0; i < sizeof (page_one_v2); i += 2) {
936                 outb (page_one_v2[i], dev->fx_dsp_msb);
937                 outb (page_one_v2[i+1], dev->fx_dsp_lsb);
938                 if (!wavefront_fx_idle (dev)) return (-1);
939         }
940     
941         if (!wavefront_fx_idle (dev)) return (-1);
942         if (!wavefront_fx_idle (dev)) return (-1);
943     
944         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
945         outb (0x02, dev->fx_dsp_page);
946         outb (0x10, dev->fx_dsp_addr);
947
948         for (i = 0; i < sizeof (page_two_v2); i++) {
949                 outb (page_two_v2[i], dev->fx_dsp_lsb);
950                 if (!wavefront_fx_idle (dev)) return (-1);
951         }
952         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
953         outb (0x03, dev->fx_dsp_page);
954         outb (0x10, dev->fx_dsp_addr);
955
956         for (i = 0; i < sizeof (page_three_v2); i++) {
957                 outb (page_three_v2[i], dev->fx_dsp_lsb);
958                 if (!wavefront_fx_idle (dev)) return (-1);
959         }
960     
961         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
962         outb (0x04, dev->fx_dsp_page);
963         outb (0x10, dev->fx_dsp_addr);
964
965         for (i = 0; i < sizeof (page_four_v2); i++) {
966                 outb (page_four_v2[i], dev->fx_dsp_lsb);
967                 if (!wavefront_fx_idle (dev)) return (-1);
968         }
969     
970         outb (FX_LSB_TRANSFER, dev->fx_lcr);
971         outb (0x06, dev->fx_dsp_page);
972
973         /* Page six v.2 is algorithmic */
974     
975         for (i = 0x10; i <= 0x3e; i += 2) {
976                 outb (i, dev->fx_dsp_addr);
977                 outb (0x00, dev->fx_dsp_msb);
978                 outb (0x00, dev->fx_dsp_lsb);
979                 if (!wavefront_fx_idle (dev)) return (-1);
980         }
981
982         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
983         outb (0x07, dev->fx_dsp_page);
984         outb (0x10, dev->fx_dsp_addr);
985
986         for (i = 0; i < sizeof (page_seven_v2); i += 2) {
987                 outb (page_seven_v2[i], dev->fx_dsp_msb);
988                 outb (page_seven_v2[i+1], dev->fx_dsp_lsb);
989                 if (!wavefront_fx_idle (dev)) return (-1);
990         }
991
992         for (i = 0x00; i < sizeof(mod_v2); i += 2) {
993                 outb (mod_v2[i], dev->fx_mod_addr);
994                 outb (mod_v2[i+1], dev->fx_mod_data);
995                 if (!wavefront_fx_idle (dev)) return (-1);
996         }
997
998         for (i = 0; i < sizeof (coefficients2); i += 4) {
999                 outb (coefficients2[i], dev->fx_dsp_page);
1000                 outb (coefficients2[i+1], dev->fx_dsp_addr);
1001                 outb (coefficients2[i+2], dev->fx_dsp_msb);
1002                 outb (coefficients2[i+3], dev->fx_dsp_lsb);
1003                 if (!wavefront_fx_idle (dev)) return (-1);
1004         }
1005
1006         for (i = 0; i < sizeof (coefficients3); i += 2) {
1007                 int x;
1008
1009                 outb (0x07, dev->fx_dsp_page);
1010                 x = (i % 4) ? 0x4e : 0x4c;
1011                 outb (x, dev->fx_dsp_addr);
1012                 outb (coefficients3[i], dev->fx_dsp_msb);
1013                 outb (coefficients3[i+1], dev->fx_dsp_lsb);
1014         }
1015
1016         outb (0x00, dev->fx_op); /* mute off */
1017         if (!wavefront_fx_idle (dev)) return (-1);
1018
1019         return (0);
1020 }