patch-2.1.6 linux/drivers/sound/dmasound.c

Next file: linux/drivers/sound/dmasound.h
Previous file: linux/drivers/sound/dmabuf.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.5/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c
@@ -1,3252 +0,0 @@
-
-/* linux/drivers/sound/dmasound.c */
-
-/*
-
-VoxWare compatible Atari TT DMA sound driver for 680x0 Linux
-
-(c) 1995 by Michael Schlueter & Michael Marte
-
-Michael Schlueter (michael@duck.syd.de) did the basic structure of the VFS
-interface and the u-law to signed byte conversion.
-
-Michael Marte (marte@informatik.uni-muenchen.de) did the sound queue,
-/dev/mixer, /dev/sndstat and complemented the VFS interface. He would like
-to thank:
-Michael Schlueter for initial ideas and documentation on the MFP and
-the DMA sound hardware.
-Therapy? for their CD 'Troublegum' which really made me rock.
-
-/dev/sndstat is based on code by Hannu Savolainen, the author of the
-VoxWare family of drivers.
-
-This file is subject to the terms and conditions of the GNU General Public
-License.  See the file COPYING in the main directory of this archive
-for more details.
-
-History:
-1995/8/25	first release
-
-1995/9/02	++roman: fixed atari_stram_alloc() call, the timer programming
-			and several race conditions
-
-1995/9/14	++roman: After some discussion with Michael Schlueter, revised
-			the interrupt disabling
-			Slightly speeded up U8->S8 translation by using long
-			operations where possible
-			Added 4:3 interpolation for /dev/audio
-
-1995/9/20	++TeSche: Fixed a bug in sq_write and changed /dev/audio
-			converting to play at 12517Hz instead of 6258Hz.
-
-1995/9/23	++TeSche: Changed sq_interrupt() and sq_play() to pre-program
-			the DMA for another frame while there's still one
-			running. This allows the IRQ response to be
-			arbitrarily delayed and playing will still continue.
-
-1995/10/14	++Guenther_Kelleter@ac3.maus.de, ++TeSche: better support for
-			Falcon audio (the Falcon doesn't raise an IRQ at the
-			end of a frame, but at the beginning instead!). uses
-			'if (codec_dma)' in lots of places to simply switch
-			between Falcon and TT code.
-
-1995/11/06	++TeSche: started introducing a hardware abstraction scheme
-			(may perhaps also serve for Amigas?), can now play
-			samples at almost all frequencies by means of a more
-			generalized expand routine, takes a good deal of care
-			to cut data only at sample sizes, buffer size is now
-			a kernel runtime option, implemented fsync() & several
-			minor improvements
-		++Guenther: useful hints and bug fixes, cross-checked it for
-			Falcons
-
-1996/3/9	++geert: support added for Amiga, A-law, 16-bit little endian.
-			Unification to drivers/sound/dmasound.c.
-1996/4/6	++Martin Mitchell: updated to 1.3 kernel.
-*/
-
-
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/major.h>
-#include <linux/config.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/bootinfo.h>
-
-#ifdef CONFIG_ATARI
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#endif /* CONFIG_AMIGA */
-
-#include "dmasound.h"
-#include <linux/soundcard.h>
-
-
-#ifdef CONFIG_ATARI
-extern void atari_microwire_cmd(int cmd);
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-   /*
-    *	The minimum period for audio depends on total (for OCS/ECS/AGA)
-    *	(Imported from arch/m68k/amiga/amisound.c)
-    */
-
-extern volatile u_short amiga_audio_min_period;
-
-
-   /*
-    *	amiga_mksound() should be able to restore the period after beeping
-    *	(Imported from arch/m68k/amiga/amisound.c)
-    */
-
-extern u_short amiga_audio_period;
-
-
-   /*
-    *	Audio DMA masks
-    */
-
-#define AMI_AUDIO_OFF	(DMAF_AUD0 | DMAF_AUD1 | DMAF_AUD2 | DMAF_AUD3)
-#define AMI_AUDIO_8	(DMAF_SETCLR | DMAF_MASTER | DMAF_AUD0 | DMAF_AUD1)
-#define AMI_AUDIO_14	(AMI_AUDIO_8 | DMAF_AUD2 | DMAF_AUD3)
-
-#endif /* CONFIG_AMIGA */
-
-
-/*** Some declarations *******************************************************/
-
-
-#define DMASND_TT		1
-#define DMASND_FALCON		2
-#define DMASND_AMIGA		3
-
-#define MAX_CATCH_RADIUS	10
-#define MIN_BUFFERS		4
-#define MIN_BUFSIZE 		4
-#define MAX_BUFSIZE		128	/* Limit for Amiga */
-
-static int catchRadius = 0, numBufs = 4, bufSize = 32;
-
-
-#define arraysize(x)	(sizeof(x)/sizeof(*(x)))
-#define min(x, y)	((x) < (y) ? (x) : (y))
-#define le2be16(x)	(((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
-#define le2be16dbl(x)	(((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
-
-#define IOCTL_IN(arg)		get_user((int *)(arg))
-#define IOCTL_OUT(arg, ret)	ioctl_return((int *)arg, ret)
-
-
-/*** Some low level helpers **************************************************/
-
-
-/* 8 bit mu-law */
-
-static char ulaw2dma8[] = {
-    -126,   -122,   -118,   -114,   -110,   -106,   -102,    -98,
-     -94,    -90,    -86,    -82,    -78,    -74,    -70,    -66,
-     -63,    -61,    -59,    -57,    -55,    -53,    -51,    -49,
-     -47,    -45,    -43,    -41,    -39,    -37,    -35,    -33,
-     -31,    -30,    -29,    -28,    -27,    -26,    -25,    -24,
-     -23,    -22,    -21,    -20,    -19,    -18,    -17,    -16,
-     -16,    -15,    -15,    -14,    -14,    -13,    -13,    -12,
-     -12,    -11,    -11,    -10,    -10,     -9,     -9,     -8,
-      -8,     -8,     -7,     -7,     -7,     -7,     -6,     -6,
-      -6,     -6,     -5,     -5,     -5,     -5,     -4,     -4,
-      -4,     -4,     -4,     -4,     -3,     -3,     -3,     -3,
-      -3,     -3,     -3,     -3,     -2,     -2,     -2,     -2,
-      -2,     -2,     -2,     -2,     -2,     -2,     -2,     -2,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,      0,
-     125,    121,    117,    113,    109,    105,    101,     97,
-      93,     89,     85,     81,     77,     73,     69,     65,
-      62,     60,     58,     56,     54,     52,     50,     48,
-      46,     44,     42,     40,     38,     36,     34,     32,
-      30,     29,     28,     27,     26,     25,     24,     23,
-      22,     21,     20,     19,     18,     17,     16,     15,
-      15,     14,     14,     13,     13,     12,     12,     11,
-      11,     10,     10,      9,      9,      8,      8,      7,
-       7,      7,      6,      6,      6,      6,      5,      5,
-       5,      5,      4,      4,      4,      4,      3,      3,
-       3,      3,      3,      3,      2,      2,      2,      2,
-       2,      2,      2,      2,      1,      1,      1,      1,
-       1,      1,      1,      1,      1,      1,      1,      1,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       0,      0,      0,      0,      0,      0,      0,      0
-};
-
-/* 8 bit A-law */
-
-static char alaw2dma8[] = {
-     -22,    -21,    -24,    -23,    -18,    -17,    -20,    -19,
-     -30,    -29,    -32,    -31,    -26,    -25,    -28,    -27,
-     -11,    -11,    -12,    -12,     -9,     -9,    -10,    -10,
-     -15,    -15,    -16,    -16,    -13,    -13,    -14,    -14,
-     -86,    -82,    -94,    -90,    -70,    -66,    -78,    -74,
-    -118,   -114,   -126,   -122,   -102,    -98,   -110,   -106,
-     -43,    -41,    -47,    -45,    -35,    -33,    -39,    -37,
-     -59,    -57,    -63,    -61,    -51,    -49,    -55,    -53,
-      -2,     -2,     -2,     -2,     -2,     -2,     -2,     -2,
-      -2,     -2,     -2,     -2,     -2,     -2,     -2,     -2,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -1,     -1,     -1,     -1,     -1,     -1,     -1,     -1,
-      -6,     -6,     -6,     -6,     -5,     -5,     -5,     -5,
-      -8,     -8,     -8,     -8,     -7,     -7,     -7,     -7,
-      -3,     -3,     -3,     -3,     -3,     -3,     -3,     -3,
-      -4,     -4,     -4,     -4,     -4,     -4,     -4,     -4,
-      21,     20,     23,     22,     17,     16,     19,     18,
-      29,     28,     31,     30,     25,     24,     27,     26,
-      10,     10,     11,     11,      8,      8,      9,      9,
-      14,     14,     15,     15,     12,     12,     13,     13,
-      86,     82,     94,     90,     70,     66,     78,     74,
-     118,    114,    126,    122,    102,     98,    110,    106,
-      43,     41,     47,     45,     35,     33,     39,     37,
-      59,     57,     63,     61,     51,     49,     55,     53,
-       1,      1,      1,      1,      1,      1,      1,      1,
-       1,      1,      1,      1,      1,      1,      1,      1,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       0,      0,      0,      0,      0,      0,      0,      0,
-       5,      5,      5,      5,      4,      4,      4,      4,
-       7,      7,      7,      7,      6,      6,      6,      6,
-       2,      2,      2,      2,      2,      2,      2,      2,
-       3,      3,      3,      3,      3,      3,      3,      3
-};
-
-
-#ifdef HAS_16BIT_TABLES
-
-/* 16 bit mu-law */
-
-static char ulaw2dma16[] = {
-    -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
-    -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
-    -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
-    -11900, -11388, -10876, -10364,  -9852,  -9340,  -8828,  -8316,
-     -7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140,
-     -5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092,
-     -3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004,
-     -2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980,
-     -1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436,
-     -1372,  -1308,  -1244,  -1180,  -1116,  -1052,   -988,   -924,
-      -876,   -844,   -812,   -780,   -748,   -716,   -684,   -652,
-      -620,   -588,   -556,   -524,   -492,   -460,   -428,   -396,
-      -372,   -356,   -340,   -324,   -308,   -292,   -276,   -260,
-      -244,   -228,   -212,   -196,   -180,   -164,   -148,   -132,
-      -120,   -112,   -104,    -96,    -88,    -80,    -72,    -64,
-       -56,    -48,    -40,    -32,    -24,    -16,     -8,      0,
-     32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956,
-     23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764,
-     15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412,
-     11900,  11388,  10876,  10364,   9852,   9340,   8828,   8316,
-      7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140,
-      5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092,
-      3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004,
-      2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980,
-      1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436,
-      1372,   1308,   1244,   1180,   1116,   1052,    988,    924,
-       876,    844,    812,    780,    748,    716,    684,    652,
-       620,    588,    556,    524,    492,    460,    428,    396,
-       372,    356,    340,    324,    308,    292,    276,    260,
-       244,    228,    212,    196,    180,    164,    148,    132,
-       120,    112,    104,     96,     88,     80,     72,     64,
-        56,     48,     40,     32,     24,     16,      8,      0,
-};
-
-/* 16 bit A-law */
-
-static char alaw2dma16[] = {
-     -5504,  -5248,  -6016,  -5760,  -4480,  -4224,  -4992,  -4736,
-     -7552,  -7296,  -8064,  -7808,  -6528,  -6272,  -7040,  -6784,
-     -2752,  -2624,  -3008,  -2880,  -2240,  -2112,  -2496,  -2368,
-     -3776,  -3648,  -4032,  -3904,  -3264,  -3136,  -3520,  -3392,
-    -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
-    -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
-    -11008, -10496, -12032, -11520,  -8960,  -8448,  -9984,  -9472,
-    -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
-      -344,   -328,   -376,   -360,   -280,   -264,   -312,   -296,
-      -472,   -456,   -504,   -488,   -408,   -392,   -440,   -424,
-       -88,    -72,   -120,   -104,    -24,     -8,    -56,    -40,
-      -216,   -200,   -248,   -232,   -152,   -136,   -184,   -168,
-     -1376,  -1312,  -1504,  -1440,  -1120,  -1056,  -1248,  -1184,
-     -1888,  -1824,  -2016,  -1952,  -1632,  -1568,  -1760,  -1696,
-      -688,   -656,   -752,   -720,   -560,   -528,   -624,   -592,
-      -944,   -912,  -1008,   -976,   -816,   -784,   -880,   -848,
-      5504,   5248,   6016,   5760,   4480,   4224,   4992,   4736,
-      7552,   7296,   8064,   7808,   6528,   6272,   7040,   6784,
-      2752,   2624,   3008,   2880,   2240,   2112,   2496,   2368,
-      3776,   3648,   4032,   3904,   3264,   3136,   3520,   3392,
-     22016,  20992,  24064,  23040,  17920,  16896,  19968,  18944,
-     30208,  29184,  32256,  31232,  26112,  25088,  28160,  27136,
-     11008,  10496,  12032,  11520,   8960,   8448,   9984,   9472,
-     15104,  14592,  16128,  15616,  13056,  12544,  14080,  13568,
-       344,    328,    376,    360,    280,    264,    312,    296,
-       472,    456,    504,    488,    408,    392,    440,    424,
-        88,     72,    120,    104,     24,      8,     56,     40,
-       216,    200,    248,    232,    152,    136,    184,    168,
-      1376,   1312,   1504,   1440,   1120,   1056,   1248,   1184,
-      1888,   1824,   2016,   1952,   1632,   1568,   1760,   1696,
-       688,    656,    752,    720,    560,    528,    624,    592,
-       944,    912,   1008,    976,    816,    784,    880,    848,
-};
-#endif /* HAS_16BIT_TABLES */
-
-
-#ifdef HAS_14BIT_TABLES
-
-/* 14 bit mu-law (LSB) */
-
-static char alaw2dma14l[] = {
-        33,     33,     33,     33,     33,     33,     33,     33,
-        33,     33,     33,     33,     33,     33,     33,     33,
-        33,     33,     33,     33,     33,     33,     33,     33,
-        33,     33,     33,     33,     33,     33,     33,     33,
-         1,      1,      1,      1,      1,      1,      1,      1,
-         1,      1,      1,      1,      1,      1,      1,      1,
-        49,     17,     49,     17,     49,     17,     49,     17,
-        49,     17,     49,     17,     49,     17,     49,     17,
-        41,     57,      9,     25,     41,     57,      9,     25,
-        41,     57,      9,     25,     41,     57,      9,     25,
-        37,     45,     53,     61,      5,     13,     21,     29,
-        37,     45,     53,     61,      5,     13,     21,     29,
-        35,     39,     43,     47,     51,     55,     59,     63,
-         3,      7,     11,     15,     19,     23,     27,     31,
-        34,     36,     38,     40,     42,     44,     46,     48,
-        50,     52,     54,     56,     58,     60,     62,      0,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        31,     31,     31,     31,     31,     31,     31,     31,
-        63,     63,     63,     63,     63,     63,     63,     63,
-        63,     63,     63,     63,     63,     63,     63,     63,
-        15,     47,     15,     47,     15,     47,     15,     47,
-        15,     47,     15,     47,     15,     47,     15,     47,
-        23,      7,     55,     39,     23,      7,     55,     39,
-        23,      7,     55,     39,     23,      7,     55,     39,
-        27,     19,     11,      3,     59,     51,     43,     35,
-        27,     19,     11,      3,     59,     51,     43,     35,
-        29,     25,     21,     17,     13,      9,      5,      1,
-        61,     57,     53,     49,     45,     41,     37,     33,
-        30,     28,     26,     24,     22,     20,     18,     16,
-        14,     12,     10,      8,      6,      4,      2,      0
-};
-
-/* 14 bit A-law (LSB) */
-
-static char alaw2dma14l[] = {
-        32,     32,     32,     32,     32,     32,     32,     32,
-        32,     32,     32,     32,     32,     32,     32,     32,
-        16,     48,     16,     48,     16,     48,     16,     48,
-        16,     48,     16,     48,     16,     48,     16,     48,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-        42,     46,     34,     38,     58,     62,     50,     54,
-        10,     14,      2,      6,     26,     30,     18,     22,
-        42,     46,     34,     38,     58,     62,     50,     54,
-        10,     14,      2,      6,     26,     30,     18,     22,
-        40,     56,      8,     24,     40,     56,      8,     24,
-        40,     56,      8,     24,     40,     56,      8,     24,
-        20,     28,      4,     12,     52,     60,     36,     44,
-        20,     28,      4,     12,     52,     60,     36,     44,
-        32,     32,     32,     32,     32,     32,     32,     32,
-        32,     32,     32,     32,     32,     32,     32,     32,
-        48,     16,     48,     16,     48,     16,     48,     16,
-        48,     16,     48,     16,     48,     16,     48,     16,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-         0,      0,      0,      0,      0,      0,      0,      0,
-        22,     18,     30,     26,      6,      2,     14,     10,
-        54,     50,     62,     58,     38,     34,     46,     42,
-        22,     18,     30,     26,      6,      2,     14,     10,
-        54,     50,     62,     58,     38,     34,     46,     42,
-        24,      8,     56,     40,     24,      8,     56,     40,
-        24,      8,     56,     40,     24,      8,     56,     40,
-        44,     36,     60,     52,     12,      4,     28,     20,
-        44,     36,     60,     52,     12,      4,     28,     20
-};
-#endif /* HAS_14BIT_TABLES */
-
-
-/*** Translations ************************************************************/
-
-
-#ifdef CONFIG_ATARI
-static long ata_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft);
-static long ata_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft);
-static long ata_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft);
-static long ata_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ata_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ata_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ata_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ata_ctx_law(const u_char *userPtr, long userCount, u_char frame[],
-			long *frameUsed, long frameLeft);
-static long ata_ctx_s8(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft);
-static long ata_ctx_u8(const u_char *userPtr, long userCount, u_char frame[],
-		        long *frameUsed, long frameLeft);
-static long ata_ctx_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft);
-static long ata_ctx_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft);
-static long ata_ctx_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft);
-static long ata_ctx_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft);
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static long ami_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft);
-static long ami_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft);
-static long ami_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft);
-static long ami_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ami_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ami_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-static long ami_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft);
-#endif /* CONFIG_AMIGA */
-
-
-/*** Machine definitions *****************************************************/
-
-
-typedef struct {
-    int type;
-    void *(*dma_alloc)(unsigned int, int);
-    void (*dma_free)(void *, unsigned int);
-    int (*irqinit)(void);
-    void (*init)(void);
-    void (*silence)(void);
-    int (*setFormat)(int);
-    int (*setVolume)(int);
-    int (*setBass)(int);
-    int (*setTreble)(int);
-    void (*play)(void);
-} MACHINE;
-
-
-/*** Low level stuff *********************************************************/
-
-
-typedef struct {
-    int format;		/* AFMT_* */
-    int stereo;		/* 0 = mono, 1 = stereo */
-    int size;		/* 8/16 bit*/
-    int speed;		/* speed */
-} SETTINGS;
-
-typedef struct {
-    long (*ct_ulaw)(const u_char *, long, u_char *, long *, long);
-    long (*ct_alaw)(const u_char *, long, u_char *, long *, long);
-    long (*ct_s8)(const u_char *, long, u_char *, long *, long);
-    long (*ct_u8)(const u_char *, long, u_char *, long *, long);
-    long (*ct_s16be)(const u_char *, long, u_char *, long *, long);
-    long (*ct_u16be)(const u_char *, long, u_char *, long *, long);
-    long (*ct_s16le)(const u_char *, long, u_char *, long *, long);
-    long (*ct_u16le)(const u_char *, long, u_char *, long *, long);
-} TRANS;
-
-struct sound_settings {
-    MACHINE mach;	/* machine dependent things */
-    SETTINGS hard;	/* hardware settings */
-    SETTINGS soft;	/* software settings */
-    SETTINGS dsp;	/* /dev/dsp default settings */
-    TRANS *trans;	/* supported translations */
-    int volume_left;	/* volume (range is machine dependent) */
-    int volume_right;
-    int bass;		/* tone (range is machine dependent) */
-    int treble;
-    int minDev;		/* minor device number currently open */
-#ifdef CONFIG_ATARI
-    int bal;		/* balance factor for expanding (not volume!) */
-    u_long data;	/* data for expanding */
-#endif /* CONFIG_ATARI */
-};
-
-static struct sound_settings sound;
-
-
-#ifdef CONFIG_ATARI
-static void *AtaAlloc(unsigned int size, int flags);
-static void AtaFree(void *, unsigned int size);
-static int AtaIrqInit(void);
-static int AtaSetBass(int bass);
-static int AtaSetTreble(int treble);
-static void TTSilence(void);
-static void TTInit(void);
-static int TTSetFormat(int format);
-static int TTSetVolume(int volume);
-static void FalconSilence(void);
-static void FalconInit(void);
-static int FalconSetFormat(int format);
-static int FalconSetVolume(int volume);
-static void ata_sq_play_next_frame(int index);
-static void AtaPlay(void);
-static void ata_sq_interrupt(int irq, struct pt_regs *fp, void *dummy);
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static void *AmiAlloc(unsigned int size, int flags);
-static void AmiFree(void *, unsigned int);
-static int AmiIrqInit(void);
-static void AmiSilence(void);
-static void AmiInit(void);
-static int AmiSetFormat(int format);
-static int AmiSetVolume(int volume);
-static int AmiSetTreble(int treble);
-static void ami_sq_play_next_frame(int index);
-static void AmiPlay(void);
-static void ami_sq_interrupt(int irq, struct pt_regs *fp, void *dummy);
-#endif /* CONFIG_AMIGA */
-
-
-/*** Mid level stuff *********************************************************/
-
-
-static void sound_silence(void);
-static void sound_init(void);
-static int sound_set_format(int format);
-static int sound_set_speed(int speed);
-static int sound_set_stereo(int stereo);
-static int sound_set_volume(int volume);
-#ifdef CONFIG_ATARI
-static int sound_set_bass(int bass);
-#endif /* CONFIG_ATARI */
-static int sound_set_treble(int treble);
-static long sound_copy_translate(const u_char *userPtr, long userCount,
-				 u_char frame[], long *frameUsed,
-				 long frameLeft);
-
-
-/*
- * /dev/mixer abstraction
- */
-
-struct sound_mixer {
-    int busy;
-};
-
-static struct sound_mixer mixer;
-
-static void mixer_init(void);
-static int mixer_open(int open_mode);
-static int mixer_release(void);
-static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg);
-
-
-/*
- * Sound queue stuff, the heart of the driver
- */
-
-struct sound_queue {
-    int max_count, block_size;
-    char **buffers;
-
-    /* it shouldn't be necessary to declare any of these volatile */
-    int front, rear, count;
-    int rear_size;
-    /*
-     *	The use of the playing field depends on the hardware
-     *
-     *	Atari: The number of frames that are loaded/playing
-     *
-     *	Amiga: Bit 0 is set: a frame is loaded
-     *	       Bit 1 is set: a frame is playing
-     */
-    int playing;
-    struct wait_queue *write_queue, *open_queue, *sync_queue;
-    int open_mode;
-    int busy, syncing;
-#ifdef CONFIG_ATARI
-    int ignore_int;		/* ++TeSche: used for Falcon */
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-    int block_size_half, block_size_quarter;
-#endif /* CONFIG_AMIGA */
-};
-
-static struct sound_queue sq;
-
-#define sq_block_address(i)	(sq.buffers[i])
-#define SIGNAL_RECEIVED	(current->signal & ~current->blocked)
-#define NON_BLOCKING(open_mode)	(open_mode & O_NONBLOCK)
-#define ONE_SECOND	HZ	/* in jiffies (100ths of a second) */
-#define NO_TIME_LIMIT	0xffffffff
-#define SLEEP(queue, time_limit) \
-	current->timeout = jiffies+(time_limit); \
-	interruptible_sleep_on(&queue);
-#define WAKE_UP(queue)	(wake_up_interruptible(&queue))
-
-static void sq_init(int numBufs, int bufSize, char **buffers);
-static void sq_play(void);
-static int sq_write(const char *src, int uLeft);
-static int sq_open(int open_mode);
-static void sq_reset(void);
-static int sq_sync(void);
-static int sq_release(void);
-
-
-/*
- * /dev/sndstat
- */
-
-struct sound_state {
-    int busy;
-    char buf[512];
-    int len, ptr;
-};
-
-static struct sound_state state;
-
-static void state_init(void);
-static int state_open(int open_mode);
-static int state_release(void);
-static int state_read(char *dest, int count);
-
-
-/*** High level stuff ********************************************************/
-
-
-static int sound_open(struct inode *inode, struct file *file);
-static int sound_fsync(struct inode *inode, struct file *filp);
-static void sound_release(struct inode *inode, struct file *file);
-static int sound_lseek(struct inode *inode, struct file *file, off_t offset,
-		       int orig);
-static int sound_read(struct inode *inode, struct file *file, char *buf,
-		      int count);
-static int sound_write(struct inode *inode, struct file *file, const char *buf,
-		       int count);
-static int ioctl_return(int *addr, int value);
-static int unknown_minor_dev(char *fname, int dev);
-static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg);
-
-
-/*** Config & Setup **********************************************************/
-
-
-void soundcard_init(void);
-void dmasound_setup(char *str, int *ints);
-void sound_setup(char *str, int *ints);		/* ++Martin: stub for now */
-
-
-/*** Translations ************************************************************/
-
-
-/* ++TeSche: radically changed for new expanding purposes...
- *
- * These two routines now deal with copying/expanding/translating the samples
- * from user space into our buffer at the right frequency. They take care about
- * how much data there's actually to read, how much buffer space there is and
- * to convert samples into the right frequency/encoding. They will only work on
- * complete samples so it may happen they leave some bytes in the input stream
- * if the user didn't write a multiple of the current sample size. They both
- * return the number of bytes they've used from both streams so you may detect
- * such a situation. Luckily all programs should be able to cope with that.
- *
- * I think I've optimized anything as far as one can do in plain C, all
- * variables should fit in registers and the loops are really short. There's
- * one loop for every possible situation. Writing a more generalized and thus
- * parameterized loop would only produce slower code. Feel free to optimize
- * this in assembler if you like. :)
- *
- * I think these routines belong here because they're not yet really hardware
- * independent, especially the fact that the Falcon can play 16bit samples
- * only in stereo is hardcoded in both of them!
- *
- * ++geert: split in even more functions (one per format)
- */
-
-#ifdef CONFIG_ATARI
-static long ata_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft)
-{
-    char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
-    long count, used;
-    u_char *p = &frame[*frameUsed];
-
-    count = min(userCount, frameLeft);
-    if (sound.soft.stereo)
-	count &= ~1;
-    used = count;
-    while (count > 0) {
-	*p++ = table[get_user(userPtr++)];
-	count--;
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ata_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft)
-{
-    long count, used;
-    void *p = &frame[*frameUsed];
-
-    count = min(userCount, frameLeft);
-    if (sound.soft.stereo)
-	count &= ~1;
-    used = count;
-    copy_from_user(p, userPtr, count);
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ata_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft)
-{
-    long count, used;
-
-    if (!sound.soft.stereo) {
-	u_char *p = &frame[*frameUsed];
-	count = min(userCount, frameLeft);
-	used = count;
-	while (count > 0) {
-	    *p++ = get_user(userPtr++) ^ 0x80;
-	    count--;
-	}
-    } else {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>1;
-	used = count*2;
-	while (count > 0) {
-	    *p++ = get_user(((u_short *)userPtr)++) ^ 0x8080;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ata_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    *p++ = data;
-	    *p++ = data;
-	    count--;
-	}
-	*frameUsed += used*2;
-    } else {
-	void *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft) & ~3;
-	used = count;
-	copy_from_user(p, userPtr, count);
-	*frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-	    *p++ = data;
-	    *p++ = data;
-	    count--;
-	}
-	*frameUsed += used*2;
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>2;
-	used = count*4;
-	while (count > 0) {
-	    *p++ = get_user(((u_int *)userPtr)++) ^ 0x80008000;
-	    count--;
-	}
-	*frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    count = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data);
-	    *p++ = data;
-	    *p++ = data;
-	    count--;
-	}
-	*frameUsed += used*2;
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>2;
-	used = count*4;
-	while (count > 0) {
-	    data = get_user(((u_int *)userPtr)++);
-	    data = le2be16dbl(data);
-	    *p++ = data;
-	    count--;
-	}
-	*frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    count = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data) ^ 0x8000;
-	    *p++ = data;
-	    *p++ = data;
-	}
-	*frameUsed += used*2;
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	count = min(userCount, frameLeft)>>2;
-	used = count;
-	while (count > 0) {
-	    data = get_user(((u_int *)userPtr)++);
-	    data = le2be16dbl(data) ^ 0x80008000;
-	    *p++ = data;
-	    count--;
-	}
-	*frameUsed += used;
-    }
-    return(used);
-}
-
-
-static long ata_ctx_law(const u_char *userPtr, long userCount, u_char frame[],
-			long *frameUsed, long frameLeft)
-{
-    char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_char *p = &frame[*frameUsed];
-	while (frameLeft) {
-	    if (bal < 0) {
-		if (!userCount)
-		    break;
-		data = table[get_user(userPtr++)];
-		userCount--;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft--;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 2) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = table[get_user(userPtr++)] << 8;
-		data |= table[get_user(userPtr++)];
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 2;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_s8(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_char *p = &frame[*frameUsed];
-	while (frameLeft) {
-	    if (bal < 0) {
-		if (!userCount)
-		    break;
-		data = get_user(userPtr++);
-		userCount--;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft--;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 2) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++);
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 2;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_u8(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_char *p = &frame[*frameUsed];
-	while (frameLeft) {
-	    if (bal < 0) {
-		if (!userCount)
-		    break;
-		data = get_user(userPtr++) ^ 0x80;
-		userCount--;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft--;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 2) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++) ^ 0x8080;
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 2;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++);
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 4)
-		    break;
-		data = get_user(((u_int *)userPtr)++);
-		userCount -= 4;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 4)
-		    break;
-		data = get_user(((u_int *)userPtr)++) ^ 0x80008000;
-		userCount -= 4;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++);
-		data = le2be16(data);
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 4)
-		    break;
-		data = get_user(((u_int *)userPtr)++);
-		data = le2be16dbl(data);
-		userCount -= 4;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-
-
-static long ata_ctx_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			  long *frameUsed, long frameLeft)
-{
-    /* this should help gcc to stuff everything into registers */
-    u_long data = sound.data;
-    long bal = sound.bal;
-    long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed;
-    long used, usedf;
-
-    used = userCount;
-    usedf = frameLeft;
-    if (!sound.soft.stereo) {
-	u_short *p = (u_short *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 2)
-		    break;
-		data = get_user(((u_short *)userPtr)++);
-		data = le2be16(data) ^ 0x8000;
-		userCount -= 2;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    } else {
-	u_long *p = (u_long *)&frame[*frameUsed];
-	while (frameLeft >= 4) {
-	    if (bal < 0) {
-		if (userCount < 4)
-		    break;
-		data = get_user(((u_int *)userPtr)++);
-		data = le2be16dbl(data) ^ 0x80008000;
-		userCount -= 4;
-		bal += hSpeed;
-	    }
-	    *p++ = data;
-	    frameLeft -= 4;
-	    bal -= sSpeed;
-	}
-    }
-    sound.bal = bal;
-    sound.data = data;
-    used -= userCount;
-    *frameUsed += usedf-frameLeft;
-    return(used);
-}
-#endif /* CONFIG_ATARI */
-
-
-#ifdef CONFIG_AMIGA
-static long ami_ct_law(const u_char *userPtr, long userCount, u_char frame[],
-		       long *frameUsed, long frameLeft)
-{
-    char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8;
-    long count, used;
-
-    if (!sound.soft.stereo) {
-	u_char *p = &frame[*frameUsed];
-	count = min(userCount, frameLeft) & ~1;
-	used = count;
-	while (count > 0) {
-	    *p++ = table[get_user(userPtr++)];
-	    count--;
-	}
-    } else {
-	u_char *left = &frame[*frameUsed>>1];
-	u_char *right = left+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    *left++ = table[get_user(userPtr++)];
-	    *right++ = table[get_user(userPtr++)];
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_s8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft)
-{
-    long count, used;
-
-    if (!sound.soft.stereo) {
-	void *p = &frame[*frameUsed];
-	count = min(userCount, frameLeft) & ~1;
-	used = count;
-	copy_from_user(p, userPtr, count);
-    } else {
-	u_char *left = &frame[*frameUsed>>1];
-	u_char *right = left+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    *left++ = get_user(userPtr++);
-	    *right++ = get_user(userPtr++);
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_u8(const u_char *userPtr, long userCount, u_char frame[],
-		      long *frameUsed, long frameLeft)
-{
-    long count, used;
-
-    if (!sound.soft.stereo) {
-	char *p = &frame[*frameUsed];
-	count = min(userCount, frameLeft) & ~1;
-	used = count;
-	while (count > 0) {
-	    *p++ = get_user(userPtr++) ^ 0x80;
-	    count--;
-	}
-    } else {
-	u_char *left = &frame[*frameUsed>>1];
-	u_char *right = left+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    *left++ = get_user(userPtr++) ^ 0x80;
-	    *right++ = get_user(userPtr++) ^ 0x80;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_s16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_char *high = &frame[*frameUsed>>1];
-	u_char *low = high+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    *high = data>>8;
-	    *low = (data>>2) & 0x3f;
-	    count--;
-	}
-    } else {
-	u_char *lefth = &frame[*frameUsed>>2];
-	u_char *leftl = lefth+sq.block_size_quarter;
-	u_char *righth = lefth+sq.block_size_half;
-	u_char *rightl = righth+sq.block_size_quarter;
-	count = min(userCount, frameLeft)>>2 & ~1;
-	used = count*4;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    *lefth = data>>8;
-	    *leftl = (data>>2) & 0x3f;
-	    data = get_user(((u_short *)userPtr)++);
-	    *righth = data>>8;
-	    *rightl = (data>>2) & 0x3f;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_u16be(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_char *high = &frame[*frameUsed>>1];
-	u_char *low = high+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-	    *high = data>>8;
-	    *low = (data>>2) & 0x3f;
-	    count--;
-	}
-    } else {
-	u_char *lefth = &frame[*frameUsed>>2];
-	u_char *leftl = lefth+sq.block_size_quarter;
-	u_char *righth = lefth+sq.block_size_half;
-	u_char *rightl = righth+sq.block_size_quarter;
-	count = min(userCount, frameLeft)>>2 & ~1;
-	used = count*4;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-	    *lefth = data>>8;
-	    *leftl = (data>>2) & 0x3f;
-	    data = get_user(((u_short *)userPtr)++) ^ 0x8000;
-	    *righth = data>>8;
-	    *rightl = (data>>2) & 0x3f;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_s16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_char *high = &frame[*frameUsed>>1];
-	u_char *low = high+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data);
-	    *high = data>>8;
-	    *low = (data>>2) & 0x3f;
-	    count--;
-	}
-    } else {
-	u_char *lefth = &frame[*frameUsed>>2];
-	u_char *leftl = lefth+sq.block_size_quarter;
-	u_char *righth = lefth+sq.block_size_half;
-	u_char *rightl = righth+sq.block_size_quarter;
-	count = min(userCount, frameLeft)>>2 & ~1;
-	used = count*4;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data);
-	    *lefth = data>>8;
-	    *leftl = (data>>2) & 0x3f;
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data);
-	    *righth = data>>8;
-	    *rightl = (data>>2) & 0x3f;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-
-
-static long ami_ct_u16le(const u_char *userPtr, long userCount, u_char frame[],
-			 long *frameUsed, long frameLeft)
-{
-    long count, used;
-    u_long data;
-
-    if (!sound.soft.stereo) {
-	u_char *high = &frame[*frameUsed>>1];
-	u_char *low = high+sq.block_size_half;
-	count = min(userCount, frameLeft)>>1 & ~1;
-	used = count*2;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data) ^ 0x8000;
-	    *high = data>>8;
-	    *low = (data>>2) & 0x3f;
-	    count--;
-	}
-    } else {
-	u_char *lefth = &frame[*frameUsed>>2];
-	u_char *leftl = lefth+sq.block_size_quarter;
-	u_char *righth = lefth+sq.block_size_half;
-	u_char *rightl = righth+sq.block_size_quarter;
-	count = min(userCount, frameLeft)>>2 & ~1;
-	used = count*4;
-	while (count > 0) {
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data) ^ 0x8000;
-	    *lefth = data>>8;
-	    *leftl = (data>>2) & 0x3f;
-	    data = get_user(((u_short *)userPtr)++);
-	    data = le2be16(data) ^ 0x8000;
-	    *righth = data>>8;
-	    *rightl = (data>>2) & 0x3f;
-	    count--;
-	}
-    }
-    *frameUsed += used;
-    return(used);
-}
-#endif /* CONFIG_AMIGA */
-
-
-#ifdef CONFIG_ATARI
-static TRANS transTTNormal = {
-    ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, NULL, NULL, NULL, NULL
-};
-
-static TRANS transTTExpanding = {
-    ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, NULL, NULL, NULL, NULL
-};
-
-static TRANS transFalconNormal = {
-    ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, ata_ct_s16be, ata_ct_u16be,
-    ata_ct_s16le, ata_ct_u16le
-};
-
-static TRANS transFalconExpanding = {
-    ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, ata_ctx_s16be,
-    ata_ctx_u16be, ata_ctx_s16le, ata_ctx_u16le
-};
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static TRANS transAmiga = {
-    ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8, ami_ct_s16be, ami_ct_u16be,
-    ami_ct_s16le, ami_ct_u16le
-};
-#endif /* CONFIG_AMIGA */
-
-
-/*** Low level stuff *********************************************************/
-
-
-#ifdef CONFIG_ATARI
-
-/*
- * Atari (TT/Falcon)
- */
-
-static void *AtaAlloc(unsigned int size, int flags)
-{
-    int order;
-    unsigned int a_size;
-    order = 0;
-    a_size = PAGE_SIZE;
-    while (a_size < size) {
-	order++;
-	a_size <<= 1;
-    }
-    return (void *) __get_dma_pages(flags, order);
-}
-
-static void AtaFree(void *obj, unsigned int size)
-{
-    int order;
-    unsigned int a_size;
-    order = 0;
-    a_size = PAGE_SIZE;
-    while (a_size < size) {
-	order++;
-	a_size <<= 1;
-    }
-    free_pages ((unsigned long) obj, order);
-}
-
-static int AtaIrqInit(void)
-{
-    /* Set up timer A. Timer A
-    will receive a signal upon end of playing from the sound
-    hardware. Furthermore Timer A is able to count events
-    and will cause an interrupt after a programmed number
-    of events. So all we need to keep the music playing is
-    to provide the sound hardware with new data upon
-    an interrupt from timer A. */
-    mfp.tim_ct_a = 0;		/* ++roman: Stop timer before programming! */
-    mfp.tim_dt_a = 1;		/* Cause interrupt after first event. */
-    mfp.tim_ct_a = 8;		/* Turn on event counting. */
-    /* Register interrupt handler. */
-    add_isr(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW, NULL, "DMA sound");
-    mfp.int_en_a |= 0x20;	/* Turn interrupt on. */
-    mfp.int_mk_a |= 0x20;
-    return(1);
-}
-
-
-#define TONE_VOXWARE_TO_DB(v) \
-	(((v) < 0) ? -12 : ((v) > 100) ? 12 : ((v) - 50) * 6 / 25)
-#define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50)
-
-
-static int AtaSetBass(int bass)
-{
-    sound.bass = TONE_VOXWARE_TO_DB(bass);
-    atari_microwire_cmd(MW_LM1992_BASS(sound.bass));
-    return(TONE_DB_TO_VOXWARE(sound.bass));
-}
-
-
-static int AtaSetTreble(int treble)
-{
-    sound.treble = TONE_VOXWARE_TO_DB(treble);
-    atari_microwire_cmd(MW_LM1992_TREBLE(sound.treble));
-    return(TONE_DB_TO_VOXWARE(sound.treble));
-}
-
-
-
-/*
- * TT
- */
-
-
-static void TTSilence(void)
-{
-    tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-    atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */
-}
-
-
-static void TTInit(void)
-{
-    int mode, i, idx;
-    const int freq[4] = {50066, 25033, 12517, 6258};
-
-    /* search a frequency that fits into the allowed error range */
-
-    idx = -1;
-    for (i = 0; i < arraysize(freq); i++)
-	/* this isn't as much useful for a TT than for a Falcon, but
-	 * then it doesn't hurt very much to implement it for a TT too.
-	 */
-	if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius)
-	    idx = i;
-    if (idx > -1) {
-	sound.soft.speed = freq[idx];
-	sound.trans = &transTTNormal;
-    } else
-	sound.trans = &transTTExpanding;
-
-    TTSilence();
-    sound.hard = sound.soft;
-
-    if (sound.hard.speed > 50066) {
-	/* we would need to squeeze the sound, but we won't do that */
-	sound.hard.speed = 50066;
-	mode = DMASND_MODE_50KHZ;
-	sound.trans = &transTTNormal;
-    } else if (sound.hard.speed > 25033) {
-	sound.hard.speed = 50066;
-	mode = DMASND_MODE_50KHZ;
-    } else if (sound.hard.speed > 12517) {
-	sound.hard.speed = 25033;
-	mode = DMASND_MODE_25KHZ;
-    } else if (sound.hard.speed > 6258) {
-	sound.hard.speed = 12517;
-	mode = DMASND_MODE_12KHZ;
-    } else {
-	sound.hard.speed = 6258;
-	mode = DMASND_MODE_6KHZ;
-    }
-
-    tt_dmasnd.mode = (sound.hard.stereo ?
-		      DMASND_MODE_STEREO : DMASND_MODE_MONO) |
-		     DMASND_MODE_8BIT | mode;
-
-    sound.bal = -sound.soft.speed;
-}
-
-
-static int TTSetFormat(int format)
-{
-    /* TT sound DMA supports only 8bit modes */
-
-    switch (format) {
-	case AFMT_QUERY:
-	    return(sound.soft.format);
-	case AFMT_MU_LAW:
-	case AFMT_A_LAW:
-	case AFMT_S8:
-	case AFMT_U8:
-	    break;
-	default:
-	    format = AFMT_S8;
-    }
-
-    sound.soft.format = format;
-    sound.soft.size = 8;
-    if (sound.minDev == SND_DEV_DSP) {
-	sound.dsp.format = format;
-	sound.dsp.size = 8;
-    }
-    TTInit();
-
-    return(format);
-}
-
-
-#define VOLUME_VOXWARE_TO_DB(v) \
-	(((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40)
-#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2)
-
-
-static int TTSetVolume(int volume)
-{
-    sound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff);
-    atari_microwire_cmd(MW_LM1992_BALLEFT(sound.volume_left));
-    sound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8);
-    atari_microwire_cmd(MW_LM1992_BALRIGHT(sound.volume_right));
-    return(VOLUME_DB_TO_VOXWARE(sound.volume_left) |
-	   (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8));
-}
-
-
-
-/*
- * Falcon
- */
-
-
-static void FalconSilence(void)
-{
-    /* stop playback, set sample rate 50kHz for PSG sound */
-    tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-    tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT;
-    tt_dmasnd.int_div = 0; /* STE compatible divider */
-    tt_dmasnd.int_ctrl = 0x0;
-    tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */
-    tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */
-    tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */
-    tt_dmasnd.adc_src = 3; /* ADC Input = PSG */
-}
-
-
-static void FalconInit(void)
-{
-    int divider, i, idx;
-    const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195};
-
-    /* search a frequency that fits into the allowed error range */
-
-    idx = -1;
-    for (i = 0; i < arraysize(freq); i++)
-	/* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would
-	 * be playable without expanding, but that now a kernel runtime
-	 * option
-	 */
-	if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius)
-	    idx = i;
-    if (idx > -1) {
-	sound.soft.speed = freq[idx];
-	sound.trans = &transFalconNormal;
-    } else
-	sound.trans = &transFalconExpanding;
-
-    FalconSilence();
-    sound.hard = sound.soft;
-
-    if (sound.hard.size == 16) {
-	/* the Falcon can play 16bit samples only in stereo */
-	sound.hard.stereo = 1;
-    }
-
-    if (sound.hard.speed > 49170) {
-	/* we would need to squeeze the sound, but we won't do that */
-	sound.hard.speed = 49170;
-	divider = 1;
-	sound.trans = &transFalconNormal;
-    } else if (sound.hard.speed > 32780) {
-	sound.hard.speed = 49170;
-	divider = 1;
-    } else if (sound.hard.speed > 24585) {
-	sound.hard.speed = 32780;
-	divider = 2;
-    } else if (sound.hard.speed > 19668) {
-	sound.hard.speed = 24585;
-	divider = 3;
-    } else if (sound.hard.speed > 16390) {
-	sound.hard.speed = 19668;
-	divider = 4;
-    } else if (sound.hard.speed > 12292) {
-	sound.hard.speed = 16390;
-	divider = 5;
-    } else if (sound.hard.speed > 9834) {
-	sound.hard.speed = 12292;
-	divider = 7;
-    } else if (sound.hard.speed > 8195) {
-	sound.hard.speed = 9834;
-	divider = 9;
-    } else {
-	sound.hard.speed = 8195;
-	divider = 11;
-    }
-    tt_dmasnd.int_div = divider;
-
-    /* Setup Falcon sound DMA for playback */
-    tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */
-    tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */
-    tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */
-    tt_dmasnd.cbar_dst = 0x0000;
-    tt_dmasnd.rec_track_select = 0;
-    tt_dmasnd.dac_src = 2; /* connect matrix to DAC */
-    tt_dmasnd.adc_src = 0; /* ADC Input = Mic */
-
-    tt_dmasnd.mode = (sound.hard.stereo ?
-		      DMASND_MODE_STEREO : DMASND_MODE_MONO) |
-		     ((sound.hard.size == 8) ?
-		       DMASND_MODE_8BIT : DMASND_MODE_16BIT) |
-		     DMASND_MODE_6KHZ;
-
-    sound.bal = -sound.soft.speed;
-}
-
-
-static int FalconSetFormat(int format)
-{
-    int size;
-    /* Falcon sound DMA supports 8bit and 16bit modes */
-
-    switch (format) {
-	case AFMT_QUERY:
-	    return(sound.soft.format);
-	case AFMT_MU_LAW:
-	case AFMT_A_LAW:
-	case AFMT_U8:
-	case AFMT_S8:
-	    size = 8;
-	    break;
-	case AFMT_S16_BE:
-	case AFMT_U16_BE:
-	case AFMT_S16_LE:
-	case AFMT_U16_LE:
-	    size = 16;
-	    break;
-	default: /* :-) */
-	    size = 8;
-	    format = AFMT_S8;
-    }
-
-    sound.soft.format = format;
-    sound.soft.size = size;
-    if (sound.minDev == SND_DEV_DSP) {
-	sound.dsp.format = format;
-	sound.dsp.size = sound.soft.size;
-    }
-
-    FalconInit();
-
-    return(format);
-}
-
-
-/* This is for the Falcon output *attenuation* in 1.5dB steps,
- * i.e. output level from 0 to -22.5dB in -1.5dB steps.
- */
-#define VOLUME_VOXWARE_TO_ATT(v) \
-	((v) < 0 ? 15 : (v) > 100 ? 0 : 15 - (v) * 3 / 20)
-#define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3)
-
-
-static int FalconSetVolume(int volume)
-{
-    sound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff);
-    sound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8);
-    tt_dmasnd.output_atten = sound.volume_left << 8 | sound.volume_right << 4;
-    return(VOLUME_ATT_TO_VOXWARE(sound.volume_left) |
-	   VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8);
-}
-
-
-static void ata_sq_play_next_frame(int index)
-{
-    char *start, *end;
-
-    /* used by AtaPlay() if all doubts whether there really is something
-     * to be played are already wiped out.
-     */
-    start = sq_block_address(sq.front);
-    end = start+((sq.count == index) ? sq.rear_size : sq.block_size);
-    /* end might not be a legal virtual address. */
-    DMASNDSetEnd(VTOP(end - 1) + 1);
-    DMASNDSetBase(VTOP(start));
-	/* Since only an even number of samples per frame can
-	be played, we might lose one byte here. (TO DO) */
-    sq.front = (sq.front+1) % sq.max_count;
-    sq.playing++;
-    tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT;
-}
-
-
-static void AtaPlay(void)
-{
-    /* ++TeSche: Note that sq.playing is no longer just a flag but holds
-     * the number of frames the DMA is currently programmed for instead,
-     * may be 0, 1 (currently being played) or 2 (pre-programmed).
-     *
-     * Changes done to sq.count and sq.playing are a bit more subtle again
-     * so now I must admit I also prefer disabling the irq here rather
-     * than considering all possible situations. But the point is that
-     * disabling the irq doesn't have any bad influence on this version of
-     * the driver as we benefit from having pre-programmed the DMA
-     * wherever possible: There's no need to reload the DMA at the exact
-     * time of an interrupt but only at some time while the pre-programmed
-     * frame is playing!
-     */
-    atari_disable_irq(IRQ_MFP_TIMA);
-
-    if (sq.playing == 2 ||	/* DMA is 'full' */
-	sq.count <= 0) {	/* nothing to do */
-	atari_enable_irq(IRQ_MFP_TIMA);
-	return;
-    }
-
-    if (sq.playing == 0) {
-	/* looks like there's nothing 'in' the DMA yet, so try
-	 * to put two frames into it (at least one is available).
-	 */
-	if (sq.count == 1 && sq.rear_size < sq.block_size && !sq.syncing) {
-	    /* hmmm, the only existing frame is not
-	     * yet filled and we're not syncing?
-	     */
-	    atari_enable_irq(IRQ_MFP_TIMA);
-	    return;
-	}
-	ata_sq_play_next_frame(1);
-	if (sq.count == 1) {
-	    /* no more frames */
-	    atari_enable_irq(IRQ_MFP_TIMA);
-	    return;
-	}
-	if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) {
-	    /* hmmm, there were two frames, but the second
-	     * one is not yet filled and we're not syncing?
-	     */
-	    atari_enable_irq(IRQ_MFP_TIMA);
-	    return;
-	}
-	ata_sq_play_next_frame(2);
-    } else {
-	/* there's already a frame being played so we may only stuff
-	 * one new into the DMA, but even if this may be the last
-	 * frame existing the previous one is still on sq.count.
-	 */
-	if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) {
-	    /* hmmm, the only existing frame is not
-	     * yet filled and we're not syncing?
-	     */
-	    atari_enable_irq(IRQ_MFP_TIMA);
-	    return;
-	}
-	ata_sq_play_next_frame(2);
-    }
-    atari_enable_irq(IRQ_MFP_TIMA);
-}
-
-
-static void ata_sq_interrupt(int irq, struct pt_regs *fp, void *dummy)
-{
-#if 0
-    /* ++TeSche: if you should want to test this... */
-    static int cnt = 0;
-    if (sq.playing == 2)
-	if (++cnt == 10) {
-	    /* simulate losing an interrupt */
-	    cnt = 0;
-	    return;
-	}
-#endif
-
-    if (sq.ignore_int && (sound.mach.type == DMASND_FALCON)) {
-	/* ++TeSche: Falcon only: ignore first irq because it comes
-	 * immediately after starting a frame. after that, irqs come
-	 * (almost) like on the TT.
-	 */
-	sq.ignore_int = 0;
-	return;
-    }
-
-    if (!sq.playing) {
-	/* playing was interrupted and sq_reset() has already cleared
-	 * the sq variables, so better don't do anything here.
-	 */
-	WAKE_UP(sq.sync_queue);
-	return;
-    }
-
-    /* Probably ;) one frame is finished. Well, in fact it may be that a
-     * pre-programmed one is also finished because there has been a long
-     * delay in interrupt delivery and we've completely lost one, but
-     * there's no way to detect such a situation. In such a case the last
-     * frame will be played more than once and the situation will recover
-     * as soon as the irq gets through.
-     */
-    sq.count--;
-    sq.playing--;
-
-    if (!sq.playing) {
-	tt_dmasnd.ctrl = DMASND_CTRL_OFF;
-	sq.ignore_int = 1;
-    }
-
-    WAKE_UP(sq.write_queue);
-	/* At least one block of the queue is free now
-	so wake up a writing process blocked because
-	of a full queue. */
-
-    if ((sq.playing != 1) || (sq.count != 1))
-	/* We must be a bit carefully here: sq.count indicates the
-	 * number of buffers used and not the number of frames to
-	 * be played. If sq.count==1 and sq.playing==1 that means
-	 * the only remaining frame was already programmed earlier
-	 * (and is currently running) so we mustn't call AtaPlay()
-	 * here, otherwise we'll play one frame too much.
-	 */
-	AtaPlay();
-
-    if (!sq.playing) WAKE_UP(sq.sync_queue);
-	/* We are not playing after AtaPlay(), so there
-	is nothing to play any more. Wake up a process
-	waiting for audio output to drain. */
-}
-#endif /* CONFIG_ATARI */
-
-
-#ifdef CONFIG_AMIGA
-
-/*
- * Amiga
- */
-
-
-static void *AmiAlloc(unsigned int size, int flags)
-{
-    return(amiga_chip_alloc((long)size));
-}
-
-static void AmiFree(void *obj, unsigned int size)
-{
-    amiga_chip_free (obj);
-}
-
-static int AmiIrqInit(void)
-{
-    /* turn off DMA for audio channels */
-    custom.dmacon = AMI_AUDIO_OFF;
-
-    /* Register interrupt handler. */
-    if (!add_isr(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0, NULL, "DMA sound"))
-	panic("Couldn't add audio interrupt");
-    return(1);
-}
-
-
-static void AmiSilence(void)
-{
-    /* turn off DMA for audio channels */
-    custom.dmacon = AMI_AUDIO_OFF;
-}
-
-
-static void AmiInit(void)
-{
-    int period, i;
-
-    AmiSilence();
-
-    if (sound.soft.speed)
-	period = amiga_colorclock/sound.soft.speed-1;
-    else
-	period = amiga_audio_min_period;
-    sound.hard = sound.soft;
-    sound.trans = &transAmiga;
-
-    if (period < amiga_audio_min_period) {
-	/* we would need to squeeze the sound, but we won't do that */
-	period = amiga_audio_min_period;
-	sound.hard.speed = amiga_colorclock/(period+1);
-    } else if (period > 65535) {
-	period = 65535;
-	sound.hard.speed = amiga_colorclock/(period+1);
-    }
-    for (i = 0; i < 4; i++)
-	custom.aud[i].audper = period;
-    amiga_audio_period = period;
-}
-
-
-static int AmiSetFormat(int format)
-{
-    int size;
-
-    /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */
-
-    switch (format) {
-	case AFMT_QUERY:
-	    return(sound.soft.format);
-	case AFMT_MU_LAW:
-	case AFMT_A_LAW:
-	case AFMT_U8:
-	case AFMT_S8:
-	    size = 8;
-	    break;
-	case AFMT_S16_BE:
-	case AFMT_U16_BE:
-	case AFMT_S16_LE:
-	case AFMT_U16_LE:
-	    size = 16;
-	    break;
-	default: /* :-) */
-	    size = 8;
-	    format = AFMT_S8;
-    }
-
-    sound.soft.format = format;
-    sound.soft.size = size;
-    if (sound.minDev == SND_DEV_DSP) {
-	sound.dsp.format = format;
-	sound.dsp.size = sound.soft.size;
-    }
-    AmiInit();
-
-    return(format);
-}
-
-
-#define VOLUME_VOXWARE_TO_AMI(v) \
-	(((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100)
-#define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64)
-
-static int AmiSetVolume(int volume)
-{
-    sound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff);
-    custom.aud[0].audvol = sound.volume_left;
-    sound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8);
-    custom.aud[1].audvol = sound.volume_right;
-    return(VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
-	   (VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
-}
-
-static int AmiSetTreble(int treble)
-{
-    sound.treble = treble;
-    if (treble > 50)
-	ciaa.pra |= 0x02;
-    else
-	ciaa.pra &= ~0x02;
-    return(treble);
-}
-
-
-#define AMI_PLAY_LOADED		1
-#define AMI_PLAY_PLAYING	2
-#define AMI_PLAY_MASK		3
-
-
-static void ami_sq_play_next_frame(int index)
-{
-    u_char *start, *ch0, *ch1, *ch2, *ch3;
-    u_long size;
-
-    /* used by AmiPlay() if all doubts whether there really is something
-     * to be played are already wiped out.
-     */
-    start = sq_block_address(sq.front);
-    size = (sq.count == index ? sq.rear_size : sq.block_size)>>1;
-
-    if (sound.hard.stereo) {
-	ch0 = start;
-	ch1 = start+sq.block_size_half;
-	size >>= 1;
-    } else {
-	ch0 = start;
-	ch1 = start;
-    }
-    if (sound.hard.size == 8) {
-	custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
-	custom.aud[0].audlen = size;
-	custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
-	custom.aud[1].audlen = size;
-	custom.dmacon = AMI_AUDIO_8;
-    } else {
-	size >>= 1;
-	custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
-	custom.aud[0].audlen = size;
-	custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
-	custom.aud[1].audlen = size;
-	if (sound.volume_left == 64 && sound.volume_right == 64) {
-	    /* We can play pseudo 14-bit only with the maximum volume */
-	    ch3 = ch0+sq.block_size_quarter;
-	    ch2 = ch1+sq.block_size_quarter;
-	    custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2);
-	    custom.aud[2].audlen = size;
-	    custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3);
-	    custom.aud[3].audlen = size;
-	    custom.dmacon = AMI_AUDIO_14;
-	} else
-	    custom.dmacon = AMI_AUDIO_8;
-    }
-    sq.front = (sq.front+1) % sq.max_count;
-    sq.playing |= AMI_PLAY_LOADED;
-}
-
-
-static void AmiPlay(void)
-{
-    int minframes = 1;
-
-    custom.intena = IF_AUD0;
-
-    if (sq.playing & AMI_PLAY_LOADED) {
-	/* There's already a frame loaded */
-	custom.intena = IF_SETCLR | IF_AUD0;
-	return;
-    }
-
-    if (sq.playing & AMI_PLAY_PLAYING)
-	/* Increase threshold: frame 1 is already being played */
-	minframes = 2;
-
-    if (sq.count < minframes) {
-	/* Nothing to do */
-	custom.intena = IF_SETCLR | IF_AUD0;
-	return;
-    }
-
-    if (sq.count <= minframes && sq.rear_size < sq.block_size && !sq.syncing) {
-	/* hmmm, the only existing frame is not
-	 * yet filled and we're not syncing?
-	 */
-	custom.intena = IF_SETCLR | IF_AUD0;
-	return;
-    }
-
-    ami_sq_play_next_frame(minframes);
-
-    custom.intena = IF_SETCLR | IF_AUD0;
-}
-
-
-static void ami_sq_interrupt(int irq, struct pt_regs *fp, void *dummy)
-{
-    int minframes = 1;
-
-    if (!sq.playing) {
-	/* Playing was interrupted and sq_reset() has already cleared
-	 * the sq variables, so better don't do anything here.
-	 */
-	WAKE_UP(sq.sync_queue);
-	return;
-    }
-
-    if (sq.playing & AMI_PLAY_PLAYING) {
-	/* We've just finished a frame */
-	sq.count--;
-	WAKE_UP(sq.write_queue);
-    }
-
-    if (sq.playing & AMI_PLAY_LOADED)
-	/* Increase threshold: frame 1 is already being played */
-	minframes = 2;
-
-    /* Shift the flags */
-    sq.playing = (sq.playing<<1) & AMI_PLAY_MASK;
-
-    if (!sq.playing)
-	/* No frame is playing, disable audio DMA */
-	custom.dmacon = AMI_AUDIO_OFF;
-
-    if (sq.count >= minframes)
-    	/* Try to play the next frame */
-	AmiPlay();
-
-    if (!sq.playing)
-	/* Nothing to play anymore.
-	   Wake up a process waiting for audio output to drain. */
-	WAKE_UP(sq.sync_queue);
-}
-#endif /* CONFIG_AMIGA */
-
-
-/*** Machine definitions *****************************************************/
-
-
-#ifdef CONFIG_ATARI
-static MACHINE machTT = {
-    DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit, TTInit, TTSilence, TTSetFormat,
-    TTSetVolume, AtaSetBass, AtaSetTreble, AtaPlay
-};
-
-static MACHINE machFalcon = {
-    DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit, FalconInit, FalconSilence,
-    FalconSetFormat, FalconSetVolume, AtaSetBass, AtaSetTreble, AtaPlay
-};
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-static MACHINE machAmiga = {
-    DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit, AmiInit, AmiSilence,
-    AmiSetFormat, AmiSetVolume, NULL, AmiSetTreble, AmiPlay
-};
-#endif /* CONFIG_AMIGA */
-
-
-/*** Mid level stuff *********************************************************/
-
-
-static void sound_silence(void)
-{
-    /* update hardware settings one more */
-    (*sound.mach.init)();
-
-    (*sound.mach.silence)();
-}
-
-
-static void sound_init(void)
-{
-    (*sound.mach.init)();
-}
-
-
-static int sound_set_format(int format)
-{
-    return(*sound.mach.setFormat)(format);
-}
-
-
-static int sound_set_speed(int speed)
-{
-    if (speed < 0)
-	return(sound.soft.speed);
-
-    sound.soft.speed = speed;
-    (*sound.mach.init)();
-    if (sound.minDev == SND_DEV_DSP)
-	sound.dsp.speed = sound.soft.speed;
-
-    return(sound.soft.speed);
-}
-
-
-static int sound_set_stereo(int stereo)
-{
-    if (stereo < 0)
-	return(sound.soft.stereo);
-
-    stereo = !!stereo;    /* should be 0 or 1 now */
-
-    sound.soft.stereo = stereo;
-    if (sound.minDev == SND_DEV_DSP)
-	sound.dsp.stereo = stereo;
-    (*sound.mach.init)();
-
-    return(stereo);
-}
-
-
-static int sound_set_volume(int volume)
-{
-    return(*sound.mach.setVolume)(volume);
-}
-
-
-#ifdef CONFIG_ATARI
-static int sound_set_bass(int bass)
-{
-    return(sound.mach.setBass ? (*sound.mach.setBass)(bass) : 50);
-}
-#endif /* CONFIG_ATARI */
-
-
-static int sound_set_treble(int treble)
-{
-    return(sound.mach.setTreble ? (*sound.mach.setTreble)(treble) : 50);
-}
-
-
-static long sound_copy_translate(const u_char *userPtr, long userCount,
-				 u_char frame[], long *frameUsed,
-				 long frameLeft)
-{
-    long (*ct_func)(const u_char *, long, u_char *, long *, long) = NULL;
-
-    switch (sound.soft.format) {
-	case AFMT_MU_LAW:
-	    ct_func = sound.trans->ct_ulaw;
-	    break;
-	case AFMT_A_LAW:
-	    ct_func = sound.trans->ct_alaw;
-	    break;
-	case AFMT_S8:
-	    ct_func = sound.trans->ct_s8;
-	    break;
-	case AFMT_U8:
-	    ct_func = sound.trans->ct_u8;
-	    break;
-	case AFMT_S16_BE:
-	    ct_func = sound.trans->ct_s16be;
-	    break;
-	case AFMT_U16_BE:
-	    ct_func = sound.trans->ct_u16be;
-	    break;
-	case AFMT_S16_LE:
-	    ct_func = sound.trans->ct_s16le;
-	    break;
-	case AFMT_U16_LE:
-	    ct_func = sound.trans->ct_u16le;
-	    break;
-    }
-    if (ct_func)
-	return(ct_func(userPtr, userCount, frame, frameUsed, frameLeft));
-    else
-	return(0);
-}
-
-
-/*
- * /dev/mixer abstraction
- */
-
-
-#define RECLEVEL_VOXWARE_TO_GAIN(v) \
-	((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20)
-#define RECLEVEL_GAIN_TO_VOXWARE(v) (((v) * 20 + 2) / 3)
-
-
-static void mixer_init(void)
-{
-    mixer.busy = 0;
-    sound.treble = 0;
-    sound.bass = 0;
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_TT:
-	    atari_microwire_cmd(MW_LM1992_VOLUME(0));
-	    sound.volume_left = 0;
-	    atari_microwire_cmd(MW_LM1992_BALLEFT(0));
-	    sound.volume_right = 0;
-	    atari_microwire_cmd(MW_LM1992_BALRIGHT(0));
-	    atari_microwire_cmd(MW_LM1992_TREBLE(0));
-	    atari_microwire_cmd(MW_LM1992_BASS(0));
-	    break;
-	case DMASND_FALCON:
-	    sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;
-	    sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;
-	    break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-	    sound.volume_left = 64;
-	    sound.volume_right = 64;
-	    custom.aud[0].audvol = sound.volume_left;
-	    custom.aud[3].audvol = 1;			/* For pseudo 14bit */
-	    custom.aud[1].audvol = sound.volume_right;
-	    custom.aud[2].audvol = 1;			/* For pseudo 14bit */
-	    sound.treble = 50;
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-}
-
-
-static int mixer_open(int open_mode)
-{
-    if (mixer.busy)
-	return(-EBUSY);
-    mixer.busy = 1;
-    return(0);
-}
-
-
-static int mixer_release(void)
-{
-    mixer.busy = 0;
-    return(0);
-}
-
-
-static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg)
-{
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_FALCON:
-	    switch (cmd) {
-		case SOUND_MIXER_READ_DEVMASK:
-		    return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
-		case SOUND_MIXER_READ_RECMASK:
-		    return(IOCTL_OUT(arg, SOUND_MASK_MIC));
-		case SOUND_MIXER_READ_STEREODEVS:
-		    return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC));
-		case SOUND_MIXER_READ_CAPS:
-		    return(IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT));
-		case SOUND_MIXER_READ_VOLUME:
-		    return(IOCTL_OUT(arg,
-			VOLUME_ATT_TO_VOXWARE(sound.volume_left) |
-			VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8));
-		case SOUND_MIXER_WRITE_MIC:
-		    tt_dmasnd.input_gain =
-			RECLEVEL_VOXWARE_TO_GAIN(IOCTL_IN(arg) & 0xff) << 4 |
-			RECLEVEL_VOXWARE_TO_GAIN(IOCTL_IN(arg) >> 8 & 0xff);
-		    /* fall thru, return set value */
-		case SOUND_MIXER_READ_MIC:
-		    return(IOCTL_OUT(arg,
-			RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) |
-			RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8));
-		case SOUND_MIXER_READ_SPEAKER:
-		    {
-			int porta;
-			cli();
-			sound_ym.rd_data_reg_sel = 14;
-			porta = sound_ym.rd_data_reg_sel;
-			sti();
-			return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-		    }
-		case SOUND_MIXER_WRITE_VOLUME:
-		    return(IOCTL_OUT(arg, sound_set_volume(IOCTL_IN(arg))));
-		case SOUND_MIXER_WRITE_SPEAKER:
-		    {
-			int porta;
-			cli();
-			sound_ym.rd_data_reg_sel = 14;
-			porta = (sound_ym.rd_data_reg_sel & ~0x40) |
-				(IOCTL_IN(arg) < 50 ? 0x40 : 0);
-			sound_ym.wd_data = porta;
-			sti();
-			return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-		    }
-	    }
-	    break;
-
-	case DMASND_TT:
-	    switch (cmd) {
-		case SOUND_MIXER_READ_DEVMASK:
-		    return(IOCTL_OUT(arg,
-			SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
-			((boot_info.bi_atari.mch_cookie >> 16) == ATARI_MCH_TT ?
-			    SOUND_MASK_SPEAKER : 0)));
-		case SOUND_MIXER_READ_RECMASK:
-		    return(IOCTL_OUT(arg, 0));
-		case SOUND_MIXER_READ_STEREODEVS:
-		    return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
-		case SOUND_MIXER_READ_VOLUME:
-		    return(IOCTL_OUT(arg,
-			VOLUME_DB_TO_VOXWARE(sound.volume_left) |
-			(VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)));
-		case SOUND_MIXER_READ_BASS:
-		    return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass)));
-		case SOUND_MIXER_READ_TREBLE:
-		    return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble)));
-		case SOUND_MIXER_READ_SPEAKER:
-		    {
-			int porta;
-			if ((boot_info.bi_atari.mch_cookie >> 16) == ATARI_MCH_TT) {
-			    cli();
-			    sound_ym.rd_data_reg_sel = 14;
-			    porta = sound_ym.rd_data_reg_sel;
-			    sti();
-			    return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-			} else
-			    return(-EINVAL);
-		    }
-		case SOUND_MIXER_WRITE_VOLUME:
-		    return(IOCTL_OUT(arg, sound_set_volume(IOCTL_IN(arg))));
-		case SOUND_MIXER_WRITE_BASS:
-		    return(IOCTL_OUT(arg, sound_set_bass(IOCTL_IN(arg))));
-		case SOUND_MIXER_WRITE_TREBLE:
-		    return(IOCTL_OUT(arg, sound_set_treble(IOCTL_IN(arg))));
-		case SOUND_MIXER_WRITE_SPEAKER:
-		    if ((boot_info.bi_atari.mch_cookie >> 16) == ATARI_MCH_TT) {
-			int porta;
-			cli();
-			sound_ym.rd_data_reg_sel = 14;
-			porta = (sound_ym.rd_data_reg_sel & ~0x40) |
-				(IOCTL_IN(arg) < 50 ? 0x40 : 0);
-			sound_ym.wd_data = porta;
-			sti();
-			return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100));
-		    } else
-			return(-EINVAL);
-	    }
-	    break;
-#endif /* CONFIG_ATARI */
-
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-	    switch (cmd) {
-		case SOUND_MIXER_READ_DEVMASK:
-		    return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE));
-		case SOUND_MIXER_READ_RECMASK:
-		    return(IOCTL_OUT(arg, 0));
-		case SOUND_MIXER_READ_STEREODEVS:
-		    return(IOCTL_OUT(arg, SOUND_MASK_VOLUME));
-		case SOUND_MIXER_READ_VOLUME:
-		    return(IOCTL_OUT(arg,
-			VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
-			VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
-		case SOUND_MIXER_WRITE_VOLUME:
-		    return(IOCTL_OUT(arg, sound_set_volume(IOCTL_IN(arg))));
-		case SOUND_MIXER_READ_TREBLE:
-		    return(IOCTL_OUT(arg, sound.treble));
-		case SOUND_MIXER_WRITE_TREBLE:
-		    return(IOCTL_OUT(arg, sound_set_treble(IOCTL_IN(arg))));
-	    }
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-
-    return(-EINVAL);
-}
-
-
-
-/*
- * Sound queue stuff, the heart of the driver
- */
-
-
-static void sq_init(int numBufs, int bufSize, char **buffers)
-{
-    sq.max_count = numBufs;
-    sq.block_size = bufSize;
-    sq.buffers = buffers;
-
-    sq.front = sq.count = 0;
-    sq.rear = -1;
-    sq.write_queue = sq.open_queue = sq.sync_queue = 0;
-    sq.busy = 0;
-    sq.syncing = 0;
-
-    sq.playing = 0;
-
-#ifdef CONFIG_ATARI
-    sq.ignore_int = 0;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-    sq.block_size_half = sq.block_size>>1;
-    sq.block_size_quarter = sq.block_size_half>>1;
-#endif /* CONFIG_AMIGA */
-
-    sound_silence();
-
-    /* whatever you like as startup mode for /dev/dsp,
-     * (/dev/audio hasn't got a startup mode). note that
-     * once changed a new open() will *not* restore these!
-     */
-    sound.dsp.format = AFMT_S8;
-    sound.dsp.stereo = 0;
-    sound.dsp.size = 8;
-
-    /* set minimum rate possible without expanding */
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_TT:
-	    sound.dsp.speed = 6258;
-	    break;
-	case DMASND_FALCON:
-	    sound.dsp.speed = 8195;
-	    break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-	    sound.dsp.speed = 8000;
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-
-    /* before the first open to /dev/dsp this wouldn't be set */
-    sound.soft = sound.dsp;
-}
-
-
-static void sq_play(void)
-{
-    (*sound.mach.play)();
-}
-
-
-/* ++TeSche: radically changed this one too */
-
-static int sq_write(const char *src, int uLeft)
-{
-    int uWritten = 0;
-    u_char *dest;
-    long uUsed, bUsed, bLeft;
-
-    /* ++TeSche: Is something like this necessary?
-     * Hey, that's an honest question! Or does any other part of the
-     * filesystem already checks this situation? I really don't know.
-     */
-    if (uLeft < 1)
-	return(0);
-
-    /* The interrupt doesn't start to play the last, incomplete frame.
-     * Thus we can append to it without disabling the interrupts! (Note
-     * also that sq.rear isn't affected by the interrupt.)
-     */
-
-    if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) {
-	dest = sq_block_address(sq.rear);
-	bUsed = sq.rear_size;
-	uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
-	src += uUsed;
-	uWritten += uUsed;
-	uLeft -= uUsed;
-	sq.rear_size = bUsed;
-    }
-
-    do {
-	if (sq.count == sq.max_count) {
-	    sq_play();
-	    if (NON_BLOCKING(sq.open_mode))
-		return(uWritten > 0 ? uWritten : -EAGAIN);
-	    SLEEP(sq.write_queue, ONE_SECOND);
-	    if (SIGNAL_RECEIVED)
-		return(uWritten > 0 ? uWritten : -EINTR);
-	}
-
-	/* Here, we can avoid disabling the interrupt by first
-	 * copying and translating the data, and then updating
-	 * the sq variables. Until this is done, the interrupt
-	 * won't see the new frame and we can work on it
-	 * undisturbed.
-	 */
-
-	dest = sq_block_address((sq.rear+1) % sq.max_count);
-	bUsed = 0;
-	bLeft = sq.block_size;
-	uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft);
-	src += uUsed;
-	uWritten += uUsed;
-	uLeft -= uUsed;
-	if (bUsed) {
-	    sq.rear = (sq.rear+1) % sq.max_count;
-	    sq.rear_size = bUsed;
-	    sq.count++;
-	}
-    } while (bUsed);   /* uUsed may have been 0 */
-
-    sq_play();
-
-    return(uWritten);
-}
-
-
-static int sq_open(int open_mode)
-{
-    if (sq.busy) {
-	if (NON_BLOCKING(open_mode))
-	    return(-EBUSY);
-	while (sq.busy) {
-	    SLEEP(sq.open_queue, ONE_SECOND);
-	    if (SIGNAL_RECEIVED)
-		return(-EINTR);
-	}
-    }
-    sq.open_mode = open_mode;
-    sq.busy = 1;
-#ifdef CONFIG_ATARI
-    sq.ignore_int = 1;
-#endif /* CONFIG_ATARI */
-    return(0);
-}
-
-
-static void sq_reset(void)
-{
-    sound_silence();
-    sq.playing = 0;
-    sq.count = 0;
-    sq.front = (sq.rear+1) % sq.max_count;
-}
-
-
-static int sq_sync(void)
-{
-    int rc = 0;
-
-    sq.syncing = 1;
-    sq_play();	/* there may be an incomplete frame waiting */
-
-    while (sq.playing) {
-	SLEEP(sq.sync_queue, ONE_SECOND);
-	if (SIGNAL_RECEIVED) {
-	    /* While waiting for audio output to drain, an interrupt occurred.
-	       Stop audio output immediately and clear the queue. */
-	    sq_reset();
-	    rc = -EINTR;
-	    break;
-	}
-    }
-
-    sq.syncing = 0;
-    return(rc);
-}
-
-
-static int sq_release(void)
-{
-    int rc = 0;
-    if (sq.busy) {
-	rc = sq_sync();
-	sq.busy = 0;
-	WAKE_UP(sq.open_queue);
-	/* Wake up a process waiting for the queue being released.
-	   Note: There may be several processes waiting for a call to open()
-		 returning. */
-    }
-    return(rc);
-}
-
-
-
-/*
- * /dev/sndstat
- */
-
-
-static void state_init(void)
-{
-    state.busy = 0;
-}
-
-
-/* state.buf should not overflow! */
-
-static int state_open(int open_mode)
-{
-    char *buffer = state.buf, *mach = "";
-    int len = 0;
-
-    if (state.busy)
-	return(-EBUSY);
-
-    state.ptr = 0;
-    state.busy = 1;
-
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_TT:
-	case DMASND_FALCON:
-	    mach = "Atari ";
-	    break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-	    mach = "Amiga ";
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-    len += sprintf(buffer+len, "%sDMA sound driver:\n", mach);
-
-    len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format);
-    switch (sound.soft.format) {
-	case AFMT_MU_LAW:
-	    len += sprintf(buffer+len, " (mu-law)");
-	    break;
-	case AFMT_A_LAW:
-	    len += sprintf(buffer+len, " (A-law)");
-	    break;
-	case AFMT_U8:
-	    len += sprintf(buffer+len, " (unsigned 8 bit)");
-	    break;
-	case AFMT_S8:
-	    len += sprintf(buffer+len, " (signed 8 bit)");
-	    break;
-	case AFMT_S16_BE:
-	    len += sprintf(buffer+len, " (signed 16 bit big)");
-	    break;
-	case AFMT_U16_BE:
-	    len += sprintf(buffer+len, " (unsigned 16 bit big)");
-	    break;
-	case AFMT_S16_LE:
-	    len += sprintf(buffer+len, " (signed 16 bit little)");
-	    break;
-	case AFMT_U16_LE:
-	    len += sprintf(buffer+len, " (unsigned 16 bit little)");
-	    break;
-    }
-    len += sprintf(buffer+len, "\n");
-    len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n",
-		   sound.soft.speed, sound.hard.speed);
-    len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n",
-		   sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono");
-    switch (sound.mach.type) {
-#ifdef CONFIG_ATARI
-	case DMASND_TT:
-	    len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-40...0]\n",
-			   sound.volume_left);
-	    len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-40...0]\n",
-			   sound.volume_right);
-	    len += sprintf(buffer+len, "\tsound.bass = %ddB [-12...+12]\n",
-			   sound.bass);
-	    len += sprintf(buffer+len, "\tsound.treble = %ddB [-12...+12]\n",
-			   sound.treble);
-	    break;
-	case DMASND_FALCON:
-	    len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-22.5...0]\n",
-			   sound.volume_left);
-	    len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-22.5...0]\n",
-			   sound.volume_right);
-	    break;
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case DMASND_AMIGA:
-	    len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n",
-			   sound.volume_left);
-	    len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n",
-			   sound.volume_right);
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-    len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d\n",
-		   sq.block_size, sq.max_count);
-    len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count,
-		   sq.rear_size);
-    len += sprintf(buffer+len, "\tsq.playing = %d sq.syncing = %d\n",
-		   sq.playing, sq.syncing);
-    state.len = len;
-    return(0);
-}
-
-
-static int state_release(void)
-{
-    state.busy = 0;
-    return(0);
-}
-
-
-static int state_read(char *dest, int count)
-{
-    int n = state.len-state.ptr;
-    if (n > count)
-	n = count;
-    if (n <= 0)
-	return(0);
-    copy_to_user(dest, &state.buf[state.ptr], n);
-    state.ptr += n;
-    return(n);
-}
-
-
-
-/*** High level stuff ********************************************************/
-
-
-static int sound_open(struct inode *inode, struct file *file)
-{
-    int dev = MINOR(inode->i_rdev) & 0x0f;
-
-    switch (dev) {
-	case SND_DEV_STATUS:
-	    return(state_open(file->f_flags));
-	case SND_DEV_CTL:
-	    return(mixer_open(file->f_flags));
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-	    {
-		int rc = sq_open(file->f_flags);
-		if (rc == 0) {
-		    sound.minDev = dev;
-		    sound.soft = sound.dsp;
-		    sound_init();
-		    if (dev == SND_DEV_AUDIO) {
-			sound_set_speed(8000);
-			sound_set_stereo(0);
-			sound_set_format(AFMT_MU_LAW);
-		    }
-		}
-		return(rc);
-	    }
-	default:
-	    return(-ENXIO);
-    }
-}
-
-
-static int sound_fsync(struct inode *inode, struct file *filp)
-{
-    int dev = MINOR(inode->i_rdev) & 0x0f;
-
-    switch (dev) {
-	case SND_DEV_STATUS:
-	case SND_DEV_CTL:
-	    return(0);
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-	    return(sq_sync());
-	default:
-	    return(unknown_minor_dev("sound_fsync", dev));
-    }
-}
-
-
-static void sound_release(struct inode *inode, struct file *file)
-{
-    int dev = MINOR(inode->i_rdev);
-
-    switch (dev & 0x0f) {
-	case SND_DEV_STATUS: state_release(); return;
-	case SND_DEV_CTL: mixer_release(); return;
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-	    sq_release(); sound.soft = sound.dsp; sound_silence();
-	    return;
-	default:
-	    unknown_minor_dev("sound_release", dev);
-    }
-}
-
-
-static int sound_lseek(struct inode *inode, struct file *file, off_t offset,
-		       int orig)
-{
-    return(-EPERM);
-}
-
-
-static int sound_read(struct inode *inode, struct file *file, char *buf,
-		      int count)
-{
-    int dev = MINOR(inode->i_rdev);
-
-    switch (dev & 0x0f) {
-	case SND_DEV_STATUS:
-	    return(state_read(buf, count));
-	case SND_DEV_CTL:
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-	    return(-EPERM);
-	default:
-	    return(unknown_minor_dev("sound_read", dev));
-    }
-}
-
-
-static int sound_write(struct inode *inode, struct file *file, const char *buf,
-		       int count)
-{
-    int dev = MINOR(inode->i_rdev);
-
-    switch (dev & 0x0f) {
-	case SND_DEV_STATUS:
-	case SND_DEV_CTL:
-	    return(-EPERM);
-	case SND_DEV_DSP:
-	case SND_DEV_AUDIO:
-	    return(sq_write(buf, count));
-	default:
-	    return(unknown_minor_dev("sound_write", dev));
-    }
-}
-
-
-static int ioctl_return(int *addr, int value)
-{
-    int error;
-
-    if (value < 0)
-	return(value);
-
-    error = verify_area(VERIFY_WRITE, addr, sizeof(int));
-    if (error)
-	return(error);
-
-    put_user(value, addr);
-    return(0);
-}
-
-
-static int unknown_minor_dev(char *fname, int dev)
-{
-    /* printk("%s: Unknown minor device %d\n", fname, dev); */
-    return(-ENXIO);
-}
-
-
-static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg)
-{
-    int dev = MINOR(inode->i_rdev);
-    u_long fmt;
-
-    switch (dev & 0x0f) {
-	case SND_DEV_STATUS:
-	    return(-EPERM);
-	case SND_DEV_CTL:
-	    return(mixer_ioctl(inode, file, cmd, arg));
-	case SND_DEV_AUDIO:
-	case SND_DEV_DSP:
-	    switch (cmd) {
-		case SNDCTL_DSP_RESET:
-		    sq_reset();
-		    return(0);
-		case SNDCTL_DSP_POST:
-		case SNDCTL_DSP_SYNC:
-		    return(sound_fsync(inode, file));
-
-		/* ++TeSche: before changing any of these it's probably wise to
-		 * wait until sound playing has settled down
-		 */
-		case SNDCTL_DSP_SPEED:
-		    sound_fsync(inode, file);
-		    return(IOCTL_OUT(arg, sound_set_speed(IOCTL_IN(arg))));
-		case SNDCTL_DSP_STEREO:
-		    sound_fsync(inode, file);
-		    return(IOCTL_OUT(arg, sound_set_stereo(IOCTL_IN(arg))));
-		case SOUND_PCM_WRITE_CHANNELS:
-		    sound_fsync(inode, file);
-		    return(IOCTL_OUT(arg, sound_set_stereo(IOCTL_IN(arg)-1)+1));
-		case SNDCTL_DSP_SETFMT:
-		    sound_fsync(inode, file);
-		    return(IOCTL_OUT(arg, sound_set_format(IOCTL_IN(arg))));
-		case SNDCTL_DSP_GETFMTS:
-		    fmt = 0;
-		    if (sound.trans) {
-			if (sound.trans->ct_ulaw)
-			    fmt |= AFMT_MU_LAW;
-			if (sound.trans->ct_alaw)
-			    fmt |= AFMT_A_LAW;
-			if (sound.trans->ct_s8)
-			    fmt |= AFMT_S8;
-			if (sound.trans->ct_u8)
-			    fmt |= AFMT_U8;
-			if (sound.trans->ct_s16be)
-			    fmt |= AFMT_S16_BE;
-			if (sound.trans->ct_u16be)
-			    fmt |= AFMT_U16_BE;
-			if (sound.trans->ct_s16le)
-			    fmt |= AFMT_S16_LE;
-			if (sound.trans->ct_u16le)
-			    fmt |= AFMT_U16_LE;
-		    }
-		    return(IOCTL_OUT(arg, fmt));
-		case SNDCTL_DSP_GETBLKSIZE:
-		    return(IOCTL_OUT(arg, 10240));
-		case SNDCTL_DSP_SUBDIVIDE:
-		case SNDCTL_DSP_SETFRAGMENT:
-		    break;
-
-		default:
-		    return(mixer_ioctl(inode, file, cmd, arg));
-	    }
-	    break;
-
-	default:
-	    return(unknown_minor_dev("sound_ioctl", dev));
-    }
-    return(-EINVAL);
-}
-
-
-static struct file_operations sound_fops =
-{
-    sound_lseek,
-    sound_read,
-    sound_write,
-    NULL,
-    NULL,                      /* select */
-    sound_ioctl,
-    NULL,
-    sound_open,
-    sound_release,
-    sound_fsync
-};
-
-
-
-/*** Config & Setup **********************************************************/
-
-
-void soundcard_init(void)
-{
-    int has_sound = 0;
-    char **buffers;
-    int i;
-
-    switch (boot_info.machtype) {
-#ifdef CONFIG_ATARI
-	case MACH_ATARI:
-	    if (ATARIHW_PRESENT(PCM_8BIT)) {
-		if (ATARIHW_PRESENT(CODEC))
-		    sound.mach = machFalcon;
-		else if (ATARIHW_PRESENT(MICROWIRE))
-		    sound.mach = machTT;
-		else
-		    break;
-		if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0)
-		    has_sound = 1;
-		else
-		    printk("DMA sound driver: Timer A interrupt already in use\n");
-	    }
-	    break;
-
-#endif /* CONFIG_ATARI */
-#ifdef CONFIG_AMIGA
-	case MACH_AMIGA:
-	    if (AMIGAHW_PRESENT(AMI_AUDIO)) {
-		sound.mach = machAmiga;
-		has_sound = 1;
-	    }
-	    break;
-#endif /* CONFIG_AMIGA */
-    }
-    if (!has_sound)
-	return;
-
-    /* Set up sound queue, /dev/audio and /dev/dsp. */
-    buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
-    if (!buffers) {
-    out_of_memory:
-	printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
-	return;
-    }
-    for (i = 0; i < numBufs; i++) {
-	buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
-	if (!buffers[i]) {
-	    while (i--)
-		sound.mach.dma_free (buffers[i], bufSize << 10);
-	    kfree (buffers);
-	    goto out_of_memory;
-        }
-    }
-
-    /* Register driver with the VFS. */
-    register_chrdev(SOUND_MAJOR, "sound", &sound_fops);
-
-    sq_init(numBufs, bufSize << 10, buffers);
-
-    /* Set up /dev/sndstat. */
-    state_init();
-
-    /* Set up /dev/mixer. */
-    mixer_init();
-
-    if (!sound.mach.irqinit()) {
-	printk("DMA sound driver: Interrupt initialization failed\n");
-	return;
-    }
-
-    printk("DMA sound driver installed, using %d buffers of %dk.\n", numBufs,
-	   bufSize);
-
-    return;
-}
-
-void sound_setup(char *str, int *ints)
-{
-    /* ++Martin: stub, could possibly be merged with soundcard.c et al later */
-}
-
-void dmasound_setup(char *str, int *ints)
-{
-    /* check the bootstrap parameter for "dmasound=" */
-
-    switch (ints[0]) {
-	case 3:
-	    if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))
-		printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius);
-	    else
-		catchRadius = ints[3];
-	    /* fall through */
-	case 2:
-	    if (ints[1] < MIN_BUFFERS)
-		printk("dmasound_setup: illegal number of buffers, using default = %d\n", numBufs);
-	    else
-		numBufs = ints[1];
-	    if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE)
-		printk("dmasound_setup: illegal buffer size, using default = %d\n", bufSize);
-	    else
-		bufSize = ints[2];
-	    break;
-	case 0:
-	    break;
-	default:
-	    printk("dmasound_setup: illegal number of arguments\n");
-    }
-}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov