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