VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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[256];
490         unsigned short *pd;
491
492         snd_assert(sdev->card != NULL, return -ENODEV);
493         
494         card = sdev->card;
495
496         snd_assert(card->private_data != NULL, return -ENODEV);
497
498         acard = card->private_data;
499         dev = &acard->wavefront;
500
501         if (copy_from_user (&r, (void __user *)arg, sizeof (wavefront_fx_info)))
502                 return -EFAULT;
503
504         switch (r.request) {
505         case WFFX_MUTE:
506                 wavefront_fx_mute (dev, r.data[0]);
507                 return -EIO;
508
509         case WFFX_MEMSET:
510                 if (r.data[2] <= 0) {
511                         snd_printk ("cannot write "
512                                 "<= 0 bytes to FX\n");
513                         return -EIO;
514                 } else if (r.data[2] == 1) {
515                         pd = (unsigned short *) &r.data[3];
516                 } else {
517                         if (r.data[2] > (long)sizeof (page_data)) {
518                                 snd_printk ("cannot write "
519                                             "> 255 bytes to FX\n");
520                                 return -EIO;
521                         }
522                         if (copy_from_user (page_data,
523                                             (unsigned char __user *) r.data[3],
524                                             r.data[2]))
525                                 return -EFAULT;
526                         pd = page_data;
527                 }
528
529                 wavefront_fx_memset (dev,
530                              r.data[0], /* page */
531                              r.data[1], /* addr */
532                              r.data[2], /* cnt */
533                              pd);
534                 break;
535
536         default:
537                 snd_printk ("FX: ioctl %d not yet supported\n",
538                             r.request);
539                 return -ENOTTY;
540         }
541         return 0;
542 }
543
544 /* YSS225 initialization.
545
546    This code was developed using DOSEMU. The Turtle Beach SETUPSND
547    utility was run with I/O tracing in DOSEMU enabled, and a reconstruction
548    of the port I/O done, using the Yamaha faxback document as a guide
549    to add more logic to the code. Its really pretty weird.
550
551    There was an alternative approach of just dumping the whole I/O
552    sequence as a series of port/value pairs and a simple loop
553    that output it. However, I hope that eventually I'll get more
554    control over what this code does, and so I tried to stick with
555    a somewhat "algorithmic" approach.
556 */
557
558
559 int __init
560 snd_wavefront_fx_start (snd_wavefront_t *dev)
561
562 {
563         unsigned int i, j;
564
565         /* Set all bits for all channels on the MOD unit to zero */
566         /* XXX But why do this twice ? */
567
568         for (j = 0; j < 2; j++) {
569                 for (i = 0x10; i <= 0xff; i++) {
570             
571                         if (!wavefront_fx_idle (dev)) {
572                                 return (-1);
573                         }
574             
575                         outb (i, dev->fx_mod_addr);
576                         outb (0x0, dev->fx_mod_data);
577                 }
578         }
579
580         if (!wavefront_fx_idle (dev)) return (-1);
581         outb (0x02, dev->fx_op);                        /* mute on */
582
583         if (!wavefront_fx_idle (dev)) return (-1);
584         outb (0x07, dev->fx_dsp_page);
585         outb (0x44, dev->fx_dsp_addr);
586         outb (0x00, dev->fx_dsp_msb);
587         outb (0x00, dev->fx_dsp_lsb);
588         if (!wavefront_fx_idle (dev)) return (-1);
589         outb (0x07, dev->fx_dsp_page);
590         outb (0x42, dev->fx_dsp_addr);
591         outb (0x00, dev->fx_dsp_msb);
592         outb (0x00, dev->fx_dsp_lsb);
593         if (!wavefront_fx_idle (dev)) return (-1);
594         outb (0x07, dev->fx_dsp_page);
595         outb (0x43, dev->fx_dsp_addr);
596         outb (0x00, dev->fx_dsp_msb);
597         outb (0x00, dev->fx_dsp_lsb);
598         if (!wavefront_fx_idle (dev)) return (-1);
599         outb (0x07, dev->fx_dsp_page);
600         outb (0x7c, dev->fx_dsp_addr);
601         outb (0x00, dev->fx_dsp_msb);
602         outb (0x00, dev->fx_dsp_lsb);
603         if (!wavefront_fx_idle (dev)) return (-1);
604         outb (0x07, dev->fx_dsp_page);
605         outb (0x7e, dev->fx_dsp_addr);
606         outb (0x00, dev->fx_dsp_msb);
607         outb (0x00, dev->fx_dsp_lsb);
608         if (!wavefront_fx_idle (dev)) return (-1);
609         outb (0x07, dev->fx_dsp_page);
610         outb (0x46, dev->fx_dsp_addr);
611         outb (0x00, dev->fx_dsp_msb);
612         outb (0x00, dev->fx_dsp_lsb);
613         if (!wavefront_fx_idle (dev)) return (-1);
614         outb (0x07, dev->fx_dsp_page);
615         outb (0x49, dev->fx_dsp_addr);
616         outb (0x00, dev->fx_dsp_msb);
617         outb (0x00, dev->fx_dsp_lsb);
618         if (!wavefront_fx_idle (dev)) return (-1);
619         outb (0x07, dev->fx_dsp_page);
620         outb (0x47, dev->fx_dsp_addr);
621         outb (0x00, dev->fx_dsp_msb);
622         outb (0x00, dev->fx_dsp_lsb);
623         if (!wavefront_fx_idle (dev)) return (-1);
624         outb (0x07, dev->fx_dsp_page);
625         outb (0x4a, dev->fx_dsp_addr);
626         outb (0x00, dev->fx_dsp_msb);
627         outb (0x00, dev->fx_dsp_lsb);
628
629         /* either because of stupidity by TB's programmers, or because it
630            actually does something, rezero the MOD page.
631         */
632         for (i = 0x10; i <= 0xff; i++) {
633         
634                 if (!wavefront_fx_idle (dev)) {
635                         return (-1);
636                 }
637         
638                 outb (i, dev->fx_mod_addr);
639                 outb (0x0, dev->fx_mod_data);
640         }
641         /* load page zero */
642
643         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
644         outb (0x00, dev->fx_dsp_page);
645         outb (0x00, dev->fx_dsp_addr);
646
647         for (i = 0; i < sizeof (page_zero); i += 2) {
648                 outb (page_zero[i], dev->fx_dsp_msb);
649                 outb (page_zero[i+1], dev->fx_dsp_lsb);
650                 if (!wavefront_fx_idle (dev)) return (-1);
651         }
652
653         /* Now load page one */
654
655         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
656         outb (0x01, dev->fx_dsp_page);
657         outb (0x00, dev->fx_dsp_addr);
658
659         for (i = 0; i < sizeof (page_one); i += 2) {
660                 outb (page_one[i], dev->fx_dsp_msb);
661                 outb (page_one[i+1], dev->fx_dsp_lsb);
662                 if (!wavefront_fx_idle (dev)) return (-1);
663         }
664     
665         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
666         outb (0x02, dev->fx_dsp_page);
667         outb (0x00, dev->fx_dsp_addr);
668
669         for (i = 0; i < sizeof (page_two); i++) {
670                 outb (page_two[i], dev->fx_dsp_lsb);
671                 if (!wavefront_fx_idle (dev)) return (-1);
672         }
673     
674         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
675         outb (0x03, dev->fx_dsp_page);
676         outb (0x00, dev->fx_dsp_addr);
677
678         for (i = 0; i < sizeof (page_three); i++) {
679                 outb (page_three[i], dev->fx_dsp_lsb);
680                 if (!wavefront_fx_idle (dev)) return (-1);
681         }
682     
683         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
684         outb (0x04, dev->fx_dsp_page);
685         outb (0x00, dev->fx_dsp_addr);
686
687         for (i = 0; i < sizeof (page_four); i++) {
688                 outb (page_four[i], dev->fx_dsp_lsb);
689                 if (!wavefront_fx_idle (dev)) return (-1);
690         }
691
692         /* Load memory area (page six) */
693     
694         outb (FX_LSB_TRANSFER, dev->fx_lcr); 
695         outb (0x06, dev->fx_dsp_page); 
696
697         for (i = 0; i < sizeof (page_six); i += 3) {
698                 outb (page_six[i], dev->fx_dsp_addr);
699                 outb (page_six[i+1], dev->fx_dsp_msb);
700                 outb (page_six[i+2], dev->fx_dsp_lsb);
701                 if (!wavefront_fx_idle (dev)) return (-1);
702         }
703     
704         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
705         outb (0x07, dev->fx_dsp_page);
706         outb (0x00, dev->fx_dsp_addr);
707
708         for (i = 0; i < sizeof (page_seven); i += 2) {
709                 outb (page_seven[i], dev->fx_dsp_msb);
710                 outb (page_seven[i+1], dev->fx_dsp_lsb);
711                 if (!wavefront_fx_idle (dev)) return (-1);
712         }
713
714         /* Now setup the MOD area. We do this algorithmically in order to
715            save a little data space. It could be done in the same fashion
716            as the "pages".
717         */
718
719         for (i = 0x00; i <= 0x0f; i++) {
720                 outb (0x01, dev->fx_mod_addr);
721                 outb (i, dev->fx_mod_data);
722                 if (!wavefront_fx_idle (dev)) return (-1);
723                 outb (0x02, dev->fx_mod_addr);
724                 outb (0x00, dev->fx_mod_data);
725                 if (!wavefront_fx_idle (dev)) return (-1);
726         }
727
728         for (i = 0xb0; i <= 0xbf; i++) {
729                 outb (i, dev->fx_mod_addr);
730                 outb (0x20, dev->fx_mod_data);
731                 if (!wavefront_fx_idle (dev)) return (-1);
732         }
733
734         for (i = 0xf0; i <= 0xff; i++) {
735                 outb (i, dev->fx_mod_addr);
736                 outb (0x20, dev->fx_mod_data);
737                 if (!wavefront_fx_idle (dev)) return (-1);
738         }
739
740         for (i = 0x10; i <= 0x1d; i++) {
741                 outb (i, dev->fx_mod_addr);
742                 outb (0xff, dev->fx_mod_data);
743                 if (!wavefront_fx_idle (dev)) return (-1);
744         }
745
746         outb (0x1e, dev->fx_mod_addr);
747         outb (0x40, dev->fx_mod_data);
748         if (!wavefront_fx_idle (dev)) return (-1);
749
750         for (i = 0x1f; i <= 0x2d; i++) {
751                 outb (i, dev->fx_mod_addr);
752                 outb (0xff, dev->fx_mod_data);
753                 if (!wavefront_fx_idle (dev)) return (-1);
754         }
755
756         outb (0x2e, dev->fx_mod_addr);
757         outb (0x00, dev->fx_mod_data);
758         if (!wavefront_fx_idle (dev)) return (-1);
759
760         for (i = 0x2f; i <= 0x3e; i++) {
761                 outb (i, dev->fx_mod_addr);
762                 outb (0x00, dev->fx_mod_data);
763                 if (!wavefront_fx_idle (dev)) return (-1);
764         }
765
766         outb (0x3f, dev->fx_mod_addr);
767         outb (0x20, dev->fx_mod_data);
768         if (!wavefront_fx_idle (dev)) return (-1);
769
770         for (i = 0x40; i <= 0x4d; i++) {
771                 outb (i, dev->fx_mod_addr);
772                 outb (0x00, dev->fx_mod_data);
773                 if (!wavefront_fx_idle (dev)) return (-1);
774         }
775
776         outb (0x4e, dev->fx_mod_addr);
777         outb (0x0e, dev->fx_mod_data);
778         if (!wavefront_fx_idle (dev)) return (-1);
779         outb (0x4f, dev->fx_mod_addr);
780         outb (0x0e, dev->fx_mod_data);
781         if (!wavefront_fx_idle (dev)) return (-1);
782
783
784         for (i = 0x50; i <= 0x6b; i++) {
785                 outb (i, dev->fx_mod_addr);
786                 outb (0x00, dev->fx_mod_data);
787                 if (!wavefront_fx_idle (dev)) return (-1);
788         }
789
790         outb (0x6c, dev->fx_mod_addr);
791         outb (0x40, dev->fx_mod_data);
792         if (!wavefront_fx_idle (dev)) return (-1);
793
794         outb (0x6d, dev->fx_mod_addr);
795         outb (0x00, dev->fx_mod_data);
796         if (!wavefront_fx_idle (dev)) return (-1);
797
798         outb (0x6e, dev->fx_mod_addr);
799         outb (0x40, dev->fx_mod_data);
800         if (!wavefront_fx_idle (dev)) return (-1);
801
802         outb (0x6f, dev->fx_mod_addr);
803         outb (0x40, dev->fx_mod_data);
804         if (!wavefront_fx_idle (dev)) return (-1);
805
806         for (i = 0x70; i <= 0x7f; i++) {
807                 outb (i, dev->fx_mod_addr);
808                 outb (0xc0, dev->fx_mod_data);
809                 if (!wavefront_fx_idle (dev)) return (-1);
810         }
811     
812         for (i = 0x80; i <= 0xaf; i++) {
813                 outb (i, dev->fx_mod_addr);
814                 outb (0x00, dev->fx_mod_data);
815                 if (!wavefront_fx_idle (dev)) return (-1);
816         }
817
818         for (i = 0xc0; i <= 0xdd; i++) {
819                 outb (i, dev->fx_mod_addr);
820                 outb (0x00, dev->fx_mod_data);
821                 if (!wavefront_fx_idle (dev)) return (-1);
822         }
823
824         outb (0xde, dev->fx_mod_addr);
825         outb (0x10, dev->fx_mod_data);
826         if (!wavefront_fx_idle (dev)) return (-1);
827         outb (0xdf, dev->fx_mod_addr);
828         outb (0x10, dev->fx_mod_data);
829         if (!wavefront_fx_idle (dev)) return (-1);
830
831         for (i = 0xe0; i <= 0xef; i++) {
832                 outb (i, dev->fx_mod_addr);
833                 outb (0x00, dev->fx_mod_data);
834                 if (!wavefront_fx_idle (dev)) return (-1);
835         }
836
837         for (i = 0x00; i <= 0x0f; i++) {
838                 outb (0x01, dev->fx_mod_addr);
839                 outb (i, dev->fx_mod_data);
840                 outb (0x02, dev->fx_mod_addr);
841                 outb (0x01, dev->fx_mod_data);
842                 if (!wavefront_fx_idle (dev)) return (-1);
843         }
844
845         outb (0x02, dev->fx_op); /* mute on */
846
847         /* Now set the coefficients and so forth for the programs above */
848
849         for (i = 0; i < sizeof (coefficients); i += 4) {
850                 outb (coefficients[i], dev->fx_dsp_page);
851                 outb (coefficients[i+1], dev->fx_dsp_addr);
852                 outb (coefficients[i+2], dev->fx_dsp_msb);
853                 outb (coefficients[i+3], dev->fx_dsp_lsb);
854                 if (!wavefront_fx_idle (dev)) return (-1);
855         }
856
857         /* Some settings (?) that are too small to bundle into loops */
858
859         if (!wavefront_fx_idle (dev)) return (-1);
860         outb (0x1e, dev->fx_mod_addr);
861         outb (0x14, dev->fx_mod_data);
862         if (!wavefront_fx_idle (dev)) return (-1);
863         outb (0xde, dev->fx_mod_addr);
864         outb (0x20, dev->fx_mod_data);
865         if (!wavefront_fx_idle (dev)) return (-1);
866         outb (0xdf, dev->fx_mod_addr);
867         outb (0x20, dev->fx_mod_data);
868     
869         /* some more coefficients */
870
871         if (!wavefront_fx_idle (dev)) return (-1);
872         outb (0x06, dev->fx_dsp_page);
873         outb (0x78, dev->fx_dsp_addr);
874         outb (0x00, dev->fx_dsp_msb);
875         outb (0x40, dev->fx_dsp_lsb);
876         if (!wavefront_fx_idle (dev)) return (-1);
877         outb (0x07, dev->fx_dsp_page);
878         outb (0x03, dev->fx_dsp_addr);
879         outb (0x0f, dev->fx_dsp_msb);
880         outb (0xff, dev->fx_dsp_lsb);
881         if (!wavefront_fx_idle (dev)) return (-1);
882         outb (0x07, dev->fx_dsp_page);
883         outb (0x0b, dev->fx_dsp_addr);
884         outb (0x0f, dev->fx_dsp_msb);
885         outb (0xff, dev->fx_dsp_lsb);
886         if (!wavefront_fx_idle (dev)) return (-1);
887         outb (0x07, dev->fx_dsp_page);
888         outb (0x02, dev->fx_dsp_addr);
889         outb (0x00, dev->fx_dsp_msb);
890         outb (0x00, dev->fx_dsp_lsb);
891         if (!wavefront_fx_idle (dev)) return (-1);
892         outb (0x07, dev->fx_dsp_page);
893         outb (0x0a, dev->fx_dsp_addr);
894         outb (0x00, dev->fx_dsp_msb);
895         outb (0x00, dev->fx_dsp_lsb);
896         if (!wavefront_fx_idle (dev)) return (-1);
897         outb (0x07, dev->fx_dsp_page);
898         outb (0x46, dev->fx_dsp_addr);
899         outb (0x00, dev->fx_dsp_msb);
900         outb (0x00, dev->fx_dsp_lsb);
901         if (!wavefront_fx_idle (dev)) return (-1);
902         outb (0x07, dev->fx_dsp_page);
903         outb (0x49, dev->fx_dsp_addr);
904         outb (0x00, dev->fx_dsp_msb);
905         outb (0x00, dev->fx_dsp_lsb);
906     
907         /* Now, for some strange reason, lets reload every page
908            and all the coefficients over again. I have *NO* idea
909            why this is done. I do know that no sound is produced
910            is this phase is omitted.
911         */
912
913         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
914         outb (0x00, dev->fx_dsp_page);  
915         outb (0x10, dev->fx_dsp_addr);
916
917         for (i = 0; i < sizeof (page_zero_v2); i += 2) {
918                 outb (page_zero_v2[i], dev->fx_dsp_msb);
919                 outb (page_zero_v2[i+1], dev->fx_dsp_lsb);
920                 if (!wavefront_fx_idle (dev)) return (-1);
921         }
922     
923         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
924         outb (0x01, dev->fx_dsp_page);
925         outb (0x10, dev->fx_dsp_addr);
926
927         for (i = 0; i < sizeof (page_one_v2); i += 2) {
928                 outb (page_one_v2[i], dev->fx_dsp_msb);
929                 outb (page_one_v2[i+1], dev->fx_dsp_lsb);
930                 if (!wavefront_fx_idle (dev)) return (-1);
931         }
932     
933         if (!wavefront_fx_idle (dev)) return (-1);
934         if (!wavefront_fx_idle (dev)) return (-1);
935     
936         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
937         outb (0x02, dev->fx_dsp_page);
938         outb (0x10, dev->fx_dsp_addr);
939
940         for (i = 0; i < sizeof (page_two_v2); i++) {
941                 outb (page_two_v2[i], dev->fx_dsp_lsb);
942                 if (!wavefront_fx_idle (dev)) return (-1);
943         }
944         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
945         outb (0x03, dev->fx_dsp_page);
946         outb (0x10, dev->fx_dsp_addr);
947
948         for (i = 0; i < sizeof (page_three_v2); i++) {
949                 outb (page_three_v2[i], dev->fx_dsp_lsb);
950                 if (!wavefront_fx_idle (dev)) return (-1);
951         }
952     
953         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
954         outb (0x04, dev->fx_dsp_page);
955         outb (0x10, dev->fx_dsp_addr);
956
957         for (i = 0; i < sizeof (page_four_v2); i++) {
958                 outb (page_four_v2[i], dev->fx_dsp_lsb);
959                 if (!wavefront_fx_idle (dev)) return (-1);
960         }
961     
962         outb (FX_LSB_TRANSFER, dev->fx_lcr);
963         outb (0x06, dev->fx_dsp_page);
964
965         /* Page six v.2 is algorithmic */
966     
967         for (i = 0x10; i <= 0x3e; i += 2) {
968                 outb (i, dev->fx_dsp_addr);
969                 outb (0x00, dev->fx_dsp_msb);
970                 outb (0x00, dev->fx_dsp_lsb);
971                 if (!wavefront_fx_idle (dev)) return (-1);
972         }
973
974         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
975         outb (0x07, dev->fx_dsp_page);
976         outb (0x10, dev->fx_dsp_addr);
977
978         for (i = 0; i < sizeof (page_seven_v2); i += 2) {
979                 outb (page_seven_v2[i], dev->fx_dsp_msb);
980                 outb (page_seven_v2[i+1], dev->fx_dsp_lsb);
981                 if (!wavefront_fx_idle (dev)) return (-1);
982         }
983
984         for (i = 0x00; i < sizeof(mod_v2); i += 2) {
985                 outb (mod_v2[i], dev->fx_mod_addr);
986                 outb (mod_v2[i+1], dev->fx_mod_data);
987                 if (!wavefront_fx_idle (dev)) return (-1);
988         }
989
990         for (i = 0; i < sizeof (coefficients2); i += 4) {
991                 outb (coefficients2[i], dev->fx_dsp_page);
992                 outb (coefficients2[i+1], dev->fx_dsp_addr);
993                 outb (coefficients2[i+2], dev->fx_dsp_msb);
994                 outb (coefficients2[i+3], dev->fx_dsp_lsb);
995                 if (!wavefront_fx_idle (dev)) return (-1);
996         }
997
998         for (i = 0; i < sizeof (coefficients3); i += 2) {
999                 int x;
1000
1001                 outb (0x07, dev->fx_dsp_page);
1002                 x = (i % 4) ? 0x4e : 0x4c;
1003                 outb (x, dev->fx_dsp_addr);
1004                 outb (coefficients3[i], dev->fx_dsp_msb);
1005                 outb (coefficients3[i+1], dev->fx_dsp_lsb);
1006         }
1007
1008         outb (0x00, dev->fx_op); /* mute off */
1009         if (!wavefront_fx_idle (dev)) return (-1);
1010
1011         return (0);
1012 }