Home | History | Annotate | Line # | Download | only in dev
aucc.c revision 1.44
      1  1.44     isaki /*	$NetBSD: aucc.c,v 1.44 2019/03/16 12:09:56 isaki Exp $ */
      2  1.20  augustss 
      3   1.1        is /*
      4  1.24        is  * Copyright (c) 1999 Bernardo Innocenti
      5  1.24        is  * All rights reserved.
      6  1.24        is  *
      7   1.1        is  * Copyright (c) 1997 Stephan Thesing
      8   1.1        is  * All rights reserved.
      9   1.1        is  *
     10   1.1        is  * Redistribution and use in source and binary forms, with or without
     11   1.1        is  * modification, are permitted provided that the following conditions
     12   1.1        is  * are met:
     13   1.1        is  * 1. Redistributions of source code must retain the above copyright
     14   1.1        is  *    notice, this list of conditions and the following disclaimer.
     15   1.1        is  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1        is  *    notice, this list of conditions and the following disclaimer in the
     17   1.1        is  *    documentation and/or other materials provided with the distribution.
     18   1.1        is  * 3. All advertising materials mentioning features or use of this software
     19   1.1        is  *    must display the following acknowledgement:
     20   1.1        is  *      This product includes software developed by Stephan Thesing.
     21   1.1        is  * 4. The name of the author may not be used to endorse or promote products
     22   1.1        is  *    derived from this software without specific prior written permission
     23   1.1        is  *
     24   1.1        is  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     25   1.1        is  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     26   1.1        is  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     27   1.1        is  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     28   1.1        is  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     29   1.1        is  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     30   1.1        is  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     31   1.1        is  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     32   1.1        is  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     33   1.1        is  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     34   1.1        is  */
     35   1.1        is 
     36  1.24        is /* TODO:
     37  1.24        is  *
     38  1.33       wiz  * - mu-law -> 14bit conversion
     39  1.24        is  * - channel allocation is wrong for 14bit mono
     40  1.24        is  * - convert the... err... conversion routines to 68k asm for best performance
     41  1.29   aymeric  * 	XXX: NO. aucc audio is limited by chipmem speed, anyway. You dont
     42  1.24        is  *	want to make life difficult for amigappc work.
     43  1.24        is  *		-is
     44  1.24        is  *
     45  1.33       wiz  * - rely on auconv.c routines for mu-law/A-law conversions
     46  1.24        is  * - perhaps use a calibration table for better 14bit output
     47  1.40     lukem  * - set 31 kHz AGA video mode to allow 44.1 kHz even if grfcc is missing
     48  1.24        is  *	in the kernel
     49  1.24        is  * - 14bit output requires maximum volume
     50  1.24        is  */
     51  1.24        is 
     52   1.1        is #include "aucc.h"
     53   1.1        is #if NAUCC > 0
     54  1.30   aymeric 
     55  1.30   aymeric #include <sys/cdefs.h>
     56  1.44     isaki __KERNEL_RCSID(0, "$NetBSD: aucc.c,v 1.44 2019/03/16 12:09:56 isaki Exp $");
     57   1.5        is 
     58   1.1        is #include <sys/param.h>
     59   1.1        is #include <sys/systm.h>
     60   1.1        is #include <sys/errno.h>
     61   1.1        is #include <sys/ioctl.h>
     62   1.1        is #include <sys/device.h>
     63   1.1        is #include <sys/proc.h>
     64   1.1        is #include <machine/cpu.h>
     65   1.1        is 
     66   1.1        is #include <sys/audioio.h>
     67   1.1        is #include <dev/audio_if.h>
     68   1.1        is #include <amiga/amiga/cc.h>
     69   1.1        is #include <amiga/amiga/custom.h>
     70   1.1        is #include <amiga/amiga/device.h>
     71   1.1        is #include <amiga/dev/auccvar.h>
     72  1.27        is 
     73  1.27        is #include "opt_lev6_defer.h"
     74   1.1        is 
     75   1.7        is 
     76   1.7        is #ifdef LEV6_DEFER
     77   1.7        is #define AUCC_MAXINT 3
     78   1.7        is #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2)
     79   1.7        is #else
     80   1.7        is #define AUCC_MAXINT 4
     81   1.7        is #define AUCC_ALLINTF (INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3)
     82   1.7        is #endif
     83   1.7        is /* this unconditionally; we may use AUD3 as slave channel with LEV6_DEFER */
     84   1.7        is #define AUCC_ALLDMAF (DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3)
     85   1.7        is 
     86   1.1        is #ifdef AUDIO_DEBUG
     87  1.29   aymeric /*extern printf(const char *,...);*/
     88   1.1        is int     auccdebug = 1;
     89   1.1        is #define DPRINTF(x)      if (auccdebug) printf x
     90   1.1        is #else
     91   1.1        is #define DPRINTF(x)
     92   1.1        is #endif
     93   1.1        is 
     94   1.1        is /* clock frequency.. */
     95  1.29   aymeric extern int eclockfreq;
     96   1.1        is 
     97   1.1        is 
     98   1.1        is /* hw audio ch */
     99   1.1        is extern struct audio_channel channel[4];
    100   1.1        is 
    101   1.1        is 
    102   1.1        is /*
    103   1.1        is  * Software state.
    104   1.1        is  */
    105   1.1        is struct aucc_softc {
    106   1.1        is 	int	sc_open;		/* single use device */
    107   1.1        is 	aucc_data_t sc_channel[4];	/* per channel freq, ... */
    108   1.1        is 	u_int	sc_encoding;		/* encoding AUDIO_ENCODING_.*/
    109   1.1        is 	int	sc_channels;		/* # of channels used */
    110  1.24        is 	int	sc_precision;		/* 8 or 16 bits */
    111  1.24        is 	int	sc_14bit;		/* 14bit output enabled */
    112   1.1        is 
    113   1.1        is 	int	sc_intrcnt;		/* interrupt count */
    114  1.37      kent 	int	sc_channelmask;		/* which channels are used ? */
    115  1.29   aymeric 	void (*sc_decodefunc)(u_char **, u_char *, int);
    116  1.24        is 				/* pointer to format conversion routine */
    117  1.41  jmcneill 
    118  1.41  jmcneill 	kmutex_t sc_lock;
    119  1.41  jmcneill 	kmutex_t sc_intr_lock;
    120   1.1        is };
    121   1.1        is 
    122   1.1        is /* interrupt interfaces */
    123  1.29   aymeric void aucc_inthdl(int);
    124   1.1        is 
    125   1.1        is /* forward declarations */
    126  1.29   aymeric static int init_aucc(struct aucc_softc *);
    127  1.29   aymeric static u_int freqtoper(u_int);
    128  1.29   aymeric static u_int pertofreq(u_int);
    129   1.1        is 
    130   1.1        is /* autoconfiguration driver */
    131  1.42       chs void	auccattach(device_t, device_t, void *);
    132  1.42       chs int	auccmatch(device_t, cfdata_t, void *);
    133   1.1        is 
    134  1.42       chs CFATTACH_DECL_NEW(aucc, sizeof(struct aucc_softc),
    135  1.32   thorpej     auccmatch, auccattach, NULL, NULL);
    136   1.1        is 
    137   1.1        is struct audio_device aucc_device = {
    138   1.1        is 	"Amiga-audio",
    139  1.24        is 	"2.0",
    140   1.1        is 	"aucc"
    141   1.1        is };
    142   1.1        is 
    143   1.1        is 
    144  1.37      kent struct aucc_softc *aucc = NULL;
    145   1.1        is 
    146   1.1        is 
    147  1.33       wiz unsigned char mulaw_to_lin[] = {
    148   1.2        is 	0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
    149   1.2        is 	0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
    150   1.2        is 	0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf,
    151   1.2        is 	0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf,
    152   1.2        is 	0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
    153   1.2        is 	0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
    154   1.2        is 	0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf3, 0xf3, 0xf4,
    155   1.2        is 	0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8,
    156   1.2        is 	0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
    157   1.2        is 	0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
    158   1.2        is 	0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
    159   1.2        is 	0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
    160   1.2        is 	0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
    161   1.2        is 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    162   1.2        is 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    163   1.2        is 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
    164   1.2        is 	0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61,
    165   1.2        is 	0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41,
    166   1.2        is 	0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30,
    167   1.2        is 	0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20,
    168   1.2        is 	0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17,
    169   1.2        is 	0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
    170   1.2        is 	0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b,
    171   1.2        is 	0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07,
    172   1.2        is 	0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05,
    173   1.2        is 	0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
    174   1.2        is 	0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
    175   1.2        is 	0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
    176   1.2        is 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    177   1.2        is 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    178   1.2        is 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    179   1.2        is 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    180   1.1        is };
    181   1.1        is 
    182   1.1        is /*
    183   1.1        is  * Define our interface to the higher level audio driver.
    184   1.1        is  */
    185  1.29   aymeric int	aucc_open(void *, int);
    186  1.29   aymeric void	aucc_close(void *);
    187  1.36      kent int	aucc_set_out_sr(void *, u_int);
    188  1.29   aymeric int	aucc_query_encoding(void *, struct audio_encoding *);
    189  1.36      kent int	aucc_round_blocksize(void *, int, int, const audio_params_t *);
    190  1.29   aymeric int	aucc_commit_settings(void *);
    191  1.29   aymeric int	aucc_start_output(void *, void *, int, void (*)(void *), void *);
    192  1.29   aymeric int	aucc_start_input(void *, void *, int, void (*)(void *), void *);
    193  1.29   aymeric int	aucc_halt_output(void *);
    194  1.29   aymeric int	aucc_halt_input(void *);
    195  1.29   aymeric int	aucc_getdev(void *, struct audio_device *);
    196  1.29   aymeric int	aucc_set_port(void *, mixer_ctrl_t *);
    197  1.29   aymeric int	aucc_get_port(void *, mixer_ctrl_t *);
    198  1.29   aymeric int	aucc_query_devinfo(void *, mixer_devinfo_t *);
    199  1.29   aymeric void	aucc_encode(int, int, int, int, u_char *, u_short **);
    200  1.36      kent int	aucc_set_params(void *, int, int, audio_params_t *, audio_params_t *,
    201  1.36      kent 			stream_filter_list_t *, stream_filter_list_t *);
    202  1.29   aymeric int	aucc_get_props(void *);
    203  1.41  jmcneill void	aucc_get_locks(void *, kmutex_t **, kmutex_t **);
    204  1.29   aymeric 
    205  1.29   aymeric 
    206  1.29   aymeric static void aucc_decode_slinear8_1ch(u_char **, u_char *, int);
    207  1.29   aymeric static void aucc_decode_slinear8_2ch(u_char **, u_char *, int);
    208  1.29   aymeric static void aucc_decode_slinear8_3ch(u_char **, u_char *, int);
    209  1.29   aymeric static void aucc_decode_slinear8_4ch(u_char **, u_char *, int);
    210  1.29   aymeric 
    211  1.29   aymeric static void aucc_decode_ulinear8_1ch(u_char **, u_char *, int);
    212  1.29   aymeric static void aucc_decode_ulinear8_2ch(u_char **, u_char *, int);
    213  1.29   aymeric static void aucc_decode_ulinear8_3ch(u_char **, u_char *, int);
    214  1.29   aymeric static void aucc_decode_ulinear8_4ch(u_char **, u_char *, int);
    215  1.29   aymeric 
    216  1.33       wiz static void aucc_decode_mulaw_1ch(u_char **, u_char *, int);
    217  1.33       wiz static void aucc_decode_mulaw_2ch(u_char **, u_char *, int);
    218  1.33       wiz static void aucc_decode_mulaw_3ch(u_char **, u_char *, int);
    219  1.33       wiz static void aucc_decode_mulaw_4ch(u_char **, u_char *, int);
    220  1.29   aymeric 
    221  1.29   aymeric static void aucc_decode_slinear16_1ch(u_char **, u_char *, int);
    222  1.29   aymeric static void aucc_decode_slinear16_2ch(u_char **, u_char *, int);
    223  1.29   aymeric static void aucc_decode_slinear16_3ch(u_char **, u_char *, int);
    224  1.29   aymeric static void aucc_decode_slinear16_4ch(u_char **, u_char *, int);
    225  1.29   aymeric 
    226  1.29   aymeric static void aucc_decode_slinear16sw_1ch(u_char **, u_char *, int);
    227  1.29   aymeric static void aucc_decode_slinear16sw_2ch(u_char **, u_char *, int);
    228  1.29   aymeric static void aucc_decode_slinear16sw_3ch(u_char **, u_char *, int);
    229  1.29   aymeric static void aucc_decode_slinear16sw_4ch(u_char **, u_char *, int);
    230  1.24        is 
    231  1.24        is 
    232  1.24        is 
    233  1.35      yamt const struct audio_hw_if sa_hw_if = {
    234  1.44     isaki 	.open			= aucc_open,
    235  1.44     isaki 	.close			= aucc_close,
    236  1.44     isaki 	.query_encoding		= aucc_query_encoding,
    237  1.44     isaki 	.set_params		= aucc_set_params,
    238  1.44     isaki 	.round_blocksize	= aucc_round_blocksize,
    239  1.44     isaki 	.commit_settings	= aucc_commit_settings,
    240  1.44     isaki 	.start_output		= aucc_start_output,
    241  1.44     isaki 	.start_input		= aucc_start_input,
    242  1.44     isaki 	.halt_output		= aucc_halt_output,
    243  1.44     isaki 	.halt_input		= aucc_halt_input,
    244  1.44     isaki 	.getdev			= aucc_getdev,
    245  1.44     isaki 	.set_port		= aucc_set_port,
    246  1.44     isaki 	.get_port		= aucc_get_port,
    247  1.44     isaki 	.query_devinfo		= aucc_query_devinfo,
    248  1.44     isaki 	.get_props		= aucc_get_props,
    249  1.44     isaki 	.get_locks		= aucc_get_locks,
    250   1.1        is };
    251   1.1        is 
    252   1.1        is /* autoconfig routines */
    253   1.1        is 
    254   1.1        is int
    255  1.42       chs auccmatch(device_t parent, cfdata_t cf, void *aux)
    256   1.1        is {
    257  1.25    kleink 	static int aucc_matched = 0;
    258  1.25    kleink 
    259  1.25    kleink 	if (!matchname((char *)aux, "aucc") ||
    260   1.1        is #ifdef DRACO
    261  1.25    kleink 	    is_draco() ||
    262   1.1        is #endif
    263  1.25    kleink 	    aucc_matched)
    264  1.25    kleink 		return 0;
    265   1.1        is 
    266  1.25    kleink 	aucc_matched = 1;
    267  1.25    kleink 	return 1;
    268   1.1        is }
    269   1.1        is 
    270   1.1        is /*
    271   1.1        is  * Audio chip found.
    272   1.1        is  */
    273   1.1        is void
    274  1.42       chs auccattach(device_t parent, device_t self, void *args)
    275   1.1        is {
    276  1.37      kent 	struct aucc_softc *sc;
    277  1.37      kent 	int i;
    278   1.1        is 
    279  1.42       chs 	sc = device_private(self);
    280   1.1        is 	printf("\n");
    281   1.1        is 
    282  1.37      kent 	if ((i=init_aucc(sc))) {
    283   1.1        is 		printf("audio: no chipmem\n");
    284   1.1        is 		return;
    285   1.1        is 	}
    286   1.1        is 
    287  1.42       chs 	audio_attach_mi(&sa_hw_if, sc, self);
    288   1.1        is }
    289   1.1        is 
    290   1.1        is 
    291   1.1        is static int
    292  1.29   aymeric init_aucc(struct aucc_softc *sc)
    293   1.1        is {
    294  1.37      kent 	int i, err;
    295   1.1        is 
    296  1.37      kent 	err = 0;
    297   1.1        is 	/* init values per channel */
    298  1.37      kent 	for (i = 0; i < 4; i++) {
    299  1.37      kent 		sc->sc_channel[i].nd_freq = 8000;
    300  1.37      kent 		sc->sc_channel[i].nd_per = freqtoper(8000);
    301  1.37      kent 		sc->sc_channel[i].nd_busy = 0;
    302  1.37      kent 		sc->sc_channel[i].nd_dma = alloc_chipmem(AUDIO_BUF_SIZE*2);
    303  1.37      kent 		if (sc->sc_channel[i].nd_dma == NULL)
    304  1.37      kent 			err = 1;
    305  1.37      kent 		sc->sc_channel[i].nd_dmalength = 0;
    306  1.37      kent 		sc->sc_channel[i].nd_volume = 64;
    307  1.37      kent 		sc->sc_channel[i].nd_intr = NULL;
    308  1.37      kent 		sc->sc_channel[i].nd_intrdata = NULL;
    309  1.37      kent 		sc->sc_channel[i].nd_doublebuf = 0;
    310  1.34       wiz 		DPRINTF(("DMA buffer for channel %d is %p\n", i,
    311   1.1        is 		    sc->sc_channel[i].nd_dma));
    312   1.1        is 	}
    313   1.1        is 
    314   1.1        is 	if (err) {
    315  1.37      kent 		for (i = 0; i < 4; i++)
    316   1.1        is 			if (sc->sc_channel[i].nd_dma)
    317   1.1        is 				free_chipmem(sc->sc_channel[i].nd_dma);
    318   1.1        is 	}
    319   1.1        is 
    320  1.37      kent 	sc->sc_channels = 1;
    321  1.37      kent 	sc->sc_channelmask = 0xf;
    322  1.37      kent 	sc->sc_precision = 8;
    323  1.24        is 	sc->sc_14bit = 0;
    324  1.37      kent 	sc->sc_encoding = AUDIO_ENCODING_ULAW;
    325  1.33       wiz 	sc->sc_decodefunc = aucc_decode_mulaw_1ch;
    326   1.1        is 
    327  1.34       wiz 	/* clear interrupts and DMA: */
    328   1.7        is 	custom.intena = AUCC_ALLINTF;
    329  1.24        is 	custom.dmacon = AUCC_ALLDMAF;
    330   1.1        is 
    331  1.41  jmcneill 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    332  1.41  jmcneill 	mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
    333  1.41  jmcneill 
    334   1.1        is 	return err;
    335   1.1        is }
    336   1.1        is 
    337   1.1        is int
    338  1.29   aymeric aucc_open(void *addr, int flags)
    339   1.1        is {
    340  1.37      kent 	struct aucc_softc *sc;
    341  1.16  augustss 	int i;
    342   1.1        is 
    343  1.37      kent 	sc = addr;
    344  1.16  augustss 	DPRINTF(("sa_open: unit %p\n",sc));
    345   1.1        is 
    346   1.1        is 	if (sc->sc_open)
    347  1.37      kent 		return EBUSY;
    348   1.1        is 	sc->sc_open = 1;
    349  1.37      kent 	for (i = 0; i < AUCC_MAXINT; i++) {
    350  1.37      kent 		sc->sc_channel[i].nd_intr = NULL;
    351  1.37      kent 		sc->sc_channel[i].nd_intrdata = NULL;
    352   1.1        is 	}
    353  1.37      kent 	aucc = sc;
    354  1.37      kent 	sc->sc_channelmask = 0xf;
    355   1.1        is 
    356  1.38  christos 	DPRINTF(("saopen: ok -> sc=%p\n",sc));
    357   1.1        is 
    358  1.37      kent 	return 0;
    359   1.1        is }
    360   1.1        is 
    361   1.1        is void
    362  1.29   aymeric aucc_close(void *addr)
    363   1.1        is {
    364  1.37      kent 	struct aucc_softc *sc;
    365   1.1        is 
    366  1.37      kent 	sc = addr;
    367  1.38  christos 	DPRINTF(("sa_close: sc=%p\n", sc));
    368   1.1        is 	/*
    369   1.1        is 	 * halt i/o, clear open flag, and done.
    370   1.1        is 	 */
    371   1.1        is 	aucc_halt_output(sc);
    372   1.1        is 	sc->sc_open = 0;
    373   1.1        is 
    374   1.1        is 	DPRINTF(("sa_close: closed.\n"));
    375   1.1        is }
    376   1.1        is 
    377   1.1        is int
    378  1.36      kent aucc_set_out_sr(void *addr, u_int sr)
    379   1.1        is {
    380  1.37      kent 	struct aucc_softc *sc;
    381   1.1        is 	u_long per;
    382  1.37      kent 	int i;
    383   1.1        is 
    384  1.37      kent 	sc = addr;
    385  1.37      kent 	per = freqtoper(sr);
    386  1.37      kent 	if (per > 0xffff)
    387   1.1        is 		return EINVAL;
    388  1.37      kent 	sr = pertofreq(per);
    389   1.1        is 
    390  1.37      kent 	for (i = 0; i < 4; i++) {
    391  1.37      kent 		sc->sc_channel[i].nd_freq = sr;
    392  1.37      kent 		sc->sc_channel[i].nd_per = per;
    393   1.1        is 	}
    394   1.1        is 
    395  1.37      kent 	return 0;
    396   1.1        is }
    397   1.1        is 
    398   1.1        is int
    399  1.29   aymeric aucc_query_encoding(void *addr, struct audio_encoding *fp)
    400   1.1        is {
    401  1.37      kent 
    402  1.24        is 	switch (fp->index) {
    403  1.37      kent 	case 0:
    404  1.37      kent 		strcpy(fp->name, AudioEslinear);
    405  1.37      kent 		fp->encoding = AUDIO_ENCODING_SLINEAR;
    406  1.37      kent 		fp->precision = 8;
    407  1.37      kent 		fp->flags = 0;
    408  1.37      kent 		break;
    409  1.37      kent 	case 1:
    410  1.37      kent 		strcpy(fp->name, AudioEmulaw);
    411  1.37      kent 		fp->encoding = AUDIO_ENCODING_ULAW;
    412  1.37      kent 		fp->precision = 8;
    413  1.37      kent 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    414  1.37      kent 		break;
    415  1.29   aymeric 
    416  1.37      kent 	case 2:
    417  1.37      kent 		strcpy(fp->name, AudioEulinear);
    418  1.37      kent 		fp->encoding = AUDIO_ENCODING_ULINEAR;
    419  1.37      kent 		fp->precision = 8;
    420  1.37      kent 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    421  1.37      kent 		break;
    422  1.24        is 
    423  1.37      kent 	case 3:
    424  1.37      kent 		strcpy(fp->name, AudioEslinear);
    425  1.37      kent 		fp->encoding = AUDIO_ENCODING_SLINEAR;
    426  1.37      kent 		fp->precision = 16;
    427  1.37      kent 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    428  1.37      kent 		break;
    429  1.24        is 
    430  1.37      kent 	case 4:
    431  1.37      kent 		strcpy(fp->name, AudioEslinear_be);
    432  1.37      kent 		fp->encoding = AUDIO_ENCODING_SLINEAR_BE;
    433  1.37      kent 		fp->precision = 16;
    434  1.37      kent 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    435  1.37      kent 		break;
    436  1.24        is 
    437  1.37      kent 	case 5:
    438  1.37      kent 		strcpy(fp->name, AudioEslinear_le);
    439  1.37      kent 		fp->encoding = AUDIO_ENCODING_SLINEAR_LE;
    440  1.37      kent 		fp->precision = 16;
    441  1.37      kent 		fp->flags = AUDIO_ENCODINGFLAG_EMULATED;
    442  1.37      kent 		break;
    443   1.3        is 
    444  1.37      kent 	default:
    445  1.37      kent 		return EINVAL;
    446  1.37      kent 		/*NOTREACHED*/
    447   1.1        is 	}
    448  1.37      kent 	return 0;
    449   1.1        is }
    450   1.1        is 
    451   1.1        is int
    452  1.36      kent aucc_set_params(void *addr, int setmode, int usemode,
    453  1.36      kent 		audio_params_t *p, audio_params_t *r,
    454  1.36      kent 		stream_filter_list_t *pfil, stream_filter_list_t *rfil)
    455   1.1        is {
    456  1.37      kent 	struct aucc_softc *sc;
    457   1.8        is 
    458  1.37      kent 	sc = addr;
    459  1.18  augustss 	/* if (setmode & AUMODE_RECORD)
    460   1.8        is 		return 0 ENXIO*/;
    461   1.8        is 
    462   1.9        is #ifdef AUCCDEBUG
    463  1.24        is 	printf("aucc_set_params(setmode 0x%x, usemode 0x%x, "
    464  1.37      kent 	       "enc %u, bits %u, chn %u, sr %u)\n", setmode, usemode,
    465  1.37      kent 	       p->encoding, p->precision, p->channels, p->sample_rate);
    466  1.24        is #endif
    467  1.24        is 
    468  1.24        is 	switch (p->precision) {
    469  1.24        is 	case 8:
    470  1.24        is 		switch (p->encoding) {
    471  1.24        is 		case AUDIO_ENCODING_ULAW:
    472  1.24        is 			switch (p->channels) {
    473  1.24        is 			case 1:
    474  1.33       wiz 				sc->sc_decodefunc = aucc_decode_mulaw_1ch;
    475  1.24        is 				break;
    476  1.24        is 			case 2:
    477  1.33       wiz 				sc->sc_decodefunc = aucc_decode_mulaw_2ch;
    478  1.24        is 				break;
    479  1.24        is 			case 3:
    480  1.33       wiz 				sc->sc_decodefunc = aucc_decode_mulaw_3ch;
    481  1.24        is 				break;
    482  1.24        is 			case 4:
    483  1.33       wiz 				sc->sc_decodefunc = aucc_decode_mulaw_4ch;
    484  1.24        is 				break;
    485  1.24        is 			default:
    486  1.24        is 				return EINVAL;
    487  1.24        is 			}
    488  1.24        is 			break;
    489  1.24        is 
    490  1.24        is 		case AUDIO_ENCODING_SLINEAR:
    491  1.24        is 		case AUDIO_ENCODING_SLINEAR_BE:
    492  1.24        is 		case AUDIO_ENCODING_SLINEAR_LE:
    493  1.24        is 			switch (p->channels) {
    494  1.24        is 			case 1:
    495  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear8_1ch;
    496  1.24        is 				break;
    497  1.24        is 			case 2:
    498  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear8_2ch;
    499  1.24        is 				break;
    500  1.24        is 			case 3:
    501  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear8_3ch;
    502  1.24        is 				break;
    503  1.24        is 			case 4:
    504  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear8_4ch;
    505  1.24        is 				break;
    506  1.24        is 			default:
    507  1.24        is 				return EINVAL;
    508  1.24        is 			}
    509  1.24        is 			break;
    510  1.24        is 
    511  1.24        is 		case AUDIO_ENCODING_ULINEAR:
    512  1.24        is 		case AUDIO_ENCODING_ULINEAR_BE:
    513  1.24        is 		case AUDIO_ENCODING_ULINEAR_LE:
    514  1.24        is 			switch (p->channels) {
    515  1.24        is 			case 1:
    516  1.24        is 				sc->sc_decodefunc = aucc_decode_ulinear8_1ch;
    517  1.24        is 				break;
    518  1.24        is 			case 2:
    519  1.24        is 				sc->sc_decodefunc = aucc_decode_ulinear8_2ch;
    520  1.24        is 				break;
    521  1.24        is 			case 3:
    522  1.24        is 				sc->sc_decodefunc = aucc_decode_ulinear8_3ch;
    523  1.24        is 				break;
    524  1.24        is 			case 4:
    525  1.24        is 				sc->sc_decodefunc = aucc_decode_ulinear8_4ch;
    526  1.24        is 				break;
    527  1.24        is 			default:
    528  1.24        is 				return EINVAL;
    529  1.24        is 			}
    530  1.24        is 			break;
    531  1.24        is 
    532  1.24        is 		default:
    533  1.24        is 			return EINVAL;
    534  1.24        is 		}
    535  1.24        is 		break;
    536  1.24        is 
    537  1.24        is 	case 16:
    538  1.24        is 		switch (p->encoding) {
    539  1.24        is #if BYTE_ORDER == BIG_ENDIAN
    540  1.24        is 		case AUDIO_ENCODING_SLINEAR:
    541  1.24        is #endif
    542  1.24        is 		case AUDIO_ENCODING_SLINEAR_BE:
    543  1.24        is 			switch (p->channels) {
    544  1.24        is 			case 1:
    545  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear16_1ch;
    546  1.24        is 				break;
    547  1.24        is 
    548  1.24        is 			case 2:
    549  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear16_2ch;
    550  1.24        is 				break;
    551  1.24        is 			case 3:
    552  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear16_3ch;
    553  1.24        is 				break;
    554  1.24        is 			case 4:
    555  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear16_4ch;
    556  1.24        is 				break;
    557  1.24        is 			default:
    558  1.24        is 				return EINVAL;
    559  1.24        is 			}
    560  1.24        is 			break;
    561  1.24        is 
    562  1.24        is #if BYTE_ORDER == LITTLE_ENDIAN
    563  1.24        is 		case AUDIO_ENCODING_SLINEAR:
    564   1.9        is #endif
    565  1.24        is 		case AUDIO_ENCODING_SLINEAR_LE:
    566  1.24        is 			switch (p->channels) {
    567  1.24        is 			case 1:
    568  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear16sw_1ch;
    569  1.24        is 				break;
    570  1.24        is 			case 2:
    571  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear16sw_2ch;
    572  1.24        is 				break;
    573  1.24        is 			case 3:
    574  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear16sw_3ch;
    575  1.24        is 				break;
    576  1.24        is 			case 4:
    577  1.24        is 				sc->sc_decodefunc = aucc_decode_slinear16sw_4ch;
    578  1.24        is 				break;
    579  1.24        is 			default:
    580  1.24        is 				return EINVAL;
    581  1.24        is 			}
    582  1.24        is 			break;
    583   1.4        is 
    584  1.24        is 		default:
    585  1.24        is 			return EINVAL;
    586  1.24        is 		}
    587  1.24        is 		break;
    588   1.8        is 
    589   1.1        is 	default:
    590   1.1        is 		return EINVAL;
    591   1.1        is 	}
    592   1.1        is 
    593   1.8        is 	sc->sc_encoding = p->encoding;
    594  1.24        is 	sc->sc_precision = p->precision;
    595  1.24        is 	sc->sc_14bit = ((p->precision == 16) && (p->channels <= 2));
    596  1.24        is 	sc->sc_channels = sc->sc_14bit ? (p->channels * 2) : p->channels;
    597   1.8        is 
    598   1.8        is 	return aucc_set_out_sr(addr, p->sample_rate);
    599   1.1        is }
    600   1.1        is 
    601   1.1        is int
    602  1.36      kent aucc_round_blocksize(void *addr, int blk,
    603  1.36      kent 		     int mode, const audio_params_t *param)
    604   1.1        is {
    605  1.37      kent 
    606  1.24        is 	/* round up to even size */
    607  1.24        is 	return blk > AUDIO_BUF_SIZE ? AUDIO_BUF_SIZE : blk;
    608   1.1        is }
    609   1.1        is 
    610   1.1        is int
    611  1.29   aymeric aucc_commit_settings(void *addr)
    612   1.1        is {
    613  1.37      kent 	struct aucc_softc *sc;
    614  1.37      kent 	int i;
    615   1.1        is 
    616   1.1        is 	DPRINTF(("sa_commit.\n"));
    617   1.1        is 
    618  1.37      kent 	sc = addr;
    619  1.37      kent 	for (i = 0; i < 4; i++) {
    620  1.37      kent 		custom.aud[i].vol = sc->sc_channel[i].nd_volume;
    621  1.37      kent 		custom.aud[i].per = sc->sc_channel[i].nd_per;
    622   1.1        is 	}
    623   1.1        is 
    624   1.1        is 	DPRINTF(("commit done\n"));
    625   1.1        is 
    626  1.37      kent 	return 0;
    627   1.1        is }
    628   1.1        is 
    629   1.1        is static int masks[4] = {1,3,7,15}; /* masks for n first channels */
    630   1.1        is static int masks2[4] = {1,2,4,8};
    631   1.1        is 
    632   1.1        is int
    633  1.29   aymeric aucc_start_output(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
    634   1.1        is {
    635   1.8        is 	struct aucc_softc *sc;
    636   1.8        is 	int mask;
    637  1.24        is 	int i, j, k, len;
    638  1.24        is 	u_char *dmap[4];
    639   1.8        is 
    640   1.1        is 
    641   1.8        is 	sc = addr;
    642   1.8        is 	mask = sc->sc_channelmask;
    643   1.1        is 
    644   1.8        is 	dmap[0] = dmap[1] = dmap[2] = dmap[3] = NULL;
    645   1.1        is 
    646   1.1        is 	DPRINTF(("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));
    647   1.1        is 
    648  1.10        is 	if (sc->sc_channels > 1)
    649  1.24        is 		mask &= masks[sc->sc_channels - 1];
    650  1.10        is 		/* we use first sc_channels channels */
    651  1.24        is 	if (mask == 0) /* active and used channels are disjoint */
    652   1.1        is 		return EINVAL;
    653   1.1        is 
    654  1.37      kent 	for (i = 0; i < 4; i++) {
    655  1.24        is 		/* channels available ? */
    656  1.24        is 		if ((masks2[i] & mask) && (sc->sc_channel[i].nd_busy))
    657   1.1        is 			return EBUSY; /* channel is busy */
    658  1.24        is 		if (channel[i].isaudio == -1)
    659   1.1        is 			return EBUSY; /* system uses them */
    660   1.1        is 	}
    661   1.1        is 
    662   1.1        is 	/* enable interrupt on 1st channel */
    663  1.24        is 	for (i = j = 0; i < AUCC_MAXINT; i++) {
    664  1.24        is 		if (masks2[i] & mask) {
    665   1.1        is 			DPRINTF(("first channel is %d\n",i));
    666  1.37      kent 			j = i;
    667  1.37      kent 			sc->sc_channel[i].nd_intr = intr;
    668  1.37      kent 			sc->sc_channel[i].nd_intrdata = arg;
    669   1.1        is 			break;
    670   1.1        is 		}
    671   1.1        is 	}
    672   1.1        is 
    673   1.8        is 	DPRINTF(("dmap is %p %p %p %p, mask=0x%x\n", dmap[0], dmap[1],
    674  1.37      kent 		 dmap[2], dmap[3], mask));
    675   1.8        is 
    676  1.34       wiz 	/* disable ints, DMA for channels, until all parameters set */
    677   1.8        is 	/* XXX dont disable DMA! custom.dmacon=mask;*/
    678  1.24        is 	custom.intreq = mask << INTB_AUD0;
    679  1.24        is 	custom.intena = mask << INTB_AUD0;
    680   1.1        is 
    681  1.34       wiz 	/* copy data to DMA buffer */
    682  1.29   aymeric 
    683   1.8        is 	if (sc->sc_channels == 1) {
    684   1.8        is 		dmap[0] =
    685   1.8        is 		dmap[1] =
    686   1.8        is 		dmap[2] =
    687  1.24        is 		dmap[3] = (u_char *)sc->sc_channel[j].nd_dma;
    688  1.37      kent 	} else {
    689  1.37      kent 		for (k = 0; k < 4; k++) {
    690  1.24        is 			if (masks2[k+j] & mask)
    691  1.24        is 				dmap[k] = (u_char *)sc->sc_channel[k+j].nd_dma;
    692   1.8        is 		}
    693   1.8        is 	}
    694   1.8        is 
    695   1.8        is 	sc->sc_channel[j].nd_doublebuf ^= 1;
    696   1.8        is 	if (sc->sc_channel[j].nd_doublebuf) {
    697  1.24        is 		dmap[0] += AUDIO_BUF_SIZE;
    698  1.24        is 		dmap[1] += AUDIO_BUF_SIZE;
    699  1.24        is 		dmap[2] += AUDIO_BUF_SIZE;
    700  1.24        is 		dmap[3] += AUDIO_BUF_SIZE;
    701   1.8        is 	}
    702   1.1        is 
    703  1.37      kent 	/*
    704  1.37      kent 	 * compute output length in bytes per channel.
    705  1.24        is 	 * divide by two only for 16bit->8bit conversion.
    706  1.24        is 	 */
    707  1.24        is 	len = cc / sc->sc_channels;
    708  1.24        is 	if (!sc->sc_14bit && (sc->sc_precision == 16))
    709  1.24        is 		len /= 2;
    710  1.24        is 
    711  1.24        is 	/* call audio decoding routine */
    712  1.24        is 	sc->sc_decodefunc (dmap, (u_char *)p, len);
    713   1.1        is 
    714  1.34       wiz 	/* DMA buffers: we use same buffer 4 all channels
    715  1.34       wiz 	 * write DMA location and length
    716  1.24        is 	 */
    717  1.24        is 	for (i = k = 0; i < 4; i++) {
    718   1.8        is 		if (masks2[i] & mask) {
    719   1.1        is 			DPRINTF(("turning channel %d on\n",i));
    720  1.24        is 			/* sc->sc_channel[i].nd_busy=1; */
    721  1.24        is 			channel[i].isaudio = 1;
    722  1.24        is 			channel[i].play_count = 1;
    723  1.24        is 			channel[i].handler = NULL;
    724  1.24        is 			custom.aud[i].per = sc->sc_channel[i].nd_per;
    725  1.24        is 			if (sc->sc_14bit && (i > 1))
    726  1.24        is 				custom.aud[i].vol = 1;
    727  1.24        is 			else
    728  1.24        is 				custom.aud[i].vol = sc->sc_channel[i].nd_volume;
    729   1.8        is 			custom.aud[i].lc = PREP_DMA_MEM(dmap[k++]);
    730  1.24        is 			custom.aud[i].len = len / 2;
    731  1.24        is 			sc->sc_channel[i].nd_mask = mask;
    732   1.1        is 			DPRINTF(("per is %d, vol is %d, len is %d\n",\
    733   1.8        is 			    sc->sc_channel[i].nd_per,
    734  1.24        is 			    sc->sc_channel[i].nd_volume, len));
    735   1.1        is 		}
    736   1.1        is 	}
    737   1.1        is 
    738  1.37      kent 	channel[j].handler = aucc_inthdl;
    739   1.1        is 
    740   1.1        is 	/* enable ints */
    741  1.24        is 	custom.intena = INTF_SETCLR | INTF_INTEN | (masks2[j] << INTB_AUD0);
    742   1.1        is 
    743  1.24        is 	DPRINTF(("enabled ints: 0x%x\n", (masks2[j] << INTB_AUD0)));
    744   1.1        is 
    745  1.34       wiz 	/* enable DMA */
    746  1.24        is 	custom.dmacon = DMAF_SETCLR | DMAF_MASTER | mask;
    747   1.1        is 
    748  1.34       wiz 	DPRINTF(("enabled DMA, mask=0x%x\n",mask));
    749   1.1        is 
    750  1.37      kent 	return 0;
    751   1.1        is }
    752   1.1        is 
    753   1.1        is /* ARGSUSED */
    754   1.1        is int
    755  1.29   aymeric aucc_start_input(void *addr, void *p, int cc, void (*intr)(void *), void *arg)
    756   1.1        is {
    757   1.1        is 
    758   1.1        is 	return ENXIO; /* no input */
    759   1.1        is }
    760   1.1        is 
    761   1.1        is int
    762  1.29   aymeric aucc_halt_output(void *addr)
    763   1.1        is {
    764  1.37      kent 	struct aucc_softc *sc;
    765  1.37      kent 	int i;
    766   1.1        is 
    767   1.1        is 	/* XXX only halt, if input is also halted ?? */
    768  1.37      kent 	sc = addr;
    769  1.34       wiz 	/* stop DMA, etc */
    770   1.7        is 	custom.intena = AUCC_ALLINTF;
    771   1.7        is 	custom.dmacon = AUCC_ALLDMAF;
    772   1.1        is 	/* mark every busy unit idle */
    773  1.37      kent 	for (i = 0; i < 4; i++) {
    774  1.37      kent 		sc->sc_channel[i].nd_busy = sc->sc_channel[i].nd_mask = 0;
    775  1.37      kent 		channel[i].isaudio = 0;
    776  1.37      kent 		channel[i].play_count = 0;
    777   1.1        is 	}
    778   1.1        is 
    779  1.37      kent 	return 0;
    780   1.1        is }
    781   1.1        is 
    782   1.1        is int
    783  1.29   aymeric aucc_halt_input(void *addr)
    784   1.1        is {
    785  1.37      kent 
    786   1.1        is 	/* no input */
    787   1.1        is 	return ENXIO;
    788   1.1        is }
    789   1.1        is 
    790   1.1        is int
    791  1.29   aymeric aucc_getdev(void *addr, struct audio_device *retp)
    792   1.1        is {
    793  1.37      kent 
    794  1.37      kent 	*retp = aucc_device;
    795  1.37      kent 	return 0;
    796   1.1        is }
    797   1.1        is 
    798   1.1        is int
    799  1.29   aymeric aucc_set_port(void *addr, mixer_ctrl_t *cp)
    800   1.1        is {
    801  1.37      kent 	struct aucc_softc *sc;
    802  1.37      kent 	int i,j;
    803   1.1        is 
    804   1.1        is 	DPRINTF(("aucc_set_port: port=%d", cp->dev));
    805  1.37      kent 	sc = addr;
    806   1.1        is 	switch (cp->type) {
    807   1.1        is 	case AUDIO_MIXER_SET:
    808  1.37      kent 		if (cp->dev != AUCC_CHANNELS)
    809   1.1        is 			return EINVAL;
    810  1.37      kent 		i = cp->un.mask;
    811  1.37      kent 		if ((i < 1) || (i > 15))
    812   1.1        is 			return EINVAL;
    813  1.24        is 
    814  1.37      kent 		sc->sc_channelmask = i;
    815   1.1        is 		break;
    816   1.1        is 
    817   1.1        is 	case AUDIO_MIXER_VALUE:
    818  1.37      kent 		i = cp->un.value.num_channels;
    819  1.37      kent 		if ((i < 1) || (i > 4))
    820   1.1        is 			return EINVAL;
    821   1.1        is 
    822  1.10        is #ifdef __XXXwhatsthat
    823  1.37      kent 		if (cp->dev != AUCC_VOLUME)
    824   1.1        is 			return EINVAL;
    825  1.10        is #endif
    826   1.1        is 
    827   1.1        is 		/* set volume for channel 0..i-1 */
    828  1.21        is 
    829  1.21        is 		/* evil workaround for xanim bug, IMO */
    830  1.21        is 		if ((sc->sc_channels == 1) && (i == 2)) {
    831  1.29   aymeric 			sc->sc_channel[0].nd_volume =
    832  1.29   aymeric 			    sc->sc_channel[3].nd_volume =
    833  1.37      kent 			    cp->un.value.level[0] >> 2;
    834  1.29   aymeric 			sc->sc_channel[1].nd_volume =
    835  1.29   aymeric 			    sc->sc_channel[2].nd_volume =
    836  1.37      kent 			    cp->un.value.level[1] >> 2;
    837  1.37      kent 		} else if (i > 1) {
    838  1.37      kent 			for (j = 0; j < i; j++)
    839  1.37      kent 				sc->sc_channel[j].nd_volume =
    840  1.37      kent 				    cp->un.value.level[j] >> 2;
    841  1.21        is 		} else if (sc->sc_channels > 1)
    842  1.37      kent 			for (j = 0; j < sc->sc_channels; j++)
    843  1.37      kent 				sc->sc_channel[j].nd_volume =
    844  1.37      kent 				    cp->un.value.level[0] >> 2;
    845  1.10        is 		else
    846  1.37      kent 			for (j = 0; j < 4; j++)
    847  1.37      kent 				sc->sc_channel[j].nd_volume =
    848  1.37      kent 				    cp->un.value.level[0] >> 2;
    849  1.10        is 		break;
    850   1.1        is 
    851   1.1        is 	default:
    852   1.1        is 		return EINVAL;
    853   1.1        is 		break;
    854   1.1        is 	}
    855   1.1        is 	return 0;
    856   1.1        is }
    857   1.1        is 
    858   1.1        is 
    859   1.1        is int
    860  1.29   aymeric aucc_get_port(void *addr, mixer_ctrl_t *cp)
    861   1.1        is {
    862  1.37      kent 	struct aucc_softc *sc;
    863  1.37      kent 	int i,j;
    864   1.1        is 
    865   1.1        is 	DPRINTF(("aucc_get_port: port=%d", cp->dev));
    866  1.37      kent 	sc = addr;
    867   1.1        is 	switch (cp->type) {
    868   1.1        is 	case AUDIO_MIXER_SET:
    869  1.37      kent 		if (cp->dev != AUCC_CHANNELS)
    870   1.1        is 			return EINVAL;
    871  1.37      kent 		cp->un.mask = sc->sc_channelmask;
    872   1.1        is 		break;
    873   1.1        is 
    874   1.1        is 	case AUDIO_MIXER_VALUE:
    875   1.1        is 		i = cp->un.value.num_channels;
    876  1.37      kent 		if ((i < 1) || (i > 4))
    877   1.1        is 			return EINVAL;
    878   1.1        is 
    879  1.37      kent 		for (j = 0; j < i; j++)
    880  1.10        is 			cp->un.value.level[j] =
    881  1.37      kent 			    (sc->sc_channel[j].nd_volume << 2) +
    882  1.37      kent 			    (sc->sc_channel[j].nd_volume >> 4);
    883   1.1        is 		break;
    884   1.1        is 
    885   1.1        is 	default:
    886   1.1        is 		return EINVAL;
    887   1.1        is 	}
    888   1.1        is 	return 0;
    889   1.1        is }
    890   1.1        is 
    891  1.16  augustss 
    892  1.16  augustss int
    893  1.29   aymeric aucc_get_props(void *addr)
    894  1.16  augustss {
    895  1.16  augustss 	return 0;
    896  1.16  augustss }
    897   1.1        is 
    898  1.41  jmcneill 
    899  1.41  jmcneill void
    900  1.41  jmcneill aucc_get_locks(void *opaque, kmutex_t **intr, kmutex_t **thread)
    901  1.41  jmcneill {
    902  1.41  jmcneill 	struct aucc_softc *sc = opaque;
    903  1.41  jmcneill 
    904  1.41  jmcneill 	*intr = &sc->sc_intr_lock;
    905  1.41  jmcneill 	*thread = &sc->sc_lock;
    906  1.41  jmcneill }
    907  1.41  jmcneill 
    908   1.1        is int
    909  1.29   aymeric aucc_query_devinfo(void *addr, register mixer_devinfo_t *dip)
    910   1.1        is {
    911  1.37      kent 	int i;
    912   1.1        is 
    913   1.1        is 	switch(dip->index) {
    914   1.1        is 	case AUCC_CHANNELS:
    915   1.1        is 		dip->type = AUDIO_MIXER_SET;
    916   1.1        is 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    917   1.1        is 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    918  1.43  christos #define setname(a) strlcpy(dip->label.name, (a), sizeof(dip->label.name))
    919  1.43  christos 		setname(AudioNspeaker);
    920  1.37      kent 		for (i = 0; i < 16; i++) {
    921  1.43  christos 			snprintf(dip->un.s.member[i].label.name,
    922  1.43  christos 			    sizeof(dip->un.s.member[i].label.name),
    923   1.1        is 			    "channelmask%d", i);
    924   1.1        is 			dip->un.s.member[i].mask = i;
    925   1.1        is 		}
    926   1.1        is 		dip->un.s.num_mem = 16;
    927   1.1        is 		break;
    928   1.1        is 
    929   1.1        is 	case AUCC_VOLUME:
    930   1.1        is 		dip->type = AUDIO_MIXER_VALUE;
    931   1.1        is 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    932   1.1        is 		dip->prev = dip->next = AUDIO_MIXER_LAST;
    933  1.43  christos 		setname(AudioNmaster);
    934   1.1        is 		dip->un.v.num_channels = 4;
    935   1.1        is 		strcpy(dip->un.v.units.name, AudioNvolume);
    936   1.1        is 		break;
    937   1.1        is 
    938   1.1        is 	case AUCC_OUTPUT_CLASS:
    939   1.1        is 		dip->type = AUDIO_MIXER_CLASS;
    940   1.1        is 		dip->mixer_class = AUCC_OUTPUT_CLASS;
    941   1.1        is 		dip->next = dip->prev = AUDIO_MIXER_LAST;
    942  1.43  christos 		setname(AudioCoutputs);
    943   1.1        is 		break;
    944  1.20  augustss 
    945   1.1        is 	default:
    946   1.1        is 		return ENXIO;
    947   1.1        is 	}
    948   1.1        is 
    949   1.1        is 	DPRINTF(("AUDIO_MIXER_DEVINFO: name=%s\n", dip->label.name));
    950   1.1        is 
    951  1.37      kent 	return 0;
    952   1.1        is }
    953   1.1        is 
    954   1.1        is /* audio int handler */
    955   1.1        is void
    956   1.1        is aucc_inthdl(int ch)
    957   1.1        is {
    958  1.37      kent 	int i;
    959  1.37      kent 	int mask;
    960   1.1        is 
    961  1.41  jmcneill 	mutex_spin_enter(&aucc->sc_intr_lock);
    962  1.37      kent 	mask = aucc->sc_channel[ch].nd_mask;
    963  1.37      kent 	/*
    964  1.37      kent 	 * for all channels in this maskgroup:
    965  1.37      kent 	 * disable DMA, int
    966  1.37      kent 	 * mark idle
    967  1.37      kent 	 */
    968  1.37      kent 	DPRINTF(("inthandler called, channel %d, mask 0x%x\n", ch, mask));
    969   1.1        is 
    970  1.37      kent 	custom.intreq = mask << INTB_AUD0; /* clear request */
    971  1.24        is 	/*
    972  1.24        is 	 * XXX: maybe we can leave ints and/or DMA on,
    973  1.24        is 	 * if another sample has to be played?
    974  1.24        is 	 */
    975  1.37      kent 	custom.intena = mask << INTB_AUD0;
    976   1.1        is 	/*
    977  1.29   aymeric 	 * XXX custom.dmacon=mask; NO!!!
    978  1.29   aymeric 	 */
    979  1.37      kent 	for (i = 0; i < 4; i++) {
    980  1.37      kent 		if (masks2[i] && mask) {
    981   1.1        is 			DPRINTF(("marking channel %d idle\n",i));
    982  1.37      kent 			aucc->sc_channel[i].nd_busy = 0;
    983  1.37      kent 			aucc->sc_channel[i].nd_mask = 0;
    984  1.37      kent 			channel[i].isaudio = channel[i].play_count = 0;
    985   1.1        is 		}
    986   1.1        is 	}
    987   1.1        is 
    988   1.1        is 	/* call handler */
    989   1.1        is 	if (aucc->sc_channel[ch].nd_intr) {
    990   1.1        is 		DPRINTF(("calling %p\n",aucc->sc_channel[ch].nd_intr));
    991  1.24        is 		(*(aucc->sc_channel[ch].nd_intr))
    992  1.24        is 		    (aucc->sc_channel[ch].nd_intrdata);
    993  1.37      kent 	} else
    994  1.24        is 		DPRINTF(("zero int handler\n"));
    995  1.41  jmcneill 	mutex_spin_exit(&aucc->sc_intr_lock);
    996   1.1        is 	DPRINTF(("ints done\n"));
    997   1.1        is }
    998   1.1        is 
    999   1.1        is /* transform frequency to period, adjust bounds */
   1000   1.1        is static u_int
   1001  1.29   aymeric freqtoper(u_int freq)
   1002  1.29   aymeric {
   1003  1.37      kent 	u_int per;
   1004  1.29   aymeric 
   1005  1.37      kent 	per = eclockfreq * 5 / freq;
   1006  1.37      kent 	if (per < 124)
   1007  1.37      kent 		per = 124;   /* must have at least 124 ticks between samples */
   1008   1.1        is 
   1009   1.1        is 	return per;
   1010   1.1        is }
   1011   1.1        is 
   1012   1.1        is /* transform period to frequency */
   1013   1.1        is static u_int
   1014  1.29   aymeric pertofreq(u_int per)
   1015  1.29   aymeric {
   1016  1.24        is 
   1017  1.37      kent 	return eclockfreq * 5 / per;
   1018  1.24        is }
   1019  1.24        is 
   1020  1.29   aymeric static void
   1021  1.29   aymeric aucc_decode_slinear8_1ch(u_char **dmap, u_char *p, int i)
   1022  1.29   aymeric {
   1023  1.37      kent 	memcpy(dmap[0], p, i);
   1024  1.24        is }
   1025  1.24        is 
   1026  1.29   aymeric static void
   1027  1.29   aymeric aucc_decode_slinear8_2ch(u_char **dmap, u_char *p, int i)
   1028  1.29   aymeric {
   1029  1.37      kent 	u_char *ch0;
   1030  1.37      kent 	u_char *ch1;
   1031  1.24        is 
   1032  1.37      kent 	ch0 = dmap[0];
   1033  1.37      kent 	ch1 = dmap[1];
   1034  1.24        is 	while (i--) {
   1035  1.24        is 		*ch0++ = *p++;
   1036  1.24        is 		*ch1++ = *p++;
   1037  1.24        is 	}
   1038  1.24        is }
   1039  1.24        is 
   1040  1.29   aymeric static void
   1041  1.29   aymeric aucc_decode_slinear8_3ch(u_char **dmap, u_char *p, int i)
   1042  1.29   aymeric {
   1043  1.37      kent 	u_char *ch0;
   1044  1.37      kent 	u_char *ch1;
   1045  1.37      kent 	u_char *ch2;
   1046  1.37      kent 
   1047  1.37      kent 	ch0 = dmap[0];
   1048  1.37      kent 	ch1 = dmap[1];
   1049  1.37      kent 	ch2 = dmap[2];
   1050  1.24        is 	while (i--) {
   1051  1.24        is 		*ch0++ = *p++;
   1052  1.24        is 		*ch1++ = *p++;
   1053  1.24        is 		*ch2++ = *p++;
   1054  1.24        is 	}
   1055  1.24        is }
   1056  1.24        is 
   1057  1.29   aymeric static void
   1058  1.29   aymeric aucc_decode_slinear8_4ch(u_char **dmap, u_char *p, int i)
   1059  1.29   aymeric {
   1060  1.37      kent 	u_char *ch0;
   1061  1.37      kent 	u_char *ch1;
   1062  1.37      kent 	u_char *ch2;
   1063  1.37      kent 	u_char *ch3;
   1064  1.37      kent 
   1065  1.37      kent 	ch0 = dmap[0];
   1066  1.37      kent 	ch1 = dmap[1];
   1067  1.37      kent 	ch2 = dmap[2];
   1068  1.37      kent 	ch3 = dmap[3];
   1069  1.24        is 	while (i--) {
   1070  1.24        is 		*ch0++ = *p++;
   1071  1.24        is 		*ch1++ = *p++;
   1072  1.24        is 		*ch2++ = *p++;
   1073  1.24        is 		*ch3++ = *p++;
   1074  1.24        is 	}
   1075  1.24        is }
   1076  1.24        is 
   1077  1.24        is static void
   1078  1.29   aymeric aucc_decode_ulinear8_1ch(u_char **dmap, u_char *p, int i)
   1079  1.24        is {
   1080  1.37      kent 	u_char *ch0;
   1081  1.24        is 
   1082  1.37      kent 	ch0 = dmap[0];
   1083  1.24        is 	while (i--)
   1084  1.24        is 		*ch0++ = *p++ - 128;
   1085  1.24        is }
   1086  1.24        is 
   1087  1.24        is static void
   1088  1.29   aymeric aucc_decode_ulinear8_2ch(u_char **dmap, u_char *p, int i)
   1089   1.1        is {
   1090  1.37      kent 	u_char *ch0;
   1091  1.37      kent 	u_char *ch1;
   1092  1.24        is 
   1093  1.37      kent 	ch0 = dmap[0];
   1094  1.37      kent 	ch1 = dmap[1];
   1095  1.24        is 	while (i--) {
   1096  1.24        is 		*ch0++ = *p++ - 128;
   1097  1.24        is 		*ch1++ = *p++ - 128;
   1098  1.24        is 	}
   1099  1.24        is }
   1100  1.24        is 
   1101  1.24        is static void
   1102  1.29   aymeric aucc_decode_ulinear8_3ch(u_char **dmap, u_char *p, int i)
   1103  1.24        is {
   1104  1.37      kent 	u_char *ch0;
   1105  1.37      kent 	u_char *ch1;
   1106  1.37      kent 	u_char *ch2;
   1107  1.37      kent 
   1108  1.37      kent 	ch0 = dmap[0];
   1109  1.37      kent 	ch1 = dmap[1];
   1110  1.37      kent 	ch2 = dmap[2];
   1111  1.24        is 	while (i--) {
   1112  1.24        is 		*ch0++ = *p++ - 128;
   1113  1.24        is 		*ch1++ = *p++ - 128;
   1114  1.24        is 		*ch2++ = *p++ - 128;
   1115  1.24        is 	}
   1116  1.24        is }
   1117  1.24        is 
   1118  1.24        is static void
   1119  1.29   aymeric aucc_decode_ulinear8_4ch(u_char **dmap, u_char *p, int i)
   1120  1.24        is {
   1121  1.37      kent 	u_char *ch0;
   1122  1.37      kent 	u_char *ch1;
   1123  1.37      kent 	u_char *ch2;
   1124  1.37      kent 	u_char *ch3;
   1125  1.37      kent 
   1126  1.37      kent 	ch0 = dmap[0];
   1127  1.37      kent 	ch1 = dmap[1];
   1128  1.37      kent 	ch2 = dmap[2];
   1129  1.37      kent 	ch3 = dmap[3];
   1130  1.24        is 	while (i--) {
   1131  1.24        is 		*ch0++ = *p++ - 128;
   1132  1.24        is 		*ch1++ = *p++ - 128;
   1133  1.24        is 		*ch2++ = *p++ - 128;
   1134  1.24        is 		*ch3++ = *p++ - 128;
   1135  1.24        is 	}
   1136  1.24        is }
   1137  1.24        is 
   1138  1.24        is 
   1139  1.24        is static void
   1140  1.33       wiz aucc_decode_mulaw_1ch(u_char **dmap, u_char *p, int i)
   1141  1.24        is {
   1142  1.37      kent 	u_char *ch0;
   1143  1.24        is 
   1144  1.37      kent 	ch0 = dmap[0];
   1145  1.24        is 	while (i--)
   1146  1.33       wiz 		*ch0++ = mulaw_to_lin[*p++];
   1147  1.24        is }
   1148  1.24        is 
   1149  1.24        is static void
   1150  1.33       wiz aucc_decode_mulaw_2ch(u_char **dmap, u_char *p, int i)
   1151  1.24        is {
   1152  1.37      kent 	u_char *ch0;
   1153  1.37      kent 	u_char *ch1;
   1154  1.24        is 
   1155  1.37      kent 	ch0 = dmap[0];
   1156  1.37      kent 	ch1 = dmap[1];
   1157  1.24        is 	while (i--) {
   1158  1.33       wiz 		*ch0++ = mulaw_to_lin[*p++];
   1159  1.33       wiz 		*ch1++ = mulaw_to_lin[*p++];
   1160  1.24        is 	}
   1161  1.24        is }
   1162   1.1        is 
   1163  1.24        is static void
   1164  1.33       wiz aucc_decode_mulaw_3ch(u_char **dmap, u_char *p, int i)
   1165  1.24        is {
   1166  1.37      kent 	u_char *ch0;
   1167  1.37      kent 	u_char *ch1;
   1168  1.37      kent 	u_char *ch2;
   1169  1.37      kent 
   1170  1.37      kent 	ch0 = dmap[0];
   1171  1.37      kent 	ch1 = dmap[1];
   1172  1.37      kent 	ch2 = dmap[2];
   1173  1.24        is 	while (i--) {
   1174  1.33       wiz 		*ch0++ = mulaw_to_lin[*p++];
   1175  1.33       wiz 		*ch1++ = mulaw_to_lin[*p++];
   1176  1.33       wiz 		*ch2++ = mulaw_to_lin[*p++];
   1177  1.24        is 	}
   1178  1.24        is }
   1179   1.1        is 
   1180  1.24        is static void
   1181  1.33       wiz aucc_decode_mulaw_4ch(u_char **dmap, u_char *p, int i)
   1182  1.24        is {
   1183  1.37      kent 	u_char *ch0;
   1184  1.37      kent 	u_char *ch1;
   1185  1.37      kent 	u_char *ch2;
   1186  1.37      kent 	u_char *ch3;
   1187  1.37      kent 
   1188  1.37      kent 	ch0 = dmap[0];
   1189  1.37      kent 	ch1 = dmap[1];
   1190  1.37      kent 	ch2 = dmap[2];
   1191  1.37      kent 	ch3 = dmap[3];
   1192  1.24        is 	while (i--) {
   1193  1.33       wiz 		*ch0++ = mulaw_to_lin[*p++];
   1194  1.33       wiz 		*ch1++ = mulaw_to_lin[*p++];
   1195  1.33       wiz 		*ch2++ = mulaw_to_lin[*p++];
   1196  1.33       wiz 		*ch3++ = mulaw_to_lin[*p++];
   1197  1.24        is 	}
   1198   1.1        is }
   1199   1.1        is 
   1200   1.1        is 
   1201  1.24        is /* 14bit output */
   1202  1.24        is static void
   1203  1.29   aymeric aucc_decode_slinear16_1ch(u_char **dmap, u_char *p, int i)
   1204  1.24        is {
   1205  1.37      kent 	u_char *ch0;
   1206  1.37      kent 	u_char *ch3;
   1207  1.24        is 
   1208  1.37      kent 	ch0 = dmap[0];
   1209  1.37      kent 	ch3 = dmap[1];		/* XXX should be 3 */
   1210  1.24        is 	while (i--) {
   1211  1.24        is 		*ch0++ = *p++;
   1212  1.24        is 		*ch3++ = *p++ >> 2;
   1213  1.24        is 	}
   1214  1.24        is }
   1215   1.1        is 
   1216  1.24        is /* 14bit stereo output */
   1217  1.24        is static void
   1218  1.29   aymeric aucc_decode_slinear16_2ch(u_char **dmap, u_char *p, int i)
   1219  1.24        is {
   1220  1.37      kent 	u_char *ch0;
   1221  1.37      kent 	u_char *ch1;
   1222  1.37      kent 	u_char *ch2;
   1223  1.37      kent 	u_char *ch3;
   1224  1.37      kent 
   1225  1.37      kent 	ch0 = dmap[0];
   1226  1.37      kent 	ch1 = dmap[1];
   1227  1.37      kent 	ch2 = dmap[2];
   1228  1.37      kent 	ch3 = dmap[3];
   1229  1.24        is 	while (i--) {
   1230  1.24        is 		*ch0++ = *p++;
   1231  1.24        is 		*ch3++ = *p++ >> 2;
   1232  1.24        is 		*ch1++ = *p++;
   1233  1.24        is 		*ch2++ = *p++ >> 2;
   1234  1.24        is 	}
   1235  1.24        is }
   1236  1.24        is 
   1237  1.24        is static void
   1238  1.29   aymeric aucc_decode_slinear16_3ch(u_char **dmap, u_char *p, int i)
   1239  1.24        is {
   1240  1.37      kent 	u_char *ch0;
   1241  1.37      kent 	u_char *ch1;
   1242  1.37      kent 	u_char *ch2;
   1243  1.37      kent 
   1244  1.37      kent 	ch0 = dmap[0];
   1245  1.37      kent 	ch1 = dmap[1];
   1246  1.37      kent 	ch2 = dmap[2];
   1247  1.24        is 	while (i--) {
   1248  1.24        is 		*ch0++ = *p++; p++;
   1249  1.24        is 		*ch1++ = *p++; p++;
   1250  1.24        is 		*ch2++ = *p++; p++;
   1251  1.24        is 	}
   1252  1.24        is }
   1253  1.24        is 
   1254  1.24        is static void
   1255  1.29   aymeric aucc_decode_slinear16_4ch(u_char **dmap, u_char *p, int i)
   1256   1.1        is {
   1257  1.37      kent 	u_char *ch0;
   1258  1.37      kent 	u_char *ch1;
   1259  1.37      kent 	u_char *ch2;
   1260  1.37      kent 	u_char *ch3;
   1261  1.37      kent 
   1262  1.37      kent 	ch0 = dmap[0];
   1263  1.37      kent 	ch1 = dmap[1];
   1264  1.37      kent 	ch2 = dmap[2];
   1265  1.37      kent 	ch3 = dmap[3];
   1266  1.24        is 	while (i--) {
   1267  1.24        is 		*ch0++ = *p++; p++;
   1268  1.24        is 		*ch1++ = *p++; p++;
   1269  1.24        is 		*ch2++ = *p++; p++;
   1270  1.24        is 		*ch3++ = *p++; p++;
   1271  1.24        is 	}
   1272  1.24        is }
   1273   1.8        is 
   1274  1.24        is /* 14bit output, swap bytes */
   1275  1.24        is static void
   1276  1.29   aymeric aucc_decode_slinear16sw_1ch(u_char **dmap, u_char *p, int i)
   1277  1.24        is {
   1278  1.37      kent 	u_char *ch0;
   1279  1.37      kent 	u_char *ch3;
   1280   1.1        is 
   1281  1.37      kent 	ch0 = dmap[0];
   1282  1.37      kent 	ch3 = dmap[1];		/* XXX should be 3 */
   1283  1.24        is 	while (i--) {
   1284  1.24        is 		*ch3++ = *p++ >> 2;
   1285  1.24        is 		*ch0++ = *p++;
   1286  1.24        is 	}
   1287  1.24        is }
   1288   1.1        is 
   1289  1.24        is static void
   1290  1.29   aymeric aucc_decode_slinear16sw_2ch(u_char **dmap, u_char *p, int i)
   1291  1.24        is {
   1292  1.37      kent 	u_char *ch0;
   1293  1.37      kent 	u_char *ch1;
   1294  1.37      kent 	u_char *ch2;
   1295  1.37      kent 	u_char *ch3;
   1296  1.37      kent 
   1297  1.37      kent 	ch0 = dmap[0];
   1298  1.37      kent 	ch1 = dmap[1];
   1299  1.37      kent 	ch2 = dmap[2];
   1300  1.37      kent 	ch3 = dmap[3];
   1301  1.24        is 	while (i--) {
   1302  1.24        is 		*ch3++ = *p++ >> 2;
   1303  1.24        is 		*ch0++ = *p++;
   1304  1.24        is 		*ch2++ = *p++ >> 2;
   1305  1.24        is 		*ch1++ = *p++;
   1306  1.24        is 	}
   1307  1.24        is }
   1308   1.1        is 
   1309  1.24        is static void
   1310  1.29   aymeric aucc_decode_slinear16sw_3ch(u_char **dmap, u_char *p, int i)
   1311  1.24        is {
   1312  1.37      kent 	u_char *ch0;
   1313  1.37      kent 	u_char *ch1;
   1314  1.37      kent 	u_char *ch2;
   1315  1.37      kent 
   1316  1.37      kent 	ch0 = dmap[0];
   1317  1.37      kent 	ch1 = dmap[1];
   1318  1.37      kent 	ch2 = dmap[2];
   1319  1.24        is 	while (i--) {
   1320  1.24        is 		p++; *ch0++ = *p++;
   1321  1.24        is 		p++; *ch1++ = *p++;
   1322  1.24        is 		p++; *ch2++ = *p++;
   1323   1.1        is 	}
   1324  1.24        is }
   1325   1.1        is 
   1326  1.24        is static void
   1327  1.29   aymeric aucc_decode_slinear16sw_4ch(u_char **dmap, u_char *p, int i)
   1328  1.24        is {
   1329  1.37      kent 	u_char *ch0;
   1330  1.37      kent 	u_char *ch1;
   1331  1.37      kent 	u_char *ch2;
   1332  1.37      kent 	u_char *ch3;
   1333  1.37      kent 
   1334  1.37      kent 	ch0 = dmap[0];
   1335  1.37      kent 	ch1 = dmap[1];
   1336  1.37      kent 	ch2 = dmap[2];
   1337  1.37      kent 	ch3 = dmap[3];
   1338  1.24        is 	while (i--) {
   1339  1.24        is 		p++; *ch0++ = *p++;
   1340  1.24        is 		p++; *ch1++ = *p++;
   1341  1.24        is 		p++; *ch2++ = *p++;
   1342  1.24        is 		p++; *ch3++ = *p++;
   1343  1.24        is 	}
   1344   1.1        is }
   1345  1.24        is 
   1346   1.1        is 
   1347   1.1        is #endif /* NAUCC > 0 */
   1348