sb16.c revision 68414
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 68414 2000-11-07 00:38:59Z cg $
32 */
33
34#include <dev/sound/pcm/sound.h>
35
36#include  <dev/sound/isa/sb.h>
37#include  <dev/sound/chip.h>
38
39#define SB16_BUFFSIZE	4096
40#define PLAIN_SB16(x) ((((x)->bd_flags) & (BD_F_SB16|BD_F_SB16X)) == BD_F_SB16)
41
42/* channel interface */
43static void *sb16chan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir);
44static int sb16chan_setformat(void *data, u_int32_t format);
45static int sb16chan_setspeed(void *data, u_int32_t speed);
46static int sb16chan_setblocksize(void *data, u_int32_t blocksize);
47static int sb16chan_trigger(void *data, int go);
48static int sb16chan_getptr(void *data);
49static pcmchan_caps *sb16chan_getcaps(void *data);
50static int sb16chan_reset(void *data);
51static int sb16chan_resetdone(void *data);
52
53static u_int32_t sb16_fmt8[] = {
54	AFMT_U8,
55	AFMT_STEREO | AFMT_U8,
56	0
57};
58static pcmchan_caps sb16_caps8 = {5000, 45000, sb16_fmt8, 0};
59
60static u_int32_t sb16_fmt16[] = {
61	AFMT_S16_LE,
62	AFMT_STEREO | AFMT_S16_LE,
63	0
64};
65static pcmchan_caps sb16_caps16 = {5000, 45000, sb16_fmt16, 0};
66
67static u_int32_t sb16x_fmt[] = {
68	AFMT_U8,
69	AFMT_STEREO | AFMT_U8,
70	AFMT_S16_LE,
71	AFMT_STEREO | AFMT_S16_LE,
72	0
73};
74static pcmchan_caps sb16x_caps = {5000, 49000, sb16x_fmt, 0};
75
76static pcm_channel sb_chantemplate = {
77	sb16chan_init,
78	NULL,
79	sb16chan_setformat,
80	sb16chan_setspeed,
81	sb16chan_setblocksize,
82	sb16chan_trigger,
83	sb16chan_getptr,
84	sb16chan_getcaps,
85	NULL, 			/* free */
86	sb16chan_reset,		/* reset */
87	sb16chan_resetdone,	/* resetdone */
88	NULL, 			/* nop3 */
89	NULL, 			/* nop4 */
90	NULL, 			/* nop5 */
91	NULL, 			/* nop6 */
92	NULL, 			/* nop7 */
93};
94
95struct sb_info;
96
97struct sb_chinfo {
98	struct sb_info *parent;
99	pcm_channel *channel;
100	snd_dbuf *buffer;
101	int dir, run, dch;
102	u_int32_t fmt, spd, blksz;
103};
104
105struct sb_info {
106    	struct resource *io_base;	/* I/O address for the board */
107    	struct resource *irq;
108   	struct resource *drq1;
109    	struct resource *drq2;
110    	void *ih;
111    	bus_dma_tag_t parent_dmat;
112
113    	int bd_id;
114    	u_long bd_flags;       /* board-specific flags */
115	int dl, dh, prio, prio16;
116    	struct sb_chinfo pch, rch;
117};
118
119static int sb_rd(struct sb_info *sb, int reg);
120static void sb_wr(struct sb_info *sb, int reg, u_int8_t val);
121static int sb_dspready(struct sb_info *sb);
122static int sb_cmd(struct sb_info *sb, u_char val);
123/* static int sb_cmd1(struct sb_info *sb, u_char cmd, int val); */
124static int sb_cmd2(struct sb_info *sb, u_char cmd, int val);
125static u_int sb_get_byte(struct sb_info *sb);
126static void sb_setmixer(struct sb_info *sb, u_int port, u_int value);
127static int sb_getmixer(struct sb_info *sb, u_int port);
128static int sb_reset_dsp(struct sb_info *sb);
129
130static void sb_intr(void *arg);
131
132static int sb16mix_init(snd_mixer *m);
133static int sb16mix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right);
134static int sb16mix_setrecsrc(snd_mixer *m, u_int32_t src);
135
136static snd_mixer sb16_mixer = {
137    	"SoundBlaster 16 mixer",
138    	sb16mix_init,
139	NULL,
140	NULL,
141    	sb16mix_set,
142    	sb16mix_setrecsrc,
143};
144
145static devclass_t pcm_devclass;
146
147/*
148 * Common code for the midi and pcm functions
149 *
150 * sb_cmd write a single byte to the CMD port.
151 * sb_cmd1 write a CMD + 1 byte arg
152 * sb_cmd2 write a CMD + 2 byte arg
153 * sb_get_byte returns a single byte from the DSP data port
154 */
155
156static int
157port_rd(struct resource *port, int off)
158{
159	return bus_space_read_1(rman_get_bustag(port), rman_get_bushandle(port), off);
160}
161
162static void
163port_wr(struct resource *port, int off, u_int8_t data)
164{
165	return bus_space_write_1(rman_get_bustag(port), rman_get_bushandle(port), off, data);
166}
167
168static int
169sb_rd(struct sb_info *sb, int reg)
170{
171	return port_rd(sb->io_base, reg);
172}
173
174static void
175sb_wr(struct sb_info *sb, int reg, u_int8_t val)
176{
177	port_wr(sb->io_base, reg, val);
178}
179
180static int
181sb_dspready(struct sb_info *sb)
182{
183	return ((sb_rd(sb, SBDSP_STATUS) & 0x80) == 0);
184}
185
186static int
187sb_dspwr(struct sb_info *sb, u_char val)
188{
189    	int  i;
190
191    	for (i = 0; i < 1000; i++) {
192		if (sb_dspready(sb)) {
193	    		sb_wr(sb, SBDSP_CMD, val);
194	    		return 1;
195		}
196		if (i > 10) DELAY((i > 100)? 1000 : 10);
197    	}
198    	printf("sb_dspwr(0x%02x) timed out.\n", val);
199    	return 0;
200}
201
202static int
203sb_cmd(struct sb_info *sb, u_char val)
204{
205#if 0
206	printf("sb_cmd: %x\n", val);
207#endif
208    	return sb_dspwr(sb, val);
209}
210
211/*
212static int
213sb_cmd1(struct sb_info *sb, u_char cmd, int val)
214{
215#if 0
216    	printf("sb_cmd1: %x, %x\n", cmd, val);
217#endif
218    	if (sb_dspwr(sb, cmd)) {
219		return sb_dspwr(sb, val & 0xff);
220    	} else return 0;
221}
222*/
223
224static int
225sb_cmd2(struct sb_info *sb, u_char cmd, int val)
226{
227#if 0
228    	printf("sb_cmd2: %x, %x\n", cmd, val);
229#endif
230    	if (sb_dspwr(sb, cmd)) {
231		return sb_dspwr(sb, val & 0xff) &&
232		       sb_dspwr(sb, (val >> 8) & 0xff);
233    	} else return 0;
234}
235
236/*
237 * in the SB, there is a set of indirect "mixer" registers with
238 * address at offset 4, data at offset 5
239 */
240static void
241sb_setmixer(struct sb_info *sb, u_int port, u_int value)
242{
243    	u_long   flags;
244
245    	flags = spltty();
246    	sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
247    	DELAY(10);
248    	sb_wr(sb, SB_MIX_DATA, (u_char) (value & 0xff));
249    	DELAY(10);
250    	splx(flags);
251}
252
253static int
254sb_getmixer(struct sb_info *sb, u_int port)
255{
256    	int val;
257    	u_long flags;
258
259    	flags = spltty();
260    	sb_wr(sb, SB_MIX_ADDR, (u_char) (port & 0xff)); /* Select register */
261    	DELAY(10);
262    	val = sb_rd(sb, SB_MIX_DATA);
263    	DELAY(10);
264    	splx(flags);
265
266    	return val;
267}
268
269static u_int
270sb_get_byte(struct sb_info *sb)
271{
272    	int i;
273
274    	for (i = 1000; i > 0; i--) {
275		if (sb_rd(sb, DSP_DATA_AVAIL) & 0x80)
276			return sb_rd(sb, DSP_READ);
277		else
278			DELAY(20);
279    	}
280    	return 0xffff;
281}
282
283static int
284sb_reset_dsp(struct sb_info *sb)
285{
286    	sb_wr(sb, SBDSP_RST, 3);
287    	DELAY(100);
288    	sb_wr(sb, SBDSP_RST, 0);
289    	if (sb_get_byte(sb) != 0xAA) {
290        	DEB(printf("sb_reset_dsp 0x%lx failed\n",
291			   rman_get_start(d->io_base)));
292		return ENXIO;	/* Sorry */
293    	}
294    	return 0;
295}
296
297/************************************************************/
298
299struct sb16_mixent {
300	int reg;
301	int bits;
302	int ofs;
303	int stereo;
304};
305
306static const struct sb16_mixent sb16_mixtab[32] = {
307    	[SOUND_MIXER_VOLUME]	= { 0x30, 5, 3, 1 },
308    	[SOUND_MIXER_PCM]	= { 0x32, 5, 3, 1 },
309    	[SOUND_MIXER_SYNTH]	= { 0x34, 5, 3, 1 },
310    	[SOUND_MIXER_CD]	= { 0x36, 5, 3, 1 },
311    	[SOUND_MIXER_LINE]	= { 0x38, 5, 3, 1 },
312    	[SOUND_MIXER_MIC]	= { 0x3a, 5, 3, 0 },
313       	[SOUND_MIXER_SPEAKER]	= { 0x3b, 5, 3, 0 },
314    	[SOUND_MIXER_IGAIN]	= { 0x3f, 2, 6, 1 },
315    	[SOUND_MIXER_OGAIN]	= { 0x41, 2, 6, 1 },
316	[SOUND_MIXER_TREBLE]	= { 0x44, 4, 4, 1 },
317    	[SOUND_MIXER_BASS]	= { 0x46, 4, 4, 1 },
318};
319
320static int
321sb16mix_init(snd_mixer *m)
322{
323    	struct sb_info *sb = mix_getdevinfo(m);
324
325	mix_setdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER |
326     		       SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD |
327     		       SOUND_MASK_IGAIN | SOUND_MASK_OGAIN |
328     		       SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE);
329
330	mix_setrecdevs(m, SOUND_MASK_SYNTH | SOUND_MASK_LINE |
331			  SOUND_MASK_MIC | SOUND_MASK_CD);
332
333	sb_setmixer(sb, 0x3c, 0x1f); /* make all output active */
334
335	sb_setmixer(sb, 0x3d, 0); /* make all inputs-l off */
336	sb_setmixer(sb, 0x3e, 0); /* make all inputs-r off */
337
338	return 0;
339}
340
341static int
342sb16mix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right)
343{
344    	struct sb_info *sb = mix_getdevinfo(m);
345    	const struct sb16_mixent *e;
346    	int max;
347
348	e = &sb16_mixtab[dev];
349	max = (1 << e->bits) - 1;
350
351	left = (left * max) / 100;
352	right = (right * max) / 100;
353
354	sb_setmixer(sb, e->reg, left << e->ofs);
355	if (e->stereo)
356		sb_setmixer(sb, e->reg + 1, right << e->ofs);
357	else
358		right = left;
359
360	left = (left * 100) / max;
361	right = (right * 100) / max;
362
363    	return left | (right << 8);
364}
365
366static int
367sb16mix_setrecsrc(snd_mixer *m, u_int32_t src)
368{
369    	struct sb_info *sb = mix_getdevinfo(m);
370    	u_char recdev;
371
372	recdev = 0;
373	if (src & SOUND_MASK_MIC)
374		recdev |= 0x01; /* mono mic */
375
376	if (src & SOUND_MASK_CD)
377		recdev |= 0x06; /* l+r cd */
378
379	if (src & SOUND_MASK_LINE)
380		recdev |= 0x18; /* l+r line */
381
382	if (src & SOUND_MASK_SYNTH)
383		recdev |= 0x60; /* l+r midi */
384
385	sb_setmixer(sb, SB16_IMASK_L, recdev);
386	sb_setmixer(sb, SB16_IMASK_R, recdev);
387
388	/*
389	 * since the same volume controls apply to the input and
390	 * output sections, the best approach to have a consistent
391	 * behaviour among cards would be to disable the output path
392	 * on devices which are used to record.
393	 * However, since users like to have feedback, we only disable
394	 * the mic -- permanently.
395	 */
396        sb_setmixer(sb, SB16_OMASK, 0x1f & ~1);
397
398	return src;
399}
400
401/************************************************************/
402
403static void
404sb16_release_resources(struct sb_info *sb, device_t dev)
405{
406    	if (sb->irq) {
407    		if (sb->ih)
408			bus_teardown_intr(dev, sb->irq, sb->ih);
409 		bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq);
410		sb->irq = 0;
411    	}
412    	if (sb->drq1) {
413		bus_release_resource(dev, SYS_RES_DRQ, 0, sb->drq1);
414		sb->drq1 = 0;
415    	}
416    	if (sb->drq2) {
417		bus_release_resource(dev, SYS_RES_DRQ, 1, sb->drq2);
418		sb->drq2 = 0;
419    	}
420    	if (sb->io_base) {
421		bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base);
422		sb->io_base = 0;
423    	}
424    	if (sb->parent_dmat) {
425		bus_dma_tag_destroy(sb->parent_dmat);
426		sb->parent_dmat = 0;
427    	}
428     	free(sb, M_DEVBUF);
429}
430
431static int
432sb16_alloc_resources(struct sb_info *sb, device_t dev)
433{
434	int rid;
435
436	rid = 0;
437	if (!sb->io_base)
438    		sb->io_base = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE);
439
440	rid = 0;
441	if (!sb->irq)
442    		sb->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE);
443
444	rid = 0;
445	if (!sb->drq1)
446    		sb->drq1 = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 0, ~0, 1, RF_ACTIVE);
447
448	rid = 1;
449	if (!sb->drq2)
450        	sb->drq2 = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 0, ~0, 1, RF_ACTIVE);
451
452    	if (sb->io_base && sb->drq1 && sb->irq) {
453		int bs = SB16_BUFFSIZE;
454
455		isa_dma_acquire(rman_get_start(sb->drq1));
456		isa_dmainit(rman_get_start(sb->drq1), bs);
457
458		if (sb->drq2) {
459			isa_dma_acquire(rman_get_start(sb->drq2));
460			isa_dmainit(rman_get_start(sb->drq2), bs);
461		}
462		return 0;
463	} else return ENXIO;
464}
465
466static void
467sb_intr(void *arg)
468{
469    	struct sb_info *sb = (struct sb_info *)arg;
470    	int reason = 3, c;
471
472    	/*
473     	 * The Vibra16X has separate flags for 8 and 16 bit transfers, but
474     	 * I have no idea how to tell capture from playback interrupts...
475     	 */
476
477	reason = 0;
478    	c = sb_getmixer(sb, IRQ_STAT);
479
480	/*
481	 * this tells us if the source is 8-bit or 16-bit dma. We
482     	 * have to check the io channel to map it to read or write...
483     	 */
484
485	if (sb->bd_flags & BD_F_SB16X) {
486    		if (c & 1) { /* 8-bit format */
487			if (sb->pch.fmt & AFMT_8BIT)
488				reason |= 1;
489			if (sb->rch.fmt & AFMT_8BIT)
490				reason |= 2;
491    		}
492    		if (c & 2) { /* 16-bit format */
493			if (sb->pch.fmt & AFMT_16BIT)
494				reason |= 1;
495			if (sb->rch.fmt & AFMT_16BIT)
496				reason |= 2;
497    		}
498	} else {
499    		if (c & 1) { /* 8-bit dma */
500			if (sb->pch.dch == sb->dl)
501				reason |= 1;
502			if (sb->rch.dch == sb->dl)
503				reason |= 2;
504    		}
505    		if (c & 2) { /* 16-bit dma */
506			if (sb->pch.dch == sb->dh)
507				reason |= 1;
508			if (sb->rch.dch == sb->dh)
509				reason |= 2;
510    		}
511	}
512#if 0
513    	printf("sb_intr: reason=%d c=0x%x\n", reason, c);
514#endif
515    	if ((reason & 1) && (sb->pch.run))
516		chn_intr(sb->pch.channel);
517
518    	if ((reason & 2) && (sb->rch.run))
519		chn_intr(sb->rch.channel);
520
521    	if (c & 1)
522		sb_rd(sb, DSP_DATA_AVAIL); /* 8-bit int ack */
523
524    	if (c & 2)
525		sb_rd(sb, DSP_DATA_AVL16); /* 16-bit int ack */
526}
527
528static int
529sb_setup(struct sb_info *sb)
530{
531	struct sb_chinfo *ch;
532	u_int8_t v;
533	int l, pprio;
534
535	if (sb->bd_flags & BD_F_DMARUN)
536		buf_isadma(sb->pch.buffer, PCMTRIG_STOP);
537	if (sb->bd_flags & BD_F_DMARUN2)
538		buf_isadma(sb->rch.buffer, PCMTRIG_STOP);
539	sb->bd_flags &= ~(BD_F_DMARUN | BD_F_DMARUN2);
540
541	sb_reset_dsp(sb);
542
543	if (sb->bd_flags & BD_F_SB16X) {
544		pprio = sb->pch.run? 1 : 0;
545		sb->pch.buffer->chan = pprio? sb->dl : -1;
546		sb->rch.buffer->chan = pprio? sb->dh : sb->dl;
547	} else {
548		if (sb->pch.run && sb->rch.run) {
549			pprio = (sb->rch.fmt & AFMT_16BIT)? 0 : 1;
550			sb->pch.buffer->chan = pprio? sb->dh : sb->dl;
551			sb->rch.buffer->chan = pprio? sb->dl : sb->dh;
552		} else {
553			if (sb->pch.run) {
554				sb->pch.buffer->chan = (sb->pch.fmt & AFMT_16BIT)? sb->dh : sb->dl;
555				sb->rch.buffer->chan = (sb->pch.fmt & AFMT_16BIT)? sb->dl : sb->dh;
556			} else if (sb->rch.run) {
557				sb->pch.buffer->chan = (sb->rch.fmt & AFMT_16BIT)? sb->dl : sb->dh;
558				sb->rch.buffer->chan = (sb->rch.fmt & AFMT_16BIT)? sb->dh : sb->dl;
559			}
560		}
561	}
562
563	sb->pch.dch = sb->pch.buffer->chan;
564	sb->rch.dch = sb->rch.buffer->chan;
565
566	sb->pch.buffer->dir = ISADMA_WRITE;
567	sb->rch.buffer->dir = ISADMA_READ;
568
569	/*
570	printf("setup: [pch = %d, pfmt = %d, pgo = %d] [rch = %d, rfmt = %d, rgo = %d]\n",
571	       sb->pch.dch, sb->pch.fmt, sb->pch.run, sb->rch.dch, sb->rch.fmt, sb->rch.run);
572	*/
573
574	ch = &sb->pch;
575	if (ch->run) {
576		l = ch->blksz;
577		if (ch->fmt & AFMT_16BIT)
578			l >>= 1;
579		l--;
580
581		/* play speed */
582		RANGE(ch->spd, 5000, 45000);
583		sb_cmd(sb, DSP_CMD_OUT16);
584    		sb_cmd(sb, ch->spd >> 8);
585		sb_cmd(sb, ch->spd & 0xff);
586
587		/* play format, length */
588		v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_DAC;
589		v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8;
590		sb_cmd(sb, v);
591
592		v = (ch->fmt & AFMT_STEREO)? DSP_F16_STEREO : 0;
593		v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0;
594		sb_cmd2(sb, v, l);
595		buf_isadma(ch->buffer, PCMTRIG_START);
596		sb->bd_flags |= BD_F_DMARUN;
597	}
598
599	ch = &sb->rch;
600	if (ch->run) {
601		l = ch->blksz;
602		if (ch->fmt & AFMT_16BIT)
603			l >>= 1;
604		l--;
605
606		/* record speed */
607		RANGE(ch->spd, 5000, 45000);
608		sb_cmd(sb, DSP_CMD_IN16);
609    		sb_cmd(sb, ch->spd >> 8);
610		sb_cmd(sb, ch->spd & 0xff);
611
612		/* record format, length */
613		v = DSP_F16_AUTO | DSP_F16_FIFO_ON | DSP_F16_ADC;
614		v |= (ch->fmt & AFMT_16BIT)? DSP_DMA16 : DSP_DMA8;
615		sb_cmd(sb, v);
616
617		v = (ch->fmt & AFMT_STEREO)? DSP_F16_STEREO : 0;
618		v |= (ch->fmt & AFMT_SIGNED)? DSP_F16_SIGNED : 0;
619		sb_cmd2(sb, v, l);
620		buf_isadma(ch->buffer, PCMTRIG_START);
621		sb->bd_flags |= BD_F_DMARUN2;
622	}
623
624    	return 0;
625}
626
627/* channel interface */
628static void *
629sb16chan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir)
630{
631	struct sb_info *sb = devinfo;
632	struct sb_chinfo *ch = (dir == PCMDIR_PLAY)? &sb->pch : &sb->rch;
633
634	ch->parent = sb;
635	ch->channel = c;
636	ch->buffer = b;
637	ch->buffer->bufsize = SB16_BUFFSIZE;
638	ch->dir = dir;
639
640	if (chn_allocbuf(ch->buffer, sb->parent_dmat) == -1)
641		return NULL;
642
643	return ch;
644}
645
646static int
647sb16chan_setformat(void *data, u_int32_t format)
648{
649	struct sb_chinfo *ch = data;
650	struct sb_info *sb = ch->parent;
651
652	ch->fmt = format;
653	sb->prio = ch->dir;
654	sb->prio16 = (ch->fmt & AFMT_16BIT)? 1 : 0;
655
656	return 0;
657}
658
659static int
660sb16chan_setspeed(void *data, u_int32_t speed)
661{
662	struct sb_chinfo *ch = data;
663
664	ch->spd = speed;
665	return speed;
666}
667
668static int
669sb16chan_setblocksize(void *data, u_int32_t blocksize)
670{
671	struct sb_chinfo *ch = data;
672
673	ch->blksz = blocksize;
674	return blocksize;
675}
676
677static int
678sb16chan_trigger(void *data, int go)
679{
680	struct sb_chinfo *ch = data;
681	struct sb_info *sb = ch->parent;
682
683	if (go == PCMTRIG_EMLDMAWR || go == PCMTRIG_EMLDMARD)
684		return 0;
685
686	if (go == PCMTRIG_START)
687		ch->run = 1;
688	else
689		ch->run = 0;
690
691	sb_setup(sb);
692
693	return 0;
694}
695
696static int
697sb16chan_getptr(void *data)
698{
699	struct sb_chinfo *ch = data;
700
701	return buf_isadmaptr(ch->buffer);
702}
703
704static pcmchan_caps *
705sb16chan_getcaps(void *data)
706{
707	struct sb_chinfo *ch = data;
708	struct sb_info *sb = ch->parent;
709
710	if ((sb->prio == 0) || (sb->prio == ch->dir))
711		return &sb16x_caps;
712	else
713		return sb->prio16? &sb16_caps8 : &sb16_caps16;
714}
715
716static int
717sb16chan_reset(void *data)
718{
719/*
720	struct sb_chinfo *ch = data;
721	struct sb_info *sb = ch->parent;
722*/
723	return 0;
724}
725
726static int
727sb16chan_resetdone(void *data)
728{
729	struct sb_chinfo *ch = data;
730	struct sb_info *sb = ch->parent;
731
732	sb->prio = 0;
733
734	return 0;
735}
736
737/************************************************************/
738
739static int
740sb16_probe(device_t dev)
741{
742    	char buf[64];
743	uintptr_t func, ver, r, f;
744
745	/* The parent device has already been probed. */
746	r = BUS_READ_IVAR(device_get_parent(dev), dev, 0, &func);
747	if (func != SCF_PCM)
748		return (ENXIO);
749
750	r = BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
751	f = (ver & 0xffff0000) >> 16;
752	ver &= 0x0000ffff;
753	if (f & BD_F_SB16) {
754		snprintf(buf, sizeof buf, "SB16 DSP %d.%02d%s", (int) ver >> 8, (int) ver & 0xff,
755			 (f & BD_F_SB16X)? " (ViBRA16X)" : "");
756    		device_set_desc_copy(dev, buf);
757		return 0;
758	} else
759		return (ENXIO);
760}
761
762static int
763sb16_attach(device_t dev)
764{
765    	struct sb_info *sb;
766	uintptr_t ver;
767    	char status[SND_STATUSLEN];
768	int bs = SB16_BUFFSIZE;
769
770    	sb = (struct sb_info *)malloc(sizeof *sb, M_DEVBUF, M_NOWAIT);
771    	if (!sb)
772		return ENXIO;
773    	bzero(sb, sizeof *sb);
774
775	BUS_READ_IVAR(device_get_parent(dev), dev, 1, &ver);
776	sb->bd_id = ver & 0x0000ffff;
777	sb->bd_flags = (ver & 0xffff0000) >> 16;
778
779    	if (sb16_alloc_resources(sb, dev))
780		goto no;
781    	if (sb_reset_dsp(sb))
782		goto no;
783	if (mixer_init(dev, &sb16_mixer, sb))
784		goto no;
785	if (bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &sb->ih))
786		goto no;
787
788	if (!sb->drq2 || (sb->bd_flags & BD_F_SB16X))
789		pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX);
790
791	sb->dl = rman_get_start(sb->drq1);
792	sb->dh = sb->drq2? rman_get_start(sb->drq2) : sb->dl;
793	sb->prio = 0;
794
795    	if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0,
796			/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
797			/*highaddr*/BUS_SPACE_MAXADDR,
798			/*filter*/NULL, /*filterarg*/NULL,
799			/*maxsize*/bs, /*nsegments*/1,
800			/*maxsegz*/0x3ffff,
801			/*flags*/0, &sb->parent_dmat) != 0) {
802		device_printf(dev, "unable to create dma tag\n");
803		goto no;
804    	}
805
806    	snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld",
807    	     	rman_get_start(sb->io_base), rman_get_start(sb->irq),
808		rman_get_start(sb->drq1));
809    	if (sb->drq2)
810		snprintf(status + strlen(status), SND_STATUSLEN - strlen(status),
811			":%ld", rman_get_start(sb->drq2));
812
813    	if (pcm_register(dev, sb, 1, 1))
814		goto no;
815	pcm_addchan(dev, PCMDIR_REC, &sb_chantemplate, sb);
816	pcm_addchan(dev, PCMDIR_PLAY, &sb_chantemplate, sb);
817
818    	pcm_setstatus(dev, status);
819
820    	return 0;
821
822no:
823    	sb16_release_resources(sb, dev);
824    	return ENXIO;
825}
826
827static int
828sb16_detach(device_t dev)
829{
830	int r;
831	struct sb_info *sb;
832
833	r = pcm_unregister(dev);
834	if (r)
835		return r;
836
837	sb = pcm_getdevinfo(dev);
838    	sb16_release_resources(sb, dev);
839	return 0;
840}
841
842static device_method_t sb16_methods[] = {
843	/* Device interface */
844	DEVMETHOD(device_probe,		sb16_probe),
845	DEVMETHOD(device_attach,	sb16_attach),
846	DEVMETHOD(device_detach,	sb16_detach),
847
848	{ 0, 0 }
849};
850
851static driver_t sb16_driver = {
852	"pcm",
853	sb16_methods,
854	sizeof(snddev_info),
855};
856
857DRIVER_MODULE(snd_sb16, sbc, sb16_driver, pcm_devclass, 0, 0);
858MODULE_DEPEND(snd_sb16, snd_pcm, PCM_MINVER, PCM_PREFVER, PCM_MAXVER);
859MODULE_VERSION(snd_sb16, 1);
860
861
862
863
864