Deleted Added
full compact
sb16.c (54237) sb16.c (54462)
1/*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * Copyright 1997,1998 Luigi Rizzo.
4 *
5 * Derived from files in the Voxware 3.5 distribution,
6 * Copyright by Hannu Savolainen 1994, under the same copyright
7 * conditions.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
1/*
2 * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
3 * Copyright 1997,1998 Luigi Rizzo.
4 *
5 * Derived from files in the Voxware 3.5 distribution,
6 * Copyright by Hannu Savolainen 1994, under the same copyright
7 * conditions.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * $FreeBSD: head/sys/dev/sound/isa/sb16.c 54237 1999-12-07 01:53:24Z billf $
31 * $FreeBSD: head/sys/dev/sound/isa/sb16.c 54462 1999-12-12 02:30:19Z cg $
32 */
33
34#include <dev/sound/pcm/sound.h>
35
36#include "sbc.h"
37
38#define __SB_MIXER_C__ /* XXX warning... */
39#include <dev/sound/isa/sb.h>
40#include <dev/sound/chip.h>
41
42/* channel interface */
43static void *sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
44static int sbchan_setdir(void *data, int dir);
45static int sbchan_setformat(void *data, u_int32_t format);
46static int sbchan_setspeed(void *data, u_int32_t speed);
47static int sbchan_setblocksize(void *data, u_int32_t blocksize);
48static int sbchan_trigger(void *data, int go);
49static int sbchan_getptr(void *data);
50static pcmchan_caps *sbchan_getcaps(void *data);
51
52/* channel interface for ESS */
53#ifdef notyet
54static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
55#endif
56static int esschan_setdir(void *data, int dir);
57static int esschan_setformat(void *data, u_int32_t format);
58static int esschan_setspeed(void *data, u_int32_t speed);
59static int esschan_setblocksize(void *data, u_int32_t blocksize);
60static int esschan_trigger(void *data, int go);
61static int esschan_getptr(void *data);
62static pcmchan_caps *esschan_getcaps(void *data);
32 */
33
34#include <dev/sound/pcm/sound.h>
35
36#include "sbc.h"
37
38#define __SB_MIXER_C__ /* XXX warning... */
39#include <dev/sound/isa/sb.h>
40#include <dev/sound/chip.h>
41
42/* channel interface */
43static void *sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
44static int sbchan_setdir(void *data, int dir);
45static int sbchan_setformat(void *data, u_int32_t format);
46static int sbchan_setspeed(void *data, u_int32_t speed);
47static int sbchan_setblocksize(void *data, u_int32_t blocksize);
48static int sbchan_trigger(void *data, int go);
49static int sbchan_getptr(void *data);
50static pcmchan_caps *sbchan_getcaps(void *data);
51
52/* channel interface for ESS */
53#ifdef notyet
54static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
55#endif
56static int esschan_setdir(void *data, int dir);
57static int esschan_setformat(void *data, u_int32_t format);
58static int esschan_setspeed(void *data, u_int32_t speed);
59static int esschan_setblocksize(void *data, u_int32_t blocksize);
60static int esschan_trigger(void *data, int go);
61static int esschan_getptr(void *data);
62static pcmchan_caps *esschan_getcaps(void *data);
63
63static pcmchan_caps sb_playcaps = {
64 4000, 22050,
65 AFMT_U8,
66 AFMT_U8
67};
68
69static pcmchan_caps sb_reccaps = {
70 4000, 13000,
71 AFMT_U8,
72 AFMT_U8
73};
74
75static pcmchan_caps sbpro_playcaps = {
76 4000, 45000,
77 AFMT_STEREO | AFMT_U8,
78 AFMT_STEREO | AFMT_U8
79};
80
81static pcmchan_caps sbpro_reccaps = {
82 4000, 15000,
83 AFMT_STEREO | AFMT_U8,
84 AFMT_STEREO | AFMT_U8
85};
86
64static pcmchan_caps sb_playcaps = {
65 4000, 22050,
66 AFMT_U8,
67 AFMT_U8
68};
69
70static pcmchan_caps sb_reccaps = {
71 4000, 13000,
72 AFMT_U8,
73 AFMT_U8
74};
75
76static pcmchan_caps sbpro_playcaps = {
77 4000, 45000,
78 AFMT_STEREO | AFMT_U8,
79 AFMT_STEREO | AFMT_U8
80};
81
82static pcmchan_caps sbpro_reccaps = {
83 4000, 15000,
84 AFMT_STEREO | AFMT_U8,
85 AFMT_STEREO | AFMT_U8
86};
87
87static pcmchan_caps sb16_playcaps = {
88static pcmchan_caps sb16_hcaps = {
88 5000, 45000,
89 AFMT_STEREO | AFMT_S16_LE,
90 AFMT_STEREO | AFMT_S16_LE
91};
92
89 5000, 45000,
90 AFMT_STEREO | AFMT_S16_LE,
91 AFMT_STEREO | AFMT_S16_LE
92};
93
93static pcmchan_caps sb16_reccaps = {
94static pcmchan_caps sb16_lcaps = {
94 5000, 45000,
95 AFMT_STEREO | AFMT_U8,
96 AFMT_STEREO | AFMT_U8
97};
98
95 5000, 45000,
96 AFMT_STEREO | AFMT_U8,
97 AFMT_STEREO | AFMT_U8
98};
99
100static pcmchan_caps sb16x_caps = {
101 5000, 49000,
102 AFMT_STEREO | AFMT_U8 /* | AFMT_S16_LE */,
103 AFMT_STEREO | AFMT_U8 /* AFMT_S16_LE */
104};
105
99static pcmchan_caps ess_playcaps = {
100 5000, 49000,
101 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
102 AFMT_STEREO | AFMT_S16_LE
103};
104
105static pcmchan_caps ess_reccaps = {
106 5000, 49000,
107 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
108 AFMT_STEREO | AFMT_S16_LE
109};
110
111static pcm_channel sb_chantemplate = {
112 sbchan_init,
113 sbchan_setdir,
114 sbchan_setformat,
115 sbchan_setspeed,
116 sbchan_setblocksize,
117 sbchan_trigger,
118 sbchan_getptr,
119 sbchan_getcaps,
120};
121
122static pcm_channel ess_chantemplate = {
123 sbchan_init,
124 esschan_setdir,
125 esschan_setformat,
126 esschan_setspeed,
127 esschan_setblocksize,
128 esschan_trigger,
129 esschan_getptr,
130 esschan_getcaps,
131};
132#define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16)
133
134struct sb_info;
135
136struct sb_chinfo {
137 struct sb_info *parent;
138 pcm_channel *channel;
139 snd_dbuf *buffer;
140 int dir;
141 u_int32_t fmt;
142 int ess_dma_started;
143};
144
145struct sb_info {
146 struct resource *io_base; /* I/O address for the board */
106static pcmchan_caps ess_playcaps = {
107 5000, 49000,
108 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
109 AFMT_STEREO | AFMT_S16_LE
110};
111
112static pcmchan_caps ess_reccaps = {
113 5000, 49000,
114 AFMT_STEREO | AFMT_U8 | AFMT_S16_LE,
115 AFMT_STEREO | AFMT_S16_LE
116};
117
118static pcm_channel sb_chantemplate = {
119 sbchan_init,
120 sbchan_setdir,
121 sbchan_setformat,
122 sbchan_setspeed,
123 sbchan_setblocksize,
124 sbchan_trigger,
125 sbchan_getptr,
126 sbchan_getcaps,
127};
128
129static pcm_channel ess_chantemplate = {
130 sbchan_init,
131 esschan_setdir,
132 esschan_setformat,
133 esschan_setspeed,
134 esschan_setblocksize,
135 esschan_trigger,
136 esschan_getptr,
137 esschan_getcaps,
138};
139#define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16)
140
141struct sb_info;
142
143struct sb_chinfo {
144 struct sb_info *parent;
145 pcm_channel *channel;
146 snd_dbuf *buffer;
147 int dir;
148 u_int32_t fmt;
149 int ess_dma_started;
150};
151
152struct sb_info {
153 struct resource *io_base; /* I/O address for the board */
147 int io_rid;
148 struct resource *irq;
154 struct resource *irq;
149 int irq_rid;
150 struct resource *drq1; /* play */
151 int drq1_rid;
152 struct resource *drq2; /* rec */
153 int drq2_rid;
155 struct resource *drq1;
156 struct resource *drq2;
154 bus_dma_tag_t parent_dmat;
155
157 bus_dma_tag_t parent_dmat;
158
156 int dma16, dma8;
157 int bd_id;
158 u_long bd_flags; /* board-specific flags */
159 struct sb_chinfo pch, rch;
160};
161
162static int sb_rd(struct sb_info *sb, int reg);
163static void sb_wr(struct sb_info *sb, int reg, u_int8_t val);
164static int sb_dspready(struct sb_info *sb);
165static int sb_cmd(struct sb_info *sb, u_char val);
166static int sb_cmd1(struct sb_info *sb, u_char cmd, int val);
167static int sb_cmd2(struct sb_info *sb, u_char cmd, int val);
168static u_int sb_get_byte(struct sb_info *sb);
159 int bd_id;
160 u_long bd_flags; /* board-specific flags */
161 struct sb_chinfo pch, rch;
162};
163
164static int sb_rd(struct sb_info *sb, int reg);
165static void sb_wr(struct sb_info *sb, int reg, u_int8_t val);
166static int sb_dspready(struct sb_info *sb);
167static int sb_cmd(struct sb_info *sb, u_char val);
168static int sb_cmd1(struct sb_info *sb, u_char cmd, int val);
169static int sb_cmd2(struct sb_info *sb, u_char cmd, int val);
170static u_int sb_get_byte(struct sb_info *sb);
169static int ess_write(struct sb_info *sb, u_char reg, int val);
170static int ess_read(struct sb_info *sb, u_char reg);
171
172/*
173 * in the SB, there is a set of indirect "mixer" registers with
174 * address at offset 4, data at offset 5
175 */
176static void sb_setmixer(struct sb_info *sb, u_int port, u_int value);
177static int sb_getmixer(struct sb_info *sb, u_int port);
171static void sb_setmixer(struct sb_info *sb, u_int port, u_int value);
172static int sb_getmixer(struct sb_info *sb, u_int port);
178
179static void sb_intr(void *arg);
180static void ess_intr(void *arg);
181static int sb_init(device_t dev, struct sb_info *sb);
182static int sb_reset_dsp(struct sb_info *sb);
183
173static int sb_reset_dsp(struct sb_info *sb);
174
175static void sb_intr(void *arg);
184static int sb_format(struct sb_chinfo *ch, u_int32_t format);
185static int sb_speed(struct sb_chinfo *ch, int speed);
186static int sb_start(struct sb_chinfo *ch);
187static int sb_stop(struct sb_chinfo *ch);
188
176static int sb_format(struct sb_chinfo *ch, u_int32_t format);
177static int sb_speed(struct sb_chinfo *ch, int speed);
178static int sb_start(struct sb_chinfo *ch);
179static int sb_stop(struct sb_chinfo *ch);
180
181static int ess_write(struct sb_info *sb, u_char reg, int val);
182static int ess_read(struct sb_info *sb, u_char reg);
183static void ess_intr(void *arg);
189static int ess_format(struct sb_chinfo *ch, u_int32_t format);
190static int ess_speed(struct sb_chinfo *ch, int speed);
191static int ess_start(struct sb_chinfo *ch);
192static int ess_stop(struct sb_chinfo *ch);
193static int ess_abort(struct sb_chinfo *ch);
184static int ess_format(struct sb_chinfo *ch, u_int32_t format);
185static int ess_speed(struct sb_chinfo *ch, int speed);
186static int ess_start(struct sb_chinfo *ch);
187static int ess_stop(struct sb_chinfo *ch);
188static int ess_abort(struct sb_chinfo *ch);
189
194static int sbmix_init(snd_mixer *m);
195static int sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right);
196static int sbmix_setrecsrc(snd_mixer *m, u_int32_t src);
197
198static snd_mixer sb_mixer = {
199 "SoundBlaster mixer",
200 sbmix_init,
201 sbmix_set,
202 sbmix_setrecsrc,
203};
204
205static devclass_t pcm_devclass;
206
207/*
208 * Common code for the midi and pcm functions
209 *
210 * sb_cmd write a single byte to the CMD port.
211 * sb_cmd1 write a CMD + 1 byte arg
212 * sb_cmd2 write a CMD + 2 byte arg
213 * sb_get_byte returns a single byte from the DSP data port
214 *
215 * ess_write is actually sb_cmd1
216 * ess_read access ext. regs via sb_cmd(0xc0, reg) followed by sb_get_byte
217 */
218
219static int
220port_rd(struct resource *port, int off)
221{
222 return bus_space_read_1(rman_get_bustag(port),
223 rman_get_bushandle(port),
224 off);
225}
226
227static void
228port_wr(struct resource *port, int off, u_int8_t data)
229{
230 return bus_space_write_1(rman_get_bustag(port),
231 rman_get_bushandle(port),
232 off, data);
233}
234
235static int
236sb_rd(struct sb_info *sb, int reg)
237{
238 return port_rd(sb->io_base, reg);
239}
240
241static void
242sb_wr(struct sb_info *sb, int reg, u_int8_t val)
243{
244 port_wr(sb->io_base, reg, val);
245}
246
247static int
248sb_dspready(struct sb_info *sb)
249{
250 return ((sb_rd(sb, SBDSP_STATUS) & 0x80) == 0);
251}
252
253static int
254sb_dspwr(struct sb_info *sb, u_char val)
255{
256 int i;
257
258 for (i = 0; i < 1000; i++) {
259 if (sb_dspready(sb)) {
260 sb_wr(sb, SBDSP_CMD, val);
261 return 1;
262 }
263 if (i > 10) DELAY((i > 100)? 1000 : 10);
264 }
265 printf("sb_dspwr(0x%02x) timed out.\n", val);
266 return 0;
267}
268
269static int
270sb_cmd(struct sb_info *sb, u_char val)
271{
272#if 0
273 printf("sb_cmd: %x\n", val);
274#endif
275 return sb_dspwr(sb, val);
276}
277
278static int
279sb_cmd1(struct sb_info *sb, u_char cmd, int val)
280{
281#if 0
282 printf("sb_cmd1: %x, %x\n", cmd, val);
283#endif
284 if (sb_dspwr(sb, cmd)) {
285 return sb_dspwr(sb, val & 0xff);
286 } else return 0;
287}
288
289static int
290sb_cmd2(struct sb_info *sb, u_char cmd, int val)
291{
292#if 0
293 printf("sb_cmd2: %x, %x\n", cmd, val);
294#endif
295 if (sb_dspwr(sb, cmd)) {
296 return sb_dspwr(sb, val & 0xff) &&
297 sb_dspwr(sb, (val >> 8) & 0xff);
298 } else return 0;
299}
300
301/*
302 * in the SB, there is a set of indirect "mixer" registers with
303 * address at offset 4, data at offset 5
304 */
305static void
306sb_setmixer(struct sb_info *sb, u_int port, u_int value)
307{
308 u_long flags;
309
310 flags = spltty();
311 sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
312 DELAY(10);
313 sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff));
314 DELAY(10);
315 splx(flags);
316}
317
318static int
319sb_getmixer(struct sb_info *sb, u_int port)
320{
321 int val;
322 u_long flags;
323
324 flags = spltty();
325 sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
326 DELAY(10);
327 val = sb_rd(sb, SB_MIX_DATA);
328 DELAY(10);
329 splx(flags);
330
331 return val;
332}
333
334static u_int
335sb_get_byte(struct sb_info *sb)
336{
337 int i;
338
339 for (i = 1000; i > 0; i--) {
340 if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80)
341 return sb_rd(sb, DSP_READ);
342 else
343 DELAY(20);
344 }
345 return 0xffff;
346}
347
348static int
349ess_write(struct sb_info *sb, u_char reg, int val)
350{
351 return sb_cmd1(sb, reg, val);
352}
353
354static int
355ess_read(struct sb_info *sb, u_char reg)
356{
357 return (sb_cmd(sb, 0xc0) && sb_cmd(sb, reg))? sb_get_byte(sb) : 0xffff;
358}
359
360static int
361sb_reset_dsp(struct sb_info *sb)
362{
363 sb_wr(sb, SBDSP_RST, 3);
364 DELAY(100);
365 sb_wr(sb, SBDSP_RST, 0);
366 if (sb_get_byte(sb) != 0xAA) {
367 DEB(printf("sb_reset_dsp 0x%lx failed\n",
368 rman_get_start(d->io_base)));
369 return ENXIO; /* Sorry */
370 }
371 if (sb->bd_flags & BD_F_ESS) sb_cmd(sb, 0xc6);
372 return 0;
373}
374
375static void
376sb_release_resources(struct sb_info *sb, device_t dev)
377{
378 /* should we bus_teardown_intr here? */
379 if (sb->irq) {
190static int sbmix_init(snd_mixer *m);
191static int sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right);
192static int sbmix_setrecsrc(snd_mixer *m, u_int32_t src);
193
194static snd_mixer sb_mixer = {
195 "SoundBlaster mixer",
196 sbmix_init,
197 sbmix_set,
198 sbmix_setrecsrc,
199};
200
201static devclass_t pcm_devclass;
202
203/*
204 * Common code for the midi and pcm functions
205 *
206 * sb_cmd write a single byte to the CMD port.
207 * sb_cmd1 write a CMD + 1 byte arg
208 * sb_cmd2 write a CMD + 2 byte arg
209 * sb_get_byte returns a single byte from the DSP data port
210 *
211 * ess_write is actually sb_cmd1
212 * ess_read access ext. regs via sb_cmd(0xc0, reg) followed by sb_get_byte
213 */
214
215static int
216port_rd(struct resource *port, int off)
217{
218 return bus_space_read_1(rman_get_bustag(port),
219 rman_get_bushandle(port),
220 off);
221}
222
223static void
224port_wr(struct resource *port, int off, u_int8_t data)
225{
226 return bus_space_write_1(rman_get_bustag(port),
227 rman_get_bushandle(port),
228 off, data);
229}
230
231static int
232sb_rd(struct sb_info *sb, int reg)
233{
234 return port_rd(sb->io_base, reg);
235}
236
237static void
238sb_wr(struct sb_info *sb, int reg, u_int8_t val)
239{
240 port_wr(sb->io_base, reg, val);
241}
242
243static int
244sb_dspready(struct sb_info *sb)
245{
246 return ((sb_rd(sb, SBDSP_STATUS) & 0x80) == 0);
247}
248
249static int
250sb_dspwr(struct sb_info *sb, u_char val)
251{
252 int i;
253
254 for (i = 0; i < 1000; i++) {
255 if (sb_dspready(sb)) {
256 sb_wr(sb, SBDSP_CMD, val);
257 return 1;
258 }
259 if (i > 10) DELAY((i > 100)? 1000 : 10);
260 }
261 printf("sb_dspwr(0x%02x) timed out.\n", val);
262 return 0;
263}
264
265static int
266sb_cmd(struct sb_info *sb, u_char val)
267{
268#if 0
269 printf("sb_cmd: %x\n", val);
270#endif
271 return sb_dspwr(sb, val);
272}
273
274static int
275sb_cmd1(struct sb_info *sb, u_char cmd, int val)
276{
277#if 0
278 printf("sb_cmd1: %x, %x\n", cmd, val);
279#endif
280 if (sb_dspwr(sb, cmd)) {
281 return sb_dspwr(sb, val & 0xff);
282 } else return 0;
283}
284
285static int
286sb_cmd2(struct sb_info *sb, u_char cmd, int val)
287{
288#if 0
289 printf("sb_cmd2: %x, %x\n", cmd, val);
290#endif
291 if (sb_dspwr(sb, cmd)) {
292 return sb_dspwr(sb, val & 0xff) &&
293 sb_dspwr(sb, (val >> 8) & 0xff);
294 } else return 0;
295}
296
297/*
298 * in the SB, there is a set of indirect "mixer" registers with
299 * address at offset 4, data at offset 5
300 */
301static void
302sb_setmixer(struct sb_info *sb, u_int port, u_int value)
303{
304 u_long flags;
305
306 flags = spltty();
307 sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
308 DELAY(10);
309 sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff));
310 DELAY(10);
311 splx(flags);
312}
313
314static int
315sb_getmixer(struct sb_info *sb, u_int port)
316{
317 int val;
318 u_long flags;
319
320 flags = spltty();
321 sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
322 DELAY(10);
323 val = sb_rd(sb, SB_MIX_DATA);
324 DELAY(10);
325 splx(flags);
326
327 return val;
328}
329
330static u_int
331sb_get_byte(struct sb_info *sb)
332{
333 int i;
334
335 for (i = 1000; i > 0; i--) {
336 if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80)
337 return sb_rd(sb, DSP_READ);
338 else
339 DELAY(20);
340 }
341 return 0xffff;
342}
343
344static int
345ess_write(struct sb_info *sb, u_char reg, int val)
346{
347 return sb_cmd1(sb, reg, val);
348}
349
350static int
351ess_read(struct sb_info *sb, u_char reg)
352{
353 return (sb_cmd(sb, 0xc0) && sb_cmd(sb, reg))? sb_get_byte(sb) : 0xffff;
354}
355
356static int
357sb_reset_dsp(struct sb_info *sb)
358{
359 sb_wr(sb, SBDSP_RST, 3);
360 DELAY(100);
361 sb_wr(sb, SBDSP_RST, 0);
362 if (sb_get_byte(sb) != 0xAA) {
363 DEB(printf("sb_reset_dsp 0x%lx failed\n",
364 rman_get_start(d->io_base)));
365 return ENXIO; /* Sorry */
366 }
367 if (sb->bd_flags & BD_F_ESS) sb_cmd(sb, 0xc6);
368 return 0;
369}
370
371static void
372sb_release_resources(struct sb_info *sb, device_t dev)
373{
374 /* should we bus_teardown_intr here? */
375 if (sb->irq) {
380 bus_release_resource(dev, SYS_RES_IRQ, sb->irq_rid, sb->irq);
376 bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq);
381 sb->irq = 0;
382 }
383 if (sb->drq1) {
377 sb->irq = 0;
378 }
379 if (sb->drq1) {
384 bus_release_resource(dev, SYS_RES_DRQ, sb->drq1_rid, sb->drq1);
380 bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1);
385 sb->drq1 = 0;
386 }
387 if (sb->drq2) {
381 sb->drq1 = 0;
382 }
383 if (sb->drq2) {
388 bus_release_resource(dev, SYS_RES_DRQ, sb->drq2_rid, sb->drq2);
384 bus_release_resource(dev, SYS_RES_DRQ, 1, sb->drq2);
389 sb->drq2 = 0;
390 }
391 if (sb->io_base) {
385 sb->drq2 = 0;
386 }
387 if (sb->io_base) {
392 bus_release_resource(dev, SYS_RES_IOPORT, sb->io_rid,
393 sb->io_base);
388 bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base);
394 sb->io_base = 0;
395 }
396 free(sb, M_DEVBUF);
397}
398
399static int
400sb_alloc_resources(struct sb_info *sb, device_t dev)
401{
389 sb->io_base = 0;
390 }
391 free(sb, M_DEVBUF);
392}
393
394static int
395sb_alloc_resources(struct sb_info *sb, device_t dev)
396{
397 int rid;
398
399 rid = 0;
402 if (!sb->io_base)
403 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
400 if (!sb->io_base)
401 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
404 &sb->io_rid, 0, ~0, 1,
402 &rid, 0, ~0, 1,
405 RF_ACTIVE);
403 RF_ACTIVE);
404 rid = 0;
406 if (!sb->irq)
407 sb->irq = bus_alloc_resource(dev, SYS_RES_IRQ,
405 if (!sb->irq)
406 sb->irq = bus_alloc_resource(dev, SYS_RES_IRQ,
408 &sb->irq_rid, 0, ~0, 1,
407 &rid, 0, ~0, 1,
409 RF_ACTIVE);
408 RF_ACTIVE);
409 rid = 0;
410 if (!sb->drq1)
411 sb->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ,
410 if (!sb->drq1)
411 sb->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ,
412 &sb->drq1_rid, 0, ~0, 1,
412 &rid, 0, ~0, 1,
413 RF_ACTIVE);
413 RF_ACTIVE);
414 if (!sb->drq2 && sb->drq2_rid > 0)
414 rid = 1;
415 if (!sb->drq2)
415 sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ,
416 sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ,
416 &sb->drq2_rid, 0, ~0, 1,
417 &rid, 0, ~0, 1,
417 RF_ACTIVE);
418
419 if (sb->io_base && sb->drq1 && sb->irq) {
418 RF_ACTIVE);
419
420 if (sb->io_base && sb->drq1 && sb->irq) {
420 sb->dma8 = rman_get_start(sb->drq1);
421 isa_dma_acquire(sb->dma8);
422 isa_dmainit(sb->dma8, DSP_BUFFSIZE);
421 isa_dma_acquire(rman_get_start(sb->drq1));
422 isa_dmainit(rman_get_start(sb->drq1), DSP_BUFFSIZE);
423
424 if (sb->drq2) {
423
424 if (sb->drq2) {
425 sb->dma16 = rman_get_start(sb->drq2);
426 isa_dma_acquire(sb->dma16);
427 isa_dmainit(sb->dma16, DSP_BUFFSIZE);
428 } else sb->dma16 = sb->dma8;
429
430 if (sb->dma8 > sb->dma16) {
431 int tmp = sb->dma16;
432 sb->dma16 = sb->dma8;
433 sb->dma8 = tmp;
425 isa_dma_acquire(rman_get_start(sb->drq2));
426 isa_dmainit(rman_get_start(sb->drq2), DSP_BUFFSIZE);
434 }
427 }
428
435 return 0;
436 } else return ENXIO;
437}
438
429 return 0;
430 } else return ENXIO;
431}
432
439static int
440sb_identify_board(device_t dev, struct sb_info *sb)
433static void
434sb16_swap(void *v, int dir)
441{
435{
442 char *fmt = NULL;
443 static char buf[64];
444 int essver = 0;
436 struct sb_info *sb = v;
437 int pb = sb->pch.buffer->dl;
438 int rb = sb->rch.buffer->dl;
439 int pc = sb->pch.buffer->chan;
440 int rc = sb->rch.buffer->chan;
441 int swp = 0;
445
442
446 sb_cmd(sb, DSP_CMD_GETVER); /* Get version */
447 sb->bd_id = (sb_get_byte(sb) << 8) | sb_get_byte(sb);
443 if (!pb && !rb) {
444 if (dir == PCMDIR_PLAY && pc < 4) swp = 1;
445 else if (dir == PCMDIR_REC && rc < 4) swp = 1;
446 if (sb->bd_flags & BD_F_SB16X) swp = !swp;
447 if (swp) {
448 int t;
448
449
449 switch (sb->bd_id >> 8) {
450 case 1: /* old sound blaster has nothing... */
451 case 2:
452 fmt = "SoundBlaster %d.%d" ; /* default */
453 break;
454
455 case 3:
456 fmt = "SoundBlaster Pro %d.%d";
457 if (sb->bd_id == 0x301) {
458 int rev;
459
460 /* Try to detect ESS chips. */
461 sb_cmd(sb, DSP_CMD_GETID); /* Return ident. bytes. */
462 essver = (sb_get_byte(sb) << 8) | sb_get_byte(sb);
463 rev = essver & 0x000f;
464 essver &= 0xfff0;
465 if (essver == 0x4880) {
466 /* the ESS488 can be treated as an SBPRO */
467 fmt = "SoundBlaster Pro (ESS488 rev %d)";
468 } else if (essver == 0x6880) {
469 if (rev < 8) fmt = "ESS688 rev %d";
470 else fmt = "ESS1868 rev %d";
471 sb->bd_flags |= BD_F_ESS;
472 } else return ENXIO;
473 sb->bd_id &= 0xff00;
474 sb->bd_id |= ((essver & 0xf000) >> 8) | rev;
450 t = sb->pch.buffer->chan;
451 sb->pch.buffer->chan = sb->rch.buffer->chan;
452 sb->rch.buffer->chan = t;
453 sb->pch.buffer->dir = B_WRITE;
454 sb->rch.buffer->dir = B_READ;
475 }
455 }
476 break;
477
478 case 4:
479 sb->bd_flags |= BD_F_SB16;
480 if (sb->bd_flags & BD_F_SB16X) fmt = "SB16 ViBRA16X %d.%d";
481 else fmt = "SoundBlaster 16 %d.%d";
482 break;
483
484 default:
485 device_printf(dev, "failed to get SB version (%x)\n",
486 sb->bd_id);
487 return ENXIO;
488 }
489 if (essver) snprintf(buf, sizeof buf, fmt, sb->bd_id & 0x000f);
490 else snprintf(buf, sizeof buf, fmt, sb->bd_id >> 8, sb->bd_id & 0xff);
491 device_set_desc_copy(dev, buf);
492 return sb_reset_dsp(sb);
456 }
493}
494
495static int
457}
458
459static int
496sb_init(device_t dev, struct sb_info *sb)
497{
498 int x, irq;
499
500 sb->bd_flags &= ~BD_F_MIX_MASK;
501 /* do various initializations depending on board id. */
502 switch (sb->bd_id >> 8) {
503 case 1: /* old sound blaster has nothing... */
504 break;
505
506 case 2:
507 sb->bd_flags |= BD_F_DUP_MIDI;
508 if (sb->bd_id > 0x200) sb->bd_flags |= BD_F_MIX_CT1335;
509 break;
510
511 case 3:
512 sb->bd_flags |= BD_F_DUP_MIDI | BD_F_MIX_CT1345;
513 break;
514
515 case 4:
516 sb->bd_flags |= BD_F_SB16 | BD_F_MIX_CT1745;
517 if (sb->dma16 != sb->dma8) sb->bd_flags |= BD_F_DUPLEX;
518
519 /* soft irq/dma configuration */
520 x = -1;
521 irq = rman_get_start(sb->irq);
522 if (irq == 5) x = 2;
523 else if (irq == 7) x = 4;
524 else if (irq == 9) x = 1;
525 else if (irq == 10) x = 8;
526 if (x == -1) device_printf(dev,
527 "bad irq %d (5/7/9/10 valid)\n",
528 irq);
529 else sb_setmixer(sb, IRQ_NR, x);
530 sb_setmixer(sb, DMA_NR, (1 << sb->dma16) | (1 << sb->dma8));
531 break;
532 }
533 return 0;
534}
535
536static int
537sb_probe(device_t dev)
538{
539 snddev_info *d = device_get_softc(dev);
540 struct sb_info *sb;
541 int allocated, i;
542 int error;
543
544 if (isa_get_vendorid(dev)) return ENXIO; /* not yet */
545
546 device_set_desc(dev, "SoundBlaster");
547 bzero(d, sizeof *d);
548 sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
549 if (!sb) return ENXIO;
550 bzero(sb, sizeof *sb);
551
552 allocated = 0;
553 sb->io_rid = 0;
554 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &sb->io_rid,
555 0, ~0, 16, RF_ACTIVE);
556 if (!sb->io_base) {
557 BVDDB(printf("sb_probe: no addr, trying (0x220, 0x240)\n"));
558 allocated = 1;
559 sb->io_rid = 0;
560 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
561 &sb->io_rid, 0x220, 0x22f,
562 16, RF_ACTIVE);
563 if (!sb->io_base) {
564 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
565 &sb->io_rid, 0x240,
566 0x24f, 16, RF_ACTIVE);
567 }
568 }
569 if (!sb->io_base) return ENXIO;
570
571 error = sb_reset_dsp(sb);
572 if (error) goto no;
573 error = sb_identify_board(dev, sb);
574 if (error) goto no;
575no:
576 i = sb->io_rid;
577 sb_release_resources(sb, dev);
578 if (allocated) bus_delete_resource(dev, SYS_RES_IOPORT, i);
579 return error;
580}
581
582static int
583sb_doattach(device_t dev, struct sb_info *sb)
584{
585 snddev_info *d = device_get_softc(dev);
586 void *ih;
460sb_doattach(device_t dev, struct sb_info *sb)
461{
462 snddev_info *d = device_get_softc(dev);
463 void *ih;
587 int error;
588 char status[SND_STATUSLEN];
589
464 char status[SND_STATUSLEN];
465
590 sb->irq_rid = 0;
591 sb->drq1_rid = 0;
592 sb->drq2_rid = 1;
593 if (sb_alloc_resources(sb, dev)) goto no;
466 if (sb_alloc_resources(sb, dev)) goto no;
594 error = sb_reset_dsp(sb);
595 if (error) goto no;
596 error = sb_identify_board(dev, sb);
597 if (error) goto no;
598
599 sb_init(dev, sb);
467 if (sb_reset_dsp(sb)) goto no;
600 mixer_init(d, &sb_mixer, sb);
468 mixer_init(d, &sb_mixer, sb);
469
601 if (sb->bd_flags & BD_F_ESS)
602 bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, ess_intr, sb, &ih);
603 else
604 bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih);
470 if (sb->bd_flags & BD_F_ESS)
471 bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, ess_intr, sb, &ih);
472 else
473 bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih);
605
606 if (sb->bd_flags & BD_F_SB16)
607 pcm_setflags(dev, pcm_getflags(dev) | SD_F_EVILSB16);
608 if (sb->dma16 == sb->dma8)
474 if ((sb->bd_flags & BD_F_SB16) && !(sb->bd_flags & BD_F_SB16X))
475 pcm_setswap(dev, sb16_swap);
476 if (!sb->drq2)
609 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
477 pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
478
610 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
611 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
612 /*highaddr*/BUS_SPACE_MAXADDR,
613 /*filter*/NULL, /*filterarg*/NULL,
614 /*maxsize*/DSP_BUFFSIZE, /*nsegments*/1,
615 /*maxsegz*/0x3ffff,
616 /*flags*/0, &sb->parent_dmat) != 0) {
617 device_printf(dev, "unable to create dma tag\n");
618 goto no;
619 }
620
479 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
480 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
481 /*highaddr*/BUS_SPACE_MAXADDR,
482 /*filter*/NULL, /*filterarg*/NULL,
483 /*maxsize*/DSP_BUFFSIZE, /*nsegments*/1,
484 /*maxsegz*/0x3ffff,
485 /*flags*/0, &sb->parent_dmat) != 0) {
486 device_printf(dev, "unable to create dma tag\n");
487 goto no;
488 }
489
621 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %d",
490 snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld",
622 rman_get_start(sb->io_base), rman_get_start(sb->irq),
491 rman_get_start(sb->io_base), rman_get_start(sb->irq),
623 sb->dma8);
624 if (sb->dma16 != sb->dma8) snprintf(status + strlen(status),
625 SND_STATUSLEN - strlen(status), ":%d", sb->dma16);
492 rman_get_start(sb->drq1));
493 if (sb->drq2) snprintf(status + strlen(status), SND_STATUSLEN - strlen(status),
494 ":%ld", rman_get_start(sb->drq2));
626
627 if (pcm_register(dev, sb, 1, 1)) goto no;
628 if (sb->bd_flags & BD_F_ESS) {
629 pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sb);
630 pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sb);
631 } else {
632 pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb);
633 pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb);
634 }
635 pcm_setstatus(dev, status);
636
637 return 0;
638
639no:
640 sb_release_resources(sb, dev);
641 return ENXIO;
642}
643
495
496 if (pcm_register(dev, sb, 1, 1)) goto no;
497 if (sb->bd_flags & BD_F_ESS) {
498 pcm_addchan(dev, PCMDIR_REC, &ess_chantemplate, sb);
499 pcm_addchan(dev, PCMDIR_PLAY, &ess_chantemplate, sb);
500 } else {
501 pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb);
502 pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb);
503 }
504 pcm_setstatus(dev, status);
505
506 return 0;
507
508no:
509 sb_release_resources(sb, dev);
510 return ENXIO;
511}
512
644static int
645sb_attach(device_t dev)
646{
647 struct sb_info *sb;
648 int flags = device_get_flags(dev);
649
650 if (flags & DV_F_DUAL_DMA) {
651 bus_set_resource(dev, SYS_RES_DRQ, 1,
652 flags & DV_F_DRQ_MASK, 1);
653 }
654 sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
655 if (!sb) return ENXIO;
656 bzero(sb, sizeof *sb);
657
658 /* XXX in probe should set io resource to right val instead of this */
659 sb->io_rid = 0;
660 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &sb->io_rid,
661 0, ~0, 16, RF_ACTIVE);
662 if (!sb->io_base) {
663 BVDDB(printf("sb_probe: no addr, trying (0x220, 0x240)\n"));
664 sb->io_rid = 0;
665 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
666 &sb->io_rid, 0x220, 0x22f,
667 16, RF_ACTIVE);
668 if (!sb->io_base) {
669 sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT,
670 &sb->io_rid, 0x240,
671 0x24f, 16, RF_ACTIVE);
672 }
673 }
674 if (!sb->io_base) return ENXIO;
675
676 return sb_doattach(dev, sb);
677}
678
679static device_method_t sb_methods[] = {
680 /* Device interface */
681 DEVMETHOD(device_probe, sb_probe),
682 DEVMETHOD(device_attach, sb_attach),
683
684 { 0, 0 }
685};
686
687static driver_t sb_driver = {
688 "pcm",
689 sb_methods,
690 sizeof(snddev_info),
691};
692
693DRIVER_MODULE(sb, isa, sb_driver, pcm_devclass, 0, 0);
694
695static void
696sb_intr(void *arg)
697{
698 struct sb_info *sb = (struct sb_info *)arg;
699 int reason = 3, c;
700
701 /*
702 * SB < 4.0 is half duplex and has only 1 bit for int source,
703 * so we fake it. SB 4.x (SB16) has the int source in a separate
704 * register.
705 * The Vibra16X has separate flags for 8 and 16 bit transfers, but
706 * I have no idea how to tell capture from playback interrupts...
707 */
708 if (sb->bd_flags & BD_F_SB16) {
709 c = sb_getmixer(sb, IRQ_STAT);
710 /* this tells us if the source is 8-bit or 16-bit dma. We
711 * have to check the io channel to map it to read or write...
712 */
713 reason = 0;
714 if (c & 1) { /* 8-bit dma */
715 if (sb->pch.fmt & AFMT_U8) reason |= 1;
716 if (sb->rch.fmt & AFMT_U8) reason |= 2;
717 }
718 if (c & 2) { /* 16-bit dma */
719 if (sb->pch.fmt & AFMT_S16_LE) reason |= 1;
720 if (sb->rch.fmt & AFMT_S16_LE) reason |= 2;
721 }
722 } else c = 1;
723#if 0
724 printf("sb_intr: reason=%d c=0x%x\n", reason, c);
725#endif
726 if ((reason & 1) && (sb->pch.buffer->dl > 0))
727 chn_intr(sb->pch.channel);
728 if ((reason & 2) && (sb->rch.buffer->dl > 0))
729 chn_intr(sb->rch.channel);
730 if (c & 1) sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */
731 if (c & 2) sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */
732}
733
734static void
735ess_intr(void *arg)
736{
737 struct sb_info *sb = (struct sb_info *)arg;
738 sb_rd(sb, DSP_DATA_AVAIL); /* int ack */
739#ifdef notyet
740 /*
741 * XXX
742 * for full-duplex mode:
743 * should read port 0x6 to identify where interrupt came from.
744 */
745#endif
746 /*
747 * We are transferring data in DSP normal mode,
748 * so clear the dl to indicate the DMA is stopped.
749 */
750 if (sb->pch.buffer->dl > 0) {
751 sb->pch.buffer->dl = -1;
752 chn_intr(sb->pch.channel);
753 }
754 if (sb->rch.buffer->dl > 0) {
755 sb->rch.buffer->dl = -1;
756 chn_intr(sb->rch.channel);
757 }
758}
759
760static int
761sb_format(struct sb_chinfo *ch, u_int32_t format)
762{
763 ch->fmt = format;
764 return 0;
765}
766
767static int
768sb_speed(struct sb_chinfo *ch, int speed)
769{
770 struct sb_info *sb = ch->parent;
771 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
772 int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
773
774 if (sb->bd_flags & BD_F_SB16) {
775 RANGE(speed, 5000, 45000);
776 sb_cmd(sb, 0x42 - play);
777 sb_cmd(sb, speed >> 8);
778 sb_cmd(sb, speed & 0xff);
779 } else {
780 u_char tconst;
781 int max_speed = 45000, tmp;
782 u_long flags;
783
784 /* here enforce speed limitations - max 22050 on sb 1.x*/
785 if (sb->bd_id <= 0x200) max_speed = 22050;
786
787 /*
788 * SB models earlier than SB Pro have low limit for the
789 * input rate. Note that this is only for input, but since
790 * we do not support separate values for rec & play....
791 */
792 if (!play) {
793 if (sb->bd_id <= 0x200) max_speed = 13000;
794 else if (sb->bd_id < 0x300) max_speed = 15000;
795 }
796 RANGE(speed, 4000, max_speed);
797 if (stereo) speed <<= 1;
798
799 /*
800 * Now the speed should be valid. Compute the value to be
801 * programmed into the board.
802 */
803 if (speed > 22050) { /* High speed mode on 2.01/3.xx */
804 tconst = (u_char)
805 ((65536 - ((256000000 + speed / 2) / speed))
806 >> 8);
807 sb->bd_flags |= BD_F_HISPEED;
808 tmp = 65536 - (tconst << 8);
809 speed = (256000000 + tmp / 2) / tmp;
810 } else {
811 sb->bd_flags &= ~BD_F_HISPEED;
812 tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
813 tmp = 256 - tconst;
814 speed = (1000000 + tmp / 2) / tmp;
815 }
816 flags = spltty();
817 sb_cmd1(sb, 0x40, tconst); /* set time constant */
818 splx(flags);
819 if (stereo) speed >>= 1;
820 }
821 return speed;
822}
823
824static int
825sb_start(struct sb_chinfo *ch)
826{
827 struct sb_info *sb = ch->parent;
828 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
829 int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0;
830 int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
831 int l = ch->buffer->dl;
513static void
514sb_intr(void *arg)
515{
516 struct sb_info *sb = (struct sb_info *)arg;
517 int reason = 3, c;
518
519 /*
520 * SB < 4.0 is half duplex and has only 1 bit for int source,
521 * so we fake it. SB 4.x (SB16) has the int source in a separate
522 * register.
523 * The Vibra16X has separate flags for 8 and 16 bit transfers, but
524 * I have no idea how to tell capture from playback interrupts...
525 */
526 if (sb->bd_flags & BD_F_SB16) {
527 c = sb_getmixer(sb, IRQ_STAT);
528 /* this tells us if the source is 8-bit or 16-bit dma. We
529 * have to check the io channel to map it to read or write...
530 */
531 reason = 0;
532 if (c & 1) { /* 8-bit dma */
533 if (sb->pch.fmt & AFMT_U8) reason |= 1;
534 if (sb->rch.fmt & AFMT_U8) reason |= 2;
535 }
536 if (c & 2) { /* 16-bit dma */
537 if (sb->pch.fmt & AFMT_S16_LE) reason |= 1;
538 if (sb->rch.fmt & AFMT_S16_LE) reason |= 2;
539 }
540 } else c = 1;
541#if 0
542 printf("sb_intr: reason=%d c=0x%x\n", reason, c);
543#endif
544 if ((reason & 1) && (sb->pch.buffer->dl > 0))
545 chn_intr(sb->pch.channel);
546 if ((reason & 2) && (sb->rch.buffer->dl > 0))
547 chn_intr(sb->rch.channel);
548 if (c & 1) sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */
549 if (c & 2) sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */
550}
551
552static void
553ess_intr(void *arg)
554{
555 struct sb_info *sb = (struct sb_info *)arg;
556 sb_rd(sb, DSP_DATA_AVAIL); /* int ack */
557#ifdef notyet
558 /*
559 * XXX
560 * for full-duplex mode:
561 * should read port 0x6 to identify where interrupt came from.
562 */
563#endif
564 /*
565 * We are transferring data in DSP normal mode,
566 * so clear the dl to indicate the DMA is stopped.
567 */
568 if (sb->pch.buffer->dl > 0) {
569 sb->pch.buffer->dl = -1;
570 chn_intr(sb->pch.channel);
571 }
572 if (sb->rch.buffer->dl > 0) {
573 sb->rch.buffer->dl = -1;
574 chn_intr(sb->rch.channel);
575 }
576}
577
578static int
579sb_format(struct sb_chinfo *ch, u_int32_t format)
580{
581 ch->fmt = format;
582 return 0;
583}
584
585static int
586sb_speed(struct sb_chinfo *ch, int speed)
587{
588 struct sb_info *sb = ch->parent;
589 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
590 int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
591
592 if (sb->bd_flags & BD_F_SB16) {
593 RANGE(speed, 5000, 45000);
594 sb_cmd(sb, 0x42 - play);
595 sb_cmd(sb, speed >> 8);
596 sb_cmd(sb, speed & 0xff);
597 } else {
598 u_char tconst;
599 int max_speed = 45000, tmp;
600 u_long flags;
601
602 /* here enforce speed limitations - max 22050 on sb 1.x*/
603 if (sb->bd_id <= 0x200) max_speed = 22050;
604
605 /*
606 * SB models earlier than SB Pro have low limit for the
607 * input rate. Note that this is only for input, but since
608 * we do not support separate values for rec & play....
609 */
610 if (!play) {
611 if (sb->bd_id <= 0x200) max_speed = 13000;
612 else if (sb->bd_id < 0x300) max_speed = 15000;
613 }
614 RANGE(speed, 4000, max_speed);
615 if (stereo) speed <<= 1;
616
617 /*
618 * Now the speed should be valid. Compute the value to be
619 * programmed into the board.
620 */
621 if (speed > 22050) { /* High speed mode on 2.01/3.xx */
622 tconst = (u_char)
623 ((65536 - ((256000000 + speed / 2) / speed))
624 >> 8);
625 sb->bd_flags |= BD_F_HISPEED;
626 tmp = 65536 - (tconst << 8);
627 speed = (256000000 + tmp / 2) / tmp;
628 } else {
629 sb->bd_flags &= ~BD_F_HISPEED;
630 tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
631 tmp = 256 - tconst;
632 speed = (1000000 + tmp / 2) / tmp;
633 }
634 flags = spltty();
635 sb_cmd1(sb, 0x40, tconst); /* set time constant */
636 splx(flags);
637 if (stereo) speed >>= 1;
638 }
639 return speed;
640}
641
642static int
643sb_start(struct sb_chinfo *ch)
644{
645 struct sb_info *sb = ch->parent;
646 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
647 int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0;
648 int stereo = (ch->fmt & AFMT_STEREO)? 1 : 0;
649 int l = ch->buffer->dl;
650 int dh = ch->buffer->chan > 3;
832 u_char i1, i2 = 0;
833
834 if (b16) l >>= 1;
835 l--;
836 if (play) sb_cmd(sb, DSP_CMD_SPKON);
837 if (sb->bd_flags & BD_F_SB16) {
838 i1 = DSP_F16_AUTO | DSP_F16_FIFO_ON |
839 (play? DSP_F16_DAC : DSP_F16_ADC);
651 u_char i1, i2 = 0;
652
653 if (b16) l >>= 1;
654 l--;
655 if (play) sb_cmd(sb, DSP_CMD_SPKON);
656 if (sb->bd_flags & BD_F_SB16) {
657 i1 = DSP_F16_AUTO | DSP_F16_FIFO_ON |
658 (play? DSP_F16_DAC : DSP_F16_ADC);
840 i1 |= (b16 && (sb->bd_flags & BD_F_DUPLEX))? DSP_DMA16 : DSP_DMA8;
659 i1 |= (b16 || dh)? DSP_DMA16 : DSP_DMA8;
841 i2 = (stereo? DSP_F16_STEREO : 0) | (b16? DSP_F16_SIGNED : 0);
842 sb_cmd(sb, i1);
843 sb_cmd2(sb, i2, l);
844 } else {
845 if (sb->bd_flags & BD_F_HISPEED) i1 = play? 0x90 : 0x98;
846 else i1 = play? 0x1c : 0x2c;
847 sb_setmixer(sb, 0x0e, stereo? 2 : 0);
848 /* an ESS extension -- they can do 16 bits */
849 if (b16) i1 |= 1;
850 sb_cmd2(sb, 0x48, l);
851 sb_cmd(sb, i1);
852 }
853 sb->bd_flags |= BD_F_DMARUN << b16;
854 return 0;
855}
856
857static int
858sb_stop(struct sb_chinfo *ch)
859{
860 struct sb_info *sb = ch->parent;
861 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
862 int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0;
863
864 if (sb->bd_flags & BD_F_HISPEED) sb_reset_dsp(sb);
865 else {
866 sb_cmd(sb, b16? DSP_CMD_DMAPAUSE_16 : DSP_CMD_DMAPAUSE_8);
867 /*
868 * The above seems to have the undocumented side effect of
869 * blocking the other side as well. If the other
870 * channel was active (SB16) I have to re-enable it :(
871 */
872 if (sb->bd_flags & (BD_F_DMARUN << (1 - b16)))
873 sb_cmd(sb, b16? 0xd4 : 0xd6 );
874 }
875 if (play) sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */
876 sb->bd_flags &= ~(BD_F_DMARUN << b16);
877 return 0;
878}
879
880/* utility functions for ESS */
881static int
882ess_format(struct sb_chinfo *ch, u_int32_t format)
883{
884 struct sb_info *sb = ch->parent;
885 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
886 int b16 = (format & AFMT_S16_LE)? 1 : 0;
887 int stereo = (format & AFMT_STEREO)? 1 : 0;
888 u_char c;
889 ch->fmt = format;
890 sb_reset_dsp(sb);
891 /* normal DMA mode */
892 ess_write(sb, 0xb8, play ? 0x00 : 0x0a);
893 /* mono/stereo */
894 c = (ess_read(sb, 0xa8) & ~0x03) | 1;
895 if (!stereo) c++;
896 ess_write(sb, 0xa8, c);
897 /* demand mode, 4 bytes/xfer */
898 ess_write(sb, 0xb9, 2);
899 /* setup dac/adc */
900 if (play) ess_write(sb, 0xb6, b16? 0x00 : 0x80);
901 ess_write(sb, 0xb7, 0x51 | (b16? 0x20 : 0x00));
902 ess_write(sb, 0xb7, 0x98 + (b16? 0x24 : 0x00) + (stereo? 0x00 : 0x38));
903 /* irq/drq control */
904 ess_write(sb, 0xb1, (ess_read(sb, 0xb1) & 0x0f) | 0x50);
905 ess_write(sb, 0xb2, (ess_read(sb, 0xb2) & 0x0f) | 0x50);
906 return 0;
907}
908
909static int
910ess_speed(struct sb_chinfo *ch, int speed)
911{
912 struct sb_info *sb = ch->parent;
913 int t;
914 RANGE (speed, 5000, 49000);
915 if (speed > 22000) {
916 t = (795500 + speed / 2) / speed;
917 speed = (795500 + t / 2) / t;
918 t = (256 - t ) | 0x80;
919 } else {
920 t = (397700 + speed / 2) / speed;
921 speed = (397700 + t / 2) / t;
922 t = 128 - t;
923 }
924 ess_write(sb, 0xa1, t); /* set time constant */
925#if 0
926 d->play_speed = d->rec_speed = speed;
927 speed = (speed * 9 ) / 20;
928#endif
929 t = 256 - 7160000 / ((speed * 9 / 20) * 82);
930 ess_write(sb, 0xa2, t);
931 return speed;
932}
933
934static int
935ess_start(struct sb_chinfo *ch)
936{
937 struct sb_info *sb = ch->parent;
938 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
939 short c = - ch->buffer->dl;
940 u_char c1;
941 /*
942 * clear bit 0 of register B8h
943 */
944#if 1
945 c1 = play ? 0x00 : 0x0a;
946 ess_write(sb, 0xb8, c1++);
947#else
948 c1 = ess_read(sb, 0xb8) & 0xfe;
949 ess_write(sb, 0xb8, c1++);
950#endif
951 /*
952 * update ESS Transfer Count Register
953 */
954 ess_write(sb, 0xa4, (u_char)((u_short)c & 0xff));
955 ess_write(sb, 0xa5, (u_char)(((u_short)c >> 8) & 0xff));
956 /*
957 * set bit 0 of register B8h
958 */
959 ess_write(sb, 0xb8, c1);
960 if (play)
961 sb_cmd(sb, DSP_CMD_SPKON);
962 return 0;
963}
964
965static int
966ess_stop(struct sb_chinfo *ch)
967{
968 struct sb_info *sb = ch->parent;
969 /*
970 * no need to send a stop command if the DMA has already stopped.
971 */
972 if (ch->buffer->dl > 0) {
973 sb_cmd(sb, DSP_CMD_DMAPAUSE_8); /* pause dma. */
974 }
975 return 0;
976}
977
978static int
979ess_abort(struct sb_chinfo *ch)
980{
981 struct sb_info *sb = ch->parent;
982 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
983 if (play) sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */
984 sb_reset_dsp(sb);
985 ess_format(ch, ch->fmt);
986 ess_speed(ch, ch->channel->speed);
987 return 0;
988}
989
990/* channel interface */
991static void *
992sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
993{
994 struct sb_info *sb = devinfo;
995 struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch;
996
997 ch->parent = sb;
998 ch->channel = c;
999 ch->buffer = b;
1000 ch->buffer->bufsize = DSP_BUFFSIZE;
1001 if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1) return NULL;
660 i2 = (stereo? DSP_F16_STEREO : 0) | (b16? DSP_F16_SIGNED : 0);
661 sb_cmd(sb, i1);
662 sb_cmd2(sb, i2, l);
663 } else {
664 if (sb->bd_flags & BD_F_HISPEED) i1 = play? 0x90 : 0x98;
665 else i1 = play? 0x1c : 0x2c;
666 sb_setmixer(sb, 0x0e, stereo? 2 : 0);
667 /* an ESS extension -- they can do 16 bits */
668 if (b16) i1 |= 1;
669 sb_cmd2(sb, 0x48, l);
670 sb_cmd(sb, i1);
671 }
672 sb->bd_flags |= BD_F_DMARUN << b16;
673 return 0;
674}
675
676static int
677sb_stop(struct sb_chinfo *ch)
678{
679 struct sb_info *sb = ch->parent;
680 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
681 int b16 = (ch->fmt & AFMT_S16_LE)? 1 : 0;
682
683 if (sb->bd_flags & BD_F_HISPEED) sb_reset_dsp(sb);
684 else {
685 sb_cmd(sb, b16? DSP_CMD_DMAPAUSE_16 : DSP_CMD_DMAPAUSE_8);
686 /*
687 * The above seems to have the undocumented side effect of
688 * blocking the other side as well. If the other
689 * channel was active (SB16) I have to re-enable it :(
690 */
691 if (sb->bd_flags & (BD_F_DMARUN << (1 - b16)))
692 sb_cmd(sb, b16? 0xd4 : 0xd6 );
693 }
694 if (play) sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */
695 sb->bd_flags &= ~(BD_F_DMARUN << b16);
696 return 0;
697}
698
699/* utility functions for ESS */
700static int
701ess_format(struct sb_chinfo *ch, u_int32_t format)
702{
703 struct sb_info *sb = ch->parent;
704 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
705 int b16 = (format & AFMT_S16_LE)? 1 : 0;
706 int stereo = (format & AFMT_STEREO)? 1 : 0;
707 u_char c;
708 ch->fmt = format;
709 sb_reset_dsp(sb);
710 /* normal DMA mode */
711 ess_write(sb, 0xb8, play ? 0x00 : 0x0a);
712 /* mono/stereo */
713 c = (ess_read(sb, 0xa8) & ~0x03) | 1;
714 if (!stereo) c++;
715 ess_write(sb, 0xa8, c);
716 /* demand mode, 4 bytes/xfer */
717 ess_write(sb, 0xb9, 2);
718 /* setup dac/adc */
719 if (play) ess_write(sb, 0xb6, b16? 0x00 : 0x80);
720 ess_write(sb, 0xb7, 0x51 | (b16? 0x20 : 0x00));
721 ess_write(sb, 0xb7, 0x98 + (b16? 0x24 : 0x00) + (stereo? 0x00 : 0x38));
722 /* irq/drq control */
723 ess_write(sb, 0xb1, (ess_read(sb, 0xb1) & 0x0f) | 0x50);
724 ess_write(sb, 0xb2, (ess_read(sb, 0xb2) & 0x0f) | 0x50);
725 return 0;
726}
727
728static int
729ess_speed(struct sb_chinfo *ch, int speed)
730{
731 struct sb_info *sb = ch->parent;
732 int t;
733 RANGE (speed, 5000, 49000);
734 if (speed > 22000) {
735 t = (795500 + speed / 2) / speed;
736 speed = (795500 + t / 2) / t;
737 t = (256 - t ) | 0x80;
738 } else {
739 t = (397700 + speed / 2) / speed;
740 speed = (397700 + t / 2) / t;
741 t = 128 - t;
742 }
743 ess_write(sb, 0xa1, t); /* set time constant */
744#if 0
745 d->play_speed = d->rec_speed = speed;
746 speed = (speed * 9 ) / 20;
747#endif
748 t = 256 - 7160000 / ((speed * 9 / 20) * 82);
749 ess_write(sb, 0xa2, t);
750 return speed;
751}
752
753static int
754ess_start(struct sb_chinfo *ch)
755{
756 struct sb_info *sb = ch->parent;
757 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
758 short c = - ch->buffer->dl;
759 u_char c1;
760 /*
761 * clear bit 0 of register B8h
762 */
763#if 1
764 c1 = play ? 0x00 : 0x0a;
765 ess_write(sb, 0xb8, c1++);
766#else
767 c1 = ess_read(sb, 0xb8) & 0xfe;
768 ess_write(sb, 0xb8, c1++);
769#endif
770 /*
771 * update ESS Transfer Count Register
772 */
773 ess_write(sb, 0xa4, (u_char)((u_short)c & 0xff));
774 ess_write(sb, 0xa5, (u_char)(((u_short)c >> 8) & 0xff));
775 /*
776 * set bit 0 of register B8h
777 */
778 ess_write(sb, 0xb8, c1);
779 if (play)
780 sb_cmd(sb, DSP_CMD_SPKON);
781 return 0;
782}
783
784static int
785ess_stop(struct sb_chinfo *ch)
786{
787 struct sb_info *sb = ch->parent;
788 /*
789 * no need to send a stop command if the DMA has already stopped.
790 */
791 if (ch->buffer->dl > 0) {
792 sb_cmd(sb, DSP_CMD_DMAPAUSE_8); /* pause dma. */
793 }
794 return 0;
795}
796
797static int
798ess_abort(struct sb_chinfo *ch)
799{
800 struct sb_info *sb = ch->parent;
801 int play = (ch->dir == PCMDIR_PLAY)? 1 : 0;
802 if (play) sb_cmd(sb, DSP_CMD_SPKOFF); /* speaker off */
803 sb_reset_dsp(sb);
804 ess_format(ch, ch->fmt);
805 ess_speed(ch, ch->channel->speed);
806 return 0;
807}
808
809/* channel interface */
810static void *
811sbchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
812{
813 struct sb_info *sb = devinfo;
814 struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch;
815
816 ch->parent = sb;
817 ch->channel = c;
818 ch->buffer = b;
819 ch->buffer->bufsize = DSP_BUFFSIZE;
820 if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1) return NULL;
1002 ch->buffer->chan = (dir == PCMDIR_PLAY)? sb->dma16 : sb->dma8;
821 ch->buffer->chan = (dir == PCMDIR_PLAY)? rman_get_start(sb->drq2)
822 : rman_get_start(sb->drq1);
1003 return ch;
1004}
1005
1006static int
1007sbchan_setdir(void *data, int dir)
1008{
1009 struct sb_chinfo *ch = data;
1010 ch->dir = dir;
1011 return 0;
1012}
1013
1014static int
1015sbchan_setformat(void *data, u_int32_t format)
1016{
1017 struct sb_chinfo *ch = data;
1018 sb_format(ch, format);
1019 return 0;
1020}
1021
1022static int
1023sbchan_setspeed(void *data, u_int32_t speed)
1024{
1025 struct sb_chinfo *ch = data;
1026 return sb_speed(ch, speed);
1027}
1028
1029static int
1030sbchan_setblocksize(void *data, u_int32_t blocksize)
1031{
1032 return blocksize;
1033}
1034
1035static int
1036sbchan_trigger(void *data, int go)
1037{
1038 struct sb_chinfo *ch = data;
1039 buf_isadma(ch->buffer, go);
1040 if (go == PCMTRIG_START) sb_start(ch); else sb_stop(ch);
1041 return 0;
1042}
1043
1044static int
1045sbchan_getptr(void *data)
1046{
1047 struct sb_chinfo *ch = data;
1048 return buf_isadmaptr(ch->buffer);
1049}
1050
1051static pcmchan_caps *
1052sbchan_getcaps(void *data)
1053{
1054 struct sb_chinfo *ch = data;
1055 int p = (ch->dir == PCMDIR_PLAY)? 1 : 0;
823 return ch;
824}
825
826static int
827sbchan_setdir(void *data, int dir)
828{
829 struct sb_chinfo *ch = data;
830 ch->dir = dir;
831 return 0;
832}
833
834static int
835sbchan_setformat(void *data, u_int32_t format)
836{
837 struct sb_chinfo *ch = data;
838 sb_format(ch, format);
839 return 0;
840}
841
842static int
843sbchan_setspeed(void *data, u_int32_t speed)
844{
845 struct sb_chinfo *ch = data;
846 return sb_speed(ch, speed);
847}
848
849static int
850sbchan_setblocksize(void *data, u_int32_t blocksize)
851{
852 return blocksize;
853}
854
855static int
856sbchan_trigger(void *data, int go)
857{
858 struct sb_chinfo *ch = data;
859 buf_isadma(ch->buffer, go);
860 if (go == PCMTRIG_START) sb_start(ch); else sb_stop(ch);
861 return 0;
862}
863
864static int
865sbchan_getptr(void *data)
866{
867 struct sb_chinfo *ch = data;
868 return buf_isadmaptr(ch->buffer);
869}
870
871static pcmchan_caps *
872sbchan_getcaps(void *data)
873{
874 struct sb_chinfo *ch = data;
875 int p = (ch->dir == PCMDIR_PLAY)? 1 : 0;
1056 if (ch->parent->bd_id <= 0x200)
876 if (ch->parent->bd_id < 0x300)
1057 return p? &sb_playcaps : &sb_reccaps;
877 return p? &sb_playcaps : &sb_reccaps;
1058 else if (ch->parent->bd_id >= 0x400)
1059 return p? &sb16_playcaps : &sb16_reccaps;
1060 else
878 else if (ch->parent->bd_id < 0x400)
1061 return p? &sbpro_playcaps : &sbpro_reccaps;
879 return p? &sbpro_playcaps : &sbpro_reccaps;
880 else if (ch->parent->bd_flags & BD_F_SB16X)
881 return &sb16x_caps;
882 else
883 return (ch->buffer->chan >= 4)? &sb16_hcaps : &sb16_lcaps;
1062}
1063/* channel interface for ESS18xx */
1064#ifdef notyet
1065static void *
1066esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
1067{
1068 /* the same as sbchan_init()? */
1069}
1070#endif
1071
1072static int
1073esschan_setdir(void *data, int dir)
1074{
1075 struct sb_chinfo *ch = data;
1076 ch->dir = dir;
1077 return 0;
1078}
1079
1080static int
1081esschan_setformat(void *data, u_int32_t format)
1082{
1083 struct sb_chinfo *ch = data;
1084 ess_format(ch, format);
1085 return 0;
1086}
1087
1088static int
1089esschan_setspeed(void *data, u_int32_t speed)
1090{
1091 struct sb_chinfo *ch = data;
1092 return ess_speed(ch, speed);
1093}
1094
1095static int
1096esschan_setblocksize(void *data, u_int32_t blocksize)
1097{
1098 return blocksize;
1099}
1100
1101static int
1102esschan_trigger(void *data, int go)
1103{
1104 struct sb_chinfo *ch = data;
1105 switch (go) {
1106 case PCMTRIG_START:
1107 if (!ch->ess_dma_started)
1108 buf_isadma(ch->buffer, go);
1109 ch->ess_dma_started = 1;
1110 ess_start(ch);
1111 break;
1112 case PCMTRIG_STOP:
1113 if (ch->buffer->dl >= 0) {
1114 buf_isadma(ch->buffer, go);
1115 ch->ess_dma_started = 0;
1116 ess_stop(ch);
1117 }
1118 break;
1119 case PCMTRIG_ABORT:
1120 default:
1121 ch->ess_dma_started = 0;
1122 ess_abort(ch);
1123 buf_isadma(ch->buffer, go);
1124 break;
1125 }
1126 return 0;
1127}
1128
1129static int
1130esschan_getptr(void *data)
1131{
1132 struct sb_chinfo *ch = data;
1133 return buf_isadmaptr(ch->buffer);
1134}
1135
1136static pcmchan_caps *
1137esschan_getcaps(void *data)
1138{
1139 struct sb_chinfo *ch = data;
1140 return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps;
1141}
1142
1143/************************************************************/
1144
1145static int
1146sbmix_init(snd_mixer *m)
1147{
1148 struct sb_info *sb = mix_getdevinfo(m);
1149
1150 switch (sb->bd_flags & BD_F_MIX_MASK) {
1151 case BD_F_MIX_CT1345: /* SB 3.0 has 1345 mixer */
1152 mix_setdevs(m, SBPRO_MIXER_DEVICES);
1153 mix_setrecdevs(m, SBPRO_RECORDING_DEVICES);
1154 sb_setmixer(sb, 0, 1); /* reset mixer */
1155 sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */
1156 sb_setmixer(sb, RECORD_SRC, 0x0); /* mic source */
1157 sb_setmixer(sb, FM_VOL, 0x0); /* no midi */
1158 break;
1159
1160 case BD_F_MIX_CT1745: /* SB16 mixer ... */
1161 mix_setdevs(m, SB16_MIXER_DEVICES);
1162 mix_setrecdevs(m, SB16_RECORDING_DEVICES);
1163 sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */
1164 sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */
1165 sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */
1166 }
1167 return 0;
1168}
1169
1170static int
1171sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right)
1172{
1173 struct sb_info *sb = mix_getdevinfo(m);
1174 int regoffs;
1175 u_char val;
1176 mixer_tab *iomap;
1177
1178 switch (sb->bd_flags & BD_F_MIX_MASK) {
1179 case BD_F_MIX_CT1345:
1180 if (sb->bd_flags & BD_F_ESS)
1181 iomap = &ess_mix;
1182 else
1183 iomap = &sbpro_mix;
1184 break;
1185
1186 case BD_F_MIX_CT1745:
1187 iomap = &sb16_mix;
1188 break;
1189
1190 default:
1191 return -1;
1192 /* XXX how about the SG NX Pro, iomap = sgnxpro_mix */
1193 }
1194
1195 /* Change left channel */
1196 regoffs = (*iomap)[dev][LEFT_CHN].regno;
1197 if (regoffs != 0) {
1198 val = sb_getmixer(sb, regoffs);
1199 change_bits(iomap, &val, dev, LEFT_CHN, left);
1200 sb_setmixer(sb, regoffs, val);
1201 }
1202
1203 /* Change right channel */
1204 regoffs = (*iomap)[dev][RIGHT_CHN].regno;
1205 if (regoffs != 0) {
1206 val = sb_getmixer(sb, regoffs); /* Read the new one */
1207 change_bits(iomap, &val, dev, RIGHT_CHN, right);
1208 sb_setmixer(sb, regoffs, val);
1209 } else
1210 right = left;
1211
1212 return left | (right << 8);
1213}
1214
1215static int
1216sbmix_setrecsrc(snd_mixer *m, u_int32_t src)
1217{
1218 struct sb_info *sb = mix_getdevinfo(m);
1219 u_char recdev;
1220
1221 switch (sb->bd_flags & BD_F_MIX_MASK) {
1222 case BD_F_MIX_CT1345:
1223 if (src == SOUND_MASK_LINE) recdev = 0x06;
1224 else if (src == SOUND_MASK_CD) recdev = 0x02;
1225 else { /* default: mic */
1226 src = SOUND_MASK_MIC;
1227 recdev = 0;
1228 }
1229 sb_setmixer(sb, RECORD_SRC, recdev |
1230 (sb_getmixer(sb, RECORD_SRC) & ~0x07));
1231 break;
1232
1233 case BD_F_MIX_CT1745: /* sb16 */
1234 recdev = 0;
1235 if (src & SOUND_MASK_MIC) recdev |= 0x01; /* mono mic */
1236 if (src & SOUND_MASK_CD) recdev |= 0x06; /* l+r cd */
1237 if (src & SOUND_MASK_LINE) recdev |= 0x18; /* l+r line */
1238 if (src & SOUND_MASK_SYNTH) recdev |= 0x60; /* l+r midi */
1239 sb_setmixer(sb, SB16_IMASK_L, recdev);
1240 sb_setmixer(sb, SB16_IMASK_R, recdev);
1241 /*
1242 * since the same volume controls apply to the input and
1243 * output sections, the best approach to have a consistent
1244 * behaviour among cards would be to disable the output path
1245 * on devices which are used to record.
1246 * However, since users like to have feedback, we only disable
1247 * the mic -- permanently.
1248 */
1249 sb_setmixer(sb, SB16_OMASK, 0x1f & ~1);
1250 break;
1251 }
1252 return src;
1253}
1254
1255static int
884}
885/* channel interface for ESS18xx */
886#ifdef notyet
887static void *
888esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
889{
890 /* the same as sbchan_init()? */
891}
892#endif
893
894static int
895esschan_setdir(void *data, int dir)
896{
897 struct sb_chinfo *ch = data;
898 ch->dir = dir;
899 return 0;
900}
901
902static int
903esschan_setformat(void *data, u_int32_t format)
904{
905 struct sb_chinfo *ch = data;
906 ess_format(ch, format);
907 return 0;
908}
909
910static int
911esschan_setspeed(void *data, u_int32_t speed)
912{
913 struct sb_chinfo *ch = data;
914 return ess_speed(ch, speed);
915}
916
917static int
918esschan_setblocksize(void *data, u_int32_t blocksize)
919{
920 return blocksize;
921}
922
923static int
924esschan_trigger(void *data, int go)
925{
926 struct sb_chinfo *ch = data;
927 switch (go) {
928 case PCMTRIG_START:
929 if (!ch->ess_dma_started)
930 buf_isadma(ch->buffer, go);
931 ch->ess_dma_started = 1;
932 ess_start(ch);
933 break;
934 case PCMTRIG_STOP:
935 if (ch->buffer->dl >= 0) {
936 buf_isadma(ch->buffer, go);
937 ch->ess_dma_started = 0;
938 ess_stop(ch);
939 }
940 break;
941 case PCMTRIG_ABORT:
942 default:
943 ch->ess_dma_started = 0;
944 ess_abort(ch);
945 buf_isadma(ch->buffer, go);
946 break;
947 }
948 return 0;
949}
950
951static int
952esschan_getptr(void *data)
953{
954 struct sb_chinfo *ch = data;
955 return buf_isadmaptr(ch->buffer);
956}
957
958static pcmchan_caps *
959esschan_getcaps(void *data)
960{
961 struct sb_chinfo *ch = data;
962 return (ch->dir == PCMDIR_PLAY)? &ess_playcaps : &ess_reccaps;
963}
964
965/************************************************************/
966
967static int
968sbmix_init(snd_mixer *m)
969{
970 struct sb_info *sb = mix_getdevinfo(m);
971
972 switch (sb->bd_flags & BD_F_MIX_MASK) {
973 case BD_F_MIX_CT1345: /* SB 3.0 has 1345 mixer */
974 mix_setdevs(m, SBPRO_MIXER_DEVICES);
975 mix_setrecdevs(m, SBPRO_RECORDING_DEVICES);
976 sb_setmixer(sb, 0, 1); /* reset mixer */
977 sb_setmixer(sb, MIC_VOL, 0x6); /* mic volume max */
978 sb_setmixer(sb, RECORD_SRC, 0x0); /* mic source */
979 sb_setmixer(sb, FM_VOL, 0x0); /* no midi */
980 break;
981
982 case BD_F_MIX_CT1745: /* SB16 mixer ... */
983 mix_setdevs(m, SB16_MIXER_DEVICES);
984 mix_setrecdevs(m, SB16_RECORDING_DEVICES);
985 sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */
986 sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */
987 sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */
988 }
989 return 0;
990}
991
992static int
993sbmix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right)
994{
995 struct sb_info *sb = mix_getdevinfo(m);
996 int regoffs;
997 u_char val;
998 mixer_tab *iomap;
999
1000 switch (sb->bd_flags & BD_F_MIX_MASK) {
1001 case BD_F_MIX_CT1345:
1002 if (sb->bd_flags & BD_F_ESS)
1003 iomap = &ess_mix;
1004 else
1005 iomap = &sbpro_mix;
1006 break;
1007
1008 case BD_F_MIX_CT1745:
1009 iomap = &sb16_mix;
1010 break;
1011
1012 default:
1013 return -1;
1014 /* XXX how about the SG NX Pro, iomap = sgnxpro_mix */
1015 }
1016
1017 /* Change left channel */
1018 regoffs = (*iomap)[dev][LEFT_CHN].regno;
1019 if (regoffs != 0) {
1020 val = sb_getmixer(sb, regoffs);
1021 change_bits(iomap, &val, dev, LEFT_CHN, left);
1022 sb_setmixer(sb, regoffs, val);
1023 }
1024
1025 /* Change right channel */
1026 regoffs = (*iomap)[dev][RIGHT_CHN].regno;
1027 if (regoffs != 0) {
1028 val = sb_getmixer(sb, regoffs); /* Read the new one */
1029 change_bits(iomap, &val, dev, RIGHT_CHN, right);
1030 sb_setmixer(sb, regoffs, val);
1031 } else
1032 right = left;
1033
1034 return left | (right << 8);
1035}
1036
1037static int
1038sbmix_setrecsrc(snd_mixer *m, u_int32_t src)
1039{
1040 struct sb_info *sb = mix_getdevinfo(m);
1041 u_char recdev;
1042
1043 switch (sb->bd_flags & BD_F_MIX_MASK) {
1044 case BD_F_MIX_CT1345:
1045 if (src == SOUND_MASK_LINE) recdev = 0x06;
1046 else if (src == SOUND_MASK_CD) recdev = 0x02;
1047 else { /* default: mic */
1048 src = SOUND_MASK_MIC;
1049 recdev = 0;
1050 }
1051 sb_setmixer(sb, RECORD_SRC, recdev |
1052 (sb_getmixer(sb, RECORD_SRC) & ~0x07));
1053 break;
1054
1055 case BD_F_MIX_CT1745: /* sb16 */
1056 recdev = 0;
1057 if (src & SOUND_MASK_MIC) recdev |= 0x01; /* mono mic */
1058 if (src & SOUND_MASK_CD) recdev |= 0x06; /* l+r cd */
1059 if (src & SOUND_MASK_LINE) recdev |= 0x18; /* l+r line */
1060 if (src & SOUND_MASK_SYNTH) recdev |= 0x60; /* l+r midi */
1061 sb_setmixer(sb, SB16_IMASK_L, recdev);
1062 sb_setmixer(sb, SB16_IMASK_R, recdev);
1063 /*
1064 * since the same volume controls apply to the input and
1065 * output sections, the best approach to have a consistent
1066 * behaviour among cards would be to disable the output path
1067 * on devices which are used to record.
1068 * However, since users like to have feedback, we only disable
1069 * the mic -- permanently.
1070 */
1071 sb_setmixer(sb, SB16_OMASK, 0x1f & ~1);
1072 break;
1073 }
1074 return src;
1075}
1076
1077static int
1256sbpnp_probe(device_t dev)
1257{
1258 char *s = NULL;
1259 u_int32_t logical_id = isa_get_logicalid(dev);
1260
1261 switch(logical_id) {
1262 case 0x01000000: /* @@@0001 */
1263 s = "Avance Asound 100";
1264 break;
1265
1266 case 0x01100000: /* @@@1001 */
1267 s = "Avance Asound 110";
1268 break;
1269
1270 case 0x01200000: /* @@@2001 */
1271 s = "Avance Logic ALS120";
1272 break;
1273
1274 case 0x68187316: /* ESS1868 */
1275 s = "ESS1868";
1276 break;
1277
1278 case 0x69187316: /* ESS1869 */
1279 case 0xacb0110e: /* Compaq's Presario 1621 ESS1869 */
1280 s = "ESS1869";
1281 break;
1282
1283 case 0x79187316: /* ESS1879 */
1284 s = "ESS1879";
1285 break;
1286
1287 case 0x88187316: /* ESS1888 */
1288 s = "ESS1888";
1289 break;
1290 }
1291 if (s) {
1292 device_set_desc(dev, s);
1293 return (0);
1294 }
1295 return ENXIO;
1296}
1297
1298static int
1299sbpnp_attach(device_t dev)
1300{
1301 struct sb_info *sb;
1302 u_int32_t vend_id = isa_get_vendorid(dev);
1303
1304 sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
1305 if (!sb) return ENXIO;
1306 bzero(sb, sizeof *sb);
1307
1308 switch(vend_id) {
1309 case 0xf0008c0e:
1310 case 0x10019305:
1311 case 0x20019305:
1312 /* XXX add here the vend_id for other vibra16X cards... */
1313 sb->bd_flags = BD_F_SB16X;
1314 }
1315 return sb_doattach(dev, sb);
1316}
1317
1318static device_method_t sbpnp_methods[] = {
1319 /* Device interface */
1320 DEVMETHOD(device_probe, sbpnp_probe),
1321 DEVMETHOD(device_attach, sbpnp_attach),
1322
1323 { 0, 0 }
1324};
1325
1326static driver_t sbpnp_driver = {
1327 "pcm",
1328 sbpnp_methods,
1329 sizeof(snddev_info),
1330};
1331
1332DRIVER_MODULE(sbpnp, isa, sbpnp_driver, pcm_devclass, 0, 0);
1333
1334#if NSBC > 0
1335#define DESCSTR " PCM Audio"
1336static int
1337sbsbc_probe(device_t dev)
1338{
1078sbsbc_probe(device_t dev)
1079{
1339 char *s = NULL;
1340 struct sndcard_func *func;
1080 char buf[64];
1081 u_int32_t func, ver, r;
1341
1342 /* The parent device has already been probed. */
1082
1083 /* The parent device has already been probed. */
1343
1344 func = device_get_ivars(dev);
1345 if (func == NULL || func->func != SCF_PCM)
1084 r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func);
1085 if (func != SCF_PCM)
1346 return (ENXIO);
1347
1086 return (ENXIO);
1087
1348 s = "SB PCM Audio";
1088 r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
1089 ver &= 0x0000ffff;
1090 snprintf(buf, sizeof buf, "SB DSP %d.%02d", ver >> 8, ver & 0xff);
1091 device_set_desc_copy(dev, buf);
1349
1092
1350 device_set_desc(dev, s);
1351 return 0;
1352}
1353
1354static int
1355sbsbc_attach(device_t dev)
1356{
1357 struct sb_info *sb;
1093 return 0;
1094}
1095
1096static int
1097sbsbc_attach(device_t dev)
1098{
1099 struct sb_info *sb;
1358 u_int32_t vend_id;
1359 device_t sbc;
1100 u_int32_t ver;
1360
1101
1361 sbc = device_get_parent(dev);
1362 vend_id = isa_get_vendorid(sbc);
1363 sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
1364 if (!sb) return ENXIO;
1365 bzero(sb, sizeof *sb);
1366
1102 sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
1103 if (!sb) return ENXIO;
1104 bzero(sb, sizeof *sb);
1105
1367 switch(vend_id) {
1368 case 0xf0008c0e:
1369 case 0x10019305:
1370 case 0x20019305:
1371 /* XXX add here the vend_id for other vibra16X cards... */
1372 sb->bd_flags = BD_F_SB16X;
1373 }
1106 BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
1107 sb->bd_id = ver & 0x0000ffff;
1108 sb->bd_flags = (ver & 0xffff0000) >> 16;
1109
1374 return sb_doattach(dev, sb);
1375}
1376
1377static device_method_t sbsbc_methods[] = {
1378 /* Device interface */
1379 DEVMETHOD(device_probe, sbsbc_probe),
1380 DEVMETHOD(device_attach, sbsbc_attach),
1381
1382 { 0, 0 }
1383};
1384
1385static driver_t sbsbc_driver = {
1386 "pcm",
1387 sbsbc_methods,
1388 sizeof(snddev_info),
1389};
1390
1391DRIVER_MODULE(sbsbc, sbc, sbsbc_driver, pcm_devclass, 0, 0);
1392
1110 return sb_doattach(dev, sb);
1111}
1112
1113static device_method_t sbsbc_methods[] = {
1114 /* Device interface */
1115 DEVMETHOD(device_probe, sbsbc_probe),
1116 DEVMETHOD(device_attach, sbsbc_attach),
1117
1118 { 0, 0 }
1119};
1120
1121static driver_t sbsbc_driver = {
1122 "pcm",
1123 sbsbc_methods,
1124 sizeof(snddev_info),
1125};
1126
1127DRIVER_MODULE(sbsbc, sbc, sbsbc_driver, pcm_devclass, 0, 0);
1128
1393#endif /* NSBC > 0 */
1129
1130