Home | History | Annotate | Line # | Download | only in dev
aucc.c revision 1.14
      1 /*	$NetBSD: aucc.c,v 1.14 1997/07/28 10:04:35 augustss Exp $	*/
      2 #undef AUDIO_DEBUG
      3 /*
      4  * Copyright (c) 1997 Stephan Thesing
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *      This product includes software developed by Stephan Thesing.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include "aucc.h"
     34 #if NAUCC > 0
     35 
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/errno.h>
     39 #include <sys/ioctl.h>
     40 #include <sys/device.h>
     41 #include <sys/proc.h>
     42 #include <machine/cpu.h>
     43 
     44 #include <sys/audioio.h>
     45 #include <dev/audio_if.h>
     46 #include <amiga/amiga/cc.h>
     47 #include <amiga/amiga/custom.h>
     48 #include <amiga/amiga/device.h>
     49 #include <amiga/dev/auccvar.h>
     50 
     51 
     52 #ifdef LEV6_DEFER
     53 #define AUCC_MAXINT 3
     54 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2)
     55 #else
     56 #define AUCC_MAXINT 4
     57 #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3)
     58 #endif
     59 /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */
     60 #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3)
     61 
     62 #ifdef AUDIO_DEBUG
     63 /*extern printf __P((const char *,...));*/
     64 int     auccdebug = 1;
     65 #define DPRINTF(x)      if (auccdebug) printf x
     66 #else
     67 #define DPRINTF(x)
     68 #endif
     69 
     70 #ifdef splaudio
     71 #undef splaudio
     72 #endif
     73 
     74 #define splaudio() spl4();
     75 
     76 /* clock frequency.. */
     77 extern int eclockfreq;
     78 
     79 
     80 /* hw audio ch */
     81 extern struct audio_channel channel[4];
     82 
     83 
     84 /*
     85  * Software state.
     86  */
     87 struct aucc_softc {
     88 	struct	device sc_dev;		/* base device */
     89 
     90 	int	sc_open;		/* single use device */
     91 	aucc_data_t sc_channel[4];	/* per channel freq, ... */
     92 	u_int	sc_encoding;		/* encoding AUDIO_ENCODING_.*/
     93 	int	sc_channels;		/* # of channels used */
     94 
     95 	int	sc_intrcnt;		/* interrupt count */
     96 	int	sc_channelmask;  	/* which channels are used ? */
     97 };
     98 
     99 /* interrupt interfaces */
    100 void aucc_inthdl __P((int));
    101 
    102 /* forward declarations */
    103 static int init_aucc __P((struct aucc_softc *));
    104 static u_int freqtoper  __P((u_int));
    105 static u_int pertofreq  __P((u_int));
    106 
    107 /* autoconfiguration driver */
    108 void	auccattach __P((struct device *, struct device *, void *));
    109 int	auccmatch __P((struct device *, struct cfdata *, void *));
    110 
    111 struct cfattach aucc_ca = {
    112 	sizeof(struct aucc_softc),
    113 	auccmatch,
    114 	auccattach
    115 };
    116 
    117 struct	cfdriver aucc_cd = {
    118 	NULL, "aucc", DV_DULL, NULL, 0
    119 };
    120 
    121 struct audio_device aucc_device = {
    122 	"Amiga-audio",
    123 	"x",
    124 	"aucc"
    125 };
    126 
    127 
    128 struct aucc_softc *aucc=NULL;
    129 
    130 
    131 unsigned char ulaw_to_lin[] = {
    132 	0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
    133 	0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
    134 	0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf,
    135 	0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf,
    136 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
    137 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
    138 	0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4,
    139 	0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
    140 	0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
    141 	0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
    142 	0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
    143 	0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
    144 	0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
    145 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    146 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    147 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
    148 	0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61,
    149 	0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41,
    150 	0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30,
    151 	0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20,
    152 	0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17,
    153 	0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
    154 	0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
    155 	0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
    156 	0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05,
    157 	0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
    158 	0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
    159 	0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
    160 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    161 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    162 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    163 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    164 };
    165 
    166 /*
    167  * Define our interface to the higher level audio driver.
    168  */
    169 int	aucc_open __P((dev_t, int));
    170 void	aucc_close __P((void *));
    171 int	aucc_set_out_sr __P((void *, u_long));
    172 int	aucc_query_encoding __P((void *, struct audio_encoding *));
    173 int	aucc_round_blocksize __P((void *, int));
    174 int	aucc_set_out_port __P((void *, int));
    175 int	aucc_get_out_port __P((void *));
    176 int	aucc_set_in_port __P((void *, int));
    177 int	aucc_get_in_port __P((void *));
    178 int	aucc_commit_settings __P((void *));
    179 int	aucc_start_output __P((void *, void *, int, void (*)(void *),
    180 				  void *));
    181 int	aucc_start_input __P((void *, void *, int, void (*)(void *),
    182 				 void *));
    183 int	aucc_halt_output __P((void *));
    184 int	aucc_halt_input __P((void *));
    185 int	aucc_cont_output __P((void *));
    186 int	aucc_cont_input __P((void *));
    187 int	aucc_getdev __P((void *, struct audio_device *));
    188 int	aucc_set_port __P((void *, mixer_ctrl_t *));
    189 int	aucc_get_port __P((void *, mixer_ctrl_t *));
    190 int	aucc_query_devinfo __P((void *, mixer_devinfo_t *));
    191 void	aucc_encode __P((int, int, int, u_char *, u_short **));
    192 int	aucc_set_params __P((void *, int, struct audio_params *,
    193 	    struct audio_params *));
    194 
    195 struct audio_hw_if sa_hw_if = {
    196 	aucc_open,
    197 	aucc_close,
    198 	NULL,
    199 	aucc_query_encoding,
    200 	aucc_set_params,
    201 	aucc_round_blocksize,
    202 	aucc_set_out_port,
    203 	aucc_get_out_port,
    204 	aucc_set_in_port,
    205 	aucc_get_in_port,
    206 	aucc_commit_settings,
    207 	NULL,
    208 	NULL,
    209 	aucc_start_output,
    210 	aucc_start_input,
    211 	aucc_halt_output,
    212 	aucc_halt_input,
    213 	aucc_cont_output,
    214 	aucc_cont_input,
    215 	NULL,
    216 	aucc_getdev,
    217 	NULL,
    218 	aucc_set_port,
    219 	aucc_get_port,
    220 	aucc_query_devinfo,
    221 	NULL,
    222 	NULL,
    223 	NULL,
    224 	0,
    225 	0
    226 };
    227 
    228 /* autoconfig routines */
    229 
    230 int
    231 auccmatch(pdp, cfp, aux)
    232 	struct device *pdp;
    233 	struct cfdata *cfp;
    234 	void *aux;
    235 {
    236 	if (matchname((char *)aux, "aucc") &&
    237 #ifdef DRACO
    238 	    !is_draco() &&
    239 #endif
    240 	    (cfp->cf_unit == 0))
    241 		return 1;
    242 
    243 	return 0;
    244 }
    245 
    246 /*
    247  * Audio chip found.
    248  */
    249 void
    250 auccattach(parent, self, args)
    251 	struct device *parent, *self;
    252 	void *args;
    253 {
    254 	register struct aucc_softc *sc = (struct aucc_softc *)self;
    255 	register int i;
    256 
    257 	printf("\n");
    258 
    259 	if((i=init_aucc(sc))) {
    260 		printf("audio: no chipmem\n");
    261 		return;
    262 	}
    263 
    264 	if (audio_hardware_attach(&sa_hw_if, sc) != 0)
    265 		printf("audio: could not attach to audio pseudo-device driver\n");
    266 	/* XXX: no way to return error, if init fails */
    267 }
    268 
    269 
    270 static int
    271 init_aucc(sc)
    272 	struct aucc_softc *sc;
    273 {
    274 	register int i, err=0;
    275 
    276 	/* init values per channel */
    277  	for (i=0;i<4;i++) {
    278 		sc->sc_channel[i].nd_freq=8000;
    279 		sc->sc_channel[i].nd_per=freqtoper(8000);
    280 		sc->sc_channel[i].nd_busy=0;
    281 		sc->sc_channel[i].nd_dma=alloc_chipmem(AUDIO_BUF_SIZE*2);
    282 		if (sc->sc_channel[i].nd_dma==NULL)
    283 			err=1;
    284 	 	sc->sc_channel[i].nd_dmalength=0;
    285 		sc->sc_channel[i].nd_volume=64;
    286 		sc->sc_channel[i].nd_intr=NULL;
    287 		sc->sc_channel[i].nd_intrdata=NULL;
    288 		sc->sc_channel[i].nd_doublebuf=0;
    289 		DPRINTF(("dma buffer for channel %d is %p\n", i,
    290 		    sc->sc_channel[i].nd_dma));
    291 
    292 	}
    293 
    294 	if (err) {
    295 		for(i=0;i<4;i++)
    296 			if (sc->sc_channel[i].nd_dma)
    297 				free_chipmem(sc->sc_channel[i].nd_dma);
    298 	}
    299 
    300 	sc->sc_channels=1;
    301 	sc->sc_channelmask=0xf;
    302 
    303 	/* clear interrupts and dma: */
    304 	custom.intena = AUCC_ALLINTF;
    305 	custom.dmacon = AUCC_ALLDMAF;;
    306 
    307 	sc->sc_encoding=AUDIO_ENCODING_ULAW;
    308 
    309 	return err;
    310 
    311 }
    312 
    313 int
    314 aucc_open(dev, flags)
    315 	dev_t dev;
    316 	int flags;
    317 {
    318 	register struct aucc_softc *sc;
    319 	int unit = AUDIOUNIT(dev);
    320 	register int i;
    321 
    322 	DPRINTF(("sa_open: unit %d\n",unit));
    323 
    324 	if (unit >= aucc_cd.cd_ndevs)
    325 		return (ENODEV);
    326 	if ((sc = aucc_cd.cd_devs[unit]) == NULL)
    327 		return (ENXIO);
    328 	if (sc->sc_open)
    329 		return (EBUSY);
    330 	sc->sc_open = 1;
    331 	for (i=0;i<AUCC_MAXINT;i++) {
    332 		sc->sc_channel[i].nd_intr=NULL;
    333 		sc->sc_channel[i].nd_intrdata=NULL;
    334 	}
    335 	aucc=sc;
    336 	sc->sc_channelmask=0xf;
    337 
    338 	DPRINTF(("saopen: ok -> sc=0x%p\n",sc));
    339 
    340 	return (0);
    341 }
    342 
    343 void
    344 aucc_close(addr)
    345 	void *addr;
    346 {
    347 	register struct aucc_softc *sc = addr;
    348 
    349 	DPRINTF(("sa_close: sc=0x%p\n", sc));
    350 	/*
    351 	 * halt i/o, clear open flag, and done.
    352 	 */
    353 	aucc_halt_output(sc);
    354 	sc->sc_open = 0;
    355 
    356 	DPRINTF(("sa_close: closed.\n"));
    357 }
    358 
    359 int
    360 aucc_set_out_sr(addr, sr)
    361 	void *addr;
    362 	u_long sr;
    363 {
    364 	struct aucc_softc *sc=addr;
    365 	u_long per;
    366 	register int i;
    367 
    368 	per=freqtoper(sr);
    369 	if (per>0xffff)
    370 		return EINVAL;
    371 	sr=pertofreq(per);
    372 
    373 	for (i=0;i<4;i++) {
    374 		sc->sc_channel[i].nd_freq=sr;
    375 		sc->sc_channel[i].nd_per=per;
    376 	}
    377 
    378 	return(0);
    379 }
    380 
    381 int
    382 aucc_query_encoding(addr, fp)
    383 	void *addr;
    384 	struct audio_encoding *fp;
    385 {
    386 	switch (fp->index) {
    387 	case 0:
    388 		strcpy(fp->name, AudioElinear);
    389 		fp->encoding = AUDIO_ENCODING_SLINEAR;
    390 		fp->precision = 8;
    391 		fp->flags = 0;
    392 		break;
    393 	case 1:
    394 		strcpy(fp->name, AudioEmulaw);
    395 		fp->encoding = AUDIO_ENCODING_ULAW;
    396 		fp->precision = 8;
    397 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    398 		break;
    399 
    400 	case 2:
    401 		strcpy(fp->name, AudioEulinear);
    402 		fp->encoding = AUDIO_ENCODING_ULINEAR;
    403 		fp->precision = 8;
    404 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    405 		break;
    406 
    407 	default:
    408 		return(EINVAL);
    409 		/*NOTREACHED*/
    410 	}
    411 	return(0);
    412 }
    413 
    414 int
    415 aucc_set_params(addr, mode, p, q)
    416 	void *addr;
    417 	int mode;
    418 	struct  audio_params *p, *q;
    419 {
    420 	struct aucc_softc *sc;
    421 
    422 	sc = addr;
    423 
    424 	/* if (mode == AUMODE_RECORD)
    425 		return 0 ENXIO*/;
    426 
    427 #ifdef AUCCDEBUG
    428 	printf("aucc_set_params(mode %x, enc %d, bits %d, chn %d, sr %ld)\n",
    429 	    mode, p->encoding, p->precision, p->channels, p->sample_rate);
    430 #endif
    431 
    432 	switch (p->encoding) {
    433 	case AUDIO_ENCODING_ULAW:
    434 	case AUDIO_ENCODING_SLINEAR:
    435 	case AUDIO_ENCODING_SLINEAR_BE:
    436 	case AUDIO_ENCODING_SLINEAR_LE:
    437 	case AUDIO_ENCODING_ULINEAR_BE:
    438 	case AUDIO_ENCODING_ULINEAR_LE:
    439 		break;
    440 
    441 	default:
    442 		return EINVAL;
    443 		/* NOTREADCHED */
    444 	}
    445 
    446 	if (p->precision != 8)
    447 		return EINVAL;
    448 
    449 	if ((p->channels<1) || (p->channels>4))
    450 		return(EINVAL);
    451 
    452 	sc->sc_channels = p->channels;
    453 	sc->sc_encoding = p->encoding;
    454 
    455 	q->encoding = p->encoding;
    456 	q->precision = p->precision;
    457 	q->channels = p->channels;
    458 	q->sample_rate = p->sample_rate;
    459 
    460 	return aucc_set_out_sr(addr, p->sample_rate);
    461 }
    462 
    463 int
    464 aucc_round_blocksize(addr, blk)
    465 	void *addr;
    466 	int blk;
    467 {
    468 
    469 
    470 	return blk>AUDIO_BUF_SIZE?AUDIO_BUF_SIZE:blk; /* round up to even size */
    471 }
    472 
    473 int
    474 aucc_set_out_port(addr, port) /* can set channels  */
    475 	void *addr;
    476 	int port;
    477 {
    478 	register struct aucc_softc *sc = addr;
    479 
    480 	/* port is mask for channels 0..3 */
    481 	if ((port<0)||(port>15))
    482 		return EINVAL;
    483 
    484 	sc->sc_channelmask=port;
    485 
    486 	return(0);
    487 }
    488 
    489 int
    490 aucc_get_out_port(addr)
    491 	void *addr;
    492 {
    493 	register struct aucc_softc *sc = addr;
    494 
    495 	return sc->sc_channelmask;
    496 }
    497 
    498 int
    499 aucc_set_in_port(addr, port)
    500 	void *addr;
    501 	int port;
    502 {
    503 	return(EINVAL); /* no input possible */
    504 
    505 }
    506 
    507 int
    508 aucc_get_in_port(addr)
    509 	void *addr;
    510 {
    511 	return(0);
    512 }
    513 
    514 int
    515 aucc_commit_settings(addr)
    516 	void *addr;
    517 {
    518 	register struct aucc_softc *sc = addr;
    519 	register int i;
    520 
    521 	DPRINTF(("sa_commit.\n"));
    522 
    523 	for (i=0;i<4;i++) {
    524 		custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    525 		custom.aud[i].per=sc->sc_channel[i].nd_per;
    526 	}
    527 
    528 	DPRINTF(("commit done\n"));
    529 
    530 	return(0);
    531 }
    532 
    533 static int masks[4] = {1,3,7,15}; /* masks for n first channels */
    534 static int masks2[4] = {1,2,4,8};
    535 
    536 int
    537 aucc_start_output(addr, p, cc, intr, arg)
    538 	void *addr;
    539 	void *p;
    540 	int cc;
    541 	void (*intr) __P((void *));
    542 	void *arg;
    543 {
    544 	struct aucc_softc *sc;
    545 	int mask;
    546 	int i,j,k;
    547 	u_short *dmap[4];
    548 	u_char *pp;
    549 
    550 
    551 	sc = addr;
    552 	mask = sc->sc_channelmask;
    553 
    554 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
    555 
    556 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
    557 
    558 	if (sc->sc_channels > 1)
    559 		mask &=masks[sc->sc_channels-1];
    560 		/* we use first sc_channels channels */
    561 	if (mask==0) /* active and used channels are disjoint */
    562 		return EINVAL;
    563 
    564 	for (i=0;i<4;i++) { /* channels available ? */
    565 		if ((masks2[i]&mask)&&(sc->sc_channel[i].nd_busy))
    566 			return EBUSY; /* channel is busy */
    567 		if (channel[i].isaudio==-1)
    568 			return EBUSY; /* system uses them */
    569 	}
    570 
    571 	/* enable interrupt on 1st channel */
    572 	for (i=j=0;i<AUCC_MAXINT;i++) {
    573 		if (masks2[i]&mask) {
    574 			DPRINTF(("first channel is %d\n",i));
    575 			j=i;
    576 			sc->sc_channel[i].nd_intr=intr;
    577 			sc->sc_channel[i].nd_intrdata=arg;
    578 			break;
    579 		}
    580 	}
    581 
    582 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
    583 		dmap[2], dmap[3], mask));
    584 
    585 	/* disable ints, dma for channels, until all parameters set */
    586 	/* XXX dont disable DMA! custom.dmacon=mask;*/
    587 	custom.intreq=mask<<INTB_AUD0;
    588 	custom.intena=mask<<INTB_AUD0;
    589 
    590 	/* copy data to dma buffer */
    591 
    592 
    593 	pp=(u_char *)p;
    594 
    595 	if (sc->sc_channels == 1) {
    596 		dmap[0] =
    597 		dmap[1] =
    598 		dmap[2] =
    599 		dmap[3] = sc->sc_channel[j].nd_dma;
    600 	} else {
    601 		for (k=0; k<4; k++) {
    602 			if (masks2[k+j]&mask)
    603 				dmap[k]=sc->sc_channel[k+j].nd_dma;
    604 		}
    605 	}
    606 
    607 	sc->sc_channel[j].nd_doublebuf ^= 1;
    608 	if (sc->sc_channel[j].nd_doublebuf) {
    609 		dmap[0] += AUDIO_BUF_SIZE/sizeof(u_short);
    610 		dmap[1] += AUDIO_BUF_SIZE/sizeof(u_short);
    611 		dmap[2] += AUDIO_BUF_SIZE/sizeof(u_short);
    612 		dmap[3] += AUDIO_BUF_SIZE/sizeof(u_short);
    613 	}
    614 
    615 	aucc_encode(sc->sc_encoding, sc->sc_channels, cc, pp, dmap);
    616 
    617 	/* dma buffers: we use same buffer 4 all channels */
    618 	/* write dma location and length */
    619 	for (i=k=0; i<4; i++) {
    620 		if (masks2[i] & mask) {
    621 			DPRINTF(("turning channel %d on\n",i));
    622 			/*  sc->sc_channel[i].nd_busy=1;*/
    623 			channel[i].isaudio=1;
    624 			channel[i].play_count=1;
    625 			channel[i].handler=NULL;
    626 			custom.aud[i].per=sc->sc_channel[i].nd_per;
    627 			custom.aud[i].vol=sc->sc_channel[i].nd_volume;
    628 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
    629 			custom.aud[i].len=cc/(sc->sc_channels*2);
    630 			sc->sc_channel[i].nd_mask=mask;
    631 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
    632 			    sc->sc_channel[i].nd_per,
    633 			    sc->sc_channel[i].nd_volume, cc>>1));
    634 
    635 		}
    636 	}
    637 
    638 	channel[j].handler=aucc_inthdl;
    639 
    640 	/* enable ints */
    641 	custom.intena=INTF_SETCLR|INTF_INTEN| (masks2[j]<<INTB_AUD0);
    642 
    643 	DPRINTF(("enabled ints: 0x%x\n",(masks2[j]<<INTB_AUD0)));
    644 
    645 	/* enable dma */
    646 	custom.dmacon=DMAF_SETCLR|DMAF_MASTER|mask;
    647 
    648 	DPRINTF(("enabled dma, mask=0x%x\n",mask));
    649 
    650 	return(0);
    651 }
    652 
    653 /* ARGSUSED */
    654 int
    655 aucc_start_input(addr, p, cc, intr, arg)
    656 	void *addr;
    657 	void *p;
    658 	int cc;
    659 	void (*intr) __P((void *));
    660 	void *arg;
    661 {
    662 
    663 	return ENXIO; /* no input */
    664 }
    665 
    666 int
    667 aucc_halt_output(addr)
    668 	void *addr;
    669 {
    670 	register struct aucc_softc *sc = addr;
    671 	register int i;
    672 
    673 	/* XXX only halt, if input is also halted ?? */
    674 	/* stop dma, etc */
    675 	custom.intena = AUCC_ALLINTF;
    676 	custom.dmacon = AUCC_ALLDMAF;
    677 	/* mark every busy unit idle */
    678 	for (i=0;i<4;i++) {
    679 		sc->sc_channel[i].nd_busy=sc->sc_channel[i].nd_mask=0;
    680 		channel[i].isaudio=0;
    681 		channel[i].play_count=0;
    682 	}
    683 
    684 	return(0);
    685 }
    686 
    687 int
    688 aucc_halt_input(addr)
    689 	void *addr;
    690 {
    691 	/* no input */
    692 
    693 	return ENXIO;
    694 }
    695 
    696 int
    697 aucc_cont_output(addr)
    698 	void *addr;
    699 {
    700 	DPRINTF(("aucc_cont_output: never called, what should it do?!\n"));
    701 	/* reenable DMA XXX */
    702 	return ENXIO;
    703 }
    704 
    705 int
    706 aucc_cont_input(addr)
    707 	void *addr;
    708 {
    709 	DPRINTF(("aucc_cont_input: never called, what should it do?!\n"));
    710 	return(0);
    711 }
    712 
    713 int
    714 aucc_getdev(addr, retp)
    715         void *addr;
    716         struct audio_device *retp;
    717 {
    718         *retp = aucc_device;
    719         return 0;
    720 }
    721 
    722 int
    723 aucc_set_port(addr, cp)
    724 	void *addr;
    725 	mixer_ctrl_t *cp;
    726 {
    727 	register struct aucc_softc *sc = addr;
    728 	register int i,j;
    729 
    730 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
    731 
    732 	switch (cp->type) {
    733 	case AUDIO_MIXER_SET:
    734 		if (cp->dev!=AUCC_CHANNELS)
    735 			return EINVAL;
    736 		i=cp->un.mask;
    737 		if ((i<1)||(i>15))
    738 			return EINVAL;
    739 		sc->sc_channelmask=i;
    740 		break;
    741 
    742 	case AUDIO_MIXER_VALUE:
    743 		i=cp->un.value.num_channels;
    744 		if ((i<1)||(i>4))
    745 			return EINVAL;
    746 
    747 #ifdef __XXXwhatsthat
    748 		if (cp->dev!=AUCC_VOLUME)
    749 			return EINVAL;
    750 #endif
    751 
    752 		/* set volume for channel 0..i-1 */
    753 		if (i>1)
    754 			for (j=0;j<i;j++)
    755 	 			sc->sc_channel[j].nd_volume =
    756 				    cp->un.value.level[j]>>2;
    757 		else if (sc->sc_channels > 1)
    758 			for (j=0; j<sc->sc_channels; j++)
    759 	 			sc->sc_channel[j].nd_volume =
    760 				    cp->un.value.level[0]>>2;
    761 		else
    762 			for (j=0; j<4; j++)
    763 	 			sc->sc_channel[j].nd_volume =
    764 				    cp->un.value.level[0]>>2;
    765 		break;
    766 
    767 	default:
    768 		return EINVAL;
    769 		break;
    770 	}
    771 	return 0;
    772 }
    773 
    774 
    775 int
    776 aucc_get_port(addr, cp)
    777 	void *addr;
    778 	mixer_ctrl_t *cp;
    779 {
    780 	register struct aucc_softc *sc = addr;
    781 	register int i,j;
    782 
    783 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
    784 
    785 	switch (cp->type) {
    786 	case AUDIO_MIXER_SET:
    787 		if (cp->dev!=AUCC_CHANNELS)
    788 			return EINVAL;
    789 		cp->un.mask=sc->sc_channelmask;
    790 		break;
    791 
    792 	case AUDIO_MIXER_VALUE:
    793 		i = cp->un.value.num_channels;
    794 		if ((i<1)||(i>4))
    795 			return EINVAL;
    796 
    797 		for (j=0;j<i;j++)
    798 			cp->un.value.level[j] =
    799 			    (sc->sc_channel[j].nd_volume<<2) +
    800 			    (sc->sc_channel[j].nd_volume>>4);
    801 		break;
    802 
    803 	default:
    804 		return EINVAL;
    805 	}
    806 	return 0;
    807 }
    808 
    809 
    810 int
    811 aucc_query_devinfo(addr, dip)
    812 	void *addr;
    813 	register mixer_devinfo_t *dip;
    814 {
    815 	register int i;
    816 
    817 	switch(dip->index) {
    818 	case AUCC_CHANNELS:
    819 		dip->type = AUDIO_MIXER_SET;
    820 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    821 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    822                 strcpy(dip->label.name, AudioNspeaker);
    823 		for (i=0;i<16;i++) {
    824 			sprintf(dip->un.s.member[i].label.name,
    825 			    "channelmask%d", i);
    826 			dip->un.s.member[i].mask = i;
    827 		}
    828 		dip->un.s.num_mem = 16;
    829 		break;
    830 
    831 	case AUCC_VOLUME:
    832 		dip->type = AUDIO_MIXER_VALUE;
    833 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    834 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    835 		strcpy(dip->label.name, AudioNspeaker);
    836 		dip->un.v.num_channels = 4;
    837 		strcpy(dip->un.v.units.name, AudioNvolume);
    838 		break;
    839 
    840 	case AUCC_OUTPUT_CLASS:
    841 		dip->type = AUDIO_MIXER_CLASS;
    842 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    843 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    844 		strcpy(dip->label.name, AudioCOutputs);
    845 		break;
    846 	default:
    847 		return ENXIO;
    848 		/*NOTREACHED*/
    849 	}
    850 
    851 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    852 
    853 	return(0);
    854 }
    855 
    856 
    857 /* audio int handler */
    858 void
    859 aucc_inthdl(int ch)
    860 {
    861 	register int i;
    862 	register int mask=aucc->sc_channel[ch].nd_mask;
    863 
    864 	/* for all channels in this maskgroup:
    865 	   disable dma, int
    866 	   mark idle */
    867 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n",ch,mask));
    868 
    869 	custom.intreq=mask<<INTB_AUD0; /* clear request */
    870 	/* XXX: maybe we can leave ints and/or DMA on, if another sample has to be played?*/
    871 	custom.intena=mask<<INTB_AUD0;
    872 	/*
    873 	 * XXX custom.dmacon=mask; NO!!!
    874 	 */
    875 	for (i=0;i<4;i++) {
    876 		if (masks2[i]&&mask) {
    877 			DPRINTF(("marking channel %d idle\n",i));
    878 			aucc->sc_channel[i].nd_busy=0;
    879 			aucc->sc_channel[i].nd_mask=0;
    880 			channel[i].isaudio=channel[i].play_count=0;
    881 		}
    882 	}
    883 
    884 	/* call handler */
    885 	if (aucc->sc_channel[ch].nd_intr) {
    886 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
    887 		(*(aucc->sc_channel[ch].nd_intr))(aucc->sc_channel[ch].nd_intrdata);
    888 	}
    889 	else DPRINTF(("zero int handler\n"));
    890 	DPRINTF(("ints done\n"));
    891 }
    892 
    893 
    894 
    895 
    896 /* transform frequency to period, adjust bounds */
    897 static u_int
    898 freqtoper(u_int freq)
    899 {
    900 	u_int per=eclockfreq*5/freq;
    901 
    902 	if (per<124)
    903 		per=124; /* must have at least 124 ticks between samples */
    904 
    905 	return per;
    906 }
    907 
    908 /* transform period to frequency */
    909 static u_int
    910 pertofreq(u_int per)
    911 {
    912 	u_int freq=eclockfreq*5/per;
    913 
    914 
    915 	return freq;
    916 }
    917 
    918 
    919 
    920 void
    921 aucc_encode(enc, channels, i, p, dmap)
    922 	int enc, channels, i;
    923 	u_char *p;
    924 	u_short **dmap;
    925 {
    926 	char *q, *r, *s, *t;
    927 	int off;
    928 	u_char *tab;
    929 
    930 #ifdef AUCCDEBUG
    931 	static int debctl = 6;
    932 #endif
    933 
    934 	off = 0;
    935 	tab = NULL;
    936 
    937 #ifdef AUCCDEBUG
    938 	if (--debctl >= 0)
    939 		printf("Enc: enc %d, chan %d, dmap %p %p %p %p\n",
    940 		    enc, channels, dmap[0], dmap[1], dmap[2], dmap[3]);
    941 #endif
    942 
    943 	switch (enc) {
    944 	case AUDIO_ENCODING_ULAW:
    945 		tab=ulaw_to_lin;
    946 		break;
    947 	case AUDIO_ENCODING_ULINEAR_BE:
    948 	case AUDIO_ENCODING_ULINEAR_LE:
    949 		off=-128;
    950 		break;
    951 	case AUDIO_ENCODING_SLINEAR_BE:
    952 	case AUDIO_ENCODING_SLINEAR_LE:
    953 		break;
    954 	default:
    955 		return;
    956 	}
    957 
    958 	q = (char *)dmap[0];
    959 	r = (char *)dmap[1];
    960 	s = (char *)dmap[2];
    961 	t = (char *)dmap[3];
    962 
    963 	if (tab)
    964 		while (i) {
    965 			switch (channels) {
    966 			case 4: *t++ = tab[*p++];
    967 			case 3: *s++ = tab[*p++];
    968 			case 2: *r++ = tab[*p++];
    969 			case 1: *q++ = tab[*p++];
    970 			}
    971 			i -= channels;
    972 		}
    973 	else
    974 		while (i) {
    975 			switch (channels) {
    976 			case 4: *t++ = *p++ + off;
    977 			case 3: *s++ = *p++ + off;
    978 			case 2: *r++ = *p++ + off;
    979 			case 1: *q++ = *p++ + off;
    980 			}
    981 			i -= channels;
    982 		}
    983 
    984 }
    985 
    986 #endif /* NAUCC > 0 */
    987