summaryrefslogtreecommitdiff
path: root/setup/Linux
diff options
context:
space:
mode:
Diffstat (limited to 'setup/Linux')
-rw-r--r--setup/Linux/arm/Makefile.osscore.arm17
-rw-r--r--setup/Linux/arm/Makefile.tmpl.arm21
-rw-r--r--setup/Linux/arm/bpabi.S119
-rw-r--r--setup/Linux/arm/bpabi.c375
-rw-r--r--setup/Linux/arm/bpabi.h125
-rw-r--r--setup/Linux/arm/lib1funcs.asm1393
-rw-r--r--setup/Linux/arm/longlong.h1465
-rw-r--r--setup/Linux/build.sh240
-rw-r--r--setup/Linux/build_arm.sh96
-rw-r--r--setup/Linux/confgen.c188
-rw-r--r--setup/Linux/copyright25
-rw-r--r--setup/Linux/installoss.sh30
-rw-r--r--setup/Linux/linsetup.sh52
-rw-r--r--setup/Linux/make.local21
-rw-r--r--setup/Linux/md5.sh20
-rw-r--r--setup/Linux/menu.ex4
-rw-r--r--setup/Linux/mkdeb.sh95
-rw-r--r--setup/Linux/mkpkg.sh33
-rw-r--r--setup/Linux/mktarball.sh22
-rw-r--r--setup/Linux/oss/build/Makefile.osscore32
-rw-r--r--setup/Linux/oss/build/Makefile.tmpl21
-rw-r--r--setup/Linux/oss/build/install.sh347
-rw-r--r--setup/Linux/oss/build/module.inc245
-rw-r--r--setup/Linux/oss/build/osscore.c2214
-rw-r--r--setup/Linux/oss/build/ossdip.h10
-rw-r--r--setup/Linux/oss/build/pci_wrapper.inc93
-rw-r--r--setup/Linux/oss/build/usb_wrapper.inc730
-rw-r--r--setup/Linux/oss/cuckoo/Makefile23
-rw-r--r--setup/Linux/oss/cuckoo/checksum.h0
-rw-r--r--setup/Linux/oss/cuckoo/cuckoo.c251
-rw-r--r--setup/Linux/oss/cuckoo/cuckoo.h171
-rw-r--r--setup/Linux/oss/cuckoo/cuckoo_midi.c310
-rw-r--r--setup/Linux/oss/cuckoo/cuckoo_mixer.c389
-rw-r--r--setup/Linux/oss/cuckoo/cuckoo_pcm.c810
-rwxr-xr-xsetup/Linux/oss/etc/S89oss80
-rw-r--r--setup/Linux/oss/scripts/90-oss_usb-create-device.fdi8
-rwxr-xr-xsetup/Linux/oss/scripts/killprocs.sh17
-rw-r--r--setup/Linux/oss/scripts/oss_usb-create-devices4
-rw-r--r--setup/Linux/oss/scripts/remove_drv.sh164
-rw-r--r--setup/Linux/oss/scripts/restore_drv.sh63
-rw-r--r--setup/Linux/oss/scripts/setup-alsa.sh32
-rwxr-xr-xsetup/Linux/oss/scripts/showprocs.sh28
-rw-r--r--setup/Linux/oss/soundon.user7
-rw-r--r--setup/Linux/postinst15
-rw-r--r--setup/Linux/postrm6
-rw-r--r--setup/Linux/preinst6
-rw-r--r--setup/Linux/prerm4
-rw-r--r--setup/Linux/removeoss.sh31
-rwxr-xr-xsetup/Linux/sbin/soundoff69
-rwxr-xr-xsetup/Linux/sbin/soundon351
-rw-r--r--setup/Linux/shlibs1
-rw-r--r--setup/Linux/spec.tmpl39
52 files changed, 10912 insertions, 0 deletions
diff --git a/setup/Linux/arm/Makefile.osscore.arm b/setup/Linux/arm/Makefile.osscore.arm
new file mode 100644
index 0000000..ffe2d3f
--- /dev/null
+++ b/setup/Linux/arm/Makefile.osscore.arm
@@ -0,0 +1,17 @@
+
+ifneq ($(KERNELRELEASE),)
+
+ obj-m := osscore.o
+
+else
+
+ PWD := $(shell pwd)
+endif
+
+default:
+ @echo "static const char __oss_compile_vermagic[];" > ubuntu_version_hack.inc
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+clean:
+ rm -f *.o *.ko *.mod.c *.mod.o .*.cmd core core.* x y z
+ rm -rf .tmp_versions
diff --git a/setup/Linux/arm/Makefile.tmpl.arm b/setup/Linux/arm/Makefile.tmpl.arm
new file mode 100644
index 0000000..a8f0df2
--- /dev/null
+++ b/setup/Linux/arm/Makefile.tmpl.arm
@@ -0,0 +1,21 @@
+include /etc/oss.conf
+
+EXTRA_CFLAGS += -I${OSSLIBDIR}/include/internals -I${OSSLIBDIR}/include/sys
+
+ifneq ($(KERNELRELEASE),)
+
+ obj-m := MODNAME.o
+
+else
+
+ #KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+ PWD := $(shell pwd)
+
+default:
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+endif
+
+clean:
+ @rm -f *.o *.ko *.mod.c *.mod.o .*.cmd core core.* x y z
+ @rm -rf .tmp_versions
diff --git a/setup/Linux/arm/bpabi.S b/setup/Linux/arm/bpabi.S
new file mode 100644
index 0000000..1f08346
--- /dev/null
+++ b/setup/Linux/arm/bpabi.S
@@ -0,0 +1,119 @@
+/* Miscellaneous BPABI functions.
+
+ Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combine
+ executable.)
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#ifdef __ARMEB__
+#define xxh r0
+#define xxl r1
+#define yyh r2
+#define yyl r3
+#else
+#define xxh r1
+#define xxl r0
+#define yyh r3
+#define yyl r2
+#endif
+
+#ifdef L_aeabi_lcmp
+
+ARM_FUNC_START aeabi_lcmp
+ cmp xxh, yyh
+ do_it lt
+ movlt r0, #-1
+ do_it gt
+ movgt r0, #1
+ do_it ne
+ RETc(ne)
+ subs r0, xxl, yyl
+ do_it lo
+ movlo r0, #-1
+ do_it hi
+ movhi r0, #1
+ RET
+ FUNC_END aeabi_lcmp
+
+#endif /* L_aeabi_lcmp */
+
+#ifdef L_aeabi_ulcmp
+
+ARM_FUNC_START aeabi_ulcmp
+ cmp xxh, yyh
+ do_it lo
+ movlo r0, #-1
+ do_it hi
+ movhi r0, #1
+ do_it ne
+ RETc(ne)
+ cmp xxl, yyl
+ do_it lo
+ movlo r0, #-1
+ do_it hi
+ movhi r0, #1
+ do_it eq
+ moveq r0, #0
+ RET
+ FUNC_END aeabi_ulcmp
+
+#endif /* L_aeabi_ulcmp */
+
+#ifdef L_aeabi_ldivmod
+
+ARM_FUNC_START aeabi_ldivmod
+ sub sp, sp, #8
+#if defined(__thumb2__)
+ mov ip, sp
+ push {ip, lr}
+#else
+ do_push {sp, lr}
+#endif
+ bl SYM(__gnu_ldivmod_helper) __PLT__
+ ldr lr, [sp, #4]
+ add sp, sp, #8
+ do_pop {r2, r3}
+ RET
+
+#endif /* L_aeabi_ldivmod */
+
+#ifdef L_aeabi_uldivmod
+
+ARM_FUNC_START aeabi_uldivmod
+ sub sp, sp, #8
+#if defined(__thumb2__)
+ mov ip, sp
+ push {ip, lr}
+#else
+ do_push {sp, lr}
+#endif
+ bl SYM(__gnu_uldivmod_helper) __PLT__
+ ldr lr, [sp, #4]
+ add sp, sp, #8
+ do_pop {r2, r3}
+ RET
+
+#endif /* L_aeabi_divmod */
+
diff --git a/setup/Linux/arm/bpabi.c b/setup/Linux/arm/bpabi.c
new file mode 100644
index 0000000..7ff8e2a
--- /dev/null
+++ b/setup/Linux/arm/bpabi.c
@@ -0,0 +1,375 @@
+/* Miscellaneous BPABI functions.
+
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combine
+ executable.)
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+extern long long __divdi3 (long long, long long);
+extern unsigned long long __udivdi3 (unsigned long long,
+ unsigned long long);
+extern long long __gnu_ldivmod_helper (long long, long long, long long *);
+extern unsigned long long __gnu_uldivmod_helper (unsigned long long,
+ unsigned long long,
+ unsigned long long *);
+#define UQItype unsigned char
+#define DWtype long long
+#define UDItype unsigned long long
+#define Wtype int
+#define USItype unsigned int
+
+#include "longlong.h"
+
+const UQItype __clz_tab[256] =
+{
+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
+};
+
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("adds %1, %4, %5\n\tadc %0, %2, %3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%r" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "%r" ((USItype) (al)), \
+ "rI" ((USItype) (bl)) __CLOBBER_CC)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subs %1, %4, %5\n\tsbc %0, %2, %3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "r" ((USItype) (al)), \
+ "rI" ((USItype) (bl)) __CLOBBER_CC)
+#define umul_ppmm(xh, xl, a, b) \
+{register USItype __t0, __t1, __t2; \
+ __asm__ ("%@ Inlined umul_ppmm\n" \
+ " mov %2, %5, lsr #16\n" \
+ " mov %0, %6, lsr #16\n" \
+ " bic %3, %5, %2, lsl #16\n" \
+ " bic %4, %6, %0, lsl #16\n" \
+ " mul %1, %3, %4\n" \
+ " mul %4, %2, %4\n" \
+ " mul %3, %0, %3\n" \
+ " mul %0, %2, %0\n" \
+ " adds %3, %4, %3\n" \
+ " addcs %0, %0, #65536\n" \
+ " adds %1, %1, %3, lsl #16\n" \
+ " adc %0, %0, %3, lsr #16" \
+ : "=&r" ((USItype) (xh)), \
+ "=r" ((USItype) (xl)), \
+ "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
+ : "r" ((USItype) (a)), \
+ "r" ((USItype) (b)) __CLOBBER_CC );}
+#define UMUL_TIME 20
+#define UDIV_TIME 100
+
+#if 1 /* Big endian */
+ struct DWstruct {Wtype high, low;};
+#else
+ struct DWstruct {Wtype low, high;};
+#endif
+
+/* We need this union to unpack/pack DImode values, since we don't have
+ any arithmetic yet. Incoming DImode parameters are stored into the
+ `ll' field, and the unpacked result is read from the struct `s'. */
+
+typedef union
+{
+ struct DWstruct s;
+ DWtype ll;
+} DWunion;
+
+UDWtype
+__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
+{
+ const DWunion nn = {.ll = n};
+ const DWunion dd = {.ll = d};
+ DWunion rr;
+ UWtype d0, d1, n0, n1, n2;
+ UWtype q0, q1;
+ UWtype b, bm;
+
+ d0 = dd.s.low;
+ d1 = dd.s.high;
+ n0 = nn.s.low;
+ n1 = nn.s.high;
+
+#if !UDIV_NEEDS_NORMALIZATION
+ if (d1 == 0)
+ {
+ if (d0 > n1)
+ {
+ /* 0q = nn / 0D */
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0. */
+ }
+ else
+ {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ udiv_qrnnd (q1, n1, 0, n1, d0);
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+
+ /* Remainder in n0. */
+ }
+
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = 0;
+ *rp = rr.ll;
+ }
+ }
+
+#else /* UDIV_NEEDS_NORMALIZATION */
+
+ if (d1 == 0)
+ {
+ if (d0 > n1)
+ {
+ /* 0q = nn / 0D */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm != 0)
+ {
+ /* Normalize, i.e. make the most significant bit of the
+ denominator set. */
+
+ d0 = d0 << bm;
+ n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
+ n0 = n0 << bm;
+ }
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0 >> bm. */
+ }
+ else
+ {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm == 0)
+ {
+ /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ leading quotient digit q1 = 1).
+
+ This special case is necessary, not an optimization.
+ (Shifts counts of W_TYPE_SIZE are undefined.) */
+
+ n1 -= d0;
+ q1 = 1;
+ }
+ else
+ {
+ /* Normalize. */
+
+ b = W_TYPE_SIZE - bm;
+
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q1, n1, n2, n1, d0);
+ }
+
+ /* n1 != d0... */
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+
+ /* Remainder in n0 >> bm. */
+ }
+
+ if (rp != 0)
+ {
+ rr.s.low = n0 >> bm;
+ rr.s.high = 0;
+ *rp = rr.ll;
+ }
+ }
+#endif /* UDIV_NEEDS_NORMALIZATION */
+
+ else
+ {
+ if (d1 > n1)
+ {
+ /* 00 = nn / DD */
+
+ q0 = 0;
+ q1 = 0;
+
+ /* Remainder in n1n0. */
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ }
+ else
+ {
+ /* 0q = NN / dd */
+
+ count_leading_zeros (bm, d1);
+ if (bm == 0)
+ {
+ /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ quotient digit q0 = 0 or 1).
+
+ This special case is necessary, not an optimization. */
+
+ /* The condition on the next line takes advantage of that
+ n1 >= d1 (true due to program flow). */
+ if (n1 > d1 || n0 >= d0)
+ {
+ q0 = 1;
+ sub_ddmmss (n1, n0, n1, n0, d1, d0);
+ }
+ else
+ q0 = 0;
+
+ q1 = 0;
+
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ }
+ else
+ {
+ UWtype m1, m0;
+ /* Normalize. */
+
+ b = W_TYPE_SIZE - bm;
+
+ d1 = (d1 << bm) | (d0 >> b);
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q0, n1, n2, n1, d1);
+ umul_ppmm (m1, m0, q0, d0);
+
+ if (m1 > n1 || (m1 == n1 && m0 > n0))
+ {
+ q0--;
+ sub_ddmmss (m1, m0, m1, m0, d1, d0);
+ }
+
+ q1 = 0;
+
+ /* Remainder in (n1n0 - m1m0) >> bm. */
+ if (rp != 0)
+ {
+ sub_ddmmss (n1, n0, n1, n0, m1, m0);
+ rr.s.low = (n1 << b) | (n0 >> bm);
+ rr.s.high = n1 >> bm;
+ *rp = rr.ll;
+ }
+ }
+ }
+ }
+
+ const DWunion ww = {{.low = q0, .high = q1}};
+ return ww.ll;
+}
+
+UDWtype
+__udivdi3 (UDWtype n, UDWtype d)
+{
+ return __udivmoddi4 (n, d, (UDWtype *) 0);
+}
+
+long long
+__divdi3 (DWtype u, DWtype v)
+{
+ Wtype c = 0;
+ DWunion uu = {.ll = u};
+ DWunion vv = {.ll = v};
+ DWtype w;
+
+ if (uu.s.high < 0)
+ c = ~c,
+ uu.ll = -uu.ll;
+ if (vv.s.high < 0)
+ c = ~c,
+ vv.ll = -vv.ll;
+
+ w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
+ if (c)
+ w = -w;
+
+ return w;
+}
+
+long long
+__gnu_ldivmod_helper (long long a,
+ long long b,
+ long long *remainder)
+{
+ long long quotient;
+
+ quotient = __divdi3 (a, b);
+ *remainder = a - b * quotient;
+ return quotient;
+}
+
+unsigned long long
+__gnu_uldivmod_helper (unsigned long long a,
+ unsigned long long b,
+ unsigned long long *remainder)
+{
+ unsigned long long quotient;
+
+ quotient = __udivdi3 (a, b);
+ *remainder = a - b * quotient;
+ return quotient;
+}
diff --git a/setup/Linux/arm/bpabi.h b/setup/Linux/arm/bpabi.h
new file mode 100644
index 0000000..a67f649
--- /dev/null
+++ b/setup/Linux/arm/bpabi.h
@@ -0,0 +1,125 @@
+/* Configuration file for ARM BPABI targets.
+ Copyright (C) 2004, 2005, 2007
+ Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+/* Use the AAPCS ABI by default. */
+#define ARM_DEFAULT_ABI ARM_ABI_AAPCS
+
+/* Assume that AAPCS ABIs should adhere to the full BPABI. */
+#define TARGET_BPABI (TARGET_AAPCS_BASED)
+
+/* BPABI targets use EABI frame unwinding tables. */
+#define TARGET_UNWIND_INFO 1
+
+/* Section 4.1 of the AAPCS requires the use of VFP format. */
+#undef FPUTYPE_DEFAULT
+#define FPUTYPE_DEFAULT FPUTYPE_VFP
+
+/* TARGET_BIG_ENDIAN_DEFAULT is set in
+ config.gcc for big endian configurations. */
+#if TARGET_BIG_ENDIAN_DEFAULT
+#define TARGET_ENDIAN_DEFAULT MASK_BIG_END
+#else
+#define TARGET_ENDIAN_DEFAULT 0
+#endif
+
+/* EABI targets should enable interworking by default. */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_INTERWORK | TARGET_ENDIAN_DEFAULT)
+
+/* The ARM BPABI functions return a boolean; they use no special
+ calling convention. */
+#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) TARGET_BPABI
+
+/* The BPABI integer comparison routines return { -1, 0, 1 }. */
+#define TARGET_LIB_INT_CMP_BIASED !TARGET_BPABI
+
+/* Tell the assembler to build BPABI binaries. */
+#undef SUBTARGET_EXTRA_ASM_SPEC
+#define SUBTARGET_EXTRA_ASM_SPEC "%{mabi=apcs-gnu|mabi=atpcs:-meabi=gnu;:-meabi=4}"
+
+/* The generic link spec in elf.h does not support shared libraries. */
+#undef LINK_SPEC
+#define LINK_SPEC "%{mbig-endian:-EB} %{mlittle-endian:-EL} " \
+ "%{static:-Bstatic} %{shared:-shared} %{symbolic:-Bsymbolic} " \
+ "-X"
+
+#if defined (__thumb__)
+#define RENAME_LIBRARY_SET ".thumb_set"
+#else
+#define RENAME_LIBRARY_SET ".set"
+#endif
+
+/* Make __aeabi_AEABI_NAME an alias for __GCC_NAME. */
+#define RENAME_LIBRARY(GCC_NAME, AEABI_NAME) \
+ __asm__ (".globl\t__aeabi_" #AEABI_NAME "\n" \
+ RENAME_LIBRARY_SET "\t__aeabi_" #AEABI_NAME \
+ ", __" #GCC_NAME "\n");
+
+/* Give some libgcc functions an additional __aeabi name. */
+#ifdef L_muldi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul)
+#endif
+#ifdef L_muldi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul)
+#endif
+#ifdef L_fixdfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixdfdi, d2lz)
+#endif
+#ifdef L_fixunsdfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfdi, d2ulz)
+#endif
+#ifdef L_fixsfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, f2lz)
+#endif
+#ifdef L_fixunssfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, f2ulz)
+#endif
+#ifdef L_floatdidf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdidf, l2d)
+#endif
+#ifdef L_floatdisf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdisf, l2f)
+#endif
+
+/* The BPABI requires that we always use an out-of-line implementation
+ of RTTI comparison, even if the target supports weak symbols,
+ because the same object file might be used on a target that does
+ not support merging symbols across DLL boundaries. This macro is
+ broken out separately so that it can be used within
+ TARGET_OS_CPP_BUILTINS in configuration files for systems based on
+ the BPABI. */
+#define TARGET_BPABI_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__GXX_TYPEINFO_EQUALITY_INLINE=0"); \
+ } \
+ while (false)
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ TARGET_BPABI_CPP_BUILTINS()
+
+/* The BPABI specifies the use of .{init,fini}_array. Therefore, we
+ do not want GCC to put anything into the .{init,fini} sections. */
+#undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
+#define INIT_ARRAY_SECTION_ASM_OP ARM_EABI_CTORS_SECTION_OP
+#define FINI_ARRAY_SECTION_ASM_OP ARM_EABI_DTORS_SECTION_OP
diff --git a/setup/Linux/arm/lib1funcs.asm b/setup/Linux/arm/lib1funcs.asm
new file mode 100644
index 0000000..e2c2201
--- /dev/null
+++ b/setup/Linux/arm/lib1funcs.asm
@@ -0,0 +1,1393 @@
+@ libgcc routines for ARM cpu.
+@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
+
+/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005, 2007
+ Free Software Foundation, Inc.
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file. (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* An executable stack is *not* required for these functions. */
+#if defined(__ELF__) && defined(__linux__)
+.section .note.GNU-stack,"",%progbits
+.previous
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+/* We need to know what prefix to add to function names. */
+
+#ifndef __USER_LABEL_PREFIX__
+#error __USER_LABEL_PREFIX__ not defined
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+#ifdef __ELF__
+#ifdef __thumb__
+#define __PLT__ /* Not supported in Thumb assembler (for now). */
+#elif defined __vxworks && !defined __PIC__
+#define __PLT__ /* Not supported by the kernel loader. */
+#else
+#define __PLT__ (PLT)
+#endif
+#define TYPE(x) .type SYM(x),function
+#define SIZE(x) .size SYM(x), . - SYM(x)
+#define LSYM(x) .x
+#else
+#define __PLT__
+#define TYPE(x)
+#define SIZE(x)
+#define LSYM(x) x
+#endif
+
+/* Function end macros. Variants for interworking. */
+
+#if defined(__ARM_ARCH_2__)
+# define __ARM_ARCH__ 2
+#endif
+
+#if defined(__ARM_ARCH_3__)
+# define __ARM_ARCH__ 3
+#endif
+
+#if defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) \
+ || defined(__ARM_ARCH_4T__)
+/* We use __ARM_ARCH__ set to 4 here, but in reality it's any processor with
+ long multiply instructions. That includes v3M. */
+# define __ARM_ARCH__ 4
+#endif
+
+#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
+ || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+ || defined(__ARM_ARCH_5TEJ__)
+# define __ARM_ARCH__ 5
+#endif
+
+#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
+# define __ARM_ARCH__ 6
+#endif
+
+#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
+ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__)
+# define __ARM_ARCH__ 7
+#endif
+
+#ifndef __ARM_ARCH__
+#error Unable to determine architecture.
+#endif
+
+/* How to return from a function call depends on the architecture variant. */
+
+#if (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
+
+# define RET bx lr
+# define RETc(x) bx##x lr
+
+/* Special precautions for interworking on armv4t. */
+# if (__ARM_ARCH__ == 4)
+
+/* Always use bx, not ldr pc. */
+# if (defined(__thumb__) || defined(__THUMB_INTERWORK__))
+# define __INTERWORKING__
+# endif /* __THUMB__ || __THUMB_INTERWORK__ */
+
+/* Include thumb stub before arm mode code. */
+# if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
+# define __INTERWORKING_STUBS__
+# endif /* __thumb__ && !__THUMB_INTERWORK__ */
+
+#endif /* __ARM_ARCH == 4 */
+
+#else
+
+# define RET mov pc, lr
+# define RETc(x) mov##x pc, lr
+
+#endif
+
+.macro cfi_pop advance, reg, cfa_offset
+#ifdef __ELF__
+ .pushsection .debug_frame
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .4byte \advance
+ .byte (0xc0 | \reg) /* DW_CFA_restore */
+ .byte 0xe /* DW_CFA_def_cfa_offset */
+ .uleb128 \cfa_offset
+ .popsection
+#endif
+.endm
+.macro cfi_push advance, reg, offset, cfa_offset
+#ifdef __ELF__
+ .pushsection .debug_frame
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .4byte \advance
+ .byte (0x80 | \reg) /* DW_CFA_offset */
+ .uleb128 (\offset / -4)
+ .byte 0xe /* DW_CFA_def_cfa_offset */
+ .uleb128 \cfa_offset
+ .popsection
+#endif
+.endm
+.macro cfi_start start_label, end_label
+#ifdef __ELF__
+ .pushsection .debug_frame
+LSYM(Lstart_frame):
+ .4byte LSYM(Lend_cie) - LSYM(Lstart_cie) @ Length of CIE
+LSYM(Lstart_cie):
+ .4byte 0xffffffff @ CIE Identifier Tag
+ .byte 0x1 @ CIE Version
+ .ascii "\0" @ CIE Augmentation
+ .uleb128 0x1 @ CIE Code Alignment Factor
+ .sleb128 -4 @ CIE Data Alignment Factor
+ .byte 0xe @ CIE RA Column
+ .byte 0xc @ DW_CFA_def_cfa
+ .uleb128 0xd
+ .uleb128 0x0
+
+ .align 2
+LSYM(Lend_cie):
+ .4byte LSYM(Lend_fde)-LSYM(Lstart_fde) @ FDE Length
+LSYM(Lstart_fde):
+ .4byte LSYM(Lstart_frame) @ FDE CIE offset
+ .4byte \start_label @ FDE initial location
+ .4byte \end_label-\start_label @ FDE address range
+ .popsection
+#endif
+.endm
+.macro cfi_end end_label
+#ifdef __ELF__
+ .pushsection .debug_frame
+ .align 2
+LSYM(Lend_fde):
+ .popsection
+\end_label:
+#endif
+.endm
+
+/* Don't pass dirn, it's there just to get token pasting right. */
+
+.macro RETLDM regs=, cond=, unwind=, dirn=ia
+#if defined (__INTERWORKING__)
+ .ifc "\regs",""
+ ldr\cond lr, [sp], #8
+ .else
+# if defined(__thumb2__)
+ pop\cond {\regs, lr}
+# else
+ ldm\cond\dirn sp!, {\regs, lr}
+# endif
+ .endif
+ .ifnc "\unwind", ""
+ /* Mark LR as restored. */
+97: cfi_pop 97b - \unwind, 0xe, 0x0
+ .endif
+ bx\cond lr
+#else
+ /* Caller is responsible for providing IT instruction. */
+ .ifc "\regs",""
+ ldr\cond pc, [sp], #8
+ .else
+# if defined(__thumb2__)
+ pop\cond {\regs, pc}
+# else
+ ldm\cond\dirn sp!, {\regs, pc}
+# endif
+ .endif
+#endif
+.endm
+
+/* The Unified assembly syntax allows the same code to be assembled for both
+ ARM and Thumb-2. However this is only supported by recent gas, so define
+ a set of macros to allow ARM code on older assemblers. */
+#if defined(__thumb2__)
+.macro do_it cond, suffix=""
+ it\suffix \cond
+.endm
+.macro shift1 op, arg0, arg1, arg2
+ \op \arg0, \arg1, \arg2
+.endm
+#define do_push push
+#define do_pop pop
+#define COND(op1, op2, cond) op1 ## op2 ## cond
+/* Perform an arithmetic operation with a variable shift operand. This
+ requires two instructions and a scratch register on Thumb-2. */
+.macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp
+ \shiftop \tmp, \src2, \shiftreg
+ \name \dest, \src1, \tmp
+.endm
+#else
+.macro do_it cond, suffix=""
+.endm
+.macro shift1 op, arg0, arg1, arg2
+ mov \arg0, \arg1, \op \arg2
+.endm
+#define do_push stmfd sp!,
+#define do_pop ldmfd sp!,
+#define COND(op1, op2, cond) op1 ## cond ## op2
+.macro shiftop name, dest, src1, src2, shiftop, shiftreg, tmp
+ \name \dest, \src1, \src2, \shiftop \shiftreg
+.endm
+#endif
+
+.macro ARM_LDIV0 name
+ str lr, [sp, #-8]!
+98: cfi_push 98b - __\name, 0xe, -0x8, 0x8
+ bl SYM (__div0) __PLT__
+ mov r0, #0 @ About as wrong as it could be.
+ RETLDM unwind=98b
+.endm
+
+
+.macro THUMB_LDIV0 name
+ push { r1, lr }
+98: cfi_push 98b - __\name, 0xe, -0x4, 0x8
+ bl SYM (__div0)
+ mov r0, #0 @ About as wrong as it could be.
+#if defined (__INTERWORKING__)
+ pop { r1, r2 }
+ bx r2
+#else
+ pop { r1, pc }
+#endif
+.endm
+
+.macro FUNC_END name
+ SIZE (__\name)
+.endm
+
+.macro DIV_FUNC_END name
+ cfi_start __\name, LSYM(Lend_div0)
+LSYM(Ldiv0):
+#ifdef __thumb__
+ THUMB_LDIV0 \name
+#else
+ ARM_LDIV0 \name
+#endif
+ cfi_end LSYM(Lend_div0)
+ FUNC_END \name
+.endm
+
+.macro THUMB_FUNC_START name
+ .globl SYM (\name)
+ TYPE (\name)
+ .thumb_func
+SYM (\name):
+.endm
+
+/* Function start macros. Variants for ARM and Thumb. */
+
+#ifdef __thumb__
+#define THUMB_FUNC .thumb_func
+#define THUMB_CODE .force_thumb
+# if defined(__thumb2__)
+#define THUMB_SYNTAX .syntax divided
+# else
+#define THUMB_SYNTAX
+# endif
+#else
+#define THUMB_FUNC
+#define THUMB_CODE
+#define THUMB_SYNTAX
+#endif
+
+.macro FUNC_START name
+ .text
+ .globl SYM (__\name)
+ TYPE (__\name)
+ .align 0
+ THUMB_CODE
+ THUMB_FUNC
+ THUMB_SYNTAX
+SYM (__\name):
+.endm
+
+/* Special function that will always be coded in ARM assembly, even if
+ in Thumb-only compilation. */
+
+#if defined(__thumb2__)
+
+/* For Thumb-2 we build everything in thumb mode. */
+.macro ARM_FUNC_START name
+ FUNC_START \name
+ .syntax unified
+.endm
+#define EQUIV .thumb_set
+.macro ARM_CALL name
+ bl __\name
+.endm
+
+#elif defined(__INTERWORKING_STUBS__)
+
+.macro ARM_FUNC_START name
+ FUNC_START \name
+ bx pc
+ nop
+ .arm
+/* A hook to tell gdb that we've switched to ARM mode. Also used to call
+ directly from other local arm routines. */
+_L__\name:
+.endm
+#define EQUIV .thumb_set
+/* Branch directly to a function declared with ARM_FUNC_START.
+ Must be called in arm mode. */
+.macro ARM_CALL name
+ bl _L__\name
+.endm
+
+#else /* !(__INTERWORKING_STUBS__ || __thumb2__) */
+
+.macro ARM_FUNC_START name
+ .text
+ .globl SYM (__\name)
+ TYPE (__\name)
+ .align 0
+ .arm
+SYM (__\name):
+.endm
+#define EQUIV .set
+.macro ARM_CALL name
+ bl __\name
+.endm
+
+#endif
+
+.macro FUNC_ALIAS new old
+ .globl SYM (__\new)
+#if defined (__thumb__)
+ .thumb_set SYM (__\new), SYM (__\old)
+#else
+ .set SYM (__\new), SYM (__\old)
+#endif
+.endm
+
+.macro ARM_FUNC_ALIAS new old
+ .globl SYM (__\new)
+ EQUIV SYM (__\new), SYM (__\old)
+#if defined(__INTERWORKING_STUBS__)
+ .set SYM (_L__\new), SYM (_L__\old)
+#endif
+.endm
+
+#ifdef __thumb__
+/* Register aliases. */
+
+work .req r4 @ XXXX is this safe ?
+dividend .req r0
+divisor .req r1
+overdone .req r2
+result .req r2
+curbit .req r3
+#endif
+#if 0
+ip .req r12
+sp .req r13
+lr .req r14
+pc .req r15
+#endif
+
+/* ------------------------------------------------------------------------ */
+/* Bodies of the division and modulo routines. */
+/* ------------------------------------------------------------------------ */
+.macro ARM_DIV_BODY dividend, divisor, result, curbit
+
+#if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
+
+ clz \curbit, \dividend
+ clz \result, \divisor
+ sub \curbit, \result, \curbit
+ rsbs \curbit, \curbit, #31
+ addne \curbit, \curbit, \curbit, lsl #1
+ mov \result, #0
+ addne pc, pc, \curbit, lsl #2
+ nop
+ .set shift, 32
+ .rept 32
+ .set shift, shift - 1
+ cmp \dividend, \divisor, lsl #shift
+ adc \result, \result, \result
+ subcs \dividend, \dividend, \divisor, lsl #shift
+ .endr
+
+#else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
+#if __ARM_ARCH__ >= 5
+
+ clz \curbit, \divisor
+ clz \result, \dividend
+ sub \result, \curbit, \result
+ mov \curbit, #1
+ mov \divisor, \divisor, lsl \result
+ mov \curbit, \curbit, lsl \result
+ mov \result, #0
+
+#else /* __ARM_ARCH__ < 5 */
+
+ @ Initially shift the divisor left 3 bits if possible,
+ @ set curbit accordingly. This allows for curbit to be located
+ @ at the left end of each 4-bit nibbles in the division loop
+ @ to save one loop in most cases.
+ tst \divisor, #0xe0000000
+ moveq \divisor, \divisor, lsl #3
+ moveq \curbit, #8
+ movne \curbit, #1
+
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+1: cmp \divisor, #0x10000000
+ cmplo \divisor, \dividend
+ movlo \divisor, \divisor, lsl #4
+ movlo \curbit, \curbit, lsl #4
+ blo 1b
+
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+1: cmp \divisor, #0x80000000
+ cmplo \divisor, \dividend
+ movlo \divisor, \divisor, lsl #1
+ movlo \curbit, \curbit, lsl #1
+ blo 1b
+
+ mov \result, #0
+
+#endif /* __ARM_ARCH__ < 5 */
+
+ @ Division loop
+1: cmp \dividend, \divisor
+ subhs \dividend, \dividend, \divisor
+ orrhs \result, \result, \curbit
+ cmp \dividend, \divisor, lsr #1
+ subhs \dividend, \dividend, \divisor, lsr #1
+ orrhs \result, \result, \curbit, lsr #1
+ cmp \dividend, \divisor, lsr #2
+ subhs \dividend, \dividend, \divisor, lsr #2
+ orrhs \result, \result, \curbit, lsr #2
+ cmp \dividend, \divisor, lsr #3
+ subhs \dividend, \dividend, \divisor, lsr #3
+ orrhs \result, \result, \curbit, lsr #3
+ cmp \dividend, #0 @ Early termination?
+ movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
+ movne \divisor, \divisor, lsr #4
+ bne 1b
+
+#endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
+
+.endm
+/* ------------------------------------------------------------------------ */
+.macro ARM_DIV2_ORDER divisor, order
+
+#if __ARM_ARCH__ >= 5
+
+ clz \order, \divisor
+ rsb \order, \order, #31
+
+#else
+
+ cmp \divisor, #(1 << 16)
+ movhs \divisor, \divisor, lsr #16
+ movhs \order, #16
+ movlo \order, #0
+
+ cmp \divisor, #(1 << 8)
+ movhs \divisor, \divisor, lsr #8
+ addhs \order, \order, #8
+
+ cmp \divisor, #(1 << 4)
+ movhs \divisor, \divisor, lsr #4
+ addhs \order, \order, #4
+
+ cmp \divisor, #(1 << 2)
+ addhi \order, \order, #3
+ addls \order, \order, \divisor, lsr #1
+
+#endif
+
+.endm
+/* ------------------------------------------------------------------------ */
+.macro ARM_MOD_BODY dividend, divisor, order, spare
+
+#if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
+
+ clz \order, \divisor
+ clz \spare, \dividend
+ sub \order, \order, \spare
+ rsbs \order, \order, #31
+ addne pc, pc, \order, lsl #3
+ nop
+ .set shift, 32
+ .rept 32
+ .set shift, shift - 1
+ cmp \dividend, \divisor, lsl #shift
+ subcs \dividend, \dividend, \divisor, lsl #shift
+ .endr
+
+#else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
+#if __ARM_ARCH__ >= 5
+
+ clz \order, \divisor
+ clz \spare, \dividend
+ sub \order, \order, \spare
+ mov \divisor, \divisor, lsl \order
+
+#else /* __ARM_ARCH__ < 5 */
+
+ mov \order, #0
+
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+1: cmp \divisor, #0x10000000
+ cmplo \divisor, \dividend
+ movlo \divisor, \divisor, lsl #4
+ addlo \order, \order, #4
+ blo 1b
+
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+1: cmp \divisor, #0x80000000
+ cmplo \divisor, \dividend
+ movlo \divisor, \divisor, lsl #1
+ addlo \order, \order, #1
+ blo 1b
+
+#endif /* __ARM_ARCH__ < 5 */
+
+ @ Perform all needed substractions to keep only the reminder.
+ @ Do comparisons in batch of 4 first.
+ subs \order, \order, #3 @ yes, 3 is intended here
+ blt 2f
+
+1: cmp \dividend, \divisor
+ subhs \dividend, \dividend, \divisor
+ cmp \dividend, \divisor, lsr #1
+ subhs \dividend, \dividend, \divisor, lsr #1
+ cmp \dividend, \divisor, lsr #2
+ subhs \dividend, \dividend, \divisor, lsr #2
+ cmp \dividend, \divisor, lsr #3
+ subhs \dividend, \dividend, \divisor, lsr #3
+ cmp \dividend, #1
+ mov \divisor, \divisor, lsr #4
+ subges \order, \order, #4
+ bge 1b
+
+ tst \order, #3
+ teqne \dividend, #0
+ beq 5f
+
+ @ Either 1, 2 or 3 comparison/substractions are left.
+2: cmn \order, #2
+ blt 4f
+ beq 3f
+ cmp \dividend, \divisor
+ subhs \dividend, \dividend, \divisor
+ mov \divisor, \divisor, lsr #1
+3: cmp \dividend, \divisor
+ subhs \dividend, \dividend, \divisor
+ mov \divisor, \divisor, lsr #1
+4: cmp \dividend, \divisor
+ subhs \dividend, \dividend, \divisor
+5:
+
+#endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
+
+.endm
+/* ------------------------------------------------------------------------ */
+.macro THUMB_DIV_MOD_BODY modulo
+ @ Load the constant 0x10000000 into our work register.
+ mov work, #1
+ lsl work, #28
+LSYM(Loop1):
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+ cmp divisor, work
+ bhs LSYM(Lbignum)
+ cmp divisor, dividend
+ bhs LSYM(Lbignum)
+ lsl divisor, #4
+ lsl curbit, #4
+ b LSYM(Loop1)
+LSYM(Lbignum):
+ @ Set work to 0x80000000
+ lsl work, #3
+LSYM(Loop2):
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+ cmp divisor, work
+ bhs LSYM(Loop3)
+ cmp divisor, dividend
+ bhs LSYM(Loop3)
+ lsl divisor, #1
+ lsl curbit, #1
+ b LSYM(Loop2)
+LSYM(Loop3):
+ @ Test for possible subtractions ...
+ .if \modulo
+ @ ... On the final pass, this may subtract too much from the dividend,
+ @ so keep track of which subtractions are done, we can fix them up
+ @ afterwards.
+ mov overdone, #0
+ cmp dividend, divisor
+ blo LSYM(Lover1)
+ sub dividend, dividend, divisor
+LSYM(Lover1):
+ lsr work, divisor, #1
+ cmp dividend, work
+ blo LSYM(Lover2)
+ sub dividend, dividend, work
+ mov ip, curbit
+ mov work, #1
+ ror curbit, work
+ orr overdone, curbit
+ mov curbit, ip
+LSYM(Lover2):
+ lsr work, divisor, #2
+ cmp dividend, work
+ blo LSYM(Lover3)
+ sub dividend, dividend, work
+ mov ip, curbit
+ mov work, #2
+ ror curbit, work
+ orr overdone, curbit
+ mov curbit, ip
+LSYM(Lover3):
+ lsr work, divisor, #3
+ cmp dividend, work
+ blo LSYM(Lover4)
+ sub dividend, dividend, work
+ mov ip, curbit
+ mov work, #3
+ ror curbit, work
+ orr overdone, curbit
+ mov curbit, ip
+LSYM(Lover4):
+ mov ip, curbit
+ .else
+ @ ... and note which bits are done in the result. On the final pass,
+ @ this may subtract too much from the dividend, but the result will be ok,
+ @ since the "bit" will have been shifted out at the bottom.
+ cmp dividend, divisor
+ blo LSYM(Lover1)
+ sub dividend, dividend, divisor
+ orr result, result, curbit
+LSYM(Lover1):
+ lsr work, divisor, #1
+ cmp dividend, work
+ blo LSYM(Lover2)
+ sub dividend, dividend, work
+ lsr work, curbit, #1
+ orr result, work
+LSYM(Lover2):
+ lsr work, divisor, #2
+ cmp dividend, work
+ blo LSYM(Lover3)
+ sub dividend, dividend, work
+ lsr work, curbit, #2
+ orr result, work
+LSYM(Lover3):
+ lsr work, divisor, #3
+ cmp dividend, work
+ blo LSYM(Lover4)
+ sub dividend, dividend, work
+ lsr work, curbit, #3
+ orr result, work
+LSYM(Lover4):
+ .endif
+
+ cmp dividend, #0 @ Early termination?
+ beq LSYM(Lover5)
+ lsr curbit, #4 @ No, any more bits to do?
+ beq LSYM(Lover5)
+ lsr divisor, #4
+ b LSYM(Loop3)
+LSYM(Lover5):
+ .if \modulo
+ @ Any subtractions that we should not have done will be recorded in
+ @ the top three bits of "overdone". Exactly which were not needed
+ @ are governed by the position of the bit, stored in ip.
+ mov work, #0xe
+ lsl work, #28
+ and overdone, work
+ beq LSYM(Lgot_result)
+
+ @ If we terminated early, because dividend became zero, then the
+ @ bit in ip will not be in the bottom nibble, and we should not
+ @ perform the additions below. We must test for this though
+ @ (rather relying upon the TSTs to prevent the additions) since
+ @ the bit in ip could be in the top two bits which might then match
+ @ with one of the smaller RORs.
+ mov curbit, ip
+ mov work, #0x7
+ tst curbit, work
+ beq LSYM(Lgot_result)
+
+ mov curbit, ip
+ mov work, #3
+ ror curbit, work
+ tst overdone, curbit
+ beq LSYM(Lover6)
+ lsr work, divisor, #3
+ add dividend, work
+LSYM(Lover6):
+ mov curbit, ip
+ mov work, #2
+ ror curbit, work
+ tst overdone, curbit
+ beq LSYM(Lover7)
+ lsr work, divisor, #2
+ add dividend, work
+LSYM(Lover7):
+ mov curbit, ip
+ mov work, #1
+ ror curbit, work
+ tst overdone, curbit
+ beq LSYM(Lgot_result)
+ lsr work, divisor, #1
+ add dividend, work
+ .endif
+LSYM(Lgot_result):
+.endm
+/* ------------------------------------------------------------------------ */
+/* Start of the Real Functions */
+/* ------------------------------------------------------------------------ */
+#ifdef L_udivsi3
+
+ FUNC_START udivsi3
+ FUNC_ALIAS aeabi_uidiv udivsi3
+
+#ifdef __thumb__
+
+ cmp divisor, #0
+ beq LSYM(Ldiv0)
+ mov curbit, #1
+ mov result, #0
+
+ push { work }
+ cmp dividend, divisor
+ blo LSYM(Lgot_result)
+
+ THUMB_DIV_MOD_BODY 0
+
+ mov r0, result
+ pop { work }
+ RET
+
+#else /* ARM version. */
+
+ subs r2, r1, #1
+ RETc(eq)
+ bcc LSYM(Ldiv0)
+ cmp r0, r1
+ bls 11f
+ tst r1, r2
+ beq 12f
+
+ ARM_DIV_BODY r0, r1, r2, r3
+
+ mov r0, r2
+ RET
+
+11: moveq r0, #1
+ movne r0, #0
+ RET
+
+12: ARM_DIV2_ORDER r1, r2
+
+ mov r0, r0, lsr r2
+ RET
+
+#endif /* ARM version */
+
+ DIV_FUNC_END udivsi3
+
+FUNC_START aeabi_uidivmod
+#ifdef __thumb__
+ push {r0, r1, lr}
+ bl SYM(__udivsi3)
+ POP {r1, r2, r3}
+ mul r2, r0
+ sub r1, r1, r2
+ bx r3
+#else
+ stmfd sp!, { r0, r1, lr }
+ bl SYM(__udivsi3)
+ ldmfd sp!, { r1, r2, lr }
+ mul r3, r2, r0
+ sub r1, r1, r3
+ RET
+#endif
+ FUNC_END aeabi_uidivmod
+
+#endif /* L_udivsi3 */
+/* ------------------------------------------------------------------------ */
+#ifdef L_umodsi3
+
+ FUNC_START umodsi3
+
+#ifdef __thumb__
+
+ cmp divisor, #0
+ beq LSYM(Ldiv0)
+ mov curbit, #1
+ cmp dividend, divisor
+ bhs LSYM(Lover10)
+ RET
+
+LSYM(Lover10):
+ push { work }
+
+ THUMB_DIV_MOD_BODY 1
+
+ pop { work }
+ RET
+
+#else /* ARM version. */
+
+ subs r2, r1, #1 @ compare divisor with 1
+ bcc LSYM(Ldiv0)
+ cmpne r0, r1 @ compare dividend with divisor
+ moveq r0, #0
+ tsthi r1, r2 @ see if divisor is power of 2
+ andeq r0, r0, r2
+ RETc(ls)
+
+ ARM_MOD_BODY r0, r1, r2, r3
+
+ RET
+
+#endif /* ARM version. */
+
+ DIV_FUNC_END umodsi3
+
+#endif /* L_umodsi3 */
+/* ------------------------------------------------------------------------ */
+#ifdef L_divsi3
+
+ FUNC_START divsi3
+ FUNC_ALIAS aeabi_idiv divsi3
+
+#ifdef __thumb__
+ cmp divisor, #0
+ beq LSYM(Ldiv0)
+
+ push { work }
+ mov work, dividend
+ eor work, divisor @ Save the sign of the result.
+ mov ip, work
+ mov curbit, #1
+ mov result, #0
+ cmp divisor, #0
+ bpl LSYM(Lover10)
+ neg divisor, divisor @ Loops below use unsigned.
+LSYM(Lover10):
+ cmp dividend, #0
+ bpl LSYM(Lover11)
+ neg dividend, dividend
+LSYM(Lover11):
+ cmp dividend, divisor
+ blo LSYM(Lgot_result)
+
+ THUMB_DIV_MOD_BODY 0
+
+ mov r0, result
+ mov work, ip
+ cmp work, #0
+ bpl LSYM(Lover12)
+ neg r0, r0
+LSYM(Lover12):
+ pop { work }
+ RET
+
+#else /* ARM version. */
+
+ cmp r1, #0
+ eor ip, r0, r1 @ save the sign of the result.
+ beq LSYM(Ldiv0)
+ rsbmi r1, r1, #0 @ loops below use unsigned.
+ subs r2, r1, #1 @ division by 1 or -1 ?
+ beq 10f
+ movs r3, r0
+ rsbmi r3, r0, #0 @ positive dividend value
+ cmp r3, r1
+ bls 11f
+ tst r1, r2 @ divisor is power of 2 ?
+ beq 12f
+
+ ARM_DIV_BODY r3, r1, r0, r2
+
+ cmp ip, #0
+ rsbmi r0, r0, #0
+ RET
+
+10: teq ip, r0 @ same sign ?
+ rsbmi r0, r0, #0
+ RET
+
+11: movlo r0, #0
+ moveq r0, ip, asr #31
+ orreq r0, r0, #1
+ RET
+
+12: ARM_DIV2_ORDER r1, r2
+
+ cmp ip, #0
+ mov r0, r3, lsr r2
+ rsbmi r0, r0, #0
+ RET
+
+#endif /* ARM version */
+
+ DIV_FUNC_END divsi3
+
+FUNC_START aeabi_idivmod
+#ifdef __thumb__
+ push {r0, r1, lr}
+ bl SYM(__divsi3)
+ POP {r1, r2, r3}
+ mul r2, r0
+ sub r1, r1, r2
+ bx r3
+#else
+ stmfd sp!, { r0, r1, lr }
+ bl SYM(__divsi3)
+ ldmfd sp!, { r1, r2, lr }
+ mul r3, r2, r0
+ sub r1, r1, r3
+ RET
+#endif
+ FUNC_END aeabi_idivmod
+
+#endif /* L_divsi3 */
+/* ------------------------------------------------------------------------ */
+#ifdef L_modsi3
+
+ FUNC_START modsi3
+
+#ifdef __thumb__
+
+ mov curbit, #1
+ cmp divisor, #0
+ beq LSYM(Ldiv0)
+ bpl LSYM(Lover10)
+ neg divisor, divisor @ Loops below use unsigned.
+LSYM(Lover10):
+ push { work }
+ @ Need to save the sign of the dividend, unfortunately, we need
+ @ work later on. Must do this after saving the original value of
+ @ the work register, because we will pop this value off first.
+ push { dividend }
+ cmp dividend, #0
+ bpl LSYM(Lover11)
+ neg dividend, dividend
+LSYM(Lover11):
+ cmp dividend, divisor
+ blo LSYM(Lgot_result)
+
+ THUMB_DIV_MOD_BODY 1
+
+ pop { work }
+ cmp work, #0
+ bpl LSYM(Lover12)
+ neg dividend, dividend
+LSYM(Lover12):
+ pop { work }
+ RET
+
+#else /* ARM version. */
+
+ cmp r1, #0
+ beq LSYM(Ldiv0)
+ rsbmi r1, r1, #0 @ loops below use unsigned.
+ movs ip, r0 @ preserve sign of dividend
+ rsbmi r0, r0, #0 @ if negative make positive
+ subs r2, r1, #1 @ compare divisor with 1
+ cmpne r0, r1 @ compare dividend with divisor
+ moveq r0, #0
+ tsthi r1, r2 @ see if divisor is power of 2
+ andeq r0, r0, r2
+ bls 10f
+
+ ARM_MOD_BODY r0, r1, r2, r3
+
+10: cmp ip, #0
+ rsbmi r0, r0, #0
+ RET
+
+#endif /* ARM version */
+
+ DIV_FUNC_END modsi3
+
+#endif /* L_modsi3 */
+/* ------------------------------------------------------------------------ */
+#ifdef L_dvmd_tls
+
+ FUNC_START div0
+ FUNC_ALIAS aeabi_idiv0 div0
+ FUNC_ALIAS aeabi_ldiv0 div0
+
+ RET
+
+ FUNC_END aeabi_ldiv0
+ FUNC_END aeabi_idiv0
+ FUNC_END div0
+
+#endif /* L_divmodsi_tools */
+/* ------------------------------------------------------------------------ */
+#ifdef L_dvmd_lnx
+@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
+
+/* Constant taken from <asm/signal.h>. */
+#define SIGFPE 8
+
+ ARM_FUNC_START div0
+
+ do_push {r1, lr}
+ mov r0, #SIGFPE
+ bl SYM(raise) __PLT__
+ RETLDM r1
+
+ FUNC_END div0
+
+#endif /* L_dvmd_lnx */
+/* ------------------------------------------------------------------------ */
+/* Dword shift operations. */
+/* All the following Dword shift variants rely on the fact that
+ shft xxx, Reg
+ is in fact done as
+ shft xxx, (Reg & 255)
+ so for Reg value in (32...63) and (-1...-31) we will get zero (in the
+ case of logical shifts) or the sign (for asr). */
+
+#ifdef __ARMEB__
+#define al r1
+#define ah r0
+#else
+#define al r0
+#define ah r1
+#endif
+
+/* Prevent __aeabi double-word shifts from being produced on SymbianOS. */
+#ifndef __symbian__
+
+#ifdef L_lshrdi3
+
+ FUNC_START lshrdi3
+ FUNC_ALIAS aeabi_llsr lshrdi3
+
+#ifdef __thumb__
+ lsr al, r2
+ mov r3, ah
+ lsr ah, r2
+ mov ip, r3
+ sub r2, #32
+ lsr r3, r2
+ orr al, r3
+ neg r2, r2
+ mov r3, ip
+ lsl r3, r2
+ orr al, r3
+ RET
+#else
+ subs r3, r2, #32
+ rsb ip, r2, #32
+ movmi al, al, lsr r2
+ movpl al, ah, lsr r3
+ orrmi al, al, ah, lsl ip
+ mov ah, ah, lsr r2
+ RET
+#endif
+ FUNC_END aeabi_llsr
+ FUNC_END lshrdi3
+
+#endif
+
+#ifdef L_ashrdi3
+
+ FUNC_START ashrdi3
+ FUNC_ALIAS aeabi_lasr ashrdi3
+
+#ifdef __thumb__
+ lsr al, r2
+ mov r3, ah
+ asr ah, r2
+ sub r2, #32
+ @ If r2 is negative at this point the following step would OR
+ @ the sign bit into all of AL. That's not what we want...
+ bmi 1f
+ mov ip, r3
+ asr r3, r2
+ orr al, r3
+ mov r3, ip
+1:
+ neg r2, r2
+ lsl r3, r2
+ orr al, r3
+ RET
+#else
+ subs r3, r2, #32
+ rsb ip, r2, #32
+ movmi al, al, lsr r2
+ movpl al, ah, asr r3
+ orrmi al, al, ah, lsl ip
+ mov ah, ah, asr r2
+ RET
+#endif
+
+ FUNC_END aeabi_lasr
+ FUNC_END ashrdi3
+
+#endif
+
+#ifdef L_ashldi3
+
+ FUNC_START ashldi3
+ FUNC_ALIAS aeabi_llsl ashldi3
+
+#ifdef __thumb__
+ lsl ah, r2
+ mov r3, al
+ lsl al, r2
+ mov ip, r3
+ sub r2, #32
+ lsl r3, r2
+ orr ah, r3
+ neg r2, r2
+ mov r3, ip
+ lsr r3, r2
+ orr ah, r3
+ RET
+#else
+ subs r3, r2, #32
+ rsb ip, r2, #32
+ movmi ah, ah, lsl r2
+ movpl ah, al, lsl r3
+ orrmi ah, ah, al, lsr ip
+ mov al, al, lsl r2
+ RET
+#endif
+ FUNC_END aeabi_llsl
+ FUNC_END ashldi3
+
+#endif
+
+#endif /* __symbian__ */
+
+/* ------------------------------------------------------------------------ */
+/* These next two sections are here despite the fact that they contain Thumb
+ assembler because their presence allows interworked code to be linked even
+ when the GCC library is this one. */
+
+/* Do not build the interworking functions when the target architecture does
+ not support Thumb instructions. (This can be a multilib option). */
+#if defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__\
+ || defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__ \
+ || __ARM_ARCH__ >= 6
+
+#if defined L_call_via_rX
+
+/* These labels & instructions are used by the Arm/Thumb interworking code.
+ The address of function to be called is loaded into a register and then
+ one of these labels is called via a BL instruction. This puts the
+ return address into the link register with the bottom bit set, and the
+ code here switches to the correct mode before executing the function. */
+
+ .text
+ .align 0
+ .force_thumb
+
+.macro call_via register
+ THUMB_FUNC_START _call_via_\register
+
+ bx \register
+ nop
+
+ SIZE (_call_via_\register)
+.endm
+
+ call_via r0
+ call_via r1
+ call_via r2
+ call_via r3
+ call_via r4
+ call_via r5
+ call_via r6
+ call_via r7
+ call_via r8
+ call_via r9
+ call_via sl
+ call_via fp
+ call_via ip
+ call_via sp
+ call_via lr
+
+#endif /* L_call_via_rX */
+
+/* Don't bother with the old interworking routines for Thumb-2. */
+/* ??? Maybe only omit these on v7m. */
+#ifndef __thumb2__
+
+#if defined L_interwork_call_via_rX
+
+/* These labels & instructions are used by the Arm/Thumb interworking code,
+ when the target address is in an unknown instruction set. The address
+ of function to be called is loaded into a register and then one of these
+ labels is called via a BL instruction. This puts the return address
+ into the link register with the bottom bit set, and the code here
+ switches to the correct mode before executing the function. Unfortunately
+ the target code cannot be relied upon to return via a BX instruction, so
+ instead we have to store the resturn address on the stack and allow the
+ called function to return here instead. Upon return we recover the real
+ return address and use a BX to get back to Thumb mode.
+
+ There are three variations of this code. The first,
+ _interwork_call_via_rN(), will push the return address onto the
+ stack and pop it in _arm_return(). It should only be used if all
+ arguments are passed in registers.
+
+ The second, _interwork_r7_call_via_rN(), instead stores the return
+ address at [r7, #-4]. It is the caller's responsibility to ensure
+ that this address is valid and contains no useful data.
+
+ The third, _interwork_r11_call_via_rN(), works in the same way but
+ uses r11 instead of r7. It is useful if the caller does not really
+ need a frame pointer. */
+
+ .text
+ .align 0
+
+ .code 32
+ .globl _arm_return
+LSYM(Lstart_arm_return):
+ cfi_start LSYM(Lstart_arm_return) LSYM(Lend_arm_return)
+ cfi_push 0, 0xe, -0x8, 0x8
+ nop @ This nop is for the benefit of debuggers, so that
+ @ backtraces will use the correct unwind information.
+_arm_return:
+ RETLDM unwind=LSYM(Lstart_arm_return)
+ cfi_end LSYM(Lend_arm_return)
+
+ .globl _arm_return_r7
+_arm_return_r7:
+ ldr lr, [r7, #-4]
+ bx lr
+
+ .globl _arm_return_r11
+_arm_return_r11:
+ ldr lr, [r11, #-4]
+ bx lr
+
+.macro interwork_with_frame frame, register, name, return
+ .code 16
+
+ THUMB_FUNC_START \name
+
+ bx pc
+ nop
+
+ .code 32
+ tst \register, #1
+ streq lr, [\frame, #-4]
+ adreq lr, _arm_return_\frame
+ bx \register
+
+ SIZE (\name)
+.endm
+
+.macro interwork register
+ .code 16
+
+ THUMB_FUNC_START _interwork_call_via_\register
+
+ bx pc
+ nop
+
+ .code 32
+ .globl LSYM(Lchange_\register)
+LSYM(Lchange_\register):
+ tst \register, #1
+ streq lr, [sp, #-8]!
+ adreq lr, _arm_return
+ bx \register
+
+ SIZE (_interwork_call_via_\register)
+
+ interwork_with_frame r7,\register,_interwork_r7_call_via_\register
+ interwork_with_frame r11,\register,_interwork_r11_call_via_\register
+.endm
+
+ interwork r0
+ interwork r1
+ interwork r2
+ interwork r3
+ interwork r4
+ interwork r5
+ interwork r6
+ interwork r7
+ interwork r8
+ interwork r9
+ interwork sl
+ interwork fp
+ interwork ip
+ interwork sp
+
+ /* The LR case has to be handled a little differently... */
+ .code 16
+
+ THUMB_FUNC_START _interwork_call_via_lr
+
+ bx pc
+ nop
+
+ .code 32
+ .globl .Lchange_lr
+.Lchange_lr:
+ tst lr, #1
+ stmeqdb r13!, {lr, pc}
+ mov ip, lr
+ adreq lr, _arm_return
+ bx ip
+
+ SIZE (_interwork_call_via_lr)
+
+#endif /* L_interwork_call_via_rX */
+#endif /* !__thumb2__ */
+#endif /* Arch supports thumb. */
+
+#ifndef __symbian__
+//#include "ieee754-df.S"
+//#include "ieee754-sf.S"
+#include "bpabi.S"
+#endif /* __symbian__ */
diff --git a/setup/Linux/arm/longlong.h b/setup/Linux/arm/longlong.h
new file mode 100644
index 0000000..a2f4e56
--- /dev/null
+++ b/setup/Linux/arm/longlong.h
@@ -0,0 +1,1465 @@
+/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
+ Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009
+ Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file into
+ combinations with other programs, and to distribute those
+ combinations without any restriction coming from the use of this
+ file. (The Lesser General Public License restrictions do apply in
+ other respects; for example, they cover modification of the file,
+ and distribution when not linked into a combine executable.)
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* You have to define the following before including this file:
+
+ UWtype -- An unsigned type, default type for operations (typically a "word")
+ UHWtype -- An unsigned type, at least half the size of UWtype.
+ UDWtype -- An unsigned type, at least twice as large a UWtype
+ W_TYPE_SIZE -- size in bits of UWtype
+
+ UQItype -- Unsigned 8 bit type.
+ SItype, USItype -- Signed and unsigned 32 bit types.
+ DItype, UDItype -- Signed and unsigned 64 bit types.
+
+ On a 32 bit machine UWtype should typically be USItype;
+ on a 64 bit machine, UWtype should typically be UDItype. */
+
+#define __BITS4 (W_TYPE_SIZE / 4)
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+#ifndef W_TYPE_SIZE
+#define W_TYPE_SIZE 32
+#define UWtype USItype
+#define UHWtype USItype
+#define UDWtype UDItype
+#endif
+
+extern const UQItype __clz_tab[256];
+
+/* Define auxiliary asm macros.
+
+ 1) umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two
+ UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype
+ word product in HIGH_PROD and LOW_PROD.
+
+ 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a
+ UDWtype product. This is just a variant of umul_ppmm.
+
+ 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+ denominator) divides a UDWtype, composed by the UWtype integers
+ HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
+ in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less
+ than DENOMINATOR for correct operation. If, in addition, the most
+ significant bit of DENOMINATOR must be 1, then the pre-processor symbol
+ UDIV_NEEDS_NORMALIZATION is defined to 1.
+
+ 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+ denominator). Like udiv_qrnnd but the numbers are signed. The quotient
+ is rounded towards 0.
+
+ 5) count_leading_zeros(count, x) counts the number of zero-bits from the
+ msb to the first nonzero bit in the UWtype X. This is the number of
+ steps X needs to be shifted left to set the msb. Undefined for X == 0,
+ unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value.
+
+ 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts
+ from the least significant end.
+
+ 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
+ high_addend_2, low_addend_2) adds two UWtype integers, composed by
+ HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
+ respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow
+ (i.e. carry out) is not stored anywhere, and is lost.
+
+ 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
+ high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
+ composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
+ LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE
+ and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere,
+ and is lost.
+
+ If any of these macros are left undefined for a particular CPU,
+ C macros are used. */
+
+/* The CPUs come in alphabetical order below.
+
+ Please add support for more CPUs here, or improve the current support
+ for the CPUs below!
+ (E.g. WE32100, IBM360.) */
+
+#if defined (__GNUC__) && !defined (NO_ASM)
+
+/* We sometimes need to clobber "cc" with gcc2, but that would not be
+ understood by gcc1. Use cpp to avoid major code duplication. */
+#if __GNUC__ < 2
+#define __CLOBBER_CC
+#define __AND_CLOBBER_CC
+#else /* __GNUC__ >= 2 */
+#define __CLOBBER_CC : "cc"
+#define __AND_CLOBBER_CC , "cc"
+#endif /* __GNUC__ < 2 */
+
+#if defined (__alpha) && W_TYPE_SIZE == 64
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ UDItype __m0 = (m0), __m1 = (m1); \
+ (ph) = __builtin_alpha_umulh (__m0, __m1); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define UMUL_TIME 46
+#ifndef LONGLONG_STANDALONE
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { UDItype __r; \
+ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
+ (r) = __r; \
+ } while (0)
+extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype);
+#define UDIV_TIME 220
+#endif /* LONGLONG_STANDALONE */
+#ifdef __alpha_cix__
+#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clzl (X))
+#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctzl (X))
+#define COUNT_LEADING_ZEROS_0 64
+#else
+#define count_leading_zeros(COUNT,X) \
+ do { \
+ UDItype __xr = (X), __t, __a; \
+ __t = __builtin_alpha_cmpbge (0, __xr); \
+ __a = __clz_tab[__t ^ 0xff] - 1; \
+ __t = __builtin_alpha_extbl (__xr, __a); \
+ (COUNT) = 64 - (__clz_tab[__t] + __a*8); \
+ } while (0)
+#define count_trailing_zeros(COUNT,X) \
+ do { \
+ UDItype __xr = (X), __t, __a; \
+ __t = __builtin_alpha_cmpbge (0, __xr); \
+ __t = ~__t & -~__t; \
+ __a = ((__t & 0xCC) != 0) * 2; \
+ __a += ((__t & 0xF0) != 0) * 4; \
+ __a += ((__t & 0xAA) != 0); \
+ __t = __builtin_alpha_extbl (__xr, __a); \
+ __a <<= 3; \
+ __t &= -__t; \
+ __a += ((__t & 0xCC) != 0) * 2; \
+ __a += ((__t & 0xF0) != 0) * 4; \
+ __a += ((__t & 0xAA) != 0); \
+ (COUNT) = __a; \
+ } while (0)
+#endif /* __alpha_cix__ */
+#endif /* __alpha */
+
+#if defined (__arc__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%r" ((USItype) (ah)), \
+ "rIJ" ((USItype) (bh)), \
+ "%r" ((USItype) (al)), \
+ "rIJ" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub.f %1, %4, %5\n\tsbc %0, %2, %3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (ah)), \
+ "rIJ" ((USItype) (bh)), \
+ "r" ((USItype) (al)), \
+ "rIJ" ((USItype) (bl)))
+/* Call libgcc routine. */
+#define umul_ppmm(w1, w0, u, v) \
+do { \
+ DWunion __w; \
+ __w.ll = __umulsidi3 (u, v); \
+ w1 = __w.s.high; \
+ w0 = __w.s.low; \
+} while (0)
+#define __umulsidi3 __umulsidi3
+UDItype __umulsidi3 (USItype, USItype);
+#endif
+
+#if defined (__arm__) && !defined (__thumb__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("adds %1, %4, %5\n\tadc %0, %2, %3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%r" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "%r" ((USItype) (al)), \
+ "rI" ((USItype) (bl)) __CLOBBER_CC)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subs %1, %4, %5\n\tsbc %0, %2, %3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "r" ((USItype) (al)), \
+ "rI" ((USItype) (bl)) __CLOBBER_CC)
+#define umul_ppmm(xh, xl, a, b) \
+{register USItype __t0, __t1, __t2; \
+ __asm__ ("%@ Inlined umul_ppmm\n" \
+ " mov %2, %5, lsr #16\n" \
+ " mov %0, %6, lsr #16\n" \
+ " bic %3, %5, %2, lsl #16\n" \
+ " bic %4, %6, %0, lsl #16\n" \
+ " mul %1, %3, %4\n" \
+ " mul %4, %2, %4\n" \
+ " mul %3, %0, %3\n" \
+ " mul %0, %2, %0\n" \
+ " adds %3, %4, %3\n" \
+ " addcs %0, %0, #65536\n" \
+ " adds %1, %1, %3, lsl #16\n" \
+ " adc %0, %0, %3, lsr #16" \
+ : "=&r" ((USItype) (xh)), \
+ "=r" ((USItype) (xl)), \
+ "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
+ : "r" ((USItype) (a)), \
+ "r" ((USItype) (b)) __CLOBBER_CC );}
+#define UMUL_TIME 20
+#define UDIV_TIME 100
+#endif /* __arm__ */
+
+#if defined (__CRIS__) && __CRIS_arch_version >= 3
+#define count_leading_zeros(COUNT, X) ((COUNT) = __builtin_clz (X))
+#if __CRIS_arch_version >= 8
+#define count_trailing_zeros(COUNT, X) ((COUNT) = __builtin_ctz (X))
+#endif
+#endif /* __CRIS__ */
+
+#if defined (__hppa) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%rM" ((USItype) (ah)), \
+ "rM" ((USItype) (bh)), \
+ "%rM" ((USItype) (al)), \
+ "rM" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "rM" ((USItype) (ah)), \
+ "rM" ((USItype) (bh)), \
+ "rM" ((USItype) (al)), \
+ "rM" ((USItype) (bl)))
+#if defined (_PA_RISC1_1)
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ union \
+ { \
+ UDItype __f; \
+ struct {USItype __w1, __w0;} __w1w0; \
+ } __t; \
+ __asm__ ("xmpyu %1,%2,%0" \
+ : "=x" (__t.__f) \
+ : "x" ((USItype) (u)), \
+ "x" ((USItype) (v))); \
+ (w1) = __t.__w1w0.__w1; \
+ (w0) = __t.__w1w0.__w0; \
+ } while (0)
+#define UMUL_TIME 8
+#else
+#define UMUL_TIME 30
+#endif
+#define UDIV_TIME 40
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __tmp; \
+ __asm__ ( \
+ "ldi 1,%0\n" \
+" extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \
+" extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n"\
+" ldo 16(%0),%0 ; Yes. Perform add.\n" \
+" extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \
+" extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n"\
+" ldo 8(%0),%0 ; Yes. Perform add.\n" \
+" extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \
+" extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n"\
+" ldo 4(%0),%0 ; Yes. Perform add.\n" \
+" extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \
+" extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n"\
+" ldo 2(%0),%0 ; Yes. Perform add.\n" \
+" extru %1,30,1,%1 ; Extract bit 1.\n" \
+" sub %0,%1,%0 ; Subtract it.\n" \
+ : "=r" (count), "=r" (__tmp) : "1" (x)); \
+ } while (0)
+#endif
+
+#if (defined (__i370__) || defined (__s390__) || defined (__mvs__)) && W_TYPE_SIZE == 32
+#define smul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {DItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __x; \
+ __asm__ ("lr %N0,%1\n\tmr %0,%2" \
+ : "=&r" (__x.__ll) \
+ : "r" (m0), "r" (m1)); \
+ (xh) = __x.__i.__h; (xl) = __x.__i.__l; \
+ } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ union {DItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __x; \
+ __x.__i.__h = n1; __x.__i.__l = n0; \
+ __asm__ ("dr %0,%2" \
+ : "=r" (__x.__ll) \
+ : "0" (__x.__ll), "r" (d)); \
+ (q) = __x.__i.__l; (r) = __x.__i.__h; \
+ } while (0)
+#endif
+
+#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add{l} {%5,%1|%1,%5}\n\tadc{l} {%3,%0|%0,%3}" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "%1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub{l} {%5,%1|%1,%5}\n\tsbb{l} {%3,%0|%0,%3}" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("mul{l} %3" \
+ : "=a" ((USItype) (w0)), \
+ "=d" ((USItype) (w1)) \
+ : "%0" ((USItype) (u)), \
+ "rm" ((USItype) (v)))
+#define udiv_qrnnd(q, r, n1, n0, dv) \
+ __asm__ ("div{l} %4" \
+ : "=a" ((USItype) (q)), \
+ "=d" ((USItype) (r)) \
+ : "0" ((USItype) (n0)), \
+ "1" ((USItype) (n1)), \
+ "rm" ((USItype) (dv)))
+#define count_leading_zeros(count, x) ((count) = __builtin_clz (x))
+#define count_trailing_zeros(count, x) ((count) = __builtin_ctz (x))
+#define UMUL_TIME 40
+#define UDIV_TIME 40
+#endif /* 80x86 */
+
+#if (defined (__x86_64__) || defined (__i386__)) && W_TYPE_SIZE == 64
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add{q} {%5,%1|%1,%5}\n\tadc{q} {%3,%0|%0,%3}" \
+ : "=r" ((UDItype) (sh)), \
+ "=&r" ((UDItype) (sl)) \
+ : "%0" ((UDItype) (ah)), \
+ "rme" ((UDItype) (bh)), \
+ "%1" ((UDItype) (al)), \
+ "rme" ((UDItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub{q} {%5,%1|%1,%5}\n\tsbb{q} {%3,%0|%0,%3}" \
+ : "=r" ((UDItype) (sh)), \
+ "=&r" ((UDItype) (sl)) \
+ : "0" ((UDItype) (ah)), \
+ "rme" ((UDItype) (bh)), \
+ "1" ((UDItype) (al)), \
+ "rme" ((UDItype) (bl)))
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("mul{q} %3" \
+ : "=a" ((UDItype) (w0)), \
+ "=d" ((UDItype) (w1)) \
+ : "%0" ((UDItype) (u)), \
+ "rm" ((UDItype) (v)))
+#define udiv_qrnnd(q, r, n1, n0, dv) \
+ __asm__ ("div{q} %4" \
+ : "=a" ((UDItype) (q)), \
+ "=d" ((UDItype) (r)) \
+ : "0" ((UDItype) (n0)), \
+ "1" ((UDItype) (n1)), \
+ "rm" ((UDItype) (dv)))
+#define count_leading_zeros(count, x) ((count) = __builtin_clzl (x))
+#define count_trailing_zeros(count, x) ((count) = __builtin_ctzl (x))
+#define UMUL_TIME 40
+#define UDIV_TIME 40
+#endif /* x86_64 */
+
+#if defined (__i960__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+ ({union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ __asm__ ("emul %2,%1,%0" \
+ : "=d" (__xx.__ll) \
+ : "%dI" ((USItype) (u)), \
+ "dI" ((USItype) (v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+ ({UDItype __w; \
+ __asm__ ("emul %2,%1,%0" \
+ : "=d" (__w) \
+ : "%dI" ((USItype) (u)), \
+ "dI" ((USItype) (v))); \
+ __w; })
+#endif /* __i960__ */
+
+#if defined (__M32R__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ /* The cmp clears the condition bit. */ \
+ __asm__ ("cmp %0,%0\n\taddx %1,%5\n\taddx %0,%3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "r" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "r" ((USItype) (bl)) \
+ : "cbit")
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ /* The cmp clears the condition bit. */ \
+ __asm__ ("cmp %0,%0\n\tsubx %1,%5\n\tsubx %0,%3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "r" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "r" ((USItype) (bl)) \
+ : "cbit")
+#endif /* __M32R__ */
+
+#if defined (__mc68000__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \
+ : "=d" ((USItype) (sh)), \
+ "=&d" ((USItype) (sl)) \
+ : "%0" ((USItype) (ah)), \
+ "d" ((USItype) (bh)), \
+ "%1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0" \
+ : "=d" ((USItype) (sh)), \
+ "=&d" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "d" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
+
+/* The '020, '030, '040, '060 and CPU32 have 32x32->64 and 64/32->32q-32r. */
+#if (defined (__mc68020__) && !defined (__mc68060__))
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("mulu%.l %3,%1:%0" \
+ : "=d" ((USItype) (w0)), \
+ "=d" ((USItype) (w1)) \
+ : "%0" ((USItype) (u)), \
+ "dmi" ((USItype) (v)))
+#define UMUL_TIME 45
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("divu%.l %4,%1:%0" \
+ : "=d" ((USItype) (q)), \
+ "=d" ((USItype) (r)) \
+ : "0" ((USItype) (n0)), \
+ "1" ((USItype) (n1)), \
+ "dmi" ((USItype) (d)))
+#define UDIV_TIME 90
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("divs%.l %4,%1:%0" \
+ : "=d" ((USItype) (q)), \
+ "=d" ((USItype) (r)) \
+ : "0" ((USItype) (n0)), \
+ "1" ((USItype) (n1)), \
+ "dmi" ((USItype) (d)))
+
+#elif defined (__mcoldfire__) /* not mc68020 */
+
+#define umul_ppmm(xh, xl, a, b) \
+ __asm__ ("| Inlined umul_ppmm\n" \
+ " move%.l %2,%/d0\n" \
+ " move%.l %3,%/d1\n" \
+ " move%.l %/d0,%/d2\n" \
+ " swap %/d0\n" \
+ " move%.l %/d1,%/d3\n" \
+ " swap %/d1\n" \
+ " move%.w %/d2,%/d4\n" \
+ " mulu %/d3,%/d4\n" \
+ " mulu %/d1,%/d2\n" \
+ " mulu %/d0,%/d3\n" \
+ " mulu %/d0,%/d1\n" \
+ " move%.l %/d4,%/d0\n" \
+ " clr%.w %/d0\n" \
+ " swap %/d0\n" \
+ " add%.l %/d0,%/d2\n" \
+ " add%.l %/d3,%/d2\n" \
+ " jcc 1f\n" \
+ " add%.l %#65536,%/d1\n" \
+ "1: swap %/d2\n" \
+ " moveq %#0,%/d0\n" \
+ " move%.w %/d2,%/d0\n" \
+ " move%.w %/d4,%/d2\n" \
+ " move%.l %/d2,%1\n" \
+ " add%.l %/d1,%/d0\n" \
+ " move%.l %/d0,%0" \
+ : "=g" ((USItype) (xh)), \
+ "=g" ((USItype) (xl)) \
+ : "g" ((USItype) (a)), \
+ "g" ((USItype) (b)) \
+ : "d0", "d1", "d2", "d3", "d4")
+#define UMUL_TIME 100
+#define UDIV_TIME 400
+#else /* not ColdFire */
+/* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX. */
+#define umul_ppmm(xh, xl, a, b) \
+ __asm__ ("| Inlined umul_ppmm\n" \
+ " move%.l %2,%/d0\n" \
+ " move%.l %3,%/d1\n" \
+ " move%.l %/d0,%/d2\n" \
+ " swap %/d0\n" \
+ " move%.l %/d1,%/d3\n" \
+ " swap %/d1\n" \
+ " move%.w %/d2,%/d4\n" \
+ " mulu %/d3,%/d4\n" \
+ " mulu %/d1,%/d2\n" \
+ " mulu %/d0,%/d3\n" \
+ " mulu %/d0,%/d1\n" \
+ " move%.l %/d4,%/d0\n" \
+ " eor%.w %/d0,%/d0\n" \
+ " swap %/d0\n" \
+ " add%.l %/d0,%/d2\n" \
+ " add%.l %/d3,%/d2\n" \
+ " jcc 1f\n" \
+ " add%.l %#65536,%/d1\n" \
+ "1: swap %/d2\n" \
+ " moveq %#0,%/d0\n" \
+ " move%.w %/d2,%/d0\n" \
+ " move%.w %/d4,%/d2\n" \
+ " move%.l %/d2,%1\n" \
+ " add%.l %/d1,%/d0\n" \
+ " move%.l %/d0,%0" \
+ : "=g" ((USItype) (xh)), \
+ "=g" ((USItype) (xl)) \
+ : "g" ((USItype) (a)), \
+ "g" ((USItype) (b)) \
+ : "d0", "d1", "d2", "d3", "d4")
+#define UMUL_TIME 100
+#define UDIV_TIME 400
+
+#endif /* not mc68020 */
+
+/* The '020, '030, '040 and '060 have bitfield insns.
+ cpu32 disguises as a 68020, but lacks them. */
+#if defined (__mc68020__) && !defined (__mcpu32__)
+#define count_leading_zeros(count, x) \
+ __asm__ ("bfffo %1{%b2:%b2},%0" \
+ : "=d" ((USItype) (count)) \
+ : "od" ((USItype) (x)), "n" (0))
+/* Some ColdFire architectures have a ff1 instruction supported via
+ __builtin_clz. */
+#elif defined (__mcfisaaplus__) || defined (__mcfisac__)
+#define count_leading_zeros(count,x) ((count) = __builtin_clz (x))
+#define COUNT_LEADING_ZEROS_0 32
+#endif
+#endif /* mc68000 */
+
+#if defined (__m88000__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%rJ" ((USItype) (ah)), \
+ "rJ" ((USItype) (bh)), \
+ "%rJ" ((USItype) (al)), \
+ "rJ" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "rJ" ((USItype) (ah)), \
+ "rJ" ((USItype) (bh)), \
+ "rJ" ((USItype) (al)), \
+ "rJ" ((USItype) (bl)))
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __cbtmp; \
+ __asm__ ("ff1 %0,%1" \
+ : "=r" (__cbtmp) \
+ : "r" ((USItype) (x))); \
+ (count) = __cbtmp ^ 31; \
+ } while (0)
+#define COUNT_LEADING_ZEROS_0 63 /* sic */
+#if defined (__mc88110__)
+#define umul_ppmm(wh, wl, u, v) \
+ do { \
+ union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ __asm__ ("mulu.d %0,%1,%2" \
+ : "=r" (__xx.__ll) \
+ : "r" ((USItype) (u)), \
+ "r" ((USItype) (v))); \
+ (wh) = __xx.__i.__h; \
+ (wl) = __xx.__i.__l; \
+ } while (0)
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ ({union {UDItype __ll; \
+ struct {USItype __h, __l;} __i; \
+ } __xx; \
+ USItype __q; \
+ __xx.__i.__h = (n1); __xx.__i.__l = (n0); \
+ __asm__ ("divu.d %0,%1,%2" \
+ : "=r" (__q) \
+ : "r" (__xx.__ll), \
+ "r" ((USItype) (d))); \
+ (r) = (n0) - __q * (d); (q) = __q; })
+#define UMUL_TIME 5
+#define UDIV_TIME 25
+#else
+#define UMUL_TIME 17
+#define UDIV_TIME 150
+#endif /* __mc88110__ */
+#endif /* __m88000__ */
+
+#if defined (__mips__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("multu %2,%3" \
+ : "=l" ((USItype) (w0)), \
+ "=h" ((USItype) (w1)) \
+ : "d" ((USItype) (u)), \
+ "d" ((USItype) (v)))
+#define UMUL_TIME 10
+#define UDIV_TIME 100
+
+#if (__mips == 32 || __mips == 64) && ! __mips16
+#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clz (X))
+#define COUNT_LEADING_ZEROS_0 32
+#endif
+#endif /* __mips__ */
+
+#if defined (__ns32000__) && W_TYPE_SIZE == 32
+#define umul_ppmm(w1, w0, u, v) \
+ ({union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ __asm__ ("meid %2,%0" \
+ : "=g" (__xx.__ll) \
+ : "%0" ((USItype) (u)), \
+ "g" ((USItype) (v))); \
+ (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
+#define __umulsidi3(u, v) \
+ ({UDItype __w; \
+ __asm__ ("meid %2,%0" \
+ : "=g" (__w) \
+ : "%0" ((USItype) (u)), \
+ "g" ((USItype) (v))); \
+ __w; })
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ ({union {UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ __xx.__i.__h = (n1); __xx.__i.__l = (n0); \
+ __asm__ ("deid %2,%0" \
+ : "=g" (__xx.__ll) \
+ : "0" (__xx.__ll), \
+ "g" ((USItype) (d))); \
+ (r) = __xx.__i.__l; (q) = __xx.__i.__h; })
+#define count_trailing_zeros(count,x) \
+ do { \
+ __asm__ ("ffsd %2,%0" \
+ : "=r" ((USItype) (count)) \
+ : "0" ((USItype) 0), \
+ "r" ((USItype) (x))); \
+ } while (0)
+#endif /* __ns32000__ */
+
+/* FIXME: We should test _IBMR2 here when we add assembly support for the
+ system vendor compilers.
+ FIXME: What's needed for gcc PowerPC VxWorks? __vxworks__ is not good
+ enough, since that hits ARM and m68k too. */
+#if (defined (_ARCH_PPC) /* AIX */ \
+ || defined (_ARCH_PWR) /* AIX */ \
+ || defined (_ARCH_COM) /* AIX */ \
+ || defined (__powerpc__) /* gcc */ \
+ || defined (__POWERPC__) /* BEOS */ \
+ || defined (__ppc__) /* Darwin */ \
+ || (defined (PPC) && ! defined (CPU_FAMILY)) /* gcc 2.7.x GNU&SysV */ \
+ || (defined (PPC) && defined (CPU_FAMILY) /* VxWorks */ \
+ && CPU_FAMILY == PPC) \
+ ) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+ else \
+ __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
+ : "=r" (sh), "=&r" (sl) \
+ : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \
+ } while (0)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (ah) && (ah) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+ else \
+ __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
+ : "=r" (sh), "=&r" (sl) \
+ : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \
+ } while (0)
+#define count_leading_zeros(count, x) \
+ __asm__ ("{cntlz|cntlzw} %0,%1" : "=r" (count) : "r" (x))
+#define COUNT_LEADING_ZEROS_0 32
+#if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \
+ || defined (__ppc__) \
+ || (defined (PPC) && ! defined (CPU_FAMILY)) /* gcc 2.7.x GNU&SysV */ \
+ || (defined (PPC) && defined (CPU_FAMILY) /* VxWorks */ \
+ && CPU_FAMILY == PPC)
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define UMUL_TIME 15
+#define smul_ppmm(ph, pl, m0, m1) \
+ do { \
+ SItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define SMUL_TIME 14
+#define UDIV_TIME 120
+#elif defined (_ARCH_PWR)
+#define UMUL_TIME 8
+#define smul_ppmm(xh, xl, m0, m1) \
+ __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (xl) : "r" (m0), "r" (m1))
+#define SMUL_TIME 4
+#define sdiv_qrnnd(q, r, nh, nl, d) \
+ __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d))
+#define UDIV_TIME 100
+#endif
+#endif /* 32-bit POWER architecture variants. */
+
+/* We should test _IBMR2 here when we add assembly support for the system
+ vendor compilers. */
+#if (defined (_ARCH_PPC64) || defined (__powerpc64__)) && W_TYPE_SIZE == 64
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
+ __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
+ else \
+ __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
+ : "=r" (sh), "=&r" (sl) \
+ : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \
+ } while (0)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ if (__builtin_constant_p (ah) && (ah) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+ else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \
+ __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
+ : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
+ else \
+ __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
+ : "=r" (sh), "=&r" (sl) \
+ : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \
+ } while (0)
+#define count_leading_zeros(count, x) \
+ __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x))
+#define COUNT_LEADING_ZEROS_0 64
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ UDItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define UMUL_TIME 15
+#define smul_ppmm(ph, pl, m0, m1) \
+ do { \
+ DItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
+ (pl) = __m0 * __m1; \
+ } while (0)
+#define SMUL_TIME 14 /* ??? */
+#define UDIV_TIME 120 /* ??? */
+#endif /* 64-bit PowerPC. */
+
+#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("a %1,%5\n\tae %0,%3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%0" ((USItype) (ah)), \
+ "r" ((USItype) (bh)), \
+ "%1" ((USItype) (al)), \
+ "r" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("s %1,%5\n\tse %0,%3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "r" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "r" ((USItype) (bl)))
+#define umul_ppmm(ph, pl, m0, m1) \
+ do { \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ( \
+ "s r2,r2\n" \
+" mts r10,%2\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" m r2,%3\n" \
+" cas %0,r2,r0\n" \
+" mfs r10,%1" \
+ : "=r" ((USItype) (ph)), \
+ "=r" ((USItype) (pl)) \
+ : "%r" (__m0), \
+ "r" (__m1) \
+ : "r2"); \
+ (ph) += ((((SItype) __m0 >> 31) & __m1) \
+ + (((SItype) __m1 >> 31) & __m0)); \
+ } while (0)
+#define UMUL_TIME 20
+#define UDIV_TIME 200
+#define count_leading_zeros(count, x) \
+ do { \
+ if ((x) >= 0x10000) \
+ __asm__ ("clz %0,%1" \
+ : "=r" ((USItype) (count)) \
+ : "r" ((USItype) (x) >> 16)); \
+ else \
+ { \
+ __asm__ ("clz %0,%1" \
+ : "=r" ((USItype) (count)) \
+ : "r" ((USItype) (x))); \
+ (count) += 16; \
+ } \
+ } while (0)
+#endif
+
+#if defined(__sh__) && !__SHMEDIA__ && W_TYPE_SIZE == 32
+#ifndef __sh1__
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ( \
+ "dmulu.l %2,%3\n\tsts%M1 macl,%1\n\tsts%M0 mach,%0" \
+ : "=r<" ((USItype)(w1)), \
+ "=r<" ((USItype)(w0)) \
+ : "r" ((USItype)(u)), \
+ "r" ((USItype)(v)) \
+ : "macl", "mach")
+#define UMUL_TIME 5
+#endif
+
+/* This is the same algorithm as __udiv_qrnnd_c. */
+#define UDIV_NEEDS_NORMALIZATION 1
+
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ extern UWtype __udiv_qrnnd_16 (UWtype, UWtype) \
+ __attribute__ ((visibility ("hidden"))); \
+ /* r0: rn r1: qn */ /* r0: n1 r4: n0 r5: d r6: d1 */ /* r2: __m */ \
+ __asm__ ( \
+ "mov%M4 %4,r5\n" \
+" swap.w %3,r4\n" \
+" swap.w r5,r6\n" \
+" jsr @%5\n" \
+" shll16 r6\n" \
+" swap.w r4,r4\n" \
+" jsr @%5\n" \
+" swap.w r1,%0\n" \
+" or r1,%0" \
+ : "=r" (q), "=&z" (r) \
+ : "1" (n1), "r" (n0), "rm" (d), "r" (&__udiv_qrnnd_16) \
+ : "r1", "r2", "r4", "r5", "r6", "pr"); \
+ } while (0)
+
+#define UDIV_TIME 80
+
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("clrt;subc %5,%1; subc %4,%0" \
+ : "=r" (sh), "=r" (sl) \
+ : "0" (ah), "1" (al), "r" (bh), "r" (bl))
+
+#endif /* __sh__ */
+
+#if defined (__SH5__) && __SHMEDIA__ && W_TYPE_SIZE == 32
+#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v)
+#define count_leading_zeros(count, x) \
+ do \
+ { \
+ UDItype x_ = (USItype)(x); \
+ SItype c_; \
+ \
+ __asm__ ("nsb %1, %0" : "=r" (c_) : "r" (x_)); \
+ (count) = c_ - 31; \
+ } \
+ while (0)
+#define COUNT_LEADING_ZEROS_0 32
+#endif
+
+#if defined (__sparc__) && !defined (__arch64__) && !defined (__sparcv9) \
+ && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%rJ" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "%rJ" ((USItype) (al)), \
+ "rI" ((USItype) (bl)) \
+ __CLOBBER_CC)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "rJ" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "rJ" ((USItype) (al)), \
+ "rI" ((USItype) (bl)) \
+ __CLOBBER_CC)
+#if defined (__sparc_v8__)
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("umul %2,%3,%1;rd %%y,%0" \
+ : "=r" ((USItype) (w1)), \
+ "=r" ((USItype) (w0)) \
+ : "r" ((USItype) (u)), \
+ "r" ((USItype) (v)))
+#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
+ __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\
+ : "=&r" ((USItype) (__q)), \
+ "=&r" ((USItype) (__r)) \
+ : "r" ((USItype) (__n1)), \
+ "r" ((USItype) (__n0)), \
+ "r" ((USItype) (__d)))
+#else
+#if defined (__sparclite__)
+/* This has hardware multiply but not divide. It also has two additional
+ instructions scan (ffs from high bit) and divscc. */
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("umul %2,%3,%1;rd %%y,%0" \
+ : "=r" ((USItype) (w1)), \
+ "=r" ((USItype) (w0)) \
+ : "r" ((USItype) (u)), \
+ "r" ((USItype) (v)))
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("! Inlined udiv_qrnnd\n" \
+" wr %%g0,%2,%%y ! Not a delayed write for sparclite\n" \
+" tst %%g0\n" \
+" divscc %3,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%%g1\n" \
+" divscc %%g1,%4,%0\n" \
+" rd %%y,%1\n" \
+" bl,a 1f\n" \
+" add %1,%4,%1\n" \
+"1: ! End of inline udiv_qrnnd" \
+ : "=r" ((USItype) (q)), \
+ "=r" ((USItype) (r)) \
+ : "r" ((USItype) (n1)), \
+ "r" ((USItype) (n0)), \
+ "rI" ((USItype) (d)) \
+ : "g1" __AND_CLOBBER_CC)
+#define UDIV_TIME 37
+#define count_leading_zeros(count, x) \
+ do { \
+ __asm__ ("scan %1,1,%0" \
+ : "=r" ((USItype) (count)) \
+ : "r" ((USItype) (x))); \
+ } while (0)
+/* Early sparclites return 63 for an argument of 0, but they warn that future
+ implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0
+ undefined. */
+#else
+/* SPARC without integer multiplication and divide instructions.
+ (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("! Inlined umul_ppmm\n" \
+" wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n"\
+" sra %3,31,%%o5 ! Don't move this insn\n" \
+" and %2,%%o5,%%o5 ! Don't move this insn\n" \
+" andcc %%g0,0,%%g1 ! Don't move this insn\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,%3,%%g1\n" \
+" mulscc %%g1,0,%%g1\n" \
+" add %%g1,%%o5,%0\n" \
+" rd %%y,%1" \
+ : "=r" ((USItype) (w1)), \
+ "=r" ((USItype) (w0)) \
+ : "%rI" ((USItype) (u)), \
+ "r" ((USItype) (v)) \
+ : "g1", "o5" __AND_CLOBBER_CC)
+#define UMUL_TIME 39 /* 39 instructions */
+/* It's quite necessary to add this much assembler for the sparc.
+ The default udiv_qrnnd (in C) is more than 10 times slower! */
+#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
+ __asm__ ("! Inlined udiv_qrnnd\n" \
+" mov 32,%%g1\n" \
+" subcc %1,%2,%%g0\n" \
+"1: bcs 5f\n" \
+" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \
+" sub %1,%2,%1 ! this kills msb of n\n" \
+" addx %1,%1,%1 ! so this can't give carry\n" \
+" subcc %%g1,1,%%g1\n" \
+"2: bne 1b\n" \
+" subcc %1,%2,%%g0\n" \
+" bcs 3f\n" \
+" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \
+" b 3f\n" \
+" sub %1,%2,%1 ! this kills msb of n\n" \
+"4: sub %1,%2,%1\n" \
+"5: addxcc %1,%1,%1\n" \
+" bcc 2b\n" \
+" subcc %%g1,1,%%g1\n" \
+"! Got carry from n. Subtract next step to cancel this carry.\n" \
+" bne 4b\n" \
+" addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n" \
+" sub %1,%2,%1\n" \
+"3: xnor %0,0,%0\n" \
+" ! End of inline udiv_qrnnd" \
+ : "=&r" ((USItype) (__q)), \
+ "=&r" ((USItype) (__r)) \
+ : "r" ((USItype) (__d)), \
+ "1" ((USItype) (__n1)), \
+ "0" ((USItype) (__n0)) : "g1" __AND_CLOBBER_CC)
+#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */
+#endif /* __sparclite__ */
+#endif /* __sparc_v8__ */
+#endif /* sparc32 */
+
+#if ((defined (__sparc__) && defined (__arch64__)) || defined (__sparcv9)) \
+ && W_TYPE_SIZE == 64
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addcc %r4,%5,%1\n\t" \
+ "add %r2,%3,%0\n\t" \
+ "bcs,a,pn %%xcc, 1f\n\t" \
+ "add %0, 1, %0\n" \
+ "1:" \
+ : "=r" ((UDItype)(sh)), \
+ "=&r" ((UDItype)(sl)) \
+ : "%rJ" ((UDItype)(ah)), \
+ "rI" ((UDItype)(bh)), \
+ "%rJ" ((UDItype)(al)), \
+ "rI" ((UDItype)(bl)) \
+ __CLOBBER_CC)
+
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subcc %r4,%5,%1\n\t" \
+ "sub %r2,%3,%0\n\t" \
+ "bcs,a,pn %%xcc, 1f\n\t" \
+ "sub %0, 1, %0\n\t" \
+ "1:" \
+ : "=r" ((UDItype)(sh)), \
+ "=&r" ((UDItype)(sl)) \
+ : "rJ" ((UDItype)(ah)), \
+ "rI" ((UDItype)(bh)), \
+ "rJ" ((UDItype)(al)), \
+ "rI" ((UDItype)(bl)) \
+ __CLOBBER_CC)
+
+#define umul_ppmm(wh, wl, u, v) \
+ do { \
+ UDItype tmp1, tmp2, tmp3, tmp4; \
+ __asm__ __volatile__ ( \
+ "srl %7,0,%3\n\t" \
+ "mulx %3,%6,%1\n\t" \
+ "srlx %6,32,%2\n\t" \
+ "mulx %2,%3,%4\n\t" \
+ "sllx %4,32,%5\n\t" \
+ "srl %6,0,%3\n\t" \
+ "sub %1,%5,%5\n\t" \
+ "srlx %5,32,%5\n\t" \
+ "addcc %4,%5,%4\n\t" \
+ "srlx %7,32,%5\n\t" \
+ "mulx %3,%5,%3\n\t" \
+ "mulx %2,%5,%5\n\t" \
+ "sethi %%hi(0x80000000),%2\n\t" \
+ "addcc %4,%3,%4\n\t" \
+ "srlx %4,32,%4\n\t" \
+ "add %2,%2,%2\n\t" \
+ "movcc %%xcc,%%g0,%2\n\t" \
+ "addcc %5,%4,%5\n\t" \
+ "sllx %3,32,%3\n\t" \
+ "add %1,%3,%1\n\t" \
+ "add %5,%2,%0" \
+ : "=r" ((UDItype)(wh)), \
+ "=&r" ((UDItype)(wl)), \
+ "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \
+ : "r" ((UDItype)(u)), \
+ "r" ((UDItype)(v)) \
+ __CLOBBER_CC); \
+ } while (0)
+#define UMUL_TIME 96
+#define UDIV_TIME 230
+#endif /* sparc64 */
+
+#if defined (__vax__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("addl2 %5,%1\n\tadwc %3,%0" \
+ : "=g" ((USItype) (sh)), \
+ "=&g" ((USItype) (sl)) \
+ : "%0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "%1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subl2 %5,%1\n\tsbwc %3,%0" \
+ : "=g" ((USItype) (sh)), \
+ "=&g" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union { \
+ UDItype __ll; \
+ struct {USItype __l, __h;} __i; \
+ } __xx; \
+ USItype __m0 = (m0), __m1 = (m1); \
+ __asm__ ("emul %1,%2,$0,%0" \
+ : "=r" (__xx.__ll) \
+ : "g" (__m0), \
+ "g" (__m1)); \
+ (xh) = __xx.__i.__h; \
+ (xl) = __xx.__i.__l; \
+ (xh) += ((((SItype) __m0 >> 31) & __m1) \
+ + (((SItype) __m1 >> 31) & __m0)); \
+ } while (0)
+#define sdiv_qrnnd(q, r, n1, n0, d) \
+ do { \
+ union {DItype __ll; \
+ struct {SItype __l, __h;} __i; \
+ } __xx; \
+ __xx.__i.__h = n1; __xx.__i.__l = n0; \
+ __asm__ ("ediv %3,%2,%0,%1" \
+ : "=g" (q), "=g" (r) \
+ : "g" (__xx.__ll), "g" (d)); \
+ } while (0)
+#endif /* __vax__ */
+
+#if defined (__xtensa__) && W_TYPE_SIZE == 32
+/* This code is not Xtensa-configuration-specific, so rely on the compiler
+ to expand builtin functions depending on what configuration features
+ are available. This avoids library calls when the operation can be
+ performed in-line. */
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ DWunion __w; \
+ __w.ll = __builtin_umulsidi3 (u, v); \
+ w1 = __w.s.high; \
+ w0 = __w.s.low; \
+ } while (0)
+#define __umulsidi3(u, v) __builtin_umulsidi3 (u, v)
+#define count_leading_zeros(COUNT, X) ((COUNT) = __builtin_clz (X))
+#define count_trailing_zeros(COUNT, X) ((COUNT) = __builtin_ctz (X))
+#endif /* __xtensa__ */
+
+#if defined (__z8000__) && W_TYPE_SIZE == 16
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \
+ : "=r" ((unsigned int)(sh)), \
+ "=&r" ((unsigned int)(sl)) \
+ : "%0" ((unsigned int)(ah)), \
+ "r" ((unsigned int)(bh)), \
+ "%1" ((unsigned int)(al)), \
+ "rQR" ((unsigned int)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \
+ : "=r" ((unsigned int)(sh)), \
+ "=&r" ((unsigned int)(sl)) \
+ : "0" ((unsigned int)(ah)), \
+ "r" ((unsigned int)(bh)), \
+ "1" ((unsigned int)(al)), \
+ "rQR" ((unsigned int)(bl)))
+#define umul_ppmm(xh, xl, m0, m1) \
+ do { \
+ union {long int __ll; \
+ struct {unsigned int __h, __l;} __i; \
+ } __xx; \
+ unsigned int __m0 = (m0), __m1 = (m1); \
+ __asm__ ("mult %S0,%H3" \
+ : "=r" (__xx.__i.__h), \
+ "=r" (__xx.__i.__l) \
+ : "%1" (__m0), \
+ "rQR" (__m1)); \
+ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \
+ (xh) += ((((signed int) __m0 >> 15) & __m1) \
+ + (((signed int) __m1 >> 15) & __m0)); \
+ } while (0)
+#endif /* __z8000__ */
+
+#endif /* __GNUC__ */
+
+/* If this machine has no inline assembler, use C macros. */
+
+#if !defined (add_ssaaaa)
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ do { \
+ UWtype __x; \
+ __x = (al) + (bl); \
+ (sh) = (ah) + (bh) + (__x < (al)); \
+ (sl) = __x; \
+ } while (0)
+#endif
+
+#if !defined (sub_ddmmss)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ do { \
+ UWtype __x; \
+ __x = (al) - (bl); \
+ (sh) = (ah) - (bh) - (__x > (al)); \
+ (sl) = __x; \
+ } while (0)
+#endif
+
+/* If we lack umul_ppmm but have smul_ppmm, define umul_ppmm in terms of
+ smul_ppmm. */
+#if !defined (umul_ppmm) && defined (smul_ppmm)
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UWtype __w1; \
+ UWtype __xm0 = (u), __xm1 = (v); \
+ smul_ppmm (__w1, w0, __xm0, __xm1); \
+ (w1) = __w1 + (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1) \
+ + (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0); \
+ } while (0)
+#endif
+
+/* If we still don't have umul_ppmm, define it using plain C. */
+#if !defined (umul_ppmm)
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ UWtype __x0, __x1, __x2, __x3; \
+ UHWtype __ul, __vl, __uh, __vh; \
+ \
+ __ul = __ll_lowpart (u); \
+ __uh = __ll_highpart (u); \
+ __vl = __ll_lowpart (v); \
+ __vh = __ll_highpart (v); \
+ \
+ __x0 = (UWtype) __ul * __vl; \
+ __x1 = (UWtype) __ul * __vh; \
+ __x2 = (UWtype) __uh * __vl; \
+ __x3 = (UWtype) __uh * __vh; \
+ \
+ __x1 += __ll_highpart (__x0);/* this can't give carry */ \
+ __x1 += __x2; /* but this indeed can */ \
+ if (__x1 < __x2) /* did we get it? */ \
+ __x3 += __ll_B; /* yes, add it in the proper pos. */ \
+ \
+ (w1) = __x3 + __ll_highpart (__x1); \
+ (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
+ } while (0)
+#endif
+
+#if !defined (__umulsidi3)
+#define __umulsidi3(u, v) \
+ ({DWunion __w; \
+ umul_ppmm (__w.s.high, __w.s.low, u, v); \
+ __w.ll; })
+#endif
+
+/* Define this unconditionally, so it can be used for debugging. */
+#define __udiv_qrnnd_c(q, r, n1, n0, d) \
+ do { \
+ UWtype __d1, __d0, __q1, __q0; \
+ UWtype __r1, __r0, __m; \
+ __d1 = __ll_highpart (d); \
+ __d0 = __ll_lowpart (d); \
+ \
+ __r1 = (n1) % __d1; \
+ __q1 = (n1) / __d1; \
+ __m = (UWtype) __q1 * __d0; \
+ __r1 = __r1 * __ll_B | __ll_highpart (n0); \
+ if (__r1 < __m) \
+ { \
+ __q1--, __r1 += (d); \
+ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+ if (__r1 < __m) \
+ __q1--, __r1 += (d); \
+ } \
+ __r1 -= __m; \
+ \
+ __r0 = __r1 % __d1; \
+ __q0 = __r1 / __d1; \
+ __m = (UWtype) __q0 * __d0; \
+ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
+ if (__r0 < __m) \
+ { \
+ __q0--, __r0 += (d); \
+ if (__r0 >= (d)) \
+ if (__r0 < __m) \
+ __q0--, __r0 += (d); \
+ } \
+ __r0 -= __m; \
+ \
+ (q) = (UWtype) __q1 * __ll_B | __q0; \
+ (r) = __r0; \
+ } while (0)
+
+/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
+ __udiv_w_sdiv (defined in libgcc or elsewhere). */
+#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
+#define udiv_qrnnd(q, r, nh, nl, d) \
+ do { \
+ USItype __r; \
+ (q) = __udiv_w_sdiv (&__r, nh, nl, d); \
+ (r) = __r; \
+ } while (0)
+#endif
+
+/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */
+#if !defined (udiv_qrnnd)
+#define UDIV_NEEDS_NORMALIZATION 1
+#define udiv_qrnnd __udiv_qrnnd_c
+#endif
+
+#if !defined (count_leading_zeros)
+#define count_leading_zeros(count, x) \
+ do { \
+ UWtype __xr = (x); \
+ UWtype __a; \
+ \
+ if (W_TYPE_SIZE <= 32) \
+ { \
+ __a = __xr < ((UWtype)1<<2*__BITS4) \
+ ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4) \
+ : (__xr < ((UWtype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
+ } \
+ else \
+ { \
+ for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \
+ if (((__xr >> __a) & 0xff) != 0) \
+ break; \
+ } \
+ \
+ (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \
+ } while (0)
+#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
+#endif
+
+#if !defined (count_trailing_zeros)
+/* Define count_trailing_zeros using count_leading_zeros. The latter might be
+ defined in asm, but if it is not, the C version above is good enough. */
+#define count_trailing_zeros(count, x) \
+ do { \
+ UWtype __ctz_x = (x); \
+ UWtype __ctz_c; \
+ count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \
+ (count) = W_TYPE_SIZE - 1 - __ctz_c; \
+ } while (0)
+#endif
+
+#ifndef UDIV_NEEDS_NORMALIZATION
+#define UDIV_NEEDS_NORMALIZATION 0
+#endif
diff --git a/setup/Linux/build.sh b/setup/Linux/build.sh
new file mode 100644
index 0000000..e889bfe
--- /dev/null
+++ b/setup/Linux/build.sh
@@ -0,0 +1,240 @@
+#!/bin/sh
+
+. ./.directories
+
+if gawk '' >/dev/null
+then
+ TXT2MAN=$SRCDIR/setup/txt2man
+else
+ echo "No gawk found. Using lesser replacement" >&2
+ cc -o txt2man origdir/setup/txt2man.c
+ TXT2MAN=./txt2man
+fi
+
+[ -z "$LD" ] && LD=ld
+
+rm -rf prototype
+
+mkdir prototype
+mkdir prototype/etc
+echo "OSSLIBDIR=$OSSLIBDIR" > prototype/etc/oss.conf
+mkdir prototype/usr
+mkdir prototype/usr/bin
+mkdir prototype/usr/share
+mkdir prototype/usr/share/man
+mkdir prototype/usr/share/man/man1
+mkdir prototype/usr/share/man/man7
+mkdir prototype/usr/share/man/man8
+mkdir prototype/usr/sbin
+mkdir -p prototype/$OSSLIBDIR
+mkdir prototype/$OSSLIBDIR/etc
+mkdir prototype/$OSSLIBDIR/save
+mkdir prototype/$OSSLIBDIR/conf.tmpl
+mkdir prototype/$OSSLIBDIR/lib
+mkdir prototype/$OSSLIBDIR/modules.regparm
+mkdir prototype/$OSSLIBDIR/modules.noregparm
+mkdir prototype/$OSSLIBDIR/objects.regparm
+mkdir prototype/$OSSLIBDIR/objects.noregparm
+mkdir prototype/$OSSLIBDIR/include
+mkdir prototype/$OSSLIBDIR/include/sys
+mkdir prototype/$OSSLIBDIR/include/internals
+mkdir prototype/$OSSLIBDIR/build
+
+chmod 700 prototype/$OSSLIBDIR/modules.*
+chmod 700 prototype/$OSSLIBDIR/objects.*
+chmod 700 prototype/$OSSLIBDIR/build
+chmod 700 prototype/$OSSLIBDIR/save
+
+if test -f regparm && test "`cat regparm` " = "1 "
+then
+ MODULES=modules.regparm
+ OBJECTS=objects.regparm
+else
+ MODULES=modules.noregparm
+ OBJECTS=objects.noregparm
+fi
+
+cp .version prototype/$OSSLIBDIR/version.dat
+
+if test "`uname -m` " != "arm "
+then
+ if ! test -f regparm
+ then
+ echo Error: ./regparm is missing
+ exit 1
+ fi
+ cp regparm prototype/$OSSLIBDIR/build
+fi
+
+# Regenerating the config file templates
+rm -f /tmp/confgen
+if ! cc -o /tmp/confgen ./setup/Linux/confgen.c
+then
+ echo Building confgen failed
+ exit 1
+fi
+
+if ! /tmp/confgen prototype/$OSSLIBDIR/conf.tmpl $OSSLIBDIR/conf kernel/drv/* kernel/nonfree/drv/*
+then
+ echo Running confgen failed
+ exit 1
+fi
+
+rm -f /tmp/confgen
+
+cp $SRCDIR/include/*.h prototype/$OSSLIBDIR/include/sys/
+cp $SRCDIR/kernel/framework/include/midiparser.h prototype/$OSSLIBDIR/include/
+cp -f $SRCDIR/kernel/OS/Linux/wrapper/wrap.h prototype/$OSSLIBDIR/build/
+cp -f $SRCDIR/kernel/framework/include/udi.h prototype/$OSSLIBDIR/build/
+cp -a $SRCDIR/kernel/framework/include/*_core.h kernel/framework/include/local_config.h prototype/$OSSLIBDIR/include/internals
+cp $SRCDIR/kernel/framework/include/ossddk/*.h prototype/$OSSLIBDIR/include/internals
+cp kernel/framework/include/timestamp.h prototype/$OSSLIBDIR/include/internals
+cp kernel/framework/include/ossddk/oss_limits.h prototype/$OSSLIBDIR/include/internals
+
+cat > prototype/$OSSLIBDIR/include/internals/WARNING.txt << EOF
+Caution: All header files included in this directory are there only because
+ some parts of OSS may need to be re-compiled. It is not safe to use
+ these files for any purposes because they will change between OSS
+ versions/builds.
+EOF
+
+(cd target/bin; rm -f ossrecord; ln -s ossplay ossrecord)
+cp -f target/build/* prototype/$OSSLIBDIR/build/
+cp -f target/bin/* prototype/usr/bin
+cp -f target/sbin/* prototype/usr/sbin
+
+cp -a $SRCDIR/setup/Linux/oss/* prototype/$OSSLIBDIR/
+cp -a $SRCDIR/setup/Linux/sbin prototype/usr/
+chmod +x prototype/$OSSLIBDIR/scripts/*
+
+if ! $LD -r -o prototype/$OSSLIBDIR/$OBJECTS/osscore.o target/objects/*.o
+then
+ echo Linking osscore failed!
+ exit 1
+fi
+
+rm -f devlist.txt devices.list
+
+for n in `find kernel/ -name .devices`
+do
+ cat $n >> devices.list
+done
+
+for n in target/modules/*.o
+do
+ N=`basename $n .o`
+ $LD -r -o prototype/$OSSLIBDIR/$MODULES/$N.o $n
+ echo Check devices for $N
+ grep "^$N[ ]" ./devices.list >> devlist.txt
+
+ rm -f /tmp/ossman.txt
+
+ if test -f $SRCDIR/kernel/drv/$N/$N.man
+ then
+ sed "s:CONFIGFILEPATH:$OSSLIBDIR/conf:g" < $SRCDIR/kernel/drv/$N/$N.man > /tmp/ossman.txt
+ $TXT2MAN -t "$CMD" -v "OSS Devices" -s 7 /tmp/ossman.txt | gzip -9 > prototype/usr/share/man/man7/$N.7.gz
+ else
+ if test -f $SRCDIR/kernel/nonfree/drv/$N/$N.man
+ then
+ sed "s:CONFIGFILEPATH:$OSSLIBDIR/conf:g" < $SRCDIR/kernel/nonfree/drv/$N/$N.man > /tmp/ossman.txt
+ $TXT2MAN -t "$CMD" -v "OSS Devices" -s 7 $SRCDIR/kernel/nonfree/drv/$N/$N.man | gzip -9 > prototype/usr/share/man/man7/$N.7.gz
+ fi
+ fi
+done
+
+sed "s:CONFIGFILEPATH:$OSSLIBDIR/conf:g" < $SRCDIR/kernel/drv/osscore/osscore.man > /tmp/ossman.txt
+$TXT2MAN -t "osscore" -v "OSS Devices" -s 7 /tmp/ossman.txt | gzip -9 > prototype/usr/share/man/man7/osscore.7.gz
+rm -f /tmp/ossman.txt
+
+# Link the optional NOREGPARM modules
+if test -d noregparm
+then
+ $LD -r -o prototype/$OSSLIBDIR/objects.noregparm/osscore.o noregparm/target/objects/*.o
+
+ for n in noregparm/target/modules/*.o
+ do
+ N=`basename $n .o`
+ $LD -r -o prototype/$OSSLIBDIR/modules.noregparm/$N.o $n
+ done
+fi
+
+for n in $SRCDIR/misc/man7/*.man
+do
+ N=`basename $n .man`
+
+ $TXT2MAN -t "$CMD" -v "OSS Devices" -s 7 $n | gzip -9 > prototype/usr/share/man/man7/$N.7.gz
+done
+
+for n in $SRCDIR/misc/man1m/*.man
+do
+ N=`basename $n .man`
+ $TXT2MAN -t "$CMD" -v "OSS System Administration Commands" -s 1 $n | gzip -9 > prototype/usr/share/man/man1/$N.1.gz
+done
+
+if ! cp lib/libOSSlib/libOSSlib.so lib/libsalsa/.libs/libsalsa.so.2.0.0 prototype/$OSSLIBDIR/lib
+then
+ echo Warning: No libsalsa library compiled
+fi
+
+cp target/lib/* prototype/$OSSLIBDIR/lib
+
+cp devlist.txt prototype/$OSSLIBDIR/etc/devices.list
+
+if test -d kernel/nonfree
+then
+ cp devlist.txt $SRCDIR/devlists/Linux
+fi
+
+# Generate Man pages for commands
+for i in target/bin/*
+do
+CMD=`basename $i`
+$TXT2MAN -t "$CMD" -v "OSS User Commands" -s 1 cmd/$CMD/$CMD.man | gzip -9 > prototype/usr/share/man/man1/$CMD.1.gz
+echo done $CMD
+done
+
+for i in target/sbin/*
+do
+ CMD=`basename $i`
+ if test -f cmd/$CMD/$CMD.man
+ then
+ $TXT2MAN -t "$CMD" -v "OSS System Administration Commands" -s 8 cmd/$CMD/$CMD.man | gzip -9 > prototype/usr/share/man/man8/$CMD.8.gz
+ echo done $CMD
+ fi
+done
+
+$TXT2MAN -t "ossdetect" -v "User Commands" -s 8 os_cmd/Linux/ossdetect/ossdetect.man | gzip -9 > prototype/usr/share/man/man8/ossdetect.8.gz
+echo done ossdetect
+
+cp -f $SRCDIR/oss/lib/flashsupport.c prototype/$OSSLIBDIR/lib
+
+# Licensing stuff
+if test -f 4front-private/osslic.c
+then
+ cc -o prototype/usr/sbin/osslic -Isetup -Ikernel/nonfree/include -Ikernel/framework/include -Iinclude -Ikernel/OS/Linux -I$SRCDIR $SRCDIR/4front-private/osslic.c
+ strip prototype/usr/sbin/osslic
+
+ BITS=3 # Default to 32 bit ELF format
+ if test "`uname -m` " = "x86_64 "
+ then
+ BITS=6 # Use 64 bit ELF format
+ fi
+ prototype/usr/sbin/osslic -q -u -$BITS./prototype/$OSSLIBDIR/objects.regparm/osscore.o
+ prototype/usr/sbin/osslic -q -u -$BITS./prototype/$OSSLIBDIR/objects.noregparm/osscore.o
+
+fi
+
+if test -f 4front-private/ossupdate.c
+then
+ #ossupdate
+ cc -I. 4front-private/ossupdate.c -s -o prototype/usr/sbin/ossupdate
+fi
+
+sh $SRCDIR/setup/build_common.sh $SRCDIR $OSSLIBDIR
+
+chmod 700 prototype/usr/sbin/*
+chmod 755 prototype/usr/bin/*
+
+(cd prototype;ls usr/sbin/* usr/bin/* etc/* usr/share/man/man*/*) > prototype/$OSSLIBDIR/sysfiles.list
+
+exit 0
diff --git a/setup/Linux/build_arm.sh b/setup/Linux/build_arm.sh
new file mode 100644
index 0000000..7031ec5
--- /dev/null
+++ b/setup/Linux/build_arm.sh
@@ -0,0 +1,96 @@
+#!/bin/sh
+
+# build script for ARM Linux (Nokia's Maemo plattform)
+
+. ./.directories
+
+KERNELDIR=~/maemo_kernel/kernel-source-diablo-2.6.21/kernel-source
+
+rm -rf prototype
+
+mkdir prototype
+mkdir prototype/etc
+echo "OSSLIBDIR=$OSSLIBDIR" > prototype/etc/oss.conf
+mkdir prototype/usr
+mkdir prototype/usr/bin
+mkdir prototype/usr/sbin
+mkdir -p prototype/$OSSLIBDIR
+mkdir prototype/$OSSLIBDIR/etc
+mkdir prototype/$OSSLIBDIR/conf.tmpl
+mkdir prototype/$OSSLIBDIR/lib
+mkdir prototype/$OSSLIBDIR/modules
+
+cp target/bin/* prototype/usr/bin
+cp target/sbin/* prototype/usr/sbin
+cp target/lib/* prototype/$OSSLIBDIR/lib
+
+# Compile the 64 bit div/mod functions required by gcc
+rm -f bpabi.s bpabi_s.o bpabi_c.o bpabi.o
+cc -c origdir/setup/Linux/arm/bpabi.c -o bpabi_c.o
+
+for n in L_udivsi3 L_idivsi3 L_divsi3 L_aeabi_ldivmod L_aeabi_uldivmod L_dvmd_lnx
+do
+# Strip position independent code (PLT) from the asm sources before compile
+cpp -static -D$n origdir/setup/Linux/arm/lib1funcs.asm | sed 's/..PLT.//g' > $n.s
+as -o $n.o $n.s
+done
+
+ld -r -o bpabi.o L*.o bpabi_c.o
+rm -f L*.s L*.o bpabi_c.o
+
+#build osscore
+
+rm -rf tmp_build
+mkdir tmp_build
+
+cp origdir/setup/Linux/arm/Makefile.osscore.arm tmp_build/Makefile
+cp origdir/setup/Linux/oss/build/osscore.c tmp_build/osscore.c
+
+cp ./kernel/framework/include/*.h tmp_build/
+cp ./kernel/OS/Linux/wrapper/wrap.h tmp_build/
+cp ./setup/Linux/oss/build/ossdip.h tmp_build/
+cp ./include/soundcard.h tmp_build/
+cp ./kernel/framework/include/ossddk/oss_exports.h tmp_build/
+
+if ! (cd tmp_build && make KERNELDIR=$KERNELDIR) > build.log 2>&1
+then
+ cat build.log
+ echo
+ echo Building osscore module failed
+ exit 1
+fi
+
+ld -r tmp_build/osscore.ko target/objects/*.o -o prototype/usr/lib/oss/modules/osscore.ko
+
+if test -f tmp_build/Module.symvers
+then
+ #Take generated symbol information and add it to module.inc
+ echo "static const struct modversion_info ____versions[]" > tmp_build/osscore_symbols.inc
+ echo " __attribute__((used))" >> tmp_build/osscore_symbols.inc
+ echo "__attribute__((section(\"__versions\"))) = {" >> tmp_build/osscore_symbols.inc
+ sed -e "s:^:{:" -e "s:\t:, \":" -e "s:\t\(.\)*:\"},:" < tmp_build/Module.symvers >> tmp_build/osscore_symbols.inc
+ echo "};" >> tmp_build/osscore_symbols.inc
+else
+ echo > tmp_build/osscore_symbols.inc
+fi
+
+cp origdir/setup/Linux/oss/build/*.inc tmp_build/
+
+for n in target/modules/*.o
+do
+ N=`basename $n .o`
+
+ cp target/build/$N.c tmp_build/$N.c
+
+ sed "s/MODNAME/$N/" < origdir/setup/Linux/arm/Makefile.tmpl.arm > tmp_build/Makefile
+ if ! (cd tmp_build && make KERNELDIR=$KERNELDIR) > build.log 2>&1
+ then
+ cat build.log
+ echo
+ echo Building $N module failed
+ exit 1
+ fi
+ ld -r tmp_build/$N.ko bpabi.o target/modules/$N.o -o prototype/usr/lib/oss/modules/$N.ko
+done
+
+exit 0
diff --git a/setup/Linux/confgen.c b/setup/Linux/confgen.c
new file mode 100644
index 0000000..53662f2
--- /dev/null
+++ b/setup/Linux/confgen.c
@@ -0,0 +1,188 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <libgen.h>
+#include <sys/stat.h>
+
+char *targetdir = "";
+char *confpath = "";
+
+static int
+copy_parms (FILE * f, FILE * conf)
+{
+ char line[1024], *s;
+ char var[256] = "", comment[64 * 1024] = "";
+ int i;
+ int ok = 0;
+
+ while (fgets (line, sizeof (line), f) != NULL)
+ {
+ for (i = 0; i < strlen (line); i++)
+ if (line[i] == '\n')
+ line[i] = 0;
+
+ s = line;
+
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (strncmp (s, "int ", 4) == 0)
+ {
+ if (*var != 0)
+ {
+ fprintf (conf, "%s\n", comment);
+ if (*var != 0)
+ fprintf (conf, "#%s\n#\n", var);
+ *var = 0;
+ *comment = 0;
+ }
+ s += 4;
+
+ for (i = 0; i < strlen (line); i++)
+ if (line[i] == ';')
+ line[i] = 0;
+ ok = 1;
+ strcpy (var, s);
+ continue;
+ }
+
+
+ s = line;
+
+ while (*s == ' ' || *s == '\t' || *s == '/' || *s == '*')
+ s++;
+
+ if (*comment != 0)
+ strcat (comment, "\n");
+ strcat (comment, "# ");
+ strcat (comment, s);
+ }
+
+ if (*var != 0)
+ {
+ fprintf (conf, "%s\n", comment);
+ fprintf (conf, "#%s\n", var);
+ }
+
+ return ok;
+}
+
+static void
+scan_dir (const char *srcdir, const char *modnam)
+{
+ char confname[256], tmp[256], line[1024];
+ char module[256], *p;
+ FILE *conf;
+ FILE *f;
+ int i;
+ struct stat st;
+
+ int check_platform = 0;
+ int platform_ok = 0;
+ int ok = 0;
+
+ strcpy (module, modnam);
+ p = module;
+ while (*p)
+ {
+ if (*p == '.')
+ *p = 0;
+ else
+ p++;
+ }
+
+ if (stat (srcdir, &st) == -1)
+ return;
+
+ if (!S_ISDIR (st.st_mode)) /* Not a directory? */
+ return;
+
+ sprintf (tmp, "%s/.nomake", srcdir);
+ if (stat (tmp, &st) != -1) /* File exists */
+ return; /* Skip this one */
+
+ sprintf (tmp, "%s/.config", srcdir);
+ if ((f = fopen (tmp, "r")) != NULL)
+ {
+ while (fgets (line, sizeof (line), f) != NULL)
+ {
+ char *s;
+ for (i = 0; i < strlen (line); i++)
+ if (line[i] == '\n')
+ line[i] = 0;
+
+ s = line;
+ while (*s && *s != '=')
+ s++;
+ if (*s == '=')
+ *s++ = 0;
+
+ if (strcmp (line, "OS") == 0 || strcmp (line, "targetos") == 0)
+ {
+ check_platform = 1;
+ if (strcmp (s, "Linux") == 0)
+ platform_ok = 1;
+ continue;
+ }
+ }
+ fclose (f);
+ }
+
+ if (check_platform && !platform_ok && strcmp (modnam, "osscore"))
+ {
+ return;
+ }
+#if 0
+ /* copy the man pages */
+ sprintf (syscmd, "sed 's:CONFIGFILEPATH:%s:g' < %s/%s.man > /tmp/ossman.man",
+ confpath, srcdir, module);
+ printf ("%s\n", syscmd);
+ unlink ("/tmp/ossman.man");
+ system (syscmd);
+
+ sprintf (syscmd,
+ "./origdir/setup/txt2man -t \"%s\" -v \"Devices\" -s 7 /tmp/ossman.man > prototype/usr/man/man7/%s.7",
+ module, module);
+ printf ("%s\n", syscmd);
+ system (syscmd);
+#endif
+
+ sprintf (confname, "%s/%s.conf", targetdir, module);
+ sprintf (tmp, "%s/.params", srcdir);
+ if ((f = fopen (tmp, "r")) != NULL)
+ {
+ if ((conf = fopen (confname, "w")) == NULL)
+ {
+ perror (confname);
+ exit (-1);
+ }
+ fprintf (conf, "# Open Sound System configuration file\n");
+ fprintf (conf,
+ "# Remove the '#' in front of the option(s) you like to set.\n#\n");
+ ok = copy_parms (f, conf);
+ fclose (f);
+// fprintf(conf, "#\n");
+ fclose (conf);
+ if (!ok)
+ unlink (confname);
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+
+ if (argc < 3)
+ exit (-1);
+
+ targetdir = argv[1];
+ confpath = argv[2];
+
+ for (i = 3; i < argc; i++)
+ {
+ scan_dir (argv[i], basename (argv[i]));
+ }
+
+ exit (0);
+}
diff --git a/setup/Linux/copyright b/setup/Linux/copyright
new file mode 100644
index 0000000..3ec1b2e
--- /dev/null
+++ b/setup/Linux/copyright
@@ -0,0 +1,25 @@
+Upstream sources are at:
+ http://www.opensound.com
+
+Authors:
+ 4Front Technologies ( http://www.4front-tech.com )
+
+Copyright:
+ Copyright (C) 2006-2008 Hannu Savolainen and Dev Mazumdar.
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 dated June, 1991.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+On Debian GNU/Linux systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
diff --git a/setup/Linux/installoss.sh b/setup/Linux/installoss.sh
new file mode 100644
index 0000000..5109fca
--- /dev/null
+++ b/setup/Linux/installoss.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+if test "$USER " != "root "
+then
+ echo "You must be super-user or logged in as root to install OSS"
+ exit 1
+fi
+
+if test "$1 " != " "
+then
+ OSSLIBDIR="$1"
+else
+ OSSLIBDIR="/usr/lib/oss"
+fi
+
+echo "Installing Open Sound System `cat "./$OSSLIBDIR/version.dat"`...."
+echo "Copying files from ./etc and ./usr into /..."
+tar -cpf - etc usr |(cd /; tar -xpf -)
+echo "Running /usr/lib/oss/build/install script...."
+if ! sh "/$OSSLIBDIR/build/install.sh"
+then
+ echo
+ echo "ERROR: install.sh script failed"
+ exit 0
+fi
+echo "OSS installation complete..."
+echo
+echo "Run /usr/sbin/soundon to start the drivers"
+echo "Run /usr/bin/osstest to test the audio"
+echo "Run /usr/bin/ossinfo to display status"
diff --git a/setup/Linux/linsetup.sh b/setup/Linux/linsetup.sh
new file mode 100644
index 0000000..dc34289
--- /dev/null
+++ b/setup/Linux/linsetup.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+if test "$CONFIGURE " != "YES "
+then
+ echo
+ echo Error: Wrong usage
+ echo
+ echo You must run `dirname $0`/configure instead of $0
+ exit 1
+fi
+
+if test "`ls .` " != " "
+then
+ echo Error: Current directory must be empty
+ exit 1
+fi
+
+if test "`uname -m` " = "arm "
+then
+# ARM doesn't have regparm support
+
+ echo Setting up for ARM architecture
+ sh $SRCDIR/setup/setupdir.sh
+ exit 0
+fi
+
+# Setup directory for REGPARM
+
+unset NO_REGPARM
+export USE_REGPARM=1
+
+echo Setting up full REGPARM compiling environment
+
+echo "SUBDIRS+=noregparm" > .makefile
+sh $SRCDIR/setup/setupdir.sh
+
+# Setup for NOREGPARM
+
+mkdir noregparm
+
+unset USE_REGPARM
+export NO_REGPARM=1
+
+echo > .nocopy
+echo Setting up kernel-only NOREGPARM compiling environment
+(cd noregparm;sh $SRCDIR/setup/setupdir.sh -K)
+rm -f .nocopy
+
+# Make sure both versions share the same timestamp.h file.
+cp -f kernel/framework/include/timestamp.h noregparm/kernel/framework/include/timestamp.h
+
+exit 0
diff --git a/setup/Linux/make.local b/setup/Linux/make.local
new file mode 100644
index 0000000..ad9ac7f
--- /dev/null
+++ b/setup/Linux/make.local
@@ -0,0 +1,21 @@
+build: kernel/framework/include/buildid.h all
+ sh build.sh
+
+copy: build
+ #rm -f ${OSSLIBDIR}/modules/*.o
+ (cd prototype; find -L . -type d | xargs -i{} mkdir -p ${DESTDIR}/{})
+ (cd prototype; find -L . -type f | xargs -i{} cp {} ${DESTDIR}/{})
+
+package: build
+ sh setup/Linux/mkpkg.sh
+
+tarball: build
+ sh setup/Linux/mktarball.sh
+
+deb: build
+ sh setup/Linux/mkdeb.sh
+
+install: copy
+ cd ${OSSLIBDIR}/build && sh install.sh
+ sync
+ soundoff && sync && soundon && echo "OSS has started OK"
diff --git a/setup/Linux/md5.sh b/setup/Linux/md5.sh
new file mode 100644
index 0000000..533c12e
--- /dev/null
+++ b/setup/Linux/md5.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+i=$2
+i=${i#.}
+
+# Create the MD5 sums file using the program we have found earlier
+case "$1" in
+ MD5SUM)
+ md5sum ".$i"
+ ;;
+ MD5)
+ x=`md5 ".$i" | awk "{ for (y=1;y<=NF;y++) if ((length(\\$y) == 32) && (\\$y !~ /[\/]/)) {print \\$y; break} }"`; echo "$x $i"
+ ;;
+ DIGEST)
+ x=`digest -a md5 ".$i"`; echo "$x $i"
+ ;;
+ OPENSSL)
+ x=`openssl md5 $i | awk "{ for (y=1;y<=NF;y++) if ((length(\\$y) == 32) && (\\$y !~ /[\/]/)) {print \\$y; break} }"`; echo "$x $i"
+ ;;
+esac
diff --git a/setup/Linux/menu.ex b/setup/Linux/menu.ex
new file mode 100644
index 0000000..854671b
--- /dev/null
+++ b/setup/Linux/menu.ex
@@ -0,0 +1,4 @@
+?package(oss-linux):needs="X11" \
+ section="Apps/Sound" \
+ title="ossxmix" \
+ command="/usr/bin/ossxmix"
diff --git a/setup/Linux/mkdeb.sh b/setup/Linux/mkdeb.sh
new file mode 100644
index 0000000..8330ae2
--- /dev/null
+++ b/setup/Linux/mkdeb.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+. ./.directories
+
+VERSION=`sh showversion.sh`
+VERSION=${VERSION#v}
+RELEASE=`cat buildid.dat`
+OSSNAME="oss-linux"
+
+# Chosing the right architecture
+if test `uname -m` = "x86_64"; then ARCH=amd64
+else ARCH=`uname -m|sed 's/^i[3-9]86/i386/'`
+fi
+
+DEBNAME=${OSSNAME}-${VERSION}-${RELEASE}_${ARCH}
+
+# Checking for known MD5 hashing programs
+if type md5sum > /dev/null 2>&1; then MD5=MD5SUM
+elif type openssl > /dev/null 2>&1; then MD5=OPENSSL
+elif type md5 > /dev/null 2>&1; then MD5=MD5
+elif type digest > /dev/null 2>&1; then MD5=DIGEST
+else echo "There has been no MD5 creation utily found. deb archive creation will be aborted." && exit 1
+fi
+
+echo building $DEBNAME.deb
+
+
+mkdir control 2>/dev/null
+echo "2.0" > debian-binary
+cat > control/control << END
+Package: $OSSNAME
+Version: ${VERSION}-${RELEASE}
+Section: sound
+Priority: optional
+Architecture: $ARCH
+Installed-Size: `du -ks prototype | awk '{print $1}'`
+Build-Depends: build-essential sed gawk libtool libgtk2.0-dev
+Depends: binutils, gcc, libc6, libgtk2.0-0, sed (>= 1.0.0)
+Conflicts: libflashsupport
+Provides: oss
+Suggests: libsdl1.2debian-oss | libsdl1.2debian-all, libesd0, libwine-oss, libsox-fmt-oss, mpg123, gstreamer0.10-plugins-bad (>= 0.10.7), libasound2-plugins
+Maintainer: 4Front Technologies <support@opensound.com>
+Description: Open Sound System (http://www.opensound.com)
+ OSS provides libraries and necessary drivers for practically all sound
+ cards on the market including PnP and many PCI ones which enable you
+ to play sound files, compose music, use MIDI (only included in the
+ testing releases) and adjust your sound card using various user space
+ programs.
+END
+
+# Copying the menu and copyright file to the right place, taking care that the md5sums generation will take place AFTER this step
+mkdir -p prototype/usr/share/menu prototype/usr/share/doc/oss-linux
+cp setup/Linux/menu.ex prototype/usr/share/menu/ossxmix
+cp setup/Linux/copyright prototype/usr/share/doc/oss-linux/
+
+
+# Create the MD5 sums file using the program we have found earlier
+(cd prototype; find . -type f -exec sh ../setup/Linux/md5.sh "$MD5" "{}" \; > ../control/md5sums)
+
+(cd prototype; find . -type f -print | sed 's/^.//g' | egrep "^/etc/" > ../control/conffiles)
+
+
+# Removing older builds
+rm -rf /tmp/prototype $DEBNAME.deb
+
+
+cp -pRf prototype /tmp
+cp setup/Linux/preinst setup/Linux/postinst setup/Linux/prerm setup/Linux/postrm control/
+if test -e prototype/$OSSLIBDIR/lib/libsalsa.so*
+then
+ cp setup/Linux/shlibs control/
+fi
+
+
+# Correcting file and directory permissions required by lintian
+chmod 0755 control/control
+
+# Building control and data archives
+(cd control; tar c * | gzip -9 > ../control.tar.gz)
+(cd /tmp/prototype; tar c ./* | gzip -9 > data.tar.gz)
+mv /tmp/prototype/data.tar.gz .
+
+
+# Creating the actual archive
+ar r $DEBNAME.deb debian-binary control.tar.gz data.tar.gz
+
+
+# Cleanup
+rm -rf /tmp/prototype control control.tar.gz data.tar.gz debian-binary
+
+
+if test -f 4front-private/export_package.sh
+then
+ sh 4front-private/export_package.sh $OSSNAME*.deb . `sh showversion.sh` /tmp `uname -i`-26
+fi
diff --git a/setup/Linux/mkpkg.sh b/setup/Linux/mkpkg.sh
new file mode 100644
index 0000000..4ccfe90
--- /dev/null
+++ b/setup/Linux/mkpkg.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+. ./.directories
+
+VERSION=`sh showversion.sh`
+RELEASE=`cat buildid.dat`
+ARCH=`uname -i`
+OSSNAME=oss-linux
+
+RPMNAME=$OSSNAME-$VERSION
+PKGNAME=$OSSNAME-$VERSION-$RELEASE.$ARCH
+echo building $RPMNAME.rpm
+
+rm -rf spec $RPMNAME
+mkdir $RPMNAME
+echo "Version: " $VERSION > spec
+echo "Release: " $RELEASE >> spec
+echo "Name: " $OSSNAME >> spec
+cat setup/Linux/spec.tmpl | sed "s:OSSLIBDIR:\"$OSSLIBDIR\":g" >> spec
+echo "%files" >> spec
+(cd prototype; find . -type f -print | sed 's/^.//g' > /tmp/filelist)
+cat /tmp/filelist >> spec
+rm -rf /tmp/prototype
+cp -af prototype /tmp
+tar zcvf /tmp/oss $RPMNAME
+rpmbuild -bb --define "_sourcedir /tmp" --define "_rpmdir ./" --define '_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm' spec
+# Cleanup
+rm -rf /tmp/oss /tmp/filelist $RPMNAME spec
+
+if test -f 4front-private/export_package.sh
+then
+ sh 4front-private/export_package.sh $PKGNAME.rpm . `sh showversion.sh` /tmp `uname -i`-26
+fi
diff --git a/setup/Linux/mktarball.sh b/setup/Linux/mktarball.sh
new file mode 100644
index 0000000..4610a4b
--- /dev/null
+++ b/setup/Linux/mktarball.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+. ./.directories
+
+VERSION=`sh showversion.sh`
+RELEASE=`cat buildid.dat`
+OSSNAME=oss-linux
+PKGNAME=$OSSNAME-$VERSION-$RELEASE-`uname -m`
+
+echo building $PKGNAME.tar.bz2
+#cp ./setup/Linux/installoss.sh prototype
+cp ./setup/Linux/removeoss.sh prototype/$OSSLIBDIR/scripts
+(cd prototype; find . -type f -print) > prototype/$OSSLIBDIR/MANIFEST
+(cd prototype; tar cfj /tmp/$PKGNAME.tar.bz2 . )
+mv /tmp/$PKGNAME.tar.bz2 .
+
+if test -f 4front-private/export_package.sh
+then
+ sh 4front-private/export_package.sh $PKGNAME.tar.bz2 . `sh showversion.sh` /tmp `uname -m`-26
+fi
+
+exit 0
diff --git a/setup/Linux/oss/build/Makefile.osscore b/setup/Linux/oss/build/Makefile.osscore
new file mode 100644
index 0000000..30d0287
--- /dev/null
+++ b/setup/Linux/oss/build/Makefile.osscore
@@ -0,0 +1,32 @@
+include /etc/oss.conf
+
+EXTRA_CFLAGS += -I${OSSLIBDIR}/include/internals -I${OSSLIBDIR}/include/sys
+
+ifneq ($(KERNELRELEASE),)
+
+ obj-m := osscore.o
+
+else
+
+ KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+ PWD := $(shell pwd)
+endif
+
+default:
+ @echo "static const char __oss_compile_vermagic[]" > ubuntu_version_hack.inc
+#The kernel build system saves kernel version (obtained via "utsrelease.h")
+#used during compile in a "vermagic" symbol. soundon compares this with
+#current version of running kernel to know when to relink modules.
+#Some Ubuntu kernels have 'uname -r' output different from "utsrelease.h"
+#contents, so we save the previous uname as a fallback check.
+# https://bugs.launchpad.net/ubuntu/+source/linux/+bug/247055
+ @echo "__attribute__((used))" >> ubuntu_version_hack.inc
+ @echo "__attribute__((section(\".modinfo\")))" >> ubuntu_version_hack.inc
+ @echo "= \"$(shell /usr/sbin/ossvermagic -z -s)\";" >> ubuntu_version_hack.inc
+
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+ @rm -f ubuntu_version_hack.inc
+
+clean:
+ rm -f *.o *.ko *.mod.c *.mod.o .*.cmd core core.* x y z ubuntu_version_hack.inc
+ rm -rf .tmp_versions
diff --git a/setup/Linux/oss/build/Makefile.tmpl b/setup/Linux/oss/build/Makefile.tmpl
new file mode 100644
index 0000000..fd331c1
--- /dev/null
+++ b/setup/Linux/oss/build/Makefile.tmpl
@@ -0,0 +1,21 @@
+include /etc/oss.conf
+
+EXTRA_CFLAGS += -I${OSSLIBDIR}/include/internals -I${OSSLIBDIR}/include/sys
+
+ifneq ($(KERNELRELEASE),)
+
+ obj-m := MODNAME.o
+
+else
+
+ KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+ PWD := $(shell pwd)
+
+default:
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+endif
+
+clean:
+ @rm -f *.o *.ko *.mod.c *.mod.o .*.cmd core core.* x y z
+ @rm -rf .tmp_versions
diff --git a/setup/Linux/oss/build/install.sh b/setup/Linux/oss/build/install.sh
new file mode 100644
index 0000000..13fdbc2
--- /dev/null
+++ b/setup/Linux/oss/build/install.sh
@@ -0,0 +1,347 @@
+#!/bin/sh
+if test -f /etc/oss.conf
+then
+ . /etc/oss.conf
+else
+ OSSLIBDIR=/usr/lib/oss
+ echo "OSSLIBDIR=/usr/lib/oss" > /etc/oss.conf
+fi
+
+[ -z "$LD" ] && LD=ld
+
+cd $OSSLIBDIR/build
+
+rm -f $OSSLIBDIR/.cuckoo_installed
+
+# Check if we should use REGPARM or non-REGPARM modules
+if /usr/sbin/ossvermagic -r || /sbin/modinfo ext3|grep -q REGPARM
+then
+ REGPARM=REGPARM
+ rm -rf $OSSLIBDIR/objects
+ ln -s $OSSLIBDIR/objects.regparm $OSSLIBDIR/objects
+ rm -rf $OSSLIBDIR/modules
+ ln -s $OSSLIBDIR/modules.regparm $OSSLIBDIR/modules
+else
+ REGPARM=NOREGPARM
+ rm -rf $OSSLIBDIR/objects
+ ln -s $OSSLIBDIR/objects.noregparm $OSSLIBDIR/objects
+ rm -rf $OSSLIBDIR/modules
+ ln -s $OSSLIBDIR/modules.noregparm $OSSLIBDIR/modules
+fi
+
+UNAME=`uname -r`
+
+if test -f /lib/modules/$UNAME/kernel/oss/vmix.ko || test -f /lib/modules/$UNAME/kernel/oss/ich.ko
+then
+# Older versions of OSS modules exist under /lib/modules. This indicates that
+# previous version of OSS has not been properly uninstalled. Run osdetect
+# again to fix rthe situation
+
+ /usr/sbin/soundoff > /dev/null 2>&1
+ /usr/sbin/ossdetect
+fi
+
+# Remove previous OSS modules from the system
+rm -rf /lib/modules/$UNAME/kernel/oss
+
+if test -f /usr/lib/oss/build/ich.c
+then
+ # Older v4.0 modules found. Remove them
+ (cd /usr/lib/oss/build ; rm -f ali5455.c allegro.c als300.c als4000.c apci97.c atiaudio.c audigyls.c audioloop.c audiopci.c cmi8788.c cmpci.c cs4280.c cs4281.c digi32.c digi96.c emu10k1x.c envy24.c envy24ht.c fm801.c geode.c hdaudio.c hdsp.c ich.c imux.c maestro.c neomagic.c ossusb.c riptide.c s3vibes.c sblive.c sbxfi.c softoss.c solo.c sonorus.c trident.c via8233.c via97.c vmix.c vortex.c ymf7xx.c)
+ echo
+ echo
+ echo Error: Older OSS version seems to be installed in your system.
+ echo Please remove previous /usr/lib/oss directory and the install OSS v4.x again.
+ soundoff
+ exit 127
+fi
+
+if ! test -f $OSSLIBDIR/objects/osscore.o
+then
+ echo Error: OSS core module for $REGPARM kernel is not available in $OSSLIBDIR/objects
+ exit 1
+fi
+
+echo
+echo OSS build environment set up for $REGPARM kernels
+
+KERNELDIR=/lib/modules/$UNAME/build
+UBUNTUPACKAGES=""
+
+OK=1
+echo
+
+if test "`which gcc 2>/dev/null` " = " "
+then
+ echo " gcc"
+ UBUNTUPACKAGES="$UBUNTUPACKAGES gcc"
+ OK=0
+fi
+
+if test "`which make 2>/dev/null` " = " "
+then
+ echo " make"
+ UBUNTUPACKAGES="$UBUNTUPACKAGES make"
+ OK=0
+fi
+
+if test "`which ld 2>/dev/null` " = " "
+then
+ echo " binutils"
+ UBUNTUPACKAGES="$UBUNTUPACKAGES binutils"
+ OK=0
+fi
+
+if ! test -f /usr/include/stdio.h
+then
+ echo " C library headers (glibc-devel or build-essential)"
+ OK=0
+ UBUNTUPACKAGES="$UBUNTUPACKAGES build-essentials"
+fi
+
+if test "$OK " = "0 "
+then
+ echo
+ echo 'Error: The above Linux package(s) seem to be missing from your system.'
+ echo ' Please install them and then try to install OSS again.'
+ echo
+ echo Please refer to the documentation of your Linux distribution if you
+ echo have problems with installing the packages.
+ echo
+
+ if grep -q Ubuntu /etc/issue # Ubuntu?
+ then
+ echo You can use the following commands to download and install all
+ echo required packages:
+ echo
+
+ for n in $UBUNTUPACKAGES
+ do
+ echo " apt-get install $n"
+ done
+
+ exit 1
+ fi
+
+ exit 1
+fi
+
+
+if ! test -f $KERNELDIR/Makefile && ! test -f /lib/modules/$UNAME/sources/Makefile
+then
+ echo
+ echo 'Warning: Cannot locate the Linux kernel development package for'
+ echo ' Linux kernel version ' $UNAME
+ echo ' Please install the kernel development package if linking the'
+ echo ' OSS modules fails.'
+ echo
+ echo The kernel development package may be called kernel-devel, kernel-smp-devel,
+ echo kernel-sources, kernel-headers or something like that. Please refer
+ echo to the documentation of your Linux distribution if there are any
+ echo difficulties in installing the kernel/driver development environment.
+ echo
+
+ if grep -q 'Fedora Core release' /etc/issue
+ then
+ if uname -v|grep -q SMP
+ then
+ echo Assuming that you are using Fedora Core 5 or later
+ echo "the right kernel source package (RPM) is probably called"
+ echo kernel-smp-devel.
+ else
+ echo Assuming that you are using Fedora Core 5 or later
+ echo "the right kernel source package (RPM) is probably called"
+ echo kernel-devel.
+ fi
+ else
+ echo For your Linux distribution the right kernel source package
+ echo might be kernel-source.
+ fi
+ echo
+
+ if grep -q Ubuntu /etc/issue || grep -q Debian /etc/issue # Ubuntu or Debian?
+ then
+ echo Under Ubuntu you may need to prepare the kernel environment
+ echo after downloading the kernel sources using
+ echo
+ echo " sudo apt-get install linux-headers-$UNAME"
+ echo " cd /usr/src/linux-headers-$UNAME/"
+# echo " sudo make prepare"
+# echo " sudo make prepare scripts"
+ echo
+ fi
+fi
+
+if ! test -d /lib/modules/$UNAME
+then
+ echo Error: Kernel directory /lib/modules/$UNAME does not exist
+ exit 1
+fi
+
+cp -f ../objects/osscore.o osscore_mainline.o
+
+rm -f Makefile
+ln -s Makefile.osscore Makefile
+
+echo Building module osscore
+
+if ! make KERNELDIR=$KERNELDIR> build.list 2>&1
+then
+ echo Failed to compile OSS
+ cat build.list
+ exit 2
+fi
+
+if ! test -d /lib/modules/$UNAME/kernel/oss
+then
+ mkdir /lib/modules/$UNAME/kernel/oss
+fi
+
+if ! test -d /lib/modules/$UNAME/kernel/oss
+then
+ echo OSS module directory /lib/modules/$UNAME/kernel/oss does not exist.
+ exit 3
+fi
+
+if ! $LD -r osscore.ko osscore_mainline.o -o /lib/modules/$UNAME/kernel/oss/osscore.ko
+then
+ echo Linking the osscore module failed
+ exit 5
+fi
+
+if test -f Module.symvers
+then
+ #Take generated symbol information and add it to module.inc
+ echo "static const struct modversion_info ____versions[]" > osscore_symbols.inc
+ echo " __attribute__((used))" >> osscore_symbols.inc
+ echo "__attribute__((section(\"__versions\"))) = {" >> osscore_symbols.inc
+ sed -e "s:^:{:" -e "s:\t:, \":" -e "s:\t\(.\)*:\"},:" < Module.symvers >> osscore_symbols.inc
+ echo "};" >> osscore_symbols.inc
+else
+ echo > osscore_symbols.inc
+fi
+
+#depmod -a
+
+for n in ../modules/*.o
+do
+ N=`basename $n .o`
+ echo Building module $N
+
+ rm -f $N_mainline.o Makefile
+
+ sed "s/MODNAME/$N/" < Makefile.tmpl > Makefile
+ ln -s $n $N_mainline.o
+
+ if ! make KERNELDIR=$KERNELDIR > build.list 2>&1
+ then
+ echo Compiling module $N failed
+ cat build.list
+ exit 4
+ fi
+
+ if ! $LD -r $N.ko $N_mainline.o -o /lib/modules/$UNAME/kernel/oss/$N.ko
+ then
+ echo Linking $N module failed
+ exit 6
+ fi
+
+ rm -f $N_mainline.o
+ make clean
+done
+
+rm -f Makefile
+
+echo "depmod -a"
+depmod -a
+
+# Copy config files for any new driver modules
+
+if ! test -d $OSSLIBDIR/conf
+then
+ mkdir $OSSLIBDIR/conf
+fi
+
+if test -d $OSSLIBDIR/conf.tmpl
+then
+ for n in $OSSLIBDIR/conf.tmpl/*.conf
+ do
+ N=`basename $n`
+
+ if ! test -f $OSSLIBDIR/conf/$N
+ then
+ cp -f $n $OSSLIBDIR/conf/
+ fi
+ done
+ rm -rf $OSSLIBDIR/conf.tmpl
+fi
+
+if ! test -f $OSSLIBDIR/etc/installed_drivers
+then
+ echo "-----------------------------"
+ /usr/sbin/ossdetect -v
+ echo "-----------------------------"
+ echo
+fi
+
+if ! test -d /etc/init.d
+then
+ mkdir /etc/init.d
+fi
+
+rm -f /etc/init.d/oss /etc/rc.d/rc3.d/S89oss /etc/rc3.d/S89oss
+cp -f $OSSLIBDIR/etc/S89oss /etc/init.d/oss
+
+chmod 744 /etc/init.d/oss
+
+if test -x /sbin/chkconfig
+then
+ /sbin/chkconfig oss on > /dev/null 2>&1
+else
+ if test -x /usr/sbin/update-rc.d
+ then
+ /usr/sbin/update-rc.d oss defaults > /dev/null 2>&1
+ else
+ if test -d etc/rc.d/rc3.d
+ then
+ rm -f /etc/rc.d/rc3.d/S89oss
+ ln -s /etc/init.d/oss /etc/rc.d/rc3.d/S89oss
+ else
+ if test -d /etc/rc3.d
+ then
+ rm -f /etc/rc3.d/S89oss
+ ln -s /etc/init.d/oss /etc/rc3.d/S89oss
+ fi
+ fi
+ fi
+fi
+
+# Install ALSA interface module (Cuckoo)
+#(cd $OSSLIBDIR/cuckoo && make clean) > /dev/null 2>&1
+#if (cd $OSSLIBDIR/cuckoo && make install) > /var/log/cuckoo.log 2>&1
+#then
+# touch $OSSLIBDIR/.cuckoo_installed
+#fi
+#(cd $OSSLIBDIR/cuckoo && make clean) > /dev/null 2>&1
+
+# Remove bogus char major 14 device files left from earlier OSS versions.
+
+rm -f `ls -l -d /dev/*|grep ^c|grep ' 14, '|sed 's/.* //'`
+
+# Recompile libflashsupport.so if possible. Otherwise use the precompiled
+# version.
+(cd $OSSLIBDIR/lib;cc -m64 -shared -fPIC -O2 -Wall -Werror flashsupport.c -o $OSSLIBDIR/lib/libflashsupport_64.so) > /dev/null 2>&1
+(cd $OSSLIBDIR/lib;cc -m32 -shared -fPIC -O2 -Wall -Werror flashsupport.c -o $OSSLIBDIR/lib/libflashsupport_32.so) > /dev/null 2>&1
+
+if test ! -f $OSSLIBDIR/etc/userdefs
+then
+ echo "autosave_mixer yes" > $OSSLIBDIR/etc/userdefs
+fi
+
+# Hal 0.5.0+ hotplug
+mkdir -p /usr/lib/hal/scripts
+ln -sf $OSSLIBDIR/scripts/oss_usb-create-devices /usr/lib/hal/scripts/
+mkdir -p /usr/share/hal/fdi/policy/20thirdparty/
+ln -sf $OSSLIBDIR/scripts/90-oss_usb-create-device.fdi /usr/share/hal/fdi/policy/20thirdparty/
+
+exit 0
diff --git a/setup/Linux/oss/build/module.inc b/setup/Linux/oss/build/module.inc
new file mode 100644
index 0000000..4e34003
--- /dev/null
+++ b/setup/Linux/oss/build/module.inc
@@ -0,0 +1,245 @@
+/*
+ * Purpose: Template for OSS modules under Linux
+ *
+ * This file is included by the low level driver modules when they are
+ * compiled in the target system. In this way this file can be modified
+ * for non-standard kernels by the customer. Compiling in the target is
+ * necessary because the driver/module framework of Linux cannot support
+ * binary drivers. Another reason is that the kbuild mechanism used to build
+ * kernel modules under Linux is not compatible with the way how the source
+ * code of OSS is organized.
+ */
+/*
+ * Copyright (C) 4Front Technologies 2005-2007. Released under GPL2 license.
+ */
+#define strcpy dummy_strcpy
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include "timestamp.h"
+#include "oss_exports.h"
+#include "wrap.h"
+#include "ossddk.h"
+#include "ossdip.h"
+#undef strcpy
+#define strcpy oss_strcpy
+#undef strlen
+#define strlen oss_strlen
+
+static int module_major = 0;
+static int instance = 0;
+
+MODULE_LICENSE ("GPL v2");
+MODULE_DESCRIPTION ("Open Sound System '" DRIVER_PURPOSE "' driver module");
+MODULE_AUTHOR ("4Front Technologies (support@opensound.com)");
+
+extern int DRIVER_ATTACH (oss_device_t * osdev);
+extern int DRIVER_DETACH (oss_device_t * osdev);
+
+#if DRIVER_TYPE==DRV_PCI
+#define DRIVER_TYPE_OK
+
+#include "pci_wrapper.inc"
+
+// MODULE_DEVICE_TABLE(pci, id_table);
+static struct pci_driver osspci_driver = {
+ .name = DRIVER_NICK,
+ .id_table = id_table,
+ .probe = osspci_probe,
+ .remove = osspci_remove
+};
+
+static int __init
+pcidrv_init (void)
+{
+ int err;
+
+ if ((err = pci_register_driver (&osspci_driver)) < 0)
+ return err;
+ oss_register_module (THIS_MODULE);
+ return 0;
+}
+
+static void __exit
+pcidrv_exit (void)
+{
+ if (module_major > 0)
+ {
+ oss_unregister_chrdev (module_major, DRIVER_NICK);
+ }
+ pci_unregister_driver (&osspci_driver);
+ oss_unregister_module (THIS_MODULE);
+}
+
+module_init (pcidrv_init);
+module_exit (pcidrv_exit);
+#endif /* PCI driver */
+
+#if DRIVER_TYPE==DRV_VIRTUAL || DRIVER_TYPE==DRV_VMIX
+#define DRIVER_TYPE_OK
+static oss_device_t *osdev = NULL;
+
+static int
+virtualdrv_init (void)
+{
+ static int instance = 0, maj;
+
+ if ((osdev =
+ osdev_create (NULL, DRIVER_TYPE, instance++, DRIVER_NICK,
+ NULL)) == NULL)
+ {
+ return -ENOMEM;
+ }
+ osdev_set_owner (osdev, THIS_MODULE);
+ maj = oss_request_major (osdev, 0, DRIVER_NICK);
+ osdev_set_major (osdev, maj);
+ if (!DRIVER_ATTACH (osdev))
+ return -EIO;
+ oss_register_module (THIS_MODULE);
+ oss_audio_delayed_attach ();
+ return 0;
+}
+
+static void
+virtualdrv_exit (void)
+{
+
+ if (!DRIVER_DETACH (osdev))
+ printk (KERN_ALERT DRIVER_NICK ": Unloading busy device\n");
+ osdev_delete (osdev);
+ oss_unregister_module (THIS_MODULE);
+}
+
+module_init (virtualdrv_init);
+module_exit (virtualdrv_exit);
+#endif /* Virtual driver */
+
+#if DRIVER_TYPE==DRV_USB
+#define DRIVER_TYPE_OK
+oss_device_t *osdev = NULL;
+static int usb_major = 0;
+
+#include "usb_wrapper.inc"
+
+static int
+usbdrv_init (void)
+{
+ int res;
+
+ if (udi_usb_installed)
+ return 0;
+ if ((osdev =
+ osdev_create (NULL, DRV_VIRTUAL, instance++, DRIVER_NICK,
+ NULL)) == NULL)
+ {
+ return -ENOMEM;
+ }
+ osdev_set_owner (osdev, THIS_MODULE);
+ usb_major = oss_request_major (osdev, 0, DRIVER_NICK);
+ if (usb_major < 0)
+ {
+ oss_cmn_err (CE_WARN, "Failed to allocate USB major (%d)\n", usb_major);
+ return -EIO;
+ }
+ osdev_set_major (osdev, usb_major);
+ oss_register_device (osdev, "USB audio core services");
+ if (!DRIVER_ATTACH (osdev))
+ return -EIO;
+ oss_register_module (THIS_MODULE);
+ oss_audio_delayed_attach ();
+
+ udi_usb_installed = 1;
+
+ if ((res = usb_register (&oss_usb)) < 0)
+ {
+ printk ("oss: usb_register failed, err=%d\n", res);
+ drv = NULL;
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static void
+usbdrv_exit (void)
+{
+ if (!udi_usb_installed)
+ return;
+ if (!DRIVER_DETACH (osdev))
+ printk (KERN_ALERT DRIVER_NICK ": Unloading busy device\n");
+ usb_deregister (&oss_usb);
+ udi_usb_installed = 0;
+ known_devices = NULL;
+ osdev_delete (osdev);
+ osdev = NULL;
+ oss_unregister_module (THIS_MODULE);
+}
+
+module_init (usbdrv_init);
+module_exit (usbdrv_exit);
+#endif /* USB driver */
+
+#ifndef DRIVER_TYPE_OK
+#error Unrecognized driver type
+#endif
+
+char *
+strcpy (char *s1, const char *s2)
+{
+ char *s = s1;
+
+ while (*s2)
+ *s1++ = *s2++;
+ *s1 = 0;
+ return s;
+}
+
+void
+oss_cmn_err (int level, const char *s, ...)
+{
+ char tmp[1024], *a[6];
+ va_list ap;
+ int i, n = 0;
+
+ va_start (ap, s);
+
+ for (i = 0; i < strlen (s); i++)
+ if (s[i] == '%')
+ n++;
+
+ for (i = 0; i < n && i < 6; i++)
+ {
+ a[i] = va_arg (ap, char *);
+ }
+
+ for (i = n; i < 6; i++)
+ a[i] = NULL;
+
+ if (level == CE_CONT)
+ {
+ sprintf (tmp, s, a[0], a[1], a[2], a[3], a[4], a[5], NULL,
+ NULL, NULL, NULL);
+ printk ("%s", tmp);
+ }
+ else
+ {
+ strcpy (tmp, DRIVER_NICK ": ");
+
+ sprintf (tmp + strlen (tmp), s, a[0], a[1], a[2], a[3], a[4], a[5],
+ NULL, NULL, NULL, NULL);
+ if (level == CE_PANIC)
+ panic (tmp);
+ printk (KERN_ALERT "%s", tmp);
+ }
+#if 0
+ /* This may cause a crash under SMP */
+ if (sound_started)
+ store_msg (tmp);
+#endif
+
+ va_end (ap);
+}
+
+#include "osscore_symbols.inc"
diff --git a/setup/Linux/oss/build/osscore.c b/setup/Linux/oss/build/osscore.c
new file mode 100644
index 0000000..1a029b4
--- /dev/null
+++ b/setup/Linux/oss/build/osscore.c
@@ -0,0 +1,2214 @@
+/*
+ * Purpose: Linux kernel version specific wrapper routines.
+ *
+ * This file will be shipped in source format and compiled in the target
+ * (customer) system. In this way minor changes between Linux versions
+ * can be fixed by the customer.
+ */
+
+/*
+ * Copyright (C) 4Front Technologies 2005-2009. Released under GPL2 license.
+ */
+//#include <linux/config.h>
+typedef int *ioctl_arg;
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <stdarg.h>
+#include <linux/vmalloc.h>
+#include "timestamp.h"
+#include "local_config.h"
+#include "oss_exports.h"
+#include "wrap.h"
+#include "ossdip.h"
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/time.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#undef strlen
+#undef strcpy
+#define strlen oss_strlen
+#define strcpy oss_strcpy
+
+typedef struct _smap_t dmap_t;
+
+#include "soundcard.h"
+#include "audio_core.h"
+#include "mixer_core.h"
+#include "ubuntu_version_hack.inc"
+
+MODULE_LICENSE ("GPL v2");
+MODULE_DESCRIPTION ("Open Sound System core services");
+MODULE_AUTHOR ("4Front Technologies (support@opensound.com)");
+
+struct _oss_mutex_t
+{
+ /* Caution! This definition must match cuckoo.h */
+ spinlock_t lock;
+ int filler; /* Make sure this structure doesn't become zero length */
+};
+
+static oss_device_t *core_osdev = NULL;
+/*
+ * Minor device list
+ */
+#define MAX_MINOR 256
+typedef struct
+{
+ int major, minor;
+ char name[32];
+} oss_minor_t;
+
+static oss_minor_t minors[MAX_MINOR];
+static int nminors = 0;
+
+/*
+ * Sleep flags. Make sure these definitions match oss_config.h.
+ */
+#define WK_NONE 0x00
+#define WK_WAKEUP 0x01
+#define WK_TIMEOUT 0x02
+#define WK_SIGNAL 0x04
+#define WK_SLEEP 0x08
+#define WK_SELECT 0x10
+
+time_t
+oss_get_time (void)
+{
+#if 1
+ return get_seconds ();
+#else
+ return xtime.tv_sec;
+#endif
+}
+
+void *oss_memset (void *t, int val, size_t l);
+
+void *
+oss_kmem_alloc (size_t size)
+{
+ void *ptr;
+ if ((ptr = vmalloc (size)) == NULL)
+ {
+ oss_cmn_err (CE_WARN, "vmalloc(%d) failed\n", size);
+ return NULL;
+ }
+ memset (ptr, 0, size);
+ return ptr;
+}
+
+void
+oss_kmem_free (void *addr)
+{
+ vfree (addr);
+}
+
+/* oss_pmalloc() moved to os_linux.c */
+
+extern oss_native_word
+oss_virt_to_bus (void *addr)
+{
+ return virt_to_bus (addr);
+}
+
+void *
+oss_memcpy (void *t_, const void *f_, size_t l)
+{
+ unsigned char *t = t_;
+ unsigned const char *f = f_;
+ int i;
+
+ for (i = 0; i < l; i++)
+ *t++ = *f++;
+
+ return t;
+}
+
+void *
+oss_memset (void *t, int val, size_t l)
+{
+ char *c = t;
+ while (l-- > 0)
+ *c++ = val;
+
+ return t;
+}
+
+int
+oss_strcmp (const char *s1, const char *s2)
+{
+ while (*s1 && *s2)
+ {
+ if (*s1 != *s2)
+ return *s1 - *s2;
+ s1++;
+ s2++;
+ }
+
+ return *s1 - *s2;
+}
+
+int
+oss_strncmp (const char *s1, const char *s2, size_t len)
+{
+ while (*s1 && *s2 && len--)
+ {
+ if (*s1 != *s2)
+ return *s1 - *s2;
+ s1++;
+ s2++;
+ }
+
+ return *s1 - *s2;
+}
+
+char *
+oss_strcpy (char *s1, const char *s2)
+{
+ char *s = s1;
+
+ while (*s2)
+ *s1++ = *s2++;
+ *s1 = '\0';
+ return s;
+}
+
+size_t
+oss_strlen (const char *s)
+{
+ int i;
+
+ for (i = 0; s[i]; i++);
+
+ return i;
+}
+
+char *
+oss_strncpy (char *s1, const char *s2, size_t l)
+{
+ char *s = s1;
+ int n = 0;
+
+ while (*s2)
+ {
+ if (n++ >= l)
+ return s;
+
+ *s1++ = *s2++;
+ }
+ *s1 = '\0';
+ return s;
+}
+
+int oss_hz = HZ;
+extern int max_intrate;
+extern int detect_trace;
+extern int src_quality;
+extern int flat_device_model;
+extern int vmix_disabled;
+extern int vmix_no_autoattach;
+extern int vmix_loopdevs;
+extern int ac97_amplifier;
+extern int ac97_recselect;
+extern int cooked_enable;
+extern int dma_buffsize;
+extern int excl_policy;
+extern int mixer_muted;
+
+module_param (oss_hz, int, S_IRUGO);
+module_param (max_intrate, int, S_IRUGO);
+module_param (detect_trace, int, S_IRUGO);
+module_param (src_quality, int, S_IRUGO);
+module_param (flat_device_model, int, S_IRUGO);
+module_param (vmix_disabled, int, S_IRUGO);
+module_param (vmix_no_autoattach, int, S_IRUGO);
+module_param (vmix_loopdevs, int, S_IRUGO);
+module_param (ac97_amplifier, int, S_IRUGO);
+module_param (ac97_recselect, int, S_IRUGO);
+module_param (cooked_enable, int, S_IRUGO);
+module_param (dma_buffsize, int, S_IRUGO);
+module_param (excl_policy, int, S_IRUGO);
+module_param (mixer_muted, int, S_IRUGO);
+
+static struct proc_dir_entry *oss_proc_root = NULL;
+static struct proc_dir_entry *oss_proc_devfiles = NULL;
+
+static ssize_t
+oss_read_devfiles (struct file *file, char __user * buf, size_t count,
+ loff_t * ppos)
+{
+ static char tmp[8192];
+ char *s;
+ static int eof = 0;
+ int i;
+
+ if (eof)
+ {
+ eof = 0;
+ return 0;
+ }
+
+ *tmp = 0;
+ s = tmp;
+
+ for (i = 0; i < nminors; i++)
+ {
+ if (strlen (tmp) > sizeof (tmp) - 20)
+ {
+ printk (KERN_ALERT "osscore: Procfs buffer too small\n");
+ return -ENOMEM;
+ }
+
+ s += sprintf (s, "%s %d %d\n",
+ minors[i].name, minors[i].major, minors[i].minor);
+ }
+
+ if (copy_to_user (buf, (void *) tmp, strlen (tmp)))
+ return -EFAULT;
+
+ eof = 1;
+ return strlen (tmp);
+}
+
+static struct file_operations oss_proc_operations = {
+ .read = oss_read_devfiles,
+};
+
+static void
+init_proc_fs (void)
+{
+ if ((oss_proc_root =
+ create_proc_entry ("opensound", 0700 | S_IFDIR, NULL)) == NULL)
+ {
+ oss_cmn_err (CE_CONT, "Cannot create /proc/opensound\n");
+ return;
+ }
+
+ if ((oss_proc_devfiles =
+ create_proc_entry ("devfiles", 0600, oss_proc_root)) == NULL)
+ {
+ oss_cmn_err (CE_CONT, "Cannot create /proc/opensound/devfiles\n");
+ return;
+ }
+
+ oss_proc_devfiles->proc_fops = &oss_proc_operations;
+}
+
+static void
+uninit_proc_fs (void)
+{
+ if (oss_proc_root)
+ {
+ if (oss_proc_devfiles)
+ remove_proc_entry ("devfiles", oss_proc_root);
+ remove_proc_entry ("opensound", NULL);
+ }
+}
+
+static int
+osscore_init (void)
+{
+ if ((core_osdev =
+ osdev_create (NULL, DRV_UNKNOWN, 0, "osscore", NULL)) == NULL)
+ {
+ oss_cmn_err (CE_WARN, "Failed to allocate OSDEV structure\n");
+ return -ENOMEM;
+ }
+
+ osdev_set_owner (core_osdev, THIS_MODULE);
+
+ init_proc_fs ();
+
+ return oss_init_osscore (core_osdev);
+}
+
+static void
+osscore_exit (void)
+{
+ uninit_proc_fs ();
+ oss_uninit_osscore (core_osdev);
+}
+
+void
+oss_udelay (unsigned long d)
+{
+ udelay (d);
+}
+
+oss_mutex_t
+oss_mutex_init (void)
+{
+ oss_mutex_t mutex;
+
+ if ((mutex = vmalloc (sizeof (*mutex))) == NULL)
+ {
+ oss_cmn_err (CE_WARN, "vmalloc(%d) failed (mutex)\n", sizeof (*mutex));
+ return NULL;
+ }
+
+ spin_lock_init (&(mutex->lock));
+
+ return mutex;
+}
+
+void
+oss_mutex_cleanup (oss_mutex_t mutex)
+{
+ vfree (mutex);
+}
+
+void
+oss_spin_lock_irqsave (oss_mutex_t mutex, oss_native_word * flags)
+{
+ unsigned long flag;
+ if (mutex == NULL)
+ return;
+ spin_lock_irqsave (&mutex->lock, flag);
+ *flags = flag;
+}
+
+void
+oss_spin_unlock_irqrestore (oss_mutex_t mutex, oss_native_word flags)
+{
+ if (mutex == NULL)
+ return;
+ spin_unlock_irqrestore (&mutex->lock, flags);
+}
+
+void
+oss_spin_lock (oss_mutex_t mutex)
+{
+ if (mutex == NULL)
+ return;
+ spin_lock (&mutex->lock);
+}
+
+void
+oss_spin_unlock (oss_mutex_t mutex)
+{
+ if (mutex == NULL)
+ return;
+ spin_unlock (&mutex->lock);
+}
+
+void *
+oss_map_pci_mem (oss_device_t * osdev, int size, unsigned long offset)
+{
+#ifdef __arm__
+ return (void*)offset;
+#else
+ return ioremap (offset, size);
+#endif
+}
+
+void
+oss_unmap_pci_mem (void *addr)
+{
+#ifndef __arm__
+ iounmap (addr);
+#endif
+}
+
+unsigned long long
+oss_get_jiffies (void)
+{
+ return jiffies_64;
+}
+
+char *
+oss_get_procname (void)
+{
+ return current->comm;
+}
+
+int
+oss_get_pid (void)
+{
+ return current->pid;
+}
+
+int
+oss_get_uid (void)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
+ return current->cred->uid;
+#else
+ return current->uid;
+#endif
+}
+
+typedef struct tmout_desc
+{
+ volatile int active;
+ int timestamp;
+ void (*func) (void *);
+ void *arg;
+
+ struct timer_list timer;
+} tmout_desc_t;
+
+static volatile int next_id = 0;
+#define MAX_TMOUTS 128
+
+tmout_desc_t tmouts[MAX_TMOUTS] = { {0} };
+
+int timeout_random = 0x12123400;
+
+void
+oss_timer_callback (unsigned long id)
+{
+ tmout_desc_t *tmout;
+ int ix;
+ void *arg;
+
+ timeout_random++;
+
+ ix = id & 0xff;
+ if (ix < 0 || ix >= MAX_TMOUTS)
+ return;
+ tmout = &tmouts[ix];
+
+ if (tmout->timestamp != id) /* Expired timer */
+ return;
+
+ if (!tmout->active)
+ return;
+
+ arg = tmout->arg;
+ tmout->active = 0;
+ tmout->timestamp = 0;
+
+ tmout->func (arg);
+}
+
+timeout_id_t
+oss_timeout (void (*func) (void *), void *arg, unsigned long long ticks)
+{
+ tmout_desc_t *tmout = NULL;
+ int id, n;
+
+ timeout_random++;
+
+ n = 0;
+ id = -1;
+
+ while (id == -1 && n < MAX_TMOUTS)
+ {
+ if (!tmouts[next_id].active)
+ {
+ tmouts[next_id].active = 1;
+ id = next_id++;
+ tmout = &tmouts[id];
+ break;
+ }
+
+ next_id = (next_id + 1) % MAX_TMOUTS;
+ }
+
+ if (id == -1) /* No timer slots available */
+ {
+ oss_cmn_err (CE_WARN, "Timeout table full\n");
+ return 0;
+ }
+
+ tmout->func = func;
+ tmout->arg = arg;
+ tmout->timestamp = id | (timeout_random & ~0xff);
+
+ init_timer (&tmout->timer);
+ tmout->timer.expires = jiffies + ticks;
+ tmout->timer.data = id | (timeout_random & ~0xff);
+ tmout->timer.function = oss_timer_callback;
+ add_timer (&tmout->timer);
+
+ return id | (timeout_random & ~0xff);
+}
+
+void
+oss_untimeout (timeout_id_t id)
+{
+ tmout_desc_t *tmout;
+ int ix;
+
+ ix = id & 0xff;
+ if (ix < 0 || ix >= MAX_TMOUTS)
+ return;
+
+ timeout_random++;
+ tmout = &tmouts[ix];
+
+ if (tmout->timestamp != id) /* Expired timer */
+ return;
+ if (tmout->active)
+ del_timer (&tmout->timer);
+ tmout->active = 0;
+ tmout->timestamp = 0;
+}
+
+int
+oss_uiomove (void *addr, size_t nbytes, enum uio_rw rwflag, uio_t * uio)
+{
+/*
+ * NOTE! Returns 0 upon success and EFAULT on failure (instead of -EFAULT
+ * (for Solaris/BSD compatibilityi)).
+ */
+
+ int c;
+ char *address = addr;
+
+ if (rwflag != uio->rw)
+ {
+ oss_cmn_err (CE_WARN, "uiomove: Bad direction\n");
+ return EFAULT;
+ }
+
+ if (uio->resid < nbytes)
+ {
+ oss_cmn_err (CE_WARN, "uiomove: Bad count %d (%d)\n", nbytes,
+ uio->resid);
+ return EFAULT;
+ }
+
+ if (uio->kernel_space)
+ return EFAULT;
+
+ switch (rwflag)
+ {
+ case UIO_READ:
+ c = nbytes;
+ if (c > 10)
+ c = 0;
+
+ if ((c = copy_to_user (uio->ptr, address, nbytes) != 0))
+ {
+ uio->resid -= nbytes;
+ oss_cmn_err (CE_CONT, "copy_to_user(%d) failed (%d)\n", nbytes, c);
+ return EFAULT;
+ }
+ break;
+
+ case UIO_WRITE:
+ if (copy_from_user (address, uio->ptr, nbytes) != 0)
+ {
+ oss_cmn_err (CE_CONT, "copy_from_user failed\n");
+ uio->resid -= nbytes;
+ return EFAULT;
+ }
+ break;
+ }
+
+ uio->resid -= nbytes;
+ uio->ptr += nbytes;
+
+ return 0;
+}
+
+int
+oss_create_uio (uio_t * uio, char *buf, size_t count, uio_rw_t rw,
+ int is_kernel)
+{
+ memset (uio, 0, sizeof (*uio));
+
+ if (is_kernel)
+ {
+ oss_cmn_err (CE_CONT,
+ "oss_create_uio: Kernel space buffers not supported\n");
+ return -EIO;
+ }
+
+ uio->ptr = buf;
+ uio->resid = count;
+ uio->kernel_space = is_kernel;
+ uio->rw = rw;
+
+ return 0;
+}
+
+void
+oss_cmn_err (int level, const char *s, ...)
+{
+ char tmp[1024], *a[6];
+ va_list ap;
+ int i, n = 0;
+
+ va_start (ap, s);
+
+ for (i = 0; i < strlen (s); i++)
+ if (s[i] == '%')
+ n++;
+
+ for (i = 0; i < n && i < 6; i++)
+ a[i] = va_arg (ap, char *);
+
+ for (i = n; i < 6; i++)
+ a[i] = NULL;
+
+ if (level == CE_CONT)
+ {
+ sprintf (tmp, s, a[0], a[1], a[2], a[3], a[4], a[5], NULL,
+ NULL, NULL, NULL);
+ printk ("%s", tmp);
+ }
+ else
+ {
+ strcpy (tmp, "osscore: ");
+ sprintf (tmp + strlen (tmp), s, a[0], a[1], a[2], a[3], a[4], a[5],
+ NULL, NULL, NULL, NULL);
+ if (level == CE_PANIC)
+ panic (tmp);
+
+ printk (KERN_ALERT "%s", tmp);
+ }
+#if 0
+ /* This may cause a crash under SMP */
+ if (sound_started)
+ store_msg (tmp);
+#endif
+
+ va_end (ap);
+}
+
+/*
+ * Sleep/wakeup
+ */
+
+struct oss_wait_queue
+{
+ volatile int flags;
+ wait_queue_head_t wq;
+};
+
+struct oss_wait_queue *
+oss_create_wait_queue (oss_device_t * osdev, const char *name)
+{
+ struct oss_wait_queue *wq;
+
+ if ((wq = vmalloc (sizeof (*wq))) == NULL)
+ {
+ oss_cmn_err (CE_WARN, "vmalloc(%d) failed (wq)\n", sizeof (*wq));
+ return NULL;
+ }
+ init_waitqueue_head (&wq->wq);
+
+ return wq;
+}
+
+void
+oss_reset_wait_queue (struct oss_wait_queue *wq)
+{
+ wq->flags = 0;
+}
+
+void
+oss_remove_wait_queue (struct oss_wait_queue *wq)
+{
+ vfree (wq);
+}
+
+int
+oss_sleep (struct oss_wait_queue *wq, oss_mutex_t * mutex, int ticks,
+ oss_native_word * flags, unsigned int *status)
+{
+ int result = 0;
+ *status = 0;
+
+ if (wq == NULL)
+ return 0;
+
+ wq->flags = 0;
+ oss_spin_unlock_irqrestore (*mutex, *flags);
+
+ if (ticks <= 0)
+ result = wait_event_interruptible (wq->wq, (wq->flags & WK_WAKEUP));
+ else
+ result =
+ wait_event_interruptible_timeout (wq->wq, (wq->flags & WK_WAKEUP),
+ ticks);
+
+ oss_spin_lock_irqsave (*mutex, flags);
+
+ if (result < 0) /* Signal received */
+ {
+ *status |= WK_SIGNAL;
+ return 1;
+ }
+
+ if (!(wq->flags & WK_WAKEUP)) /* Timeout */
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+oss_register_poll (struct oss_wait_queue *wq, oss_mutex_t * mutex,
+ oss_native_word * flags, oss_poll_event_t * ev)
+{
+ oss_spin_unlock_irqrestore (*mutex, *flags);
+ poll_wait ((struct file *) ev->file, &wq->wq,
+ (struct poll_table_struct *) ev->wait);
+ oss_spin_lock_irqsave (*mutex, flags);
+ return 0;
+}
+
+void
+oss_wakeup (struct oss_wait_queue *wq, oss_mutex_t * mutex,
+ oss_native_word * flags, short events)
+{
+ if (wq == NULL)
+ return;
+
+ wq->flags |= WK_WAKEUP;
+ oss_spin_unlock_irqrestore (*mutex, *flags);
+ wake_up (&wq->wq);
+ oss_spin_lock_irqsave (*mutex, flags);
+}
+
+void
+oss_reserve_pages (oss_native_word start_addr, oss_native_word end_addr)
+{
+ struct page *page, *lastpage;
+
+ lastpage = virt_to_page (end_addr);
+
+ for (page = virt_to_page (start_addr); page <= lastpage; page++)
+ set_bit (PG_reserved, &page->flags);
+}
+
+void
+oss_unreserve_pages (oss_native_word start_addr, oss_native_word end_addr)
+{
+ struct page *page, *lastpage;
+
+ lastpage = virt_to_page (end_addr);
+
+ for (page = virt_to_page (start_addr); page <= lastpage; page++)
+ clear_bit (PG_reserved, &page->flags);
+}
+
+void *
+oss_contig_malloc (oss_device_t * osdev, int buffsize, oss_uint64_t memlimit,
+ oss_native_word * phaddr)
+{
+ char *start_addr, *end_addr;
+ int sz, size;
+ int flags = 0;
+
+ *phaddr = 0;
+
+#ifdef GFP_DMA32
+ if (memlimit < 0x0000000100000000LL)
+ flags |= GFP_DMA32;
+#endif
+
+ if (memlimit < 0x00000000ffffffffLL)
+ flags |= GFP_DMA;
+
+ start_addr = NULL;
+
+ for (sz = 0, size = PAGE_SIZE; size < buffsize; sz++, size <<= 1);
+
+ if (buffsize != (PAGE_SIZE * (1 << sz)))
+ {
+#if 0
+ printk
+ ("Contig_malloc: Invalid size %d != %ld\n", buffsize,
+ PAGE_SIZE * (1 << sz));
+#endif
+ }
+
+ start_addr = (char *) __get_free_pages (GFP_KERNEL | flags, sz);
+
+ if (start_addr == NULL)
+ {
+ cmn_err (CE_NOTE, "Failed to allocate memory buffer of %d bytes\n",
+ buffsize);
+ return NULL;
+ }
+ else
+ {
+ /* make some checks */
+ end_addr = start_addr + buffsize - 1;
+
+ oss_reserve_pages ((oss_native_word) start_addr,
+ (oss_native_word) end_addr);
+ }
+
+ *phaddr = virt_to_bus (start_addr);
+ return start_addr;
+}
+
+void
+oss_contig_free (oss_device_t * osdev, void *p, int buffsize)
+{
+ int sz, size;
+ caddr_t start_addr, end_addr;
+
+ if (p == NULL)
+ return;
+
+ for (sz = 0, size = PAGE_SIZE; size < buffsize; sz++, size <<= 1);
+
+ start_addr = p;
+ end_addr = p + buffsize - 1;
+
+ oss_unreserve_pages ((oss_native_word) start_addr,
+ (oss_native_word) end_addr);
+ free_pages ((unsigned long) p, sz);
+}
+
+/*
+ * These typedefs must match definition of struct file_operations.
+ * (See notes in routine oss_register_chrdev).
+ */
+typedef ssize_t (*read_t) (struct file *, char *, size_t, loff_t *);
+typedef ssize_t (*write_t) (struct file *, const char *, size_t, loff_t *);
+typedef unsigned int (*poll_t) (struct file *, poll_table *);
+typedef poll_table select_table;
+
+typedef int (*readdir_t) (struct inode *, struct file *, void *, filldir_t);
+typedef int (*ioctl_t) (struct inode *, struct file *, unsigned int,
+ unsigned long);
+typedef long (*new_ioctl_t) (struct file *, unsigned int, unsigned long);
+typedef int (*mmap_t) (struct file *, struct vm_area_struct *);
+typedef int (*open_t) (struct inode *, struct file *);
+
+typedef int (*release_t) (struct inode *, struct file *);
+typedef int (*fasync_t) (int, struct file *, int);
+typedef int (*fsync_t) (struct inode *, struct file *);
+
+static loff_t
+oss_no_llseek (struct file *file, loff_t offset, int orig)
+{
+ return -EINVAL;
+}
+
+static int
+oss_no_fsync (struct file *f, struct dentry *d, int datasync)
+{
+ return -EINVAL;
+}
+
+static int
+oss_no_fasync (int x, struct file *f, int m)
+{
+ return -EINVAL;
+}
+
+/*
+ * Wrappers for installing and uninstalling character and block devices.
+ *
+ * The oss_file_operation_handle structure differs from kernel's
+ * file_operations structure in parameters of the driver entry points.
+ * Kernel inode, file, wait_struct, vm_are_struct etc. typed arguments
+ * are replaced by wrapper handles.
+ */
+
+static struct file_operations *
+alloc_fop (oss_device_t * osdev, struct oss_file_operation_handle *op)
+{
+/*
+ * This routine performs initialization of kernel file_operations structure
+ * from oss_file_operation_handle structure. Each procedure pointer is copied
+ * to a temporary variable before doing the actual assignment. This
+ * prevents unnecessary warnings while it still enables compatibility
+ * warnings.
+ *
+ * Any warning given by this routine may indicate that kernel fs
+ * call interface has changed significantly (added parameters to the routines).
+ * In this case definition routine in oss_file_operation_handle must be updated
+ * and WRAPPER_VERSION must be incremented.
+ */
+
+ struct file_operations *fop;
+
+ poll_t tmp_poll = (poll_t) op->poll;
+ read_t tmp_read = (read_t) op->read;
+ write_t tmp_write = (write_t) op->write;
+ /* readdir_t tmp_readdir = (readdir_t)op->readdir; */
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
+ ioctl_t tmp_ioctl = (ioctl_t) op->ioctl;
+#endif
+ mmap_t tmp_mmap = (mmap_t) op->mmap;
+ open_t tmp_open = (open_t) op->open;
+ release_t tmp_release = (release_t) op->release;
+ new_ioctl_t tmp_unlocked_ioctl = (new_ioctl_t) op->unlocked_ioctl;
+ new_ioctl_t tmp_compat_ioctl = (new_ioctl_t) op->compat_ioctl;
+
+ fop = (struct file_operations *)
+ oss_kmem_alloc (sizeof (struct file_operations));
+
+ memset ((char *) fop, 0, sizeof (struct file_operations));
+
+/*
+ * Now the assignment
+ */
+ fop->llseek = oss_no_llseek;
+ fop->read = tmp_read;
+ fop->write = tmp_write;
+ fop->readdir = NULL; /* tmp_readdir; */
+ fop->poll = tmp_poll;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)
+ fop->ioctl = tmp_ioctl;
+#endif
+ fop->mmap = tmp_mmap;
+ fop->open = tmp_open;
+ fop->release = tmp_release;
+ fop->fsync = oss_no_fsync;
+ fop->fasync = oss_no_fasync;
+ fop->lock = NULL;
+ fop->flush = NULL;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ fop->owner = osdev_get_owner (osdev);
+#endif
+#ifdef HAVE_UNLOCKED_IOCTL
+ fop->unlocked_ioctl = tmp_unlocked_ioctl;
+#endif
+#ifdef HAVE_COMPAT_IOCTL
+ fop->compat_ioctl = tmp_compat_ioctl;
+#endif
+
+ return fop;
+}
+
+int
+oss_register_chrdev (oss_device_t * osdev, unsigned int major,
+ const char *name, struct oss_file_operation_handle *op)
+{
+ int maj;
+ maj = register_chrdev (major, name, alloc_fop (osdev, op));
+
+ return maj;
+}
+
+void
+oss_register_minor (int major, int minor, char *name)
+{
+ if (nminors >= MAX_MINOR)
+ {
+ oss_cmn_err (CE_WARN, "Too many device files\n");
+ return;
+ }
+
+ minors[nminors].major = major;
+ minors[nminors].minor = minor;
+ strcpy (minors[nminors].name, name);
+ nminors++;
+}
+
+int
+oss_unregister_chrdev (unsigned int major, const char *name)
+{
+ unregister_chrdev (major, name);
+ return 0;
+}
+
+int
+oss_inode_get_minor (oss_inode_handle_t * inode)
+{
+ return MINOR (((struct inode *) inode)->i_rdev);
+}
+
+int
+oss_file_get_flags (oss_file_handle_t * file)
+{
+ return ((struct file *) file)->f_flags;
+}
+
+void *
+oss_file_get_private (oss_file_handle_t * file)
+{
+ return ((struct file *) file)->private_data;
+}
+
+void
+oss_file_set_private (oss_file_handle_t * file, void *v)
+{
+ ((struct file *) file)->private_data = v;
+}
+
+int
+oss_vma_get_flags (oss_vm_area_handle_t * vma)
+{
+ return ((struct vm_area_struct *) vma)->vm_flags;
+}
+
+int
+oss_do_mmap (oss_vm_area_handle_t * v, oss_native_word dmabuf_phys,
+ int bytes_in_use)
+{
+ struct vm_area_struct *vma = (struct vm_area_struct *) v;
+ int res, size;
+
+ if (vma->vm_pgoff != 0)
+ {
+ oss_cmn_err (CE_WARN, "mmap() offset must be 0.\n");
+ return -EINVAL;
+ }
+
+ size = vma->vm_end - vma->vm_start;
+
+ if (size != bytes_in_use)
+ {
+ oss_cmn_err (CE_WARN, "mmap() size = %ld. Should be %d\n",
+ size, bytes_in_use);
+ return -EBUSY;
+ }
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
+ res = io_remap_page_range (vma, vma->vm_start,
+ dmabuf_phys, size, vma->vm_page_prot);
+
+#else
+ res = io_remap_pfn_range (vma, vma->vm_start,
+ dmabuf_phys >> PAGE_SHIFT,
+ size, vma->vm_page_prot);
+#endif
+
+ if (res)
+ {
+ oss_cmn_err (CE_WARN, "io_remap_pfn_range returned %d\n", res);
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+/* As a special exception, if you link this library with other files,
+ some of which are compiled with GCC, to produce an executable,
+ this library does not by itself cause the resulting executable
+ to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+typedef unsigned int UQItype __attribute__ ((mode (QI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+
+typedef int word_type __attribute__ ((mode (__word__)));
+
+/* DIstructs are pairs of SItype values in the order determined by
+ little/big ENDIAN. */
+
+#if defined(__i386__) || defined(__x86_64__)
+struct DIstruct
+{
+ SItype low, high;
+};
+#endif
+
+
+#ifndef __arm__
+/* We need this union to unpack/pack DImode values, since we don't have
+ any arithmetic yet. Incoming DImode parameters are stored into the
+ `ll' field, and the unpacked result is read from the struct `s'. */
+
+typedef union
+{
+ struct DIstruct s;
+ DItype ll;
+} DIunion;
+
+
+/* From gcc/longlong.h */
+
+#ifndef SI_TYPE_SIZE
+#define SI_TYPE_SIZE 32
+#endif
+
+#define __BITS4 (SI_TYPE_SIZE / 4)
+#define __ll_B (1L << (SI_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
+#define __ll_highpart(t) ((USItype) (t) / __ll_B)
+
+#if defined(__i386__) || defined(__x86_64__)
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("subl %5,%1\n" \
+ "sbbl %3,%0" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
+#define umul_ppmm(w1, w0, u, v) \
+ __asm__ ("mull %3" \
+ : "=a" ((USItype) (w0)), \
+ "=d" ((USItype) (w1)) \
+ : "%0" ((USItype) (u)), \
+ "rm" ((USItype) (v)))
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ __asm__ ("divl %4" \
+ : "=a" ((USItype) (q)), \
+ "=d" ((USItype) (r)) \
+ : "0" ((USItype) (n0)), \
+ "1" ((USItype) (n1)), \
+ "rm" ((USItype) (d)))
+#define count_leading_zeros(count, x) \
+ do { \
+ USItype __cbtmp; \
+ __asm__ ("bsrl %1,%0" \
+ : "=r" (__cbtmp) : "rm" ((USItype) (x))); \
+ (count) = __cbtmp ^ 31; \
+ } while (0)
+#endif /* __i386__ */
+
+/* If this machine has no inline assembler, use C macros. */
+
+/* Define this unconditionally, so it can be used for debugging. */
+#define __udiv_qrnnd_c(q, r, n1, n0, d) \
+ do { \
+ USItype __d1, __d0, __q1, __q0; \
+ USItype __r1, __r0, __m; \
+ __d1 = __ll_highpart (d); \
+ __d0 = __ll_lowpart (d); \
+ \
+ __r1 = (n1) % __d1; \
+ __q1 = (n1) / __d1; \
+ __m = (USItype) __q1 * __d0; \
+ __r1 = __r1 * __ll_B | __ll_highpart (n0); \
+ if (__r1 < __m) \
+ { \
+ __q1--, __r1 += (d); \
+ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+ if (__r1 < __m) \
+ __q1--, __r1 += (d); \
+ } \
+ __r1 -= __m; \
+ \
+ __r0 = __r1 % __d1; \
+ __q0 = __r1 / __d1; \
+ __m = (USItype) __q0 * __d0; \
+ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
+ if (__r0 < __m) \
+ { \
+ __q0--, __r0 += (d); \
+ if (__r0 >= (d)) \
+ if (__r0 < __m) \
+ __q0--, __r0 += (d); \
+ } \
+ __r0 -= __m; \
+ \
+ (q) = (USItype) __q1 * __ll_B | __q0; \
+ (r) = __r0; \
+ } while (0)
+
+/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */
+#if !defined (udiv_qrnnd)
+#define UDIV_NEEDS_NORMALIZATION 1
+#define udiv_qrnnd __udiv_qrnnd_c
+#endif
+
+/* End of gcc/longlong.h */
+
+
+static inline DItype
+__negdi2 (DItype u)
+{
+ DIunion w;
+ DIunion uu;
+
+ uu.ll = u;
+
+ w.s.low = -uu.s.low;
+ w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
+
+ return w.ll;
+}
+
+static inline UDItype
+__udivmoddi4 (UDItype n, UDItype d, UDItype * rp)
+{
+ DIunion ww;
+ DIunion nn, dd;
+ DIunion rr;
+ USItype d0, d1, n0, n1, n2;
+ USItype q0, q1;
+ USItype b, bm;
+
+ nn.ll = n;
+ dd.ll = d;
+
+ d0 = dd.s.low;
+ d1 = dd.s.high;
+ n0 = nn.s.low;
+ n1 = nn.s.high;
+
+#ifndef UDIV_NEEDS_NORMALIZATION
+ if (d1 == 0)
+ {
+ if (d0 > n1)
+ {
+ /* 0q = nn / 0D */
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0. */
+ }
+ else
+ {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ udiv_qrnnd (q1, n1, 0, n1, d0);
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+
+ /* Remainder in n0. */
+ }
+
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = 0;
+ *rp = rr.ll;
+ }
+ }
+
+#else /* UDIV_NEEDS_NORMALIZATION */
+
+ if (d1 == 0)
+ {
+ if (d0 > n1)
+ {
+ /* 0q = nn / 0D */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm != 0)
+ {
+ /* Normalize, i.e. make the most significant bit of the
+ denominator set. */
+
+ d0 = d0 << bm;
+ n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
+ n0 = n0 << bm;
+ }
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0 >> bm. */
+ }
+ else
+ {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm == 0)
+ {
+ /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ leading quotient digit q1 = 1).
+
+ This special case is necessary, not an optimization.
+ (Shifts counts of SI_TYPE_SIZE are undefined.) */
+
+ n1 -= d0;
+ q1 = 1;
+ }
+ else
+ {
+ /* Normalize. */
+
+ b = SI_TYPE_SIZE - bm;
+
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q1, n1, n2, n1, d0);
+ }
+
+ /* n1 != d0... */
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+
+ /* Remainder in n0 >> bm. */
+ }
+
+ if (rp != 0)
+ {
+ rr.s.low = n0 >> bm;
+ rr.s.high = 0;
+ *rp = rr.ll;
+ }
+ }
+#endif /* UDIV_NEEDS_NORMALIZATION */
+
+ else
+ {
+ if (d1 > n1)
+ {
+ /* 00 = nn / DD */
+
+ q0 = 0;
+ q1 = 0;
+
+ /* Remainder in n1n0. */
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ }
+ else
+ {
+ /* 0q = NN / dd */
+
+ count_leading_zeros (bm, d1);
+ if (bm == 0)
+ {
+ /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ quotient digit q0 = 0 or 1).
+
+ This special case is necessary, not an optimization. */
+
+ /* The condition on the next line takes advantage of that
+ n1 >= d1 (true due to program flow). */
+ if (n1 > d1 || n0 >= d0)
+ {
+ q0 = 1;
+ sub_ddmmss (n1, n0, n1, n0, d1, d0);
+ }
+ else
+ q0 = 0;
+
+ q1 = 0;
+
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ }
+ else
+ {
+ USItype m1, m0;
+ /* Normalize. */
+
+ b = SI_TYPE_SIZE - bm;
+
+ d1 = (d1 << bm) | (d0 >> b);
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q0, n1, n2, n1, d1);
+ umul_ppmm (m1, m0, q0, d0);
+
+ if (m1 > n1 || (m1 == n1 && m0 > n0))
+ {
+ q0--;
+ sub_ddmmss (m1, m0, m1, m0, d1, d0);
+ }
+
+ q1 = 0;
+
+ /* Remainder in (n1n0 - m1m0) >> bm. */
+ if (rp != 0)
+ {
+ sub_ddmmss (n1, n0, n1, n0, m1, m0);
+ rr.s.low = (n1 << b) | (n0 >> bm);
+ rr.s.high = n1 >> bm;
+ *rp = rr.ll;
+ }
+ }
+ }
+ }
+
+ ww.s.low = q0;
+ ww.s.high = q1;
+ return ww.ll;
+}
+
+DItype
+__divdi3 (DItype u, DItype v)
+{
+ word_type c = 0;
+ DIunion uu, vv;
+ DItype w;
+
+ uu.ll = u;
+ vv.ll = v;
+
+ if (uu.s.high < 0)
+ c = ~c, uu.ll = __negdi2 (uu.ll);
+ if (vv.s.high < 0)
+ c = ~c, vv.ll = __negdi2 (vv.ll);
+
+ w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
+ if (c)
+ w = __negdi2 (w);
+
+ return w;
+}
+
+
+DItype
+__moddi3 (DItype u, DItype v)
+{
+ word_type c = 0;
+ DIunion uu, vv;
+ DItype w;
+
+ uu.ll = u;
+ vv.ll = v;
+
+ if (uu.s.high < 0)
+ c = ~c, uu.ll = __negdi2 (uu.ll);
+ if (vv.s.high < 0)
+ vv.ll = __negdi2 (vv.ll);
+
+ (void) __udivmoddi4 (uu.ll, vv.ll, (UDItype *) & w);
+ if (c)
+ w = __negdi2 (w);
+
+ return w;
+}
+
+
+UDItype
+__umoddi3 (UDItype u, UDItype v)
+{
+ UDItype w;
+
+ (void) __udivmoddi4 (u, v, (UDItype *) & w);
+
+ return w;
+}
+
+
+UDItype
+__udivdi3 (UDItype n, UDItype d)
+{
+ return __udivmoddi4 (n, d, (UDItype *) 0);
+}
+#endif
+
+#ifdef __arm__
+void
+raise(void)
+{
+ oss_cmn_err (CE_PANIC, "raise() got called\n");
+}
+
+#endif
+
+dev_info_t *
+oss_create_pcidip (struct pci_dev * pcidev)
+{
+ dev_info_t *dip;
+
+ if ((dip = oss_pmalloc (sizeof (*dip))) == NULL)
+ return NULL;
+
+ memset (dip, 0, sizeof (*dip));
+ dip->pcidev = pcidev;
+
+ return dip;
+}
+
+int
+osscore_pci_read_config_byte (dev_info_t * dip, unsigned int where,
+ unsigned char *val)
+{
+ return pci_read_config_byte (dip->pcidev, where, val);
+}
+
+int
+osscore_pci_read_config_irq (dev_info_t * dip, unsigned int where,
+ unsigned char *val)
+{
+ *val = dip->pcidev->irq;
+ return 0; // PCIBIOS_SUCCESSFUL
+}
+
+int
+osscore_pci_read_config_word (dev_info_t * dip, unsigned int where,
+ unsigned short *val)
+{
+ if (dip == NULL)
+ {
+ oss_cmn_err (CE_CONT, "osscore_pci_read_config_word: dip==NULL\n");
+ return -1;
+ }
+ return pci_read_config_word (dip->pcidev, where, val);
+}
+
+int
+osscore_pci_read_config_dword (dev_info_t * dip, unsigned int where,
+ unsigned int *val)
+{
+ return pci_read_config_dword (dip->pcidev, where, val);
+}
+
+int
+osscore_pci_write_config_byte (dev_info_t * dip, unsigned int where,
+ unsigned char val)
+{
+ return pci_write_config_byte (dip->pcidev, where, val);
+}
+
+int
+osscore_pci_write_config_word (dev_info_t * dip, unsigned int where,
+ unsigned short val)
+{
+ return pci_write_config_word (dip->pcidev, where, val);
+}
+
+int
+osscore_pci_write_config_dword (dev_info_t * dip, unsigned int where,
+ unsigned int val)
+{
+ return pci_write_config_dword (dip->pcidev, where, val);
+}
+
+int
+osscore_pci_enable_msi (dev_info_t * dip)
+{
+ pci_enable_msi (dip->pcidev);
+ return (dip->pcidev->irq);
+}
+
+/* These definitions must match with oss_config.h */
+typedef int (*oss_tophalf_handler_t) (struct _oss_device_t * osdev);
+typedef void (*oss_bottomhalf_handler_t) (struct _oss_device_t * osdev);
+
+typedef struct
+{
+ int irq;
+ oss_device_t *osdev;
+ oss_tophalf_handler_t top;
+ oss_bottomhalf_handler_t bottom;
+} osscore_intr_t;
+
+#define MAX_INTRS 32
+
+static osscore_intr_t intrs[MAX_INTRS] = { {0} };
+static int nintrs = 0;
+
+static irqreturn_t
+osscore_intr (int irq, void *arg)
+{
+ int serviced;
+ osscore_intr_t *intr = arg;
+
+ if (intr->osdev == NULL || intr->top == NULL) /* Removed interrupt */
+ return 0;
+
+ serviced = intr->top (intr->osdev);
+ oss_inc_intrcount (intr->osdev, serviced);
+ if (serviced)
+ {
+ if (intr->bottom != NULL)
+ intr->bottom (intr->osdev);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+extern int oss_pci_read_config_irq (oss_device_t * osdev, unsigned long where,
+ unsigned char *val);
+
+char *
+oss_pci_read_devpath (dev_info_t * dip)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
+ return dev_name(&dip->pcidev->dev);
+#else
+ return dip->pcidev->dev.bus_id;
+#endif
+}
+
+int
+oss_register_interrupts (oss_device_t * osdev, int irqnum,
+ oss_tophalf_handler_t top,
+ oss_bottomhalf_handler_t bottom)
+{
+
+ unsigned char pci_irq_line;
+ osscore_intr_t *intr;
+ char *name;
+ int err;
+
+ if (nintrs >= MAX_INTRS)
+ {
+ oss_cmn_err (CE_CONT,
+ "oss_register_interrupts: Too many interrupt handlers\n");
+ return -ENOMEM;
+ }
+
+ intr = &intrs[nintrs];
+
+ if (oss_pci_read_config_irq (osdev, PCI_INTERRUPT_LINE, &pci_irq_line) > 0)
+ return -EIO;
+
+ intr->irq = pci_irq_line;
+ intr->osdev = osdev;
+ intr->top = top;
+ intr->bottom = bottom;
+
+ name = osdev_get_nick (osdev);
+#ifndef IRQF_SHARED
+#define IRQF_SHARED SA_SHIRQ
+#endif
+
+ if ((err =
+ request_irq (pci_irq_line, osscore_intr, IRQF_SHARED, name, intr)) < 0)
+ {
+ oss_cmn_err (CE_CONT, "request_irq(%d) failed, err=%d\n", pci_irq_line,
+ err);
+ return err;
+ }
+
+ nintrs++;
+
+ return 0;
+}
+
+void
+oss_unregister_interrupts (oss_device_t * osdev)
+{
+ int i;
+
+ for (i = 0; i < nintrs; i++)
+ if (intrs[i].osdev == osdev)
+ {
+ free_irq (intrs[i].irq, &intrs[i]);
+ intrs[i].osdev = NULL;
+ intrs[i].top = NULL;
+ intrs[i].bottom = NULL;
+ }
+}
+
+int
+oss_copy_to_user (void *to, const void *from, unsigned long n)
+{
+ return copy_to_user (to, from, n);
+}
+
+int
+oss_copy_from_user (void *to, const void *from, unsigned long n)
+{
+ return copy_from_user (to, from, n);
+}
+
+static int refcount = 0;
+
+typedef struct
+{
+ struct module *module;
+ int active;
+} oss_module_t;
+
+#define OSS_MAX_MODULES 50
+
+static oss_module_t oss_modules[OSS_MAX_MODULES];
+static int num_oss_modules = 0;
+
+void
+oss_inc_refcounts (void)
+{
+ int i;
+ refcount++;
+ for (i = 0; i < num_oss_modules; i++)
+ if (oss_modules[i].active)
+ {
+ if (!try_module_get (oss_modules[i].module))
+ oss_cmn_err (CE_WARN, "try_module_get() failed\n");
+ }
+}
+
+void
+oss_dec_refcounts (void)
+{
+ int i;
+ refcount--;
+ for (i = 0; i < num_oss_modules; i++)
+ if (oss_modules[i].active)
+ {
+ module_put (oss_modules[i].module);
+ }
+}
+
+void
+oss_register_module (struct module *mod)
+{
+ int i, n = -1;
+
+ for (i = 0; i < num_oss_modules; i++)
+ if (!oss_modules[i].active)
+ {
+ n = i;
+ break;
+ }
+
+ if (n == -1)
+ {
+ if (num_oss_modules >= OSS_MAX_MODULES)
+ {
+ printk (KERN_ALERT "Too many OSS modules\n");
+ return;
+ }
+
+ n = num_oss_modules++;
+ }
+
+ oss_modules[n].module = mod;
+ oss_modules[n].active = 1;
+}
+
+void
+oss_unregister_module (struct module *mod)
+{
+ int i;
+
+ for (i = 0; i < num_oss_modules; i++)
+ if (oss_modules[i].active && oss_modules[i].module == mod)
+ {
+ oss_modules[i].active = 0;
+ oss_modules[i].module = NULL;
+ return;
+ }
+}
+
+module_init (osscore_init);
+module_exit (osscore_exit);
+
+#ifdef CONFIG_OSS_VMIX_FLOAT
+
+#define FP_SAVE(envbuf) asm ("fnsave %0":"=m" (*envbuf));
+#define FP_RESTORE(envbuf) asm ("frstor %0":"=m" (*envbuf));
+
+/* SSE/SSE2 compatible macros */
+#define FX_SAVE(envbuf) asm ("fxsave %0":"=m" (*envbuf));
+#define FX_RESTORE(envbuf) asm ("fxrstor %0":"=m" (*envbuf));
+
+static int old_arch = 0; /* No SSE/SSE2 instructions */
+
+#if 0
+static inline unsigned long
+read_cr0 (void)
+{
+ unsigned long cr0;
+ asm volatile ("movq %%cr0,%0":"=r" (cr0));
+ return cr0;
+}
+
+static inline void
+write_cr0 (unsigned long val)
+{
+ asm volatile ("movq %0,%%cr0"::"r" (val));
+}
+
+static inline unsigned long
+read_cr4 (void)
+{
+ unsigned long cr4;
+ asm volatile ("movq %%cr4,%0":"=r" (cr4));
+ return cr4;
+}
+
+static inline void
+write_cr4 (unsigned long val)
+{
+ asm volatile ("movq %0,%%cr4"::"r" (val));
+}
+#endif
+
+static inline unsigned long long
+read_mxcsr (void)
+{
+ unsigned long long mxcsr;
+ asm volatile ("stmxcsr %0":"=m" (mxcsr));
+ return mxcsr;
+}
+
+static inline void
+write_mxcsr (unsigned long long val)
+{
+ asm volatile ("ldmxcsr %0"::"m" (val));
+}
+
+int
+oss_fp_check (void)
+{
+ int eax, ebx, ecx, edx;
+#define FLAGS_ID (1<<21)
+
+ oss_native_word flags_reg;
+
+ local_save_flags (flags_reg);
+ flags_reg &= ~FLAGS_ID;
+ local_irq_restore (flags_reg);
+
+ local_save_flags (flags_reg);
+ if (flags_reg & FLAGS_ID)
+ return 0;
+
+ flags_reg |= FLAGS_ID;
+ local_irq_restore (flags_reg);
+
+ local_save_flags (flags_reg);
+ if (!(flags_reg & FLAGS_ID))
+ return 0;
+
+#define CPUID_FXSR (1<<24)
+#define CPUID_SSE (1<<25)
+#define CPUID_SSE2 (1<<26)
+
+ cpuid (1, &eax, &ebx, &ecx, &edx);
+
+ if (!(edx & CPUID_FXSR))
+ return -1;
+
+ /*
+ * Older machines require different FP handling than the latest ones. Use the SSE
+ * instruction set as an indicator.
+ */
+ if (!(edx & CPUID_SSE))
+ old_arch = 1;
+
+ return 1;
+}
+
+void
+oss_fp_save (short *envbuf, unsigned int flags[])
+{
+ flags[0] = read_cr0 ();
+ write_cr0 (flags[0] & ~0x0e); /* Clear CR0.TS/MP/EM */
+
+ if (old_arch)
+ {
+ FP_SAVE (envbuf);
+ }
+ else
+ {
+ flags[1] = read_cr4 ();
+ write_cr4 (flags[1] | 0x600); /* Set OSFXSR & OSXMMEXCEPT */
+ FX_SAVE (envbuf);
+ asm ("fninit");
+ asm ("fwait");
+ write_mxcsr (0x1f80);
+ }
+ flags[2] = read_cr0 ();
+}
+
+void
+oss_fp_restore (short *envbuf, unsigned int flags[])
+{
+ asm ("fwait");
+ if (old_arch)
+ {
+ FP_RESTORE (envbuf);
+ }
+ else
+ {
+ FX_RESTORE (envbuf);
+ write_cr4 (flags[1]); /* Restore cr4 */
+ }
+ write_cr0 (flags[0]); /* Restore cr0 */
+}
+#endif
+
+#if 0
+void
+__stack_chk_fail (void)
+{
+ panic ("__stack_chk_fail\n");
+}
+#endif
+
+/*
+ * Exported symbols
+ */
+
+#define EXPORT_FUNC(name) extern void name(void);EXPORT_SYMBOL(name);
+#define EXPORT_DATA(name) extern int name;EXPORT_SYMBOL(name);
+
+/* EXPORT_SYMBOL (__stack_chk_fail); */
+
+#ifdef CONFIG_OSS_VMIX_FLOAT
+EXPORT_SYMBOL (oss_fp_check);
+EXPORT_SYMBOL (oss_fp_save);
+EXPORT_SYMBOL (oss_fp_restore);
+#endif
+
+EXPORT_SYMBOL (oss_register_chrdev);
+EXPORT_SYMBOL (oss_unregister_chrdev);
+EXPORT_SYMBOL (oss_reserve_pages);
+EXPORT_SYMBOL (oss_unreserve_pages);
+EXPORT_FUNC (ac97_install);
+EXPORT_FUNC (ac97_install_full);
+EXPORT_FUNC (ac97_playrate);
+EXPORT_FUNC (ac97_recrate);
+EXPORT_FUNC (ac97_varrate);
+EXPORT_FUNC (ac97_override_control);
+EXPORT_FUNC (ac97_init_ext);
+EXPORT_FUNC (ac97_mixer_set);
+EXPORT_FUNC (ac97_spdif_setup);
+EXPORT_FUNC (ac97_spdifout_ctl);
+EXPORT_FUNC (ac97_remove_control);
+EXPORT_SYMBOL (ac97_amplifier);
+EXPORT_FUNC (ac97_disable_spdif);
+EXPORT_FUNC (ac97_enable_spdif);
+EXPORT_FUNC (ac97_mixext_ctl);
+EXPORT_FUNC (ac97_spdifin_ctl);
+EXPORT_FUNC (oss_pci_byteswap);
+EXPORT_SYMBOL (mixer_ext_truncate);
+EXPORT_SYMBOL (mixer_ext_rebuild_all);
+EXPORT_FUNC (remux_install);
+EXPORT_SYMBOL (oss_strlen);
+EXPORT_SYMBOL (oss_strcmp);
+EXPORT_FUNC (oss_install_mididev);
+EXPORT_DATA (detect_trace);
+EXPORT_SYMBOL (dmap_get_qhead);
+EXPORT_SYMBOL (dmap_get_qtail);
+EXPORT_FUNC (oss_alloc_dmabuf);
+EXPORT_SYMBOL (oss_contig_free);
+EXPORT_SYMBOL (oss_contig_malloc);
+EXPORT_FUNC (oss_disable_device);
+EXPORT_FUNC (oss_free_dmabuf);
+EXPORT_SYMBOL (oss_map_pci_mem);
+EXPORT_SYMBOL (oss_install_audiodev);
+EXPORT_SYMBOL (oss_install_audiodev_with_devname);
+EXPORT_FUNC (oss_audio_set_error);
+EXPORT_SYMBOL (load_mixer_volumes);
+EXPORT_SYMBOL (oss_unmap_pci_mem);
+EXPORT_SYMBOL (oss_memset);
+EXPORT_SYMBOL (oss_mutex_cleanup);
+EXPORT_SYMBOL (oss_mutex_init);
+EXPORT_SYMBOL (oss_register_device);
+EXPORT_SYMBOL (oss_register_interrupts);
+EXPORT_SYMBOL (oss_inc_intrcount);
+EXPORT_SYMBOL (oss_spin_lock);
+EXPORT_SYMBOL (oss_spin_lock_irqsave);
+EXPORT_SYMBOL (oss_spin_unlock);
+EXPORT_SYMBOL (oss_spin_unlock_irqrestore);
+EXPORT_SYMBOL (oss_udelay);
+EXPORT_FUNC (oss_unregister_device);
+EXPORT_SYMBOL (oss_unregister_interrupts);
+EXPORT_SYMBOL (oss_virt_to_bus);
+EXPORT_FUNC (oss_pci_read_config_byte);
+EXPORT_FUNC (oss_pci_read_config_word);
+EXPORT_FUNC (oss_pci_read_config_dword);
+EXPORT_FUNC (oss_pci_write_config_byte);
+EXPORT_FUNC (oss_pci_write_config_word);
+EXPORT_FUNC (oss_pci_write_config_dword);
+EXPORT_FUNC (oss_pci_enable_msi);
+EXPORT_SYMBOL (oss_pci_read_config_irq);
+EXPORT_SYMBOL (oss_pci_read_devpath);
+EXPORT_SYMBOL (oss_get_jiffies);
+EXPORT_SYMBOL (mixer_find_ext);
+EXPORT_SYMBOL (oss_install_mixer);
+EXPORT_SYMBOL (oss_strcpy);
+EXPORT_SYMBOL (oss_kmem_free);
+#ifndef __arm__
+EXPORT_FUNC (uart401_init);
+EXPORT_FUNC (uart401_disable);
+EXPORT_FUNC (uart401_irq);
+#endif
+EXPORT_SYMBOL (mixer_ext_set_init_fn);
+EXPORT_SYMBOL (mixer_ext_set_vmix_init_fn);
+#ifdef CONFIG_OSS_VMIX
+EXPORT_FUNC (vmix_attach_audiodev);
+EXPORT_FUNC (vmix_detach_audiodev);
+EXPORT_FUNC (vmix_change_devnames);
+#endif
+EXPORT_SYMBOL (mixer_ext_set_strings);
+EXPORT_SYMBOL (mixer_ext_create_group);
+EXPORT_SYMBOL (mixer_ext_create_group_flags);
+EXPORT_SYMBOL (mixer_ext_create_control);
+EXPORT_SYMBOL (oss_strncpy);
+EXPORT_SYMBOL (oss_memcpy);
+EXPORT_SYMBOL (oss_kmem_alloc);
+EXPORT_DATA (oss_hz);
+EXPORT_FUNC (oss_spdif_open);
+EXPORT_FUNC (oss_spdif_ioctl);
+EXPORT_FUNC (oss_spdif_install);
+EXPORT_FUNC (oss_spdif_uninstall);
+EXPORT_FUNC (oss_spdif_close);
+EXPORT_FUNC (oss_spdif_mix_init);
+EXPORT_FUNC (oss_spdif_setrate);
+EXPORT_FUNC (create_new_card);
+EXPORT_FUNC (oss_audio_ioctl);
+EXPORT_FUNC (oss_audio_open_engine);
+EXPORT_FUNC (oss_audio_release);
+EXPORT_FUNC (oss_audio_set_rate);
+EXPORT_SYMBOL (oss_uiomove);
+EXPORT_SYMBOL (oss_get_pid);
+EXPORT_SYMBOL (oss_get_uid);
+EXPORT_SYMBOL (oss_get_procname);
+EXPORT_SYMBOL (mix_cvt);
+EXPORT_FUNC (oss_audio_set_format);
+EXPORT_FUNC (oss_audio_set_channels);
+EXPORT_FUNC (midiparser_create);
+EXPORT_FUNC (midiparser_input);
+EXPORT_FUNC (midiparser_unalloc);
+EXPORT_FUNC (mixer_ext_create_device);
+EXPORT_SYMBOL (mixer_ext_recrw);
+EXPORT_SYMBOL (mixer_ext_rw);
+EXPORT_SYMBOL (mixer_ext_set_enum);
+EXPORT_SYMBOL (mixer_ext_set_description);
+EXPORT_SYMBOL (osdev_create);
+EXPORT_FUNC (osdev_clone);
+EXPORT_SYMBOL (osdev_delete);
+EXPORT_FUNC (oss_audio_chpoll);
+EXPORT_FUNC (oss_audio_delayed_attach);
+EXPORT_FUNC (oss_audio_read);
+EXPORT_FUNC (oss_audio_write);
+EXPORT_SYMBOL (oss_create_wait_queue);
+EXPORT_SYMBOL (oss_remove_wait_queue);
+EXPORT_SYMBOL (oss_reset_wait_queue);
+EXPORT_SYMBOL (oss_sleep);
+EXPORT_SYMBOL (oss_strncmp);
+EXPORT_SYMBOL (oss_timeout);
+EXPORT_SYMBOL (oss_untimeout);
+EXPORT_SYMBOL (oss_wakeup);
+#if 0
+EXPORT_FUNC (ossddk_ac97_install);
+EXPORT_FUNC (ossddk_ac97_is_varrate);
+EXPORT_FUNC (ossddk_ac97_remove);
+EXPORT_FUNC (ossddk_ac97_set_ext_init);
+EXPORT_FUNC (ossddk_ac97_set_playrate);
+EXPORT_FUNC (ossddk_ac97_set_recrate);
+EXPORT_FUNC (ossddk_adev_get_devc);
+EXPORT_FUNC (ossddk_adev_get_dmapin);
+EXPORT_FUNC (ossddk_adev_get_dmapout);
+EXPORT_FUNC (ossddk_adev_get_flags);
+EXPORT_FUNC (ossddk_adev_get_label);
+EXPORT_FUNC (ossddk_adev_get_portc);
+EXPORT_FUNC (ossddk_adev_get_portc_play);
+EXPORT_FUNC (ossddk_adev_get_portc_record);
+EXPORT_FUNC (ossddk_adev_get_songname);
+EXPORT_FUNC (ossddk_adev_set_buflimits);
+EXPORT_FUNC (ossddk_adev_set_caps);
+EXPORT_FUNC (ossddk_adev_set_channels);
+EXPORT_FUNC (ossddk_adev_set_devc);
+EXPORT_FUNC (ossddk_adev_set_enable_flag);
+EXPORT_FUNC (ossddk_adev_set_flags);
+EXPORT_FUNC (ossddk_adev_set_formats);
+EXPORT_FUNC (ossddk_adev_set_label);
+EXPORT_FUNC (ossddk_adev_set_magic);
+EXPORT_FUNC (ossddk_adev_set_mixer);
+EXPORT_FUNC (ossddk_adev_set_portc);
+EXPORT_FUNC (ossddk_adev_set_portc_play);
+EXPORT_FUNC (ossddk_adev_set_portc_record);
+EXPORT_FUNC (ossddk_adev_set_portnum);
+EXPORT_FUNC (ossddk_adev_set_rates);
+EXPORT_FUNC (ossddk_adev_set_ratesource);
+EXPORT_FUNC (ossddk_adev_set_songname);
+EXPORT_FUNC (ossddk_adev_set_unloaded_flag);
+EXPORT_FUNC (ossddk_audio_inputintr);
+EXPORT_FUNC (ossddk_audio_outputintr);
+EXPORT_FUNC (ossddk_disable_device);
+EXPORT_FUNC (ossddk_dmap_get_buffsize);
+EXPORT_FUNC (ossddk_dmap_get_buffused);
+EXPORT_FUNC (ossddk_dmap_get_dmabuf);
+EXPORT_FUNC (ossddk_dmap_get_fragsize);
+EXPORT_FUNC (ossddk_dmap_get_numfrags);
+EXPORT_FUNC (ossddk_dmap_get_phys);
+EXPORT_FUNC (ossddk_dmap_get_private);
+EXPORT_FUNC (ossddk_dmap_get_qhead);
+EXPORT_FUNC (ossddk_dmap_get_qtail);
+EXPORT_FUNC (ossddk_dmap_set_buffsize);
+EXPORT_FUNC (ossddk_dmap_set_callback);
+EXPORT_FUNC (ossddk_dmap_set_dmabuf);
+EXPORT_FUNC (ossddk_dmap_set_fragsize);
+EXPORT_FUNC (ossddk_dmap_set_numfrags);
+EXPORT_FUNC (ossddk_dmap_set_phys);
+EXPORT_FUNC (ossddk_dmap_set_playerror);
+EXPORT_FUNC (ossddk_dmap_set_private);
+EXPORT_FUNC (ossddk_dmap_set_recerror);
+EXPORT_FUNC (ossddk_install_audiodev);
+EXPORT_FUNC (ossddk_install_mixer);
+EXPORT_FUNC (ossddk_mixer_create_control);
+EXPORT_FUNC (ossddk_mixer_create_group);
+EXPORT_FUNC (ossddk_mixer_get_devc);
+EXPORT_FUNC (ossddk_mixer_set_strings);
+EXPORT_FUNC (ossddk_mixer_touch);
+EXPORT_FUNC (ossddk_mixer_truncate);
+EXPORT_FUNC (ossddk_osdev_get_devc);
+EXPORT_FUNC (ossddk_register_device);
+EXPORT_FUNC (ossddk_unregister_device);
+#endif
+EXPORT_SYMBOL (osdev_set_major);
+EXPORT_SYMBOL (osdev_set_owner);
+EXPORT_SYMBOL (osdev_get_owner);
+EXPORT_SYMBOL (oss_create_pcidip);
+EXPORT_SYMBOL (touch_mixer);
+EXPORT_SYMBOL (oss_mixer_ext);
+EXPORT_SYMBOL (oss_request_major);
+EXPORT_SYMBOL (audio_engines);
+EXPORT_DATA (midi_devs);
+EXPORT_SYMBOL (mixer_devs);
+EXPORT_SYMBOL (mixer_devs_p);
+EXPORT_DATA (num_audio_engines);
+EXPORT_DATA (num_mididevs);
+EXPORT_SYMBOL (num_mixers);
+EXPORT_DATA (oss_timing_mutex);
+EXPORT_DATA (oss_num_cards);
+EXPORT_FUNC (oss_do_timing);
+EXPORT_FUNC (oss_do_timing2);
+EXPORT_FUNC (oss_timing_enter);
+EXPORT_FUNC (oss_timing_leave);
+#ifndef __arm__
+EXPORT_SYMBOL (__udivdi3);
+EXPORT_SYMBOL (__umoddi3);
+EXPORT_SYMBOL (__divdi3);
+#else
+EXPORT_SYMBOL (raise);
+#endif
+EXPORT_SYMBOL (oss_copy_from_user);
+EXPORT_SYMBOL (oss_copy_to_user);
+EXPORT_SYMBOL (osdev_set_irqparms);
+EXPORT_SYMBOL (osdev_get_irqparms);
+EXPORT_SYMBOL (osdev_get_nick);
+EXPORT_SYMBOL (osdev_get_instance);
+EXPORT_SYMBOL (oss_inc_refcounts);
+EXPORT_SYMBOL (oss_dec_refcounts);
+EXPORT_SYMBOL (oss_register_module);
+EXPORT_SYMBOL (oss_unregister_module);
+EXPORT_SYMBOL (oss_audio_reset);
+EXPORT_SYMBOL (oss_audio_start_syncgroup);
+EXPORT_SYMBOL (oss_encode_enum);
+EXPORT_SYMBOL (dmap_get_qlen);
+EXPORT_SYMBOL (num_audio_devfiles);
+EXPORT_SYMBOL (oss_audio_inc_byte_counter);
+EXPORT_SYMBOL (oss_audio_register_client);
+EXPORT_SYMBOL (audio_devfiles);
+EXPORT_FUNC (oss_get_cardinfo);
+EXPORT_SYMBOL (oss_pmalloc);
+EXPORT_SYMBOL (oss_add_audio_devlist);
+EXPORT_FUNC (oss_memblk_malloc);
+EXPORT_FUNC (oss_memblk_free);
+EXPORT_FUNC (oss_memblk_unalloc);
+EXPORT_DATA (oss_global_memblk);
+EXPORT_FUNC (oss_get_procinfo);
+EXPORT_DATA (mixer_muted);
+
+#ifdef CONFIG_OSS_MIDI
+EXPORT_FUNC (oss_midi_ioctl);
+EXPORT_FUNC (oss_midi_copy_timer);
+#endif
diff --git a/setup/Linux/oss/build/ossdip.h b/setup/Linux/oss/build/ossdip.h
new file mode 100644
index 0000000..811e70a
--- /dev/null
+++ b/setup/Linux/oss/build/ossdip.h
@@ -0,0 +1,10 @@
+/*
+ * Purpose: Definition of the _dev_info_t structure for Linux
+ */
+#ifndef OSSDIP_H
+#define OSSDIP_H
+struct _dev_info_t
+{
+ struct pci_dev *pcidev;
+};
+#endif
diff --git a/setup/Linux/oss/build/pci_wrapper.inc b/setup/Linux/oss/build/pci_wrapper.inc
new file mode 100644
index 0000000..e08ec3a
--- /dev/null
+++ b/setup/Linux/oss/build/pci_wrapper.inc
@@ -0,0 +1,93 @@
+/*
+ * Purpose: PCI wrapper routines for Linux
+ *
+ * This source file contains probe and remove routines for PCI devices.
+ * This code will be compiled in the target system.
+ */
+/*
+ * Copyright (C) 4Front Technologies 2005-2007. Released under GPL2 license.
+ */
+typedef struct
+{
+ struct pci_dev *pcidev;
+ oss_device_t *osdev;
+} dev_map_t;
+
+#define MAX_INSTANCE 10
+static dev_map_t dev_map[MAX_INSTANCE];
+static int n_devmap = 0;
+
+static int __devinit
+osspci_probe (struct pci_dev *pcidev, const struct pci_device_id *pciid)
+{
+ oss_device_t *osdev;
+ dev_info_t *dip;
+
+ if (n_devmap >= MAX_INSTANCE)
+ {
+ printk (KERN_ALERT "oss: Too many instances of " DRIVER_NICK);
+ return -ENOMEM;
+ }
+
+ if ((dip = oss_create_pcidip (pcidev)) == NULL)
+ return -ENOMEM;
+
+ if ((osdev =
+ osdev_create (dip, DRIVER_TYPE, instance++, DRIVER_NICK,
+ NULL)) == NULL)
+ {
+ return -ENOMEM;
+ }
+
+ osdev_set_owner (osdev, THIS_MODULE);
+
+ if (module_major == 0)
+ module_major = oss_request_major (osdev, 0, DRIVER_NICK);
+ if (module_major <= 0)
+ {
+ printk (KERN_ALERT "Failed to allocate major device for " DRIVER_NICK);
+ return -EIO;
+
+ }
+ osdev_set_major (osdev, module_major);
+
+ pci_enable_device (pcidev);
+ if (!DRIVER_ATTACH (osdev))
+ {
+ pci_disable_device (pcidev);
+ return -EIO;
+ }
+
+ dev_map[n_devmap].pcidev = pcidev;
+ dev_map[n_devmap++].osdev = osdev;
+ oss_audio_delayed_attach ();
+
+ return 0;
+}
+
+static void __devexit
+osspci_remove (struct pci_dev *pcidev)
+{
+ int i;
+ oss_device_t *osdev;
+
+ for (i = 0; i < n_devmap; i++)
+ if (dev_map[i].pcidev == pcidev)
+ {
+ osdev = dev_map[i].osdev;
+ if (!DRIVER_DETACH (osdev))
+ printk (KERN_ALERT DRIVER_NICK ": Unloading busy device\n");
+ pci_disable_device (dev_map[i].pcidev);
+ osdev_delete (osdev);
+
+ return;
+ }
+
+ printk (KERN_ALERT DRIVER_NICK ": Can't find the PCI device to detach\n");
+}
+
+void
+oss_pcie_init (oss_device_t * osdev, int flags)
+{
+ /* TODO: Do we need to do something here? */
+}
diff --git a/setup/Linux/oss/build/usb_wrapper.inc b/setup/Linux/oss/build/usb_wrapper.inc
new file mode 100644
index 0000000..ee199a7
--- /dev/null
+++ b/setup/Linux/oss/build/usb_wrapper.inc
@@ -0,0 +1,730 @@
+/*
+ * Purpose: Low level USB wrapper routines for Linux (2.6.x and later)
+ *
+ * This file contains the Linux specific USB support routines defined in udi.h
+ */
+/*
+ * Copyright (C) 4Front Technologies 2005-2007. Released under GPL2 license.
+ */
+#include "udi.h"
+
+#undef IO_DEBUG
+static const udi_usb_devinfo *known_devices = NULL;
+
+#define MAX_DEVICE_SLOTS 20
+
+int udi_usb_trace = 0;
+
+static udi_usb_driver *drv = NULL;
+extern void *oss_pmalloc (size_t sz);
+
+struct udi_usb_devc
+{
+ struct usb_device *usb_dev;
+ const struct usb_device_id *id;
+ const udi_usb_devinfo *udi_usb_dev;
+ char *devpath;
+
+ int enabled;
+
+ int vendor, product, class, subclass;
+ struct usb_interface *iface;
+ int iface_number;
+ char *dev_name;
+ char *altsetting_labels;
+ int default_altsetting;
+ unsigned int altsetting_mask;
+ udi_usb_driver *drv;
+ void *client_devc;
+ int num_altsettings;
+ int usb_version;
+ struct usb_host_interface *altsetting;
+
+};
+
+struct _udi_endpoint_handle_t
+{
+ unsigned char desc[32];
+};
+
+#define MAX_DEVC 32
+
+static udi_usb_devc usb_devc_list[MAX_DEVC] = { {0} };
+static int ndevs = 0;
+
+udi_endpoint_handle_t *
+udi_open_endpoint (udi_usb_devc * usbdev, void *ep_descr)
+{
+ return (udi_endpoint_handle_t *) ep_descr;
+}
+
+void
+udi_close_endpoint (udi_endpoint_handle_t * eph)
+{
+ // NOP
+}
+
+int
+udi_endpoint_get_num (udi_endpoint_handle_t * eph)
+{
+ return eph->desc[2] /* & 0x7f */;
+}
+
+#if 1
+static void
+dump_configs (struct usb_device *dev)
+{
+ int c;
+
+ printk ("#configs %d\n", dev->descriptor.bNumConfigurations);
+
+ for (c = 0; c < dev->descriptor.bNumConfigurations; c++)
+ {
+ int i, j, k;
+ struct usb_host_config *config = &dev->config[c];
+
+ printk ("\tConfig #%d - #interfaces=%d\n", c,
+ config->desc.bNumInterfaces);
+
+ for (j = 0; j < config->desc.bNumInterfaces; j++)
+ {
+ struct usb_interface *ifp = config->interface[j];
+ printk ("\t\tInterface #%d - altsettings=%d\n", j,
+ ifp->num_altsetting);
+
+ for (k = 0; k < ifp->num_altsetting; k++)
+ {
+ struct usb_host_interface *alt = &ifp->altsetting[k];
+ unsigned char *buf = alt->extra;
+
+ printk ("\t\t\tAlt setting #%d:\n", k);
+
+ for (i = 0; i < alt->extralen; i++)
+ {
+ if (!(i % 8))
+ {
+ if (i)
+ printk ("\n");
+ printk ("\t\t\t%04x: ", i);
+ }
+ printk ("%02x ", buf[i]);
+ }
+
+ printk ("\n");
+ }
+ }
+ }
+}
+#endif
+
+static int
+udi_attach_usbdev (struct usb_device *dev,
+ oss_device_t * osdev,
+ char *devpath,
+ struct usb_interface *iface,
+ const struct usb_device_id *id,
+ const udi_usb_devinfo * udi_usb_dev)
+{
+ int cfg_num, ep;
+
+ udi_usb_devc *devc = &usb_devc_list[ndevs];
+ struct usb_host_interface *alts;
+
+ if (ndevs >= MAX_DEVC)
+ {
+ printk ("OSS: Too many USB audio/midi devices\n");
+ return -ENODEV;
+ }
+
+ if (udi_usb_trace > 1)
+ printk ("OSS: Attaching USB device %x:%x/%d, class=%x:%x, name=%s\n",
+ dev->descriptor.idVendor, dev->descriptor.idProduct,
+ iface->altsetting[0].desc.bInterfaceNumber,
+ iface->altsetting[0].desc.bInterfaceClass,
+ iface->altsetting[0].desc.bInterfaceSubClass, udi_usb_dev->name);
+
+ devc->usb_dev = dev;
+ devc->id = id;
+ devc->udi_usb_dev = udi_usb_dev;
+
+ devc->vendor = dev->descriptor.idVendor;
+ devc->product = dev->descriptor.idProduct;
+ devc->usb_version = dev->descriptor.bcdUSB >> 8;
+ devc->class = iface->altsetting[0].desc.bInterfaceClass;
+ devc->subclass = iface->altsetting[0].desc.bInterfaceSubClass;
+ devc->iface_number = iface->altsetting[0].desc.bInterfaceNumber;
+ devc->iface = iface;
+ devc->dev_name = udi_usb_dev->name;
+ devc->devpath = devpath;
+ devc->num_altsettings = iface->num_altsetting;
+ devc->altsetting = iface->altsetting;
+
+ alts = &iface->altsetting[devc->num_altsettings - 1];
+ ep = 0;
+
+ if (alts->desc.bNumEndpoints > 1)
+ ep = 1;
+
+ if (udi_usb_trace > 2)
+ {
+ int i;
+
+ for (i = 0; i < alts->desc.bNumEndpoints; i++)
+ {
+ printk ("Endpoint: %02x\n",
+ alts->endpoint[i].desc.bEndpointAddress);
+ }
+ }
+
+ cfg_num = 0;
+
+ devc->enabled = 1;
+ devc->drv = drv;
+
+ if (udi_usb_trace > 2)
+ dump_configs (dev);
+
+ if ((devc->client_devc = drv->attach (devc, osdev)) == NULL)
+ {
+ return -EIO;
+ }
+
+ ndevs++;
+
+ usb_set_intfdata (iface, devc);
+ return 0;
+}
+
+static char *prev_devices[32] = { NULL };
+static int nprev_devices = 0;
+
+static int
+udi_usb_probe (struct usb_interface *iface, const struct usb_device_id *id)
+{
+ int i;
+ static int ncalls = 0;
+ oss_device_t *osdev = NULL;
+ dev_info_t *dip = NULL; // TODO
+
+ char nick[32];
+ int inst = 0;
+
+ struct usb_device *dev = interface_to_usbdev (iface);
+
+ if (ncalls++ > 100)
+ return -EIO;
+
+ sprintf (nick, "usb%04x%04x-", dev->descriptor.idVendor,
+ dev->descriptor.idProduct);
+
+/*
+ * Find out how many instances of this device (ID) are already attached.
+ */
+
+ for (i = 0; i < nprev_devices; i++)
+ {
+ if (strcmp (nick, prev_devices[i]) == 0)
+ {
+ inst++;
+ }
+ }
+
+ prev_devices[nprev_devices] = oss_pmalloc (strlen (nick) + 1);
+ strcpy (prev_devices[nprev_devices], nick);
+ if (nprev_devices < 32)
+ nprev_devices++;
+
+ if ((osdev = osdev_create (dip, DRV_USB, inst, nick, NULL)) == NULL)
+ {
+ return -ENOMEM;
+ }
+ osdev_set_owner (osdev, THIS_MODULE);
+ osdev_set_major (osdev, usb_major);
+
+ i = 0;
+ if (udi_usb_trace > 1)
+ printk ("\n\nProbing dev=%s id=%x:%x/%d\n", dev->devpath,
+ dev->descriptor.idVendor,
+ dev->descriptor.idProduct,
+ iface->altsetting[0].desc.bInterfaceNumber);
+
+ while (i >= 0 && known_devices[i].vendor >= 0)
+ {
+ if (dev->descriptor.idVendor == known_devices[i].vendor &&
+ dev->descriptor.idProduct == known_devices[i].product)
+ {
+ int ret;
+ const udi_usb_devinfo *d = &known_devices[i];
+ ret = udi_attach_usbdev (dev, osdev, dev->devpath, iface, id, d);
+ return ret;
+ }
+ else
+ i++;
+ }
+
+/* Try the "generic" device */
+ {
+ int ret;
+ const udi_usb_devinfo *d = &known_devices[i];
+ ret = udi_attach_usbdev (dev, osdev, dev->devpath, iface, id, d);
+ return ret;
+ }
+
+ return -ENODEV;
+}
+
+static void
+udi_usb_disconnect (struct usb_interface *iface)
+{
+ udi_usb_devc *devc = usb_get_intfdata (iface);
+ //struct usb_device *dev = interface_to_usbdev (iface);
+
+ if (devc == (udi_usb_devc *) - 1)
+ return;
+
+ if (!devc->enabled)
+ return;
+
+ if (udi_usb_trace > 0)
+ printk ("OSS: Disconnect USB device %x:%x %s\n", devc->vendor,
+ devc->product, devc->udi_usb_dev->name);
+ devc->drv->disconnect (devc->client_devc);
+ devc->enabled = 0;
+}
+
+static struct usb_driver oss_usb = {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+owner:THIS_MODULE,
+#endif
+name:"oss_usb",
+probe:udi_usb_probe,
+disconnect:udi_usb_disconnect,
+id_table:udi_usb_table
+};
+
+static int udi_usb_installed = 0;
+
+int
+udi_attach_usbdriver (oss_device_t * osdev, const udi_usb_devinfo * devlist,
+ udi_usb_driver * driver)
+{
+ drv = driver;
+ known_devices = devlist;
+ return 1;
+}
+
+void
+udi_unload_usbdriver (oss_device_t * osdev)
+{
+}
+
+/*
+ * Device access routines
+ */
+
+int
+udi_usbdev_get_class (udi_usb_devc * usbdev)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+
+ return devc->class;
+}
+
+int
+udi_usbdev_get_subclass (udi_usb_devc * usbdev)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+
+ return devc->subclass;
+}
+
+int
+udi_usbdev_get_vendor (udi_usb_devc * usbdev)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+
+ return devc->vendor;
+}
+
+int
+udi_usbdev_get_product (udi_usb_devc * usbdev)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+
+ return devc->product;
+}
+
+int
+udi_usbdev_get_inum (udi_usb_devc * usbdev)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+
+ return devc->iface_number;
+}
+
+int
+udi_usbdev_set_interface (udi_usb_devc * usbdev, int inum, int altset)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+
+ return usb_set_interface (devc->usb_dev, inum, altset);
+}
+
+unsigned char *
+udi_usbdev_get_endpoint (udi_usb_devc * usbdev, int altsetting, int n,
+ int *len)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+ int num_endpoints;
+ struct usb_device *dev;
+ struct usb_host_interface *alts;
+ struct usb_interface *iface;
+
+ dev = devc->usb_dev;
+ iface = devc->iface;
+
+ if (altsetting >= devc->num_altsettings)
+ return NULL;
+
+ alts = &iface->altsetting[altsetting];
+
+ num_endpoints = alts->desc.bNumEndpoints;
+
+ if (n >= num_endpoints)
+ return NULL;
+
+ *len = alts->endpoint[n].desc.bLength;
+ return (unsigned char *) &alts->endpoint[n].desc;
+}
+
+int
+udi_usbdev_get_num_altsettings (udi_usb_devc * usbdev)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+
+ return devc->num_altsettings;
+}
+
+int
+udi_usbdev_get_usb_version (udi_usb_devc * usbdev)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+
+ return devc->usb_version;
+}
+
+unsigned char *
+udi_usbdev_get_altsetting (udi_usb_devc * usbdev, int n, int *size)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+ struct usb_host_interface *alt;
+
+ if (n < 0 || n >= devc->num_altsettings)
+ {
+ /* printk("udi usb: Bad altsetting %d (%d)\n", n, n >= devc->num_altsettings); */
+ return NULL;
+ }
+
+ alt = &devc->altsetting[n];
+
+ *size = alt->extralen;
+ return alt->extra;
+}
+
+char *
+udi_usbdev_get_name (udi_usb_devc * usbdev)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+
+ return devc->dev_name == NULL ? "Unknown" : devc->dev_name;
+}
+
+
+char *
+udi_usbdev_get_altsetting_labels (udi_usb_devc * usbdev, int if_num, int *default_alt, unsigned int *mask)
+{
+ int i;
+
+ *default_alt=1;
+ *mask=0xffffffff;
+
+ if (usbdev->udi_usb_dev == NULL) /* No device definitions available */
+ {
+ return NULL;
+ }
+
+ for (i=0;usbdev->udi_usb_dev->altsettings[i].altsetting_labels!=NULL;i++)
+ if (i==if_num)
+ {
+ *default_alt = usbdev->udi_usb_dev->altsettings[i].default_altsetting;
+ *mask = usbdev->udi_usb_dev->altsettings[i].altsetting_mask;
+ if (*mask==0)
+ *mask=0xffffffff;
+ return usbdev->udi_usb_dev->altsettings[i].altsetting_labels;
+ }
+
+ return NULL; /* Not found */
+}
+
+char *
+udi_usbdev_get_string (udi_usb_devc * usbdev, int ix)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+ static char str[100];
+ int err;
+
+ if (ix == 0)
+ return NULL;
+
+ if ((err = usb_string (devc->usb_dev, ix, str, sizeof (str) - 1)) != 0)
+ {
+ return NULL;
+ }
+
+ return str;
+}
+
+char *
+udi_usbdev_get_devpath (udi_usb_devc * usbdev)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+
+ return devc->devpath;
+}
+
+int
+udi_usb_snd_control_msg (udi_usb_devc * usbdev, unsigned int endpoint,
+ unsigned char rq,
+ unsigned char rqtype,
+ unsigned short value,
+ unsigned short index,
+ void *buf, int len, int timeout)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+ int err;
+
+ if (!devc->enabled)
+ return -EPIPE;
+
+ if (timeout < 0)
+ timeout = 0;
+
+#ifdef IO_DEBUG
+ printk ("Snd %x (%x) rq=%x, rt=%x, v=%x, ix=%x, l=%d %02x %02x\n",
+ devc->usb_dev,
+ usb_sndctrlpipe (devc->usb_dev, endpoint),
+ rq, rqtype, value, index, len, b[0], b[1]);
+#endif
+ err = usb_control_msg (devc->usb_dev,
+ usb_sndctrlpipe (devc->usb_dev, endpoint),
+ rq, rqtype, value, index, buf, len, timeout);
+#ifdef IO_DEBUG
+ if (err < 0)
+ printk ("Usb write error %d\n", err);
+#endif
+
+ return err;
+}
+
+int
+udi_usb_rcv_control_msg (udi_usb_devc * usbdev, unsigned int endpoint,
+ unsigned char rq,
+ unsigned char rqtype,
+ unsigned short value,
+ unsigned short index,
+ void *buf, int len, int timeout)
+{
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+ int err;
+
+ if (!devc->enabled)
+ return -EPIPE;
+
+ if (timeout < 0)
+ timeout = 0;
+
+#ifdef IO_DEBUG
+ printk ("Rcv %x (%x) rq=%x, rt=%x, v=%x, ix=%x, l=%d\n",
+ devc->usb_dev,
+ (unsigned int) usb_rcvctrlpipe (devc->usb_dev, endpoint),
+ rq, rqtype | USB_DIR_IN, value, index, len);
+#endif
+ err = usb_control_msg (devc->usb_dev,
+ (unsigned int) usb_rcvctrlpipe (devc->usb_dev,
+ endpoint), rq,
+ rqtype | USB_DIR_IN, value, index, buf, len,
+ timeout);
+#ifdef IO_DEBUG
+ if (err < 0)
+ printk ("Usb read error %d\n", err);
+ else
+ printk ("Got %02x %02x\n", b[0], b[1]);
+#endif
+
+ return err;
+}
+
+/* Request stuff */
+
+struct udi_usb_request
+{
+ struct urb *urb;
+ udi_usb_complete_func_t callback;
+ void *callback_arg;
+ int active;
+ void *data;
+};
+
+udi_usb_request_t
+ * udi_usb_alloc_request (udi_usb_devc * usbdev, udi_endpoint_handle_t * eph,
+ int nframes, int xfer_type)
+{
+ udi_usb_request_t *rq;
+ udi_usb_devc *devc = (udi_usb_devc *) usbdev;
+
+ if ((rq = kmalloc (sizeof (*rq), GFP_KERNEL)) == NULL)
+ {
+ printk ("udi_usb_alloc_request: Out of memory\n");
+ return NULL;
+ }
+
+ memset (rq, 0, sizeof (*rq));
+
+ if ((rq->urb = usb_alloc_urb (nframes, 0)) == NULL)
+ {
+ kfree (rq);
+ printk ("udi_usb_alloc_request: Failed to allocate URB\n");
+ return NULL;
+ }
+
+ rq->urb->dev = devc->usb_dev;
+ rq->urb->number_of_packets = nframes;
+ rq->active = 0;
+
+ return rq;
+}
+
+void
+udi_usb_free_request (udi_usb_request_t * request)
+{
+ if (request == NULL)
+ return;
+
+ udi_usb_cancel_request (request);
+
+ usb_free_urb (request->urb);
+ kfree (request);
+}
+
+unsigned char *
+udi_usb_request_actdata (udi_usb_request_t * request)
+{
+ return request->data;
+}
+
+static void
+complete_func (struct urb *urb)
+{
+ udi_usb_request_t *request = urb->context;
+
+ request->active = 0;
+ request->callback (request, request->callback_arg);
+}
+
+int
+udi_usb_submit_request (udi_usb_request_t * request,
+ udi_usb_complete_func_t callback, void *callback_arg,
+ udi_endpoint_handle_t * eph, int xfer_type,
+ void *data, int data_len)
+{
+ struct urb *urb;
+ struct usb_device *d;
+ int i, err;
+ int endpoint = eph->desc[2] & 0x7f;
+
+ if (request == NULL)
+ return -EINVAL;
+
+ urb = request->urb;
+ d = urb->dev;
+ request->callback = callback;
+ request->callback_arg = callback_arg;
+ request->data = data;
+ urb->complete = (usb_complete_t) complete_func;
+ urb->context = request;
+ urb->transfer_buffer = data;
+
+ for (i = 0; i < urb->number_of_packets; i++)
+ {
+ urb->iso_frame_desc[i].status = 0;
+ urb->iso_frame_desc[i].length = data_len;
+ urb->iso_frame_desc[i].offset = i * data_len;
+ }
+
+ urb->transfer_buffer_length = urb->actual_length = data_len;
+
+ switch (xfer_type)
+ {
+ case UDI_USBXFER_ISO_WRITE:
+ urb->pipe = usb_sndisocpipe (urb->dev, endpoint);
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->interval = 1;
+ break;
+
+ case UDI_USBXFER_ISO_READ:
+ urb->pipe = usb_rcvisocpipe (urb->dev, endpoint);
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->interval = 1;
+ break;
+
+ case UDI_USBXFER_BULK_READ:
+ usb_fill_bulk_urb (urb, d, usb_rcvbulkpipe (d, endpoint),
+ data, data_len,
+ (usb_complete_t) complete_func, request);
+ break;
+
+ case UDI_USBXFER_INTR_READ:
+ usb_fill_int_urb (urb, d, usb_rcvintpipe (d, endpoint),
+ data, data_len,
+ (usb_complete_t) complete_func, request, 8);
+ break;
+
+ case UDI_USBXFER_BULK_WRITE:
+ usb_fill_bulk_urb (urb, d, usb_sndbulkpipe (d, endpoint),
+ data, data_len,
+ (usb_complete_t) complete_func, request);
+ break;
+
+ default:
+ printk ("udi usb: Bad xfer type %d\n", xfer_type);
+ return -EINVAL;
+ }
+
+#ifdef SLAB_ATOMIC
+ if ((err = usb_submit_urb (request->urb, SLAB_ATOMIC)) >= 0)
+ request->active = 1;
+#else
+ /*
+ * Linux 2.6.20 and later don't have SLAB_ATOMIC
+ */
+ if ((err = usb_submit_urb (request->urb, GFP_ATOMIC)) >= 0)
+ request->active = 1;
+#endif
+ return err;
+}
+
+int
+udi_usb_request_actlen (udi_usb_request_t * request)
+{
+ return request->urb->actual_length;
+}
+
+void
+udi_usb_cancel_request (udi_usb_request_t * request)
+{
+ if (request == NULL || !request->active)
+ return;
+
+ usb_kill_urb (request->urb);
+
+}
diff --git a/setup/Linux/oss/cuckoo/Makefile b/setup/Linux/oss/cuckoo/Makefile
new file mode 100644
index 0000000..da9013b
--- /dev/null
+++ b/setup/Linux/oss/cuckoo/Makefile
@@ -0,0 +1,23 @@
+ccflags-y += -I/usr/lib/oss
+
+ifneq ($(KERNELRELEASE),)
+
+ obj-m := cuckoo.o cuckoo_pcm.o cuckoo_mixer.o
+
+else
+
+ KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+ PWD := $(shell pwd)
+
+default:
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+endif
+
+install: default
+ cp *.ko /lib/modules/`uname -r`/kernel/oss
+ depmod -a
+
+clean:
+ rm -f *.o *.ko *.mod.c *.mod.o .*.cmd core core.* x y z
+ rm -rf .tmp_versions Modules.symvers
diff --git a/setup/Linux/oss/cuckoo/checksum.h b/setup/Linux/oss/cuckoo/checksum.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/setup/Linux/oss/cuckoo/checksum.h
diff --git a/setup/Linux/oss/cuckoo/cuckoo.c b/setup/Linux/oss/cuckoo/cuckoo.c
new file mode 100644
index 0000000..b7a04a6
--- /dev/null
+++ b/setup/Linux/oss/cuckoo/cuckoo.c
@@ -0,0 +1,251 @@
+/*
+ * This software module makes it possible to use Open Sound System for Linux
+ * (the _professional_ version) as a low level driver source for ALSA.
+ *
+ * Copyright (C) 2004-2009 Hannu Savolainen (hannu@opensound.com).
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+/*
+ * !!!!!!!!!!!!!!!!!!!! Important !!!!!!!!!!!!!!!!!!
+ *
+ * If this file doesn't compile, you must not try to resolve the problem
+ * without perfect understanding of internals of Linux kernel, ALSA and
+ * Open Sound System.
+ *
+ * Instead you need to check that you are using the version of this file
+ * that matches the versions of ALSA, OSS and Linux you are currently using.
+ */
+
+#ifndef KBUILD_MODNAME
+#define KBUILD_MODNAME cuckoo
+#endif
+
+#include "cuckoo.h"
+
+#include "./checksum.h"
+
+#ifdef VERMAGIC_STRING
+static const char vermagic[] = VERMAGIC_STRING;
+#endif
+
+MODULE_AUTHOR ("Hannu Savolainen <hannu@opensound.com>");
+MODULE_LICENSE ("GPL v2");
+//MODULE_CLASSES("{sound}");
+MODULE_DESCRIPTION ("OSS low level driver interface for ALSA");
+
+#define CUCKOO_MAXCARD SNDRV_CARDS
+static int index[CUCKOO_MAXCARD] = SNDRV_DEFAULT_IDX;
+static char *id[CUCKOO_MAXCARD] = SNDRV_DEFAULT_STR;
+static int enable[CUCKOO_MAXCARD] = SNDRV_DEFAULT_ENABLE_PNP;
+
+static int
+snd_cuckoo_free (cuckoo_t * chip)
+{
+ // TODO
+ return 0;
+}
+
+static int
+snd_cuckoo_dev_free (snd_device_t * device)
+{
+ cuckoo_t *cuckoo = (cuckoo_t *) device->device_data;
+ return snd_cuckoo_free (cuckoo);
+}
+
+static int
+snd_cuckoo_create (snd_card_t * card, int osscard, cuckoo_t ** rchip)
+{
+ cuckoo_t *chip;
+ int err;
+
+ static snd_device_ops_t ops = {
+ .dev_free = snd_cuckoo_dev_free
+ };
+
+ *rchip = NULL;
+
+ if ((chip = (cuckoo_t *) kmalloc (sizeof (cuckoo_t), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ chip->card = card;
+ chip->osscard = osscard;
+ chip->ncapture = chip->nplay = chip->npcm = 0;
+
+ if ((err = snd_device_new (card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0)
+ {
+ snd_cuckoo_free (chip);
+ return err;
+ }
+
+ *rchip = chip;
+ return 0;
+}
+
+static snd_card_t *cards[SNDRV_CARDS];
+static int ncards = 0;
+
+int
+init_module (void)
+{
+ int err;
+ int dev, cardno;
+ char tmp[100];
+ int pass;
+
+#if 0
+ // TODO
+ if ((err = udi_connect (WRAPPER_VERSION)) < 0)
+ return err;
+
+ if (strcmp (oss_checksum, cuckoo_checksum) != 0)
+ {
+ printk
+ ("cuckoo: Error OSS incompatibility problem. Please recompile.\n");
+ return -EIO;
+ }
+#endif
+
+ for (pass = 0; pass < 2; pass++)
+ {
+ cardno = -1;
+
+ for (dev = 0; dev < num_audio_engines; dev++)
+ {
+ adev_p adev = audio_engines[dev];
+ cuckoo_t *chip;
+ snd_card_t *card = NULL;
+
+ if (pass == 0)
+ {
+ // Ignore non-virtual devices
+ if (!(adev->flags & ADEV_VIRTUAL))
+ continue;
+ }
+ else
+ {
+ // Ignore virtual devices
+ if ((adev->flags & ADEV_VIRTUAL))
+ continue;
+ }
+
+ if (adev->card_number < 0)
+ {
+ printk ("cuckoo: Ignored audio device %d - %s\n", dev,
+ adev->name);
+ continue;
+ }
+
+ if (adev->card_number != cardno)
+ {
+ oss_card_info cd;
+
+ cardno = adev->card_number;
+
+ if (oss_get_cardinfo (cardno, &cd) < 0)
+ {
+ printk ("oss_get_cardinfo(%d) failed\n", cardno);
+ continue;
+ }
+
+ // printk("Card %d: %s/%s\n", cardno, cd.shortname, cd.longname);
+ printk ("Card %d: %s/%s\n", cardno, cd.shortname, cd.longname);
+
+ if (ncards >= CUCKOO_MAXCARD)
+ {
+ printk
+ ("Cuckoo: Too many audio devices (%d), only %d supported. by ALSA.\n",
+ num_audio_engines, CUCKOO_MAXCARD);
+ return -EIO;
+ }
+
+ if (!enable[ncards])
+ {
+ printk ("cuckoo: Device was not enabled (yet)\n");
+ return -EIO;
+ }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+ if ((card =
+ snd_card_new (index[ncards], id[ncards], THIS_MODULE,
+ 0)) == NULL)
+#else
+ if (
+ snd_card_create (index[ncards], id[ncards], THIS_MODULE,
+ 0, &card) != 0)
+#endif
+ {
+ printk ("cuckoo: Can't create a card instance\n");
+ return -EIO;
+ }
+
+ if ((err = snd_cuckoo_create (card, cardno, &chip)) < 0)
+ {
+ printk ("cuckoo: Couldn't create a chip instance (%d)\n",
+ err);
+ snd_card_free (card);
+ return err;
+ }
+
+#define oss_version_string "v4.x" // TODO
+ sprintf (tmp, "OSS %s", oss_version_string);
+ strlcpy (card->driver, tmp);
+ strlcpy (card->shortname, cd.shortname);
+ strlcpy (card->longname, cd.longname);
+
+ if ((err = install_pcm_instances (chip, cardno)) < 0)
+ return err;
+
+ if ((err = install_mixer_instances (chip, cardno)) < 0)
+ return err;
+
+ // if ((err=install_midiport_instances(chip, cardno))<0)
+ // return err;
+
+ if ((err = snd_card_register (card)) < 0)
+ {
+ printk ("cuckoo: Couldn't register card(%s) err=%d\n",
+ card->shortname, err);
+ continue; // TODO: Should handle this in more intelligent way
+
+ snd_card_free (card);
+ return err;
+ }
+
+ cards[ncards++] = card;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void
+cleanup_module (void)
+{
+ int i;
+
+ for (i = 0; i < ncards; i++)
+ snd_card_free (cards[i]);
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,5))
+#undef unix
+struct module __this_module
+ __attribute__ ((section (".gnu.linkonce.this_module"))) =
+{
+ .name = __stringify (KBUILD_MODNAME),.init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module
+#endif
+};
+#endif
diff --git a/setup/Linux/oss/cuckoo/cuckoo.h b/setup/Linux/oss/cuckoo/cuckoo.h
new file mode 100644
index 0000000..3df2966
--- /dev/null
+++ b/setup/Linux/oss/cuckoo/cuckoo.h
@@ -0,0 +1,171 @@
+/*
+ * This software module makes it possible to use Open Ssund System for Linux
+ * (the _professional_ version) as a low level driver source for ALSA.
+ *
+ * Copyright (C) 2004-2006 Hannu Savolainen (hannu@voimakentta.net).
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+#define _KERNEL
+
+/*
+ * !!!!!!!!!!!!!!!!!!!! Important !!!!!!!!!!!!!!!!!!
+ *
+ * If this file doesn't compile, you must not try to resolve the problem
+ * without perfect understanding of internals of Linux kernel, ALSA and
+ * Open Sound System.
+ *
+ * Instead you need to check that you are using the version of this file
+ * that matches the versions of ALSA, OSS and Linux you are currently using.
+ */
+
+#define _KERNEL
+#include "../include/sys/soundcard.h"
+
+#include <linux/version.h>
+
+#define _LOOSE_KERNEL_NAMES
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18)
+#include <linux/config.h>
+#else
+#include <linux/autoconf.h>
+#endif
+
+#if !defined(__SMP__) && defined(CONFIG_SMP)
+#define __SMP__
+#endif
+#include <linux/module.h>
+
+#include <stdarg.h>
+
+extern int oss_get_cardinfo (int cardnum, oss_card_info * ci); /* from oss_config.h */
+
+#include <linux/param.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/fcntl.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <linux/pci.h>
+#include <linux/apm_bios.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/poll.h>
+
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+//#include <asm/mach-default/irq_vectors.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+
+struct _oss_mutex_t
+{
+ /* Caution! This definition must match Linux/osscore.c */
+ spinlock_t lock;
+};
+
+#define audio_devs dummy_audio_devs
+
+#include "../include/internals/oss_exports.h"
+#include "../build/wrap.h"
+#include "../include/internals/ossddk.h"
+
+typedef struct oss_wait_queue oss_wait_queue_t; /* This must match oss_config.h */
+
+#include "../include/internals/ossddk.h"
+
+//#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+
+#include "../build/osscore_symbols.inc"
+
+#define SNDRV_GET_ID
+#include <sound/initval.h>
+
+typedef caddr_t ioctl_arg;
+typedef char snd_rw_buf;
+
+typedef int sound_os_info;
+
+#define WR_BUF_CONST const
+
+#include "../include/internals/audio_core.h"
+#include "../include/internals/mixer_core.h"
+
+typedef struct _snd_cuckoo cuckoo_t, chip_t;
+
+typedef struct
+{
+ adev_p adev;
+} cuckoo_pcm_t;
+
+#define MAX_OSSPCM 24 // Max # of PCM devices/card instance
+
+#if 1
+// Older ALSA versions used to define these...
+typedef struct snd_card snd_card_t;
+typedef struct snd_pcm snd_pcm_t;
+typedef struct snd_rawmidi snd_rawmidi_t;
+typedef struct snd_rawmidi_substream snd_rawmidi_substream_t;
+typedef struct snd_rawmidi_ops snd_rawmidi_ops_t;
+typedef struct snd_kcontrol snd_kcontrol_t;
+typedef struct snd_kcontrol_new snd_kcontrol_new_t;
+typedef struct snd_ctl_elem_info snd_ctl_elem_info_t;
+typedef struct snd_ctl_elem_value snd_ctl_elem_value_t;
+typedef struct snd_pcm_substream snd_pcm_substream_t;
+typedef struct snd_pcm_hardware snd_pcm_hardware_t;
+typedef struct snd_pcm_runtime snd_pcm_runtime_t;
+typedef struct snd_pcm_hw_params snd_pcm_hw_params_t;
+typedef struct snd_pcm_ops snd_pcm_ops_t;
+typedef struct snd_device snd_device_t;
+typedef struct snd_device_ops snd_device_ops_t;
+#endif
+
+struct _snd_cuckoo
+{
+ snd_card_t *card;
+ snd_pcm_t *pcm[MAX_OSSPCM];
+ adev_p play_adev[MAX_OSSPCM], capture_adev[MAX_OSSPCM];
+ int osscard;
+ int nplay, ncapture, npcm;
+};
+
+#define cuckoo_t_magic 0xaabbccdd
+#define chip__tmagic cuckoo_t_magic
+
+//#define OPEN_READ PCM_ENABLE_INPUT
+//#define OPEN_WRITE PCM_ENABLE_OUTPUT
+
+extern int install_mixer_instances (cuckoo_t * chip, int cardno);
+extern int install_midiport_instances (cuckoo_t * chip, int cardno);
+extern int install_pcm_instances (cuckoo_t * chip, int cardno);
+
+// Disable locking for now
+#define udi_spin_lock_irqsave(a, b) *(b)=0
+#define udi_spin_unlock_irqrestore(a, b)
+
+#define strlcpy(a, b) {strncpy(a, b, sizeof(a)-1);a[sizeof(a)-1]=0;}
diff --git a/setup/Linux/oss/cuckoo/cuckoo_midi.c b/setup/Linux/oss/cuckoo/cuckoo_midi.c
new file mode 100644
index 0000000..949379b
--- /dev/null
+++ b/setup/Linux/oss/cuckoo/cuckoo_midi.c
@@ -0,0 +1,310 @@
+/*
+ * This software module makes it possible to use Open Sound System for Linux
+ * (the _professional_ version) as a low level driver source for ALSA.
+ *
+ * Copyright (C) 2004 Hannu Savolainen (hannu@voimakentta.net).
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+/*
+ * !!!!!!!!!!!!!!!!!!!! Important !!!!!!!!!!!!!!!!!!
+ *
+ * If this file doesn't compile, you must not try to resolve the problem
+ * without perfect understanding of internals of Linux kernel, ALSA and
+ * Open Sound System.
+ *
+ * Instead you need to check that you are using the version of this file
+ * that matches the versions of ALSA, OSS and Linux you are currently using.
+ */
+
+#include "cuckoo.h"
+#include <sound/rawmidi.h>
+#include <midi_core.h>
+
+static snd_rawmidi_t *rmidis[256] = { NULL };
+
+static int
+cuckoo_uart_input_open (snd_rawmidi_substream_t * substream)
+{
+#if 0
+ mpu401_t *mpu;
+ int err;
+
+ mpu =
+ snd_magic_cast (mpu401_t, substream->rmidi->private_data, return -ENXIO);
+ if (mpu->open_input && (err = mpu->open_input (mpu)) < 0)
+ return err;
+ if (!test_bit (MPU401_MODE_BIT_OUTPUT, &mpu->mode))
+ {
+ cuckoo_uart_cmd (mpu, MPU401_RESET, 1);
+ cuckoo_uart_cmd (mpu, MPU401_ENTER_UART, 1);
+ }
+ mpu->substream_input = substream;
+ atomic_set (&mpu->rx_loop, 1);
+ set_bit (MPU401_MODE_BIT_INPUT, &mpu->mode);
+#endif
+ return 0;
+}
+
+static int
+cuckoo_uart_output_open (snd_rawmidi_substream_t * substream)
+{
+ int dev;
+
+ dev = (int) substream->rmidi->private_data;
+
+ printk ("Output open %d\n", dev);
+
+ return -EIO;
+#if 0
+ mpu401_t *mpu;
+ int err;
+ if (mpu->open_output && (err = mpu->open_output (mpu)) < 0)
+ return err;
+ if (!test_bit (MPU401_MODE_BIT_INPUT, &mpu->mode))
+ {
+ cuckoo_uart_cmd (mpu, MPU401_RESET, 1);
+ cuckoo_uart_cmd (mpu, MPU401_ENTER_UART, 1);
+ }
+ mpu->substream_output = substream;
+ atomic_set (&mpu->tx_loop, 1);
+ set_bit (MPU401_MODE_BIT_OUTPUT, &mpu->mode);
+#endif
+ return 0;
+}
+
+static int
+cuckoo_uart_input_close (snd_rawmidi_substream_t * substream)
+{
+#if 0
+ mpu401_t *mpu;
+
+ mpu =
+ snd_magic_cast (mpu401_t, substream->rmidi->private_data, return -ENXIO);
+ clear_bit (MPU401_MODE_BIT_INPUT, &mpu->mode);
+ mpu->substream_input = NULL;
+ if (!test_bit (MPU401_MODE_BIT_OUTPUT, &mpu->mode))
+ cuckoo_uart_cmd (mpu, MPU401_RESET, 0);
+ if (mpu->close_input)
+ mpu->close_input (mpu);
+#endif
+ return 0;
+}
+
+static int
+cuckoo_uart_output_close (snd_rawmidi_substream_t * substream)
+{
+#if 0
+ mpu401_t *mpu;
+
+ mpu =
+ snd_magic_cast (mpu401_t, substream->rmidi->private_data, return -ENXIO);
+ clear_bit (MPU401_MODE_BIT_OUTPUT, &mpu->mode);
+ mpu->substream_output = NULL;
+ if (!test_bit (MPU401_MODE_BIT_INPUT, &mpu->mode))
+ cuckoo_uart_cmd (mpu, MPU401_RESET, 0);
+ if (mpu->close_output)
+ mpu->close_output (mpu);
+#endif
+ return 0;
+}
+
+static void
+cuckoo_uart_input_trigger (snd_rawmidi_substream_t * substream, int up)
+{
+#if 0
+ unsigned long flags;
+ mpu401_t *mpu;
+ int max = 64;
+
+ mpu = snd_magic_cast (mpu401_t, substream->rmidi->private_data, return);
+ if (up)
+ {
+ if (!test_and_set_bit (MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
+ {
+ /* first time - flush FIFO */
+ while (max-- > 0)
+ mpu->read (mpu, MPU401D (mpu));
+ if (mpu->irq < 0)
+ cuckoo_uart_add_timer (mpu, 1);
+ }
+
+ /* read data in advance */
+ /* prevent double enter via rawmidi->event callback */
+ if (atomic_dec_and_test (&mpu->rx_loop))
+ {
+ local_irq_save (flags);
+ if (spin_trylock (&mpu->input_lock))
+ {
+ cuckoo_uart_input_read (mpu);
+ spin_unlock (&mpu->input_lock);
+ }
+ local_irq_restore (flags);
+ }
+ atomic_inc (&mpu->rx_loop);
+ }
+ else
+ {
+ if (mpu->irq < 0)
+ cuckoo_uart_remove_timer (mpu, 1);
+ clear_bit (MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
+ }
+#endif
+}
+
+#if 0
+static void
+cuckoo_uart_input_read (void *mpu)
+{
+ int max = 128;
+ unsigned char byte;
+
+ while (max-- > 0)
+ {
+ if (cuckoo_input_avail (mpu))
+ {
+ byte = mpu->read (mpu, MPU401D (mpu));
+ if (test_bit (MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
+ snd_rawmidi_receive (mpu->substream_input, &byte, 1);
+ }
+ else
+ {
+ break; /* input not available */
+ }
+ }
+}
+#endif
+
+#if 0
+static void
+cuckoo_uart_output_write (void *mpu)
+{
+ unsigned char byte;
+ int max = 256, timeout;
+
+ do
+ {
+ if (snd_rawmidi_transmit_peek (mpu->substream_output, &byte, 1) == 1)
+ {
+ for (timeout = 100; timeout > 0; timeout--)
+ {
+ if (cuckoo_output_ready (mpu))
+ {
+ mpu->write (mpu, byte, MPU401D (mpu));
+ snd_rawmidi_transmit_ack (mpu->substream_output, 1);
+ break;
+ }
+ }
+ if (timeout == 0)
+ break; /* Tx FIFO full - try again later */
+ }
+ else
+ {
+ cuckoo_uart_remove_timer (mpu, 0);
+ break; /* no other data - leave the tx loop */
+ }
+ }
+ while (--max > 0);
+}
+#endif
+
+static void
+cuckoo_uart_output_trigger (snd_rawmidi_substream_t * substream, int up)
+{
+ int dev;
+
+ dev = (int) substream->rmidi->private_data;
+ printk ("Output trigger %d\n", dev);
+#if 0
+ if (up)
+ {
+ set_bit (MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
+
+ /* try to add the timer at each output trigger,
+ * since the output timer might have been removed in
+ * cuckoo_uart_output_write().
+ */
+ cuckoo_uart_add_timer (mpu, 0);
+
+ /* output pending data */
+ /* prevent double enter via rawmidi->event callback */
+ if (atomic_dec_and_test (&mpu->tx_loop))
+ {
+ local_irq_save (flags);
+ if (spin_trylock (&mpu->output_lock))
+ {
+ cuckoo_uart_output_write (mpu);
+ spin_unlock (&mpu->output_lock);
+ }
+ local_irq_restore (flags);
+ }
+ atomic_inc (&mpu->tx_loop);
+ }
+ else
+ {
+ cuckoo_uart_remove_timer (mpu, 0);
+ clear_bit (MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
+ }
+#endif
+}
+
+static snd_rawmidi_ops_t cuckoo_uart_output = {
+ .open = cuckoo_uart_output_open,
+ .close = cuckoo_uart_output_close,
+ .trigger = cuckoo_uart_output_trigger,
+};
+
+static snd_rawmidi_ops_t cuckoo_uart_input = {
+ .open = cuckoo_uart_input_open,
+ .close = cuckoo_uart_input_close,
+ .trigger = cuckoo_uart_input_trigger,
+};
+
+extern mididev_p *midi_devs;
+
+int
+install_midiport_instances (cuckoo_t * chip, int cardno)
+{
+ int dev, devix = 0;
+
+ for (dev = 0; dev < num_mididevs; dev++)
+ if (midi_devs[dev]->card_number == cardno)
+ {
+ mididev_p mididev = midi_devs[dev];
+ snd_rawmidi_t *rmidi;
+ int err;
+
+//printk("Midi device %s\n", mididev->info.name);
+
+ if ((err = snd_rawmidi_new (chip->card, mididev->name, devix,
+ 1, 1, &rmidi)) < 0)
+ {
+ printk ("cuckoo: Failed to register rawmidi device, err=%d\n",
+ err);
+ return 0;
+ }
+
+ rmidi->private_data = (void *) dev;
+ strcpy (rmidi->name, mididev->name);
+ rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
+ SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
+ snd_rawmidi_set_ops (rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+ &cuckoo_uart_output);
+ snd_rawmidi_set_ops (rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+ &cuckoo_uart_input);
+
+ devix++;
+ rmidis[dev] = rmidi;
+ } // dev
+
+ return 0;
+}
diff --git a/setup/Linux/oss/cuckoo/cuckoo_mixer.c b/setup/Linux/oss/cuckoo/cuckoo_mixer.c
new file mode 100644
index 0000000..6d2bb6d
--- /dev/null
+++ b/setup/Linux/oss/cuckoo/cuckoo_mixer.c
@@ -0,0 +1,389 @@
+/*
+ * This software module makes it possible to use Open Sound System for Linux
+ * (the _professional_ version) as a low level driver source for ALSA.
+ *
+ * Copyright (C) 2004 Hannu Savolainen (hannu@voimakentta.net).
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+/*
+ * !!!!!!!!!!!!!!!!!!!! Important !!!!!!!!!!!!!!!!!!
+ *
+ * If this file doesn't compile, you must not try to resolve the problem
+ * without perfect understanding of internals of Linux kernel, ALSA and
+ * Open Sound System.
+ *
+ * Instead you need to check that you are using the version of this file
+ * that matches the versions of ALSA, OSS and Linux you are currently using.
+ */
+
+#include "cuckoo.h"
+
+MODULE_AUTHOR ("Hannu Savolainen <hannu@opensound.com>");
+MODULE_LICENSE ("GPL v2");
+MODULE_DESCRIPTION ("OSS mixer low level driver interface for ALSA");
+
+typedef struct
+{
+ char *name, *data;
+} enum_entry_t;
+
+#if 0
+static void
+downshift (char *s)
+{
+ while (*s)
+ {
+ if (*s >= 'A' && *s <= 'Z')
+ *s += 32;
+ s++;
+ }
+}
+#endif
+
+static int
+get_mixer_info (snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ oss_mixext ext;
+ int dev, ix;
+
+ dev = ext.dev = kcontrol->private_value >> 16;
+ ix = ext.ctrl = kcontrol->private_value & 0xffff;;
+
+ oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_EXTINFO, (caddr_t) & ext);
+
+ switch (ext.type)
+ {
+ case MIXT_STEREOSLIDER:
+ case MIXT_STEREOVU:
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = ext.minvalue;
+ uinfo->value.integer.max = ext.maxvalue;
+ break;
+
+ case MIXT_MONOSLIDER:
+ case MIXT_MONOVU:
+ case MIXT_SLIDER:
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = ext.minvalue;
+ uinfo->value.integer.max = ext.maxvalue;
+ break;
+
+ case MIXT_ONOFF:
+ case MIXT_MUTE:
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ break;
+
+ case MIXT_ENUM:
+ {
+ static const char *texts[] = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
+ "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
+ "30", "31", "32"
+ };
+ oss_mixer_enuminfo enumdef;
+ uinfo->value.enumerated.items = ext.maxvalue;
+
+ if (uinfo->value.enumerated.item < 0)
+ uinfo->value.enumerated.item = 0;
+ if (uinfo->value.enumerated.item >= ext.maxvalue)
+ uinfo->value.enumerated.item = ext.maxvalue - 1;
+ if (uinfo->value.enumerated.item > 31)
+ uinfo->value.enumerated.item = 31;
+ strcpy (uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+
+ enumdef.dev = ext.dev;
+ enumdef.ctrl = ext.ctrl;
+ if (oss_mixer_ext
+ (dev, OSS_DEV_MIXER, SNDCTL_MIX_ENUMINFO,
+ (caddr_t) & enumdef) >= 0)
+ {
+ char *text;
+
+ text =
+ &enumdef.strings[enumdef.
+ strindex[uinfo->value.enumerated.item]];
+ strcpy (uinfo->value.enumerated.name, text);
+ }
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = ext.maxvalue;
+ }
+ break;
+
+ default:
+ printk ("cuckoo: mixer_info(%d/%d) - unknown type %d\n", dev, ix,
+ ext.type);
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = ext.minvalue;
+ uinfo->value.integer.max = ext.maxvalue;
+ return 0;
+ }
+
+ return 0;
+}
+
+static int
+mixer_get (snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ oss_mixext ext;
+ oss_mixer_value val;
+ int dev, ix, err;
+
+ dev = ext.dev = kcontrol->private_value >> 16;
+ ix = ext.ctrl = kcontrol->private_value & 0xffff;;
+ if ((err =
+ oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_EXTINFO,
+ (caddr_t) & ext)) < 0)
+ return err;
+
+ val.dev = dev;
+ val.ctrl = ix;
+ val.timestamp = ext.timestamp;
+ if ((err =
+ oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_READ,
+ (caddr_t) & val)) < 0)
+ return err;
+
+ switch (ext.type)
+ {
+ case MIXT_STEREOVU:
+ case MIXT_STEREOSLIDER:
+ ucontrol->value.integer.value[0] = val.value & 0xff; // Left
+ ucontrol->value.integer.value[1] = (val.value >> 8) & 0xff; // Right
+ break;
+
+ case MIXT_MONOSLIDER:
+ case MIXT_MONOVU:
+ case MIXT_SLIDER:
+ ucontrol->value.integer.value[0] = val.value & 0xff;
+ break;
+
+ case MIXT_ONOFF:
+ case MIXT_MUTE:
+ ucontrol->value.integer.value[0] = !!val.value;
+ break;
+
+ case MIXT_ENUM:
+ ucontrol->value.integer.value[0] = val.value;
+ break;
+
+ default:
+ printk ("cuckoo: mixer_get(%d/%d) - unknown type %d\n", dev, ix,
+ ext.type);
+ ucontrol->value.integer.value[0] = val.value & 0xff;
+ return 0;
+ }
+
+ return 0;
+}
+
+static int
+mixer_put (snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ oss_mixext ext;
+ oss_mixer_value val;
+ int dev, ix, err;
+
+ dev = ext.dev = kcontrol->private_value >> 16;
+ ix = ext.ctrl = kcontrol->private_value & 0xffff;;
+ if ((err =
+ oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_EXTINFO,
+ (caddr_t) & ext)) < 0)
+ return err;
+
+ val.dev = dev;
+ val.ctrl = ix;
+ val.timestamp = ext.timestamp;
+
+ switch (ext.type)
+ {
+ case MIXT_STEREOSLIDER:
+ val.value = ucontrol->value.integer.value[0] | // Left
+ ucontrol->value.integer.value[1] << 8; // Right
+ if ((err =
+ oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_WRITE,
+ (caddr_t) & val)) < 0)
+ return err;
+ break;
+
+ case MIXT_MONOSLIDER:
+ case MIXT_SLIDER:
+ val.value = ucontrol->value.integer.value[0];
+ if ((err =
+ oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_WRITE,
+ (caddr_t) & val)) < 0)
+ return err;
+ break;
+
+ case MIXT_ONOFF:
+ case MIXT_MUTE:
+ val.value = !!ucontrol->value.integer.value[0];
+ if ((err =
+ oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_WRITE,
+ (caddr_t) & val)) < 0)
+ return err;
+ break;
+
+ case MIXT_ENUM:
+ val.value = ucontrol->value.integer.value[0];
+ if ((err =
+ oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_WRITE,
+ (caddr_t) & val)) < 0)
+ return err;
+ break;
+
+ case MIXT_MONOVU:
+ case MIXT_STEREOVU:
+ return -EPERM;
+
+ default:
+ printk ("cuckoo: mixer_put(%d/%d) - unknown type %d\n", dev, ix,
+ ext.type);
+ val.value = ucontrol->value.integer.value[0];
+ if ((err =
+ oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_WRITE,
+ (caddr_t) & val)) < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static void
+add_control (cuckoo_t * chip, int dev, int ix, oss_mixext * ext, char *name)
+{
+ int i, ok, err = 0;
+ snd_kcontrol_new_t my_control;
+
+// Upshift the name if it's an single part one
+
+ ok = 0;
+ for (i = 0; i < strlen (name); i++)
+ if (name[i] == '.')
+ ok = 1;
+ if (!ok)
+ for (i = 0; i < strlen (name); i++)
+ if (name[i] >= 'a' && name[i] <= 'z')
+ name[i] -= 32;
+
+// Add the control
+
+ memset (&my_control, 0, sizeof (my_control));
+
+ my_control.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ my_control.name = name;
+ my_control.index = 0;
+ my_control.access = 0;
+
+ if (ext->flags & MIXF_READABLE)
+ my_control.access |= SNDRV_CTL_ELEM_ACCESS_READ;
+ if (ext->flags & MIXF_WRITEABLE)
+ my_control.access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
+ if ((ext->flags & 0x3) == MIXF_READABLE) /* Read only */
+ my_control.access |= SNDRV_CTL_ELEM_ACCESS_VOLATILE;
+
+ my_control.private_value = (dev << 16) | ix;
+ my_control.info = get_mixer_info;
+ my_control.get = mixer_get;
+ my_control.put = mixer_put;
+
+ switch (ext->type)
+ {
+ case MIXT_ENUM:
+ case MIXT_ONOFF:
+ case MIXT_MUTE:
+ case MIXT_STEREOSLIDER:
+ case MIXT_SLIDER:
+ case MIXT_MONOSLIDER:
+ case MIXT_MONOVU:
+ case MIXT_STEREOVU:
+ if ((err =
+ snd_ctl_add (chip->card, snd_ctl_new1 (&my_control, chip))) < 0)
+ {
+ printk ("cuckoo: snd_ctl_add(%s) failed, err=%d\n", ext->extname,
+ err);
+ return;
+ }
+ break;
+ }
+}
+
+int
+install_mixer_instances (cuckoo_t * chip, int cardno)
+{
+ int dev;
+ mixer_operations_t **cuckoo_mixer_devs = mixer_devs_p;
+
+ for (dev = 0; dev < num_mixers; dev++)
+ if (cuckoo_mixer_devs[dev]->card_number == cardno)
+ {
+ int nrext, i, sz;
+
+ touch_mixer (dev);
+
+ nrext = dev;
+ oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_NREXT,
+ (ioctl_arg) & nrext);
+
+ if (nrext == 0)
+ continue;
+
+ sz = nrext * (sizeof (char *) + 32); // 32 characters / name (average)
+
+ for (i = 0; i < nrext; i++)
+ {
+ oss_mixext ext;
+ int parent = 0;
+ oss_mixext_root *root = NULL;
+
+ ext.dev = dev;
+ ext.ctrl = i;
+ oss_mixer_ext (dev, OSS_DEV_MIXER, SNDCTL_MIX_EXTINFO,
+ (caddr_t) & ext);
+
+ switch (ext.type)
+ {
+ case MIXT_DEVROOT:
+ root = (oss_mixext_root *) & ext.data;
+ break;
+
+ case MIXT_GROUP:
+ parent = ext.parent;
+ break;
+
+ case MIXT_MARKER:
+ break;
+
+ default:
+ add_control (chip, dev, i, &ext, ext.extname);
+ break;
+ } // Switch
+
+ } // i
+
+
+ } // dev
+
+ return 0;
+}
+
+EXPORT_SYMBOL (install_mixer_instances);
diff --git a/setup/Linux/oss/cuckoo/cuckoo_pcm.c b/setup/Linux/oss/cuckoo/cuckoo_pcm.c
new file mode 100644
index 0000000..2ae08b5
--- /dev/null
+++ b/setup/Linux/oss/cuckoo/cuckoo_pcm.c
@@ -0,0 +1,810 @@
+/*
+ * This software module makes it possible to use Open Sound System for Linux
+ * (the _professional_ version) as a low level driver source for ALSA.
+ *
+ * Copyright (C) 2004 Hannu Savolainen (hannu@voimakentta.net).
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+/*
+ * !!!!!!!!!!!!!!!!!!!! Important !!!!!!!!!!!!!!!!!!
+ *
+ * If this file doesn't compile, you must not try to resolve the problem
+ * without perfect understanding of internals of Linux kernel, ALSA and
+ * Open Sound System.
+ *
+ * Instead you need to check that you are using the version of this file
+ * that matches the versions of ALSA, OSS and Linux you are currently using.
+ */
+
+#include "cuckoo.h"
+
+MODULE_AUTHOR ("Hannu Savolainen <hannu@opensound.com>");
+MODULE_LICENSE ("GPL v2");
+MODULE_DESCRIPTION ("OSS PCM low level driver interface for ALSA");
+
+static snd_pcm_substream_t *cuckoo_playsubstream[256] = { NULL };
+static snd_pcm_substream_t *cuckoo_capturesubstream[256] = { NULL };
+
+static snd_pcm_hardware_t snd_cuckoo_playback = {
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 4000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (64 * 1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (32 * 1024),
+ .periods_min = 2,
+ .periods_max = 1024,
+ .fifo_size = 0,
+};
+
+static snd_pcm_hardware_t snd_cuckoo_capture = {
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 4000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (128 * 1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (64 * 1024),
+ .periods_min = 2,
+ .periods_max = 1024,
+ .fifo_size = 0,
+};
+
+static void
+cuckoo_outputintr (int dev, int notify_only)
+{
+ snd_pcm_substream_t *substream;
+ adev_t *adev;
+ dmap_t *dmap;
+ oss_native_word flags;
+
+ if (dev < 0 || dev > 255)
+ return;
+
+ adev = audio_devfiles[dev];
+ dmap = adev->dmap_out;
+
+ dmap->fragment_counter = (dmap->fragment_counter + 1) % dmap->nfrags;
+
+ substream = cuckoo_playsubstream[dev];
+ if (substream == NULL)
+ return;
+
+ udi_spin_lock_irqsave (&adev->mutex, &flags);
+ snd_pcm_period_elapsed (substream);
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+}
+
+static void
+cuckoo_inputintr (int dev, int intr_flags)
+{
+ snd_pcm_substream_t *substream;
+ adev_t *adev;
+ dmap_t *dmap;
+ oss_native_word flags;
+
+ if (dev < 0 || dev > 255)
+ return;
+
+ adev = audio_devfiles[dev];
+ dmap = adev->dmap_in;
+
+ dmap->fragment_counter = (dmap->fragment_counter + 1) % dmap->nfrags;
+
+ substream = cuckoo_capturesubstream[dev];
+ if (substream == NULL)
+ return;
+
+ udi_spin_lock_irqsave (&adev->mutex, &flags);
+ snd_pcm_period_elapsed (substream);
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+}
+
+static void
+copy_hw_caps (snd_pcm_runtime_t * runtime, adev_t * adev, int dir)
+{
+ u64 fmts = 0;
+ int i;
+ unsigned int fmtmask;
+
+ if (dir == OPEN_WRITE)
+ {
+ fmtmask = adev->oformat_mask;
+ }
+ else
+ {
+ fmtmask = adev->iformat_mask;
+ }
+
+ for (i = 0; i < 32; i++)
+ switch (fmtmask & (1 << i))
+ {
+ case AFMT_MU_LAW:
+ fmts |= SNDRV_PCM_FMTBIT_MU_LAW;
+ break;
+ case AFMT_A_LAW:
+ fmts |= SNDRV_PCM_FMTBIT_A_LAW;
+ break;
+ case AFMT_IMA_ADPCM:
+ fmts |= SNDRV_PCM_FMTBIT_IMA_ADPCM;
+ break;
+ case AFMT_U8:
+ fmts |= SNDRV_PCM_FMTBIT_U8;
+ break;
+ case AFMT_S8:
+ fmts |= SNDRV_PCM_FMTBIT_S8;
+ break;
+ case AFMT_S16_LE:
+ fmts |= SNDRV_PCM_FMTBIT_S16_LE;
+ break;
+ case AFMT_S16_BE:
+ fmts |= SNDRV_PCM_FMTBIT_S16_BE;
+ break;
+ case AFMT_S24_LE:
+ fmts |= SNDRV_PCM_FMTBIT_S24_LE;
+ break;
+ case AFMT_S24_BE:
+ fmts |= SNDRV_PCM_FMTBIT_S24_BE;
+ break;
+ case AFMT_S32_LE:
+ fmts |= SNDRV_PCM_FMTBIT_S32_LE;
+ break;
+ case AFMT_S32_BE:
+ fmts |= SNDRV_PCM_FMTBIT_S32_BE;
+ break;
+ case AFMT_MPEG:
+ fmts |= SNDRV_PCM_FMTBIT_MPEG;
+ break;
+ case AFMT_FLOAT:
+ fmts |= SNDRV_PCM_FMTBIT_FLOAT_LE;
+ break;
+ case AFMT_SPDIF_RAW:
+ fmts |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
+ break;
+ }
+
+ runtime->hw.formats = fmts;
+
+ if (adev->min_block > 0)
+ runtime->hw.period_bytes_min = adev->min_block;
+ if (adev->max_block > 0)
+ runtime->hw.period_bytes_max = adev->max_block;
+
+ if (adev->flags & ADEV_NOMMAP)
+ runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID);
+
+ if (adev->max_rate > adev->min_rate)
+ {
+ runtime->hw.rate_min = adev->min_rate;
+ runtime->hw.rate_max = adev->max_rate;
+ }
+
+ if (!(adev->caps & DSP_CAP_FREERATE))
+ runtime->hw.rates &=
+ ~(SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000);
+}
+
+static int
+snd_cuckoo_playback_open (snd_pcm_substream_t * substream)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int snum = substream->number;
+ int err;
+ adev_t *adev;
+ oss_native_word flags;
+ struct fileinfo tmp_finfo;
+
+ if (snum < 0 || snum >= chip->npcm)
+ {
+ printk ("cuckoo: Playback open - bad substream index %d\n", snum);
+ return -EIO;
+ }
+
+ adev = chip->play_adev[snum];
+ printk ("cuckoo_playback_open(%d=%s)\n", adev->engine_num, adev->name);
+
+ cuckoo_playsubstream[adev->engine_num] = substream;
+
+ if (adev->dmap_out == NULL || adev->dmap_out->dmabuf == NULL)
+ {
+ printk ("cuckoo: dev %d - no buffer available\n", adev->engine_num);
+ return -ENOMEM;
+ }
+
+ if (adev->open_mode != 0)
+ {
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+ return -EBUSY;
+ }
+
+ tmp_finfo.mode = OPEN_WRITE;
+ tmp_finfo.acc_flags = 0;
+ if ((err =
+ oss_audio_open_engine (adev->engine_num, OSS_DEV_DSP,
+ &tmp_finfo, 1, OF_SMALLBUF,
+ NULL)) < 0)
+ {
+ return err;
+ }
+
+ udi_spin_lock_irqsave (&adev->mutex, &flags);
+ adev->open_mode = OPEN_WRITE;
+ runtime->hw = snd_cuckoo_playback;
+ copy_hw_caps (runtime, adev, OPEN_WRITE);
+ snd_pcm_set_sync (substream);
+ adev->pid = current->pid;
+ strncpy (adev->cmd, current->comm, sizeof (adev->cmd) - 1);
+ adev->cmd[sizeof (adev->cmd) - 1] = 0;
+ adev->outputintr = cuckoo_outputintr;
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+
+ return 0;
+}
+
+static int
+snd_cuckoo_capture_open (snd_pcm_substream_t * substream)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int snum = substream->number;
+ int err;
+ adev_t *adev;
+ oss_native_word flags;
+ struct fileinfo tmp_finfo;
+
+ if (snum < 0 || snum >= chip->npcm)
+ {
+ printk ("cuckoo: Capture open - bad substream index %d\n", snum);
+ return -EIO;
+ }
+
+ adev = chip->capture_adev[snum];
+
+ cuckoo_capturesubstream[adev->engine_num] = substream;
+
+ if (adev->dmap_in == NULL || adev->dmap_in->dmabuf == NULL)
+ {
+ printk ("cuckoo: dev %d - no buffer available\n", adev->engine_num);
+ return -ENOMEM;
+ }
+
+ if (adev->open_mode != 0)
+ {
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+ return -EBUSY;
+ }
+
+ tmp_finfo.mode = OPEN_READ;
+ tmp_finfo.acc_flags = 0;
+ if ((err =
+ oss_audio_open_engine (adev->engine_num, OSS_DEV_DSP,
+ &tmp_finfo, 1, OF_SMALLBUF,
+ NULL)) < 0)
+ {
+ return err;
+ }
+
+ udi_spin_lock_irqsave (&adev->mutex, &flags);
+ adev->open_mode = OPEN_READ;
+ runtime->hw = snd_cuckoo_capture;
+ copy_hw_caps (runtime, adev, OPEN_READ);
+ snd_pcm_set_sync (substream);
+ adev->pid = current->pid;
+ strncpy (adev->cmd, current->comm, sizeof (adev->cmd) - 1);
+ adev->cmd[sizeof (adev->cmd) - 1] = 0;
+ adev->inputintr = cuckoo_inputintr;
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+
+ return 0;
+}
+
+static int
+snd_cuckoo_playback_close (snd_pcm_substream_t * substream)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ int snum = substream->number;
+ adev_t *adev;
+ oss_native_word flags;
+ struct fileinfo tmp_finfo;
+
+ if (snum < 0 || snum >= chip->npcm)
+ return -ENXIO;
+
+ adev = chip->play_adev[snum];
+
+ udi_spin_lock_irqsave (&adev->mutex, &flags);
+ cuckoo_playsubstream[adev->engine_num] = NULL;
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+
+ tmp_finfo.mode = OPEN_WRITE;
+ tmp_finfo.acc_flags = 0;
+ oss_audio_release (adev->engine_num, &tmp_finfo);
+
+ return 0;
+}
+
+static int
+snd_cuckoo_capture_close (snd_pcm_substream_t * substream)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ int snum = substream->number;
+ adev_t *adev;
+ oss_native_word flags;
+ struct fileinfo tmp_finfo;
+
+ if (snum < 0 || snum >= chip->npcm)
+ return -ENXIO;
+
+ adev = chip->capture_adev[snum];
+
+ udi_spin_lock_irqsave (&adev->mutex, &flags);
+ cuckoo_capturesubstream[adev->engine_num] = NULL;
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+
+ tmp_finfo.mode = OPEN_READ;
+ tmp_finfo.acc_flags = 0;
+ oss_audio_release (adev->engine_num, &tmp_finfo);
+
+ return 0;
+}
+
+static int
+snd_cuckoo_playback_hw_params (snd_pcm_substream_t * substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int snum = substream->number;
+ adev_t *adev;
+ dmap_t *dmap;
+
+ if (snum < 0 || snum >= chip->npcm)
+ return -ENXIO;
+
+ adev = chip->play_adev[snum];
+ dmap = adev->dmap_out;
+
+ if (dmap->dmabuf == NULL)
+ return -ENOMEM;
+
+ runtime->dma_area = dmap->dmabuf;
+ runtime->dma_addr = dmap->dmabuf_phys;
+ runtime->dma_bytes = dmap->buffsize;
+ memset (dmap->dmabuf, 0, dmap->buffsize);
+
+ return 0;
+}
+
+static int
+snd_cuckoo_capture_hw_params (snd_pcm_substream_t * substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int snum = substream->number;
+ adev_t *adev;
+ dmap_t *dmap;
+
+ if (snum < 0 || snum >= chip->npcm)
+ return -ENXIO;
+
+ adev = chip->capture_adev[snum];
+ dmap = adev->dmap_in;
+
+ if (dmap->dmabuf == NULL)
+ return -ENOMEM;
+
+ runtime->dma_area = dmap->dmabuf;
+ runtime->dma_addr = dmap->dmabuf_phys;
+ runtime->dma_bytes = dmap->buffsize;
+ memset (dmap->dmabuf, 0, dmap->buffsize);
+
+ return 0;
+}
+
+static int
+snd_cuckoo_hw_free (snd_pcm_substream_t * substream)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+
+ runtime->dma_area = NULL;
+ runtime->dma_addr = 0;
+ runtime->dma_bytes = 0;
+
+ return 0;
+}
+
+static int
+snd_cuckoo_playback_prepare (snd_pcm_substream_t * substream)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int snum = substream->number, err;
+ adev_t *adev;
+ oss_native_word flags;
+ dmap_t *dmap;
+
+ if (snum < 0 || snum >= chip->npcm)
+ return -ENXIO;
+
+ adev = chip->play_adev[snum];
+ dmap = adev->dmap_out;
+
+ udi_spin_lock_irqsave (&adev->mutex, &flags);
+
+ adev->d->adrv_set_format (adev->engine_num,
+ snd_pcm_format_width (runtime->format));
+ runtime->channels =
+ adev->d->adrv_set_channels (adev->engine_num, runtime->channels);
+ runtime->rate = adev->d->adrv_set_rate (adev->engine_num, runtime->rate);
+ adev->user_parms.rate = adev->user_parms.rate = runtime->rate;
+
+ dmap->bytes_in_use = snd_pcm_lib_buffer_bytes (substream);
+ dmap->fragment_size = snd_pcm_lib_period_bytes (substream);
+
+#if 1
+ {
+ int f, s;;
+
+ f = dmap->fragment_size / 4;
+ if (f < 128)
+ f = dmap->fragment_size / 2;
+ if (f < 128)
+ f = dmap->fragment_size;
+
+ s = dmap->bytes_in_use;
+ while (s > f)
+ s /= 2;
+
+ dmap->fragment_size = s;
+ }
+#endif
+
+ if (adev->max_block > 0 && dmap->fragment_size > adev->max_block)
+ dmap->fragment_size = adev->max_block;
+ if (adev->min_block > 0 && dmap->fragment_size < adev->min_block)
+ dmap->fragment_size = adev->min_block;
+ if (dmap->fragment_size < 8)
+ dmap->fragment_size = 8;
+ dmap->nfrags = dmap->bytes_in_use / dmap->fragment_size;
+
+ err =
+ adev->d->adrv_prepare_for_output (adev->engine_num, dmap->fragment_size,
+ dmap->nfrags);
+ cuckoo_playsubstream[adev->engine_num] = substream;
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+ return err;
+}
+
+static int
+snd_cuckoo_capture_prepare (snd_pcm_substream_t * substream)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int snum = substream->number, err;
+ adev_t *adev;
+ oss_native_word flags;
+ dmap_t *dmap;
+
+ if (snum < 0 || snum >= chip->npcm)
+ return -ENXIO;
+
+ adev = chip->capture_adev[snum];
+ dmap = adev->dmap_in;
+
+ udi_spin_lock_irqsave (&adev->mutex, &flags);
+
+ adev->d->adrv_set_format (adev->engine_num,
+ snd_pcm_format_width (runtime->format));
+ adev->d->adrv_set_channels (adev->engine_num, runtime->channels);
+ adev->d->adrv_set_rate (adev->engine_num, runtime->rate);
+
+ dmap->bytes_in_use = snd_pcm_lib_buffer_bytes (substream);
+ dmap->fragment_size = snd_pcm_lib_period_bytes (substream);
+
+#if 1
+ {
+ int f, s;;
+
+ f = dmap->fragment_size / 4;
+ if (f < 128)
+ f = dmap->fragment_size / 2;
+ if (f < 128)
+ f = dmap->fragment_size;
+
+ s = dmap->bytes_in_use;
+ while (s > f)
+ s /= 2;
+
+ dmap->fragment_size = s;
+ }
+#endif
+
+ if (adev->max_block > 0 && dmap->fragment_size > adev->max_block)
+ dmap->fragment_size = adev->max_block;
+ if (adev->min_block > 0 && dmap->fragment_size < adev->min_block)
+ dmap->fragment_size = adev->min_block;
+ if (dmap->fragment_size < 8)
+ dmap->fragment_size = 8;
+ dmap->nfrags = dmap->bytes_in_use / dmap->fragment_size;
+
+ err =
+ adev->d->adrv_prepare_for_input (adev->engine_num, dmap->fragment_size,
+ dmap->nfrags);
+ cuckoo_capturesubstream[adev->engine_num] = substream;
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+ return err;
+}
+
+static int
+snd_cuckoo_playback_trigger (snd_pcm_substream_t * substream, int cmd)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ //snd_pcm_runtime_t *runtime = substream->runtime;
+ int snum = substream->number;
+ adev_t *adev;
+ oss_native_word flags;
+ dmap_t *dmap;
+ int err = 0;
+
+ if (snum < 0 || snum >= chip->npcm)
+ return -ENXIO;
+
+ adev = chip->play_adev[snum];
+ dmap = adev->dmap_out;
+
+ udi_spin_lock_irqsave (&adev->mutex, &flags);
+
+ switch (cmd)
+ {
+ case SNDRV_PCM_TRIGGER_START:
+ adev->d->adrv_output_block (adev->engine_num, dmap->dmabuf_phys,
+ dmap->bytes_in_use, dmap->fragment_size, 0);
+ adev->d->adrv_trigger (adev->engine_num, PCM_ENABLE_OUTPUT);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ adev->d->adrv_trigger (adev->engine_num, 0);
+ break;
+
+ default:
+ printk ("cuckoo: Bad trigger cmd %x\n", cmd);
+ err = -EIO;
+ goto fail;
+ }
+
+fail:
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+ return err;
+}
+
+static int
+snd_cuckoo_capture_trigger (snd_pcm_substream_t * substream, int cmd)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ //snd_pcm_runtime_t *runtime = substream->runtime;
+ int snum = substream->number;
+ adev_t *adev;
+ oss_native_word flags;
+ dmap_t *dmap;
+ int err = 0;
+
+ if (snum < 0 || snum >= chip->npcm)
+ return -ENXIO;
+
+ adev = chip->capture_adev[snum];
+ dmap = adev->dmap_in;
+
+ udi_spin_lock_irqsave (&adev->mutex, &flags);
+
+ switch (cmd)
+ {
+ case SNDRV_PCM_TRIGGER_START:
+ adev->d->adrv_start_input (adev->engine_num, dmap->dmabuf_phys,
+ dmap->bytes_in_use, dmap->fragment_size, 0);
+ adev->d->adrv_trigger (adev->engine_num, PCM_ENABLE_INPUT);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ adev->d->adrv_trigger (adev->engine_num, 0);
+ break;
+
+ default:
+ printk ("cuckoo: Bad trigger cmd %x\n", cmd);
+ err = -EIO;
+ goto fail;
+ }
+
+fail:
+ udi_spin_unlock_irqrestore (&adev->mutex, flags);
+ return err;
+}
+
+static snd_pcm_uframes_t
+snd_cuckoo_playback_pointer (snd_pcm_substream_t * substream)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ //snd_pcm_runtime_t *runtime = substream->runtime;
+ int snum = substream->number;
+ adev_t *adev;
+ dmap_t *dmap;
+ int pos;
+
+ if (snum < 0 || snum >= chip->npcm)
+ return -ENXIO;
+
+ adev = chip->play_adev[snum];
+ dmap = adev->dmap_out;
+
+ if (adev->d->adrv_get_output_pointer != NULL)
+ pos =
+ adev->d->adrv_get_output_pointer (adev->engine_num, dmap, PCM_ENABLE_OUTPUT);
+ else
+ {
+ pos = dmap->fragment_counter * dmap->fragment_size;
+ }
+ pos = bytes_to_frames (substream->runtime, pos);
+
+ return pos;
+}
+
+static snd_pcm_uframes_t
+snd_cuckoo_capture_pointer (snd_pcm_substream_t * substream)
+{
+ cuckoo_t *chip = snd_pcm_substream_chip (substream);
+ //snd_pcm_runtime_t *runtime = substream->runtime;
+ int snum = substream->number;
+ adev_t *adev;
+ dmap_t *dmap;
+ int pos;
+
+ if (snum < 0 || snum >= chip->npcm)
+ return -ENXIO;
+
+ adev = chip->capture_adev[snum];
+ dmap = adev->dmap_in;
+
+ if (adev->d->adrv_get_input_pointer != NULL)
+ pos =
+ adev->d->adrv_get_input_pointer (adev->engine_num, dmap, PCM_ENABLE_INPUT);
+ else
+ {
+ pos = dmap->fragment_counter * dmap->fragment_size;
+ }
+ pos = bytes_to_frames (substream->runtime, pos);
+
+ return pos;
+}
+
+static snd_pcm_ops_t snd_cuckoo_playback_ops = {
+ .open = snd_cuckoo_playback_open,
+ .close = snd_cuckoo_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cuckoo_playback_hw_params,
+ .hw_free = snd_cuckoo_hw_free,
+ .prepare = snd_cuckoo_playback_prepare,
+ .trigger = snd_cuckoo_playback_trigger,
+ .pointer = snd_cuckoo_playback_pointer,
+};
+
+static snd_pcm_ops_t snd_cuckoo_capture_ops = {
+ .open = snd_cuckoo_capture_open,
+ .close = snd_cuckoo_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cuckoo_capture_hw_params,
+ .hw_free = snd_cuckoo_hw_free,
+ .prepare = snd_cuckoo_capture_prepare,
+ .trigger = snd_cuckoo_capture_trigger,
+ .pointer = snd_cuckoo_capture_pointer,
+};
+
+int
+install_pcm_instances (cuckoo_t * chip, int cardno)
+{
+ int dev, err, ok = 0;
+ int ninputs = 0, noutputs = 0;
+
+ for (dev = 0; dev < num_audio_devfiles; dev++)
+ if (audio_devfiles[dev]->card_number == cardno)
+ {
+ adev_t *adev = audio_devfiles[dev];
+ adev_t *nextdev = audio_devfiles[dev + 1];
+ snd_pcm_t *pcm;
+
+ ninputs = noutputs = 0;
+
+ ok = 0;
+/* Special handling for shadow devices */
+ if (dev < num_audio_devfiles - 1 && (adev->flags & ADEV_DUPLEX))
+ if ((nextdev->flags & ADEV_DUPLEX)
+ && (nextdev->flags & ADEV_SHADOW))
+ ok = 1;
+
+// Devices with one recording engine and multiple playback ones
+ if (dev < num_audio_devfiles - 1 && (adev->flags & ADEV_DUPLEX))
+ if (adev->card_number == nextdev->card_number)
+ if ((nextdev->flags & ADEV_NOINPUT))
+ ok = 1;
+
+ if (ok) // Device needs special handling
+ {
+ if ((err =
+ snd_pcm_new (chip->card, "OSS/Linux", chip->npcm, 1, 1,
+ &pcm)) < 0)
+ {
+ printk ("cuckoo: snd_pcm_new failed - error %d\n", err);
+ return err;
+ }
+
+ pcm->private_data = chip;
+ chip->pcm[chip->npcm++] = pcm;
+ strlcpy (pcm->name, adev->name);
+
+ chip->capture_adev[chip->ncapture++] = nextdev;
+ snd_pcm_set_ops (pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_cuckoo_capture_ops);
+
+ chip->play_adev[chip->nplay++] = adev;
+ snd_pcm_set_ops (pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_cuckoo_playback_ops);
+
+ dev++;
+ continue;
+ }
+
+ if (!(adev->flags & ADEV_NOINPUT))
+ ninputs = 1;
+ if (!(adev->flags & ADEV_NOOUTPUT))
+ noutputs = 1;
+
+ if ((err =
+ snd_pcm_new (chip->card, "OSS/Linux", chip->npcm, noutputs,
+ ninputs, &pcm)) < 0)
+ {
+ printk ("cuckoo: snd_pcm_new failed - error %d\n", err);
+ return err;
+ }
+
+ pcm->private_data = chip;
+ chip->pcm[chip->npcm++] = pcm;
+ strlcpy (pcm->name, adev->name);
+
+ if (noutputs > 0)
+ {
+ chip->play_adev[chip->nplay++] = adev;
+ snd_pcm_set_ops (pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_cuckoo_playback_ops);
+ }
+
+ if (ninputs > 0)
+ {
+ chip->capture_adev[chip->ncapture++] = adev;
+ snd_pcm_set_ops (pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_cuckoo_capture_ops);
+ }
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL (install_pcm_instances);
diff --git a/setup/Linux/oss/etc/S89oss b/setup/Linux/oss/etc/S89oss
new file mode 100755
index 0000000..5a1cdcd
--- /dev/null
+++ b/setup/Linux/oss/etc/S89oss
@@ -0,0 +1,80 @@
+#!/bin/bash
+#
+# /etc/rc.d/init.d/oss
+#
+# Starts the OSS sound driver
+#
+# chkconfig: 2345 80 20
+# description: Open Sound System for Linux (OSS/Linux) is a \
+# commercial quality sound driver distributed by 4Front Technologies \
+# (http://www.opensound.com).
+
+### BEGIN INIT INFO
+# Provides: oss
+# Required-Start: $local_fs $remote_fs
+# Should-Start:
+# Required-Stop:
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: Start OSS
+### END INIT INFO
+
+# Source function library.
+if test -f /lib/lsb/init-functions
+then
+. /lib/lsb/init-functions
+fi
+
+if test -f /etc/rc.d/init.d/functions
+then
+. /etc/rc.d/init.d/functions
+fi
+
+# Add oss configuration.
+. /etc/oss.conf
+
+RETVAL=0
+
+#
+# See how we were called.
+#
+case "$1" in
+ start)
+ # Check if OSS is already running
+ echo -n 'Starting Open Sound System: '
+ if ! test -f /usr/sbin/soundon
+ then
+ exit 0
+ fi
+
+ if test -f $OSSLIBDIR/starting
+ then
+ ls -l $OSSLIBDIR/starting
+ echo Previous start of OSS crashed the system
+ echo Please resolve the situation and remove file
+ echo \"$OSSLIBDIR/starting\". Then start OSS by
+ echo running soundon
+ exit 0
+ fi
+
+ if ! /usr/sbin/soundon
+ then
+ echo Starting OSS failed
+ fi
+ rm -f $OSSLIBDIR/starting
+ ;;
+ stop)
+ echo -n 'Stopping Open Sound System: '
+
+ /usr/sbin/savemixer
+ exit 0
+ ;;
+ restart)
+ $0 stop
+ /usr/sbin/soundoff
+ $0 start
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart}"
+ exit 1
+esac
diff --git a/setup/Linux/oss/scripts/90-oss_usb-create-device.fdi b/setup/Linux/oss/scripts/90-oss_usb-create-device.fdi
new file mode 100644
index 0000000..28744f9
--- /dev/null
+++ b/setup/Linux/oss/scripts/90-oss_usb-create-device.fdi
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<deviceinfo version="0.2">
+ <device>
+ <match key="info.linux.driver" string="oss_usb">
+ <append key="info.callouts.add" type="strlist">oss_usb-create-devices</append>
+ </match>
+ </device>
+</deviceinfo>
diff --git a/setup/Linux/oss/scripts/killprocs.sh b/setup/Linux/oss/scripts/killprocs.sh
new file mode 100755
index 0000000..ce8d26d
--- /dev/null
+++ b/setup/Linux/oss/scripts/killprocs.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+PROCS="`fuser /dev/mixer* /dev/dsp* /dev/audio* /dev/sequencer /dev/music /dev/midi* 2>/dev/null`"
+
+if test "$PROCS " = " "
+then
+ exit 0
+fi
+
+for pid in $PROCS
+do
+ #ps ax|grep "^ *$pid "
+ echo killing $pid
+ kill $pid
+done
+
+sleep 2
+exit 0
diff --git a/setup/Linux/oss/scripts/oss_usb-create-devices b/setup/Linux/oss/scripts/oss_usb-create-devices
new file mode 100644
index 0000000..a6de13c
--- /dev/null
+++ b/setup/Linux/oss/scripts/oss_usb-create-devices
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+/usr/sbin/ossdetect -d
+/usr/sbin/ossdevlinks
diff --git a/setup/Linux/oss/scripts/remove_drv.sh b/setup/Linux/oss/scripts/remove_drv.sh
new file mode 100644
index 0000000..55cc1b4
--- /dev/null
+++ b/setup/Linux/oss/scripts/remove_drv.sh
@@ -0,0 +1,164 @@
+#!/bin/sh
+if test -f /etc/oss.conf
+then
+ . /etc/oss.conf
+else
+ OSSLIBDIR=/usr/lib/oss
+fi
+
+# This script wipes out the previously installed sound drivers
+# from the system.
+
+# Backup all kernel sound drivers (ALSA) and remove the kernel/sound
+# directory from the system. Untar the backup package to return ALSA
+# back in business.
+
+if test -x /sbin/chkconfig
+then
+ /sbin/chkconfig alsasound off > /dev/null 2>&1
+elif test -x /usr/sbin/update-rc.d
+then
+ /usr/sbin/update-rc.d -f alsa-utils remove > /dev/null 2>&1
+elif test -x /usr/sbin/alsa
+then
+ /usr/sbin/alsa force-unload > /dev/null 2>&1
+fi
+
+if test -d /lib/modules/`uname -r`/kernel/sound
+then
+ if ! test -f /lib/modules/`uname -r`/sound-preoss.tar.bz2
+ then
+ (cd /lib/modules/`uname -r`; tar cfj /lib/modules/`uname -r`/sound-preoss.tar.bz2 kernel/sound)
+ fi
+
+ rm -rf /lib/modules/`uname -r`/kernel/sound
+ depmod -a
+fi
+
+# Kill all applications using ALSA or OSS/Free devices
+
+# We have to use ugly replacement of fuser since this command got broken
+# in some Linux recent distributions.
+
+KILL=0
+
+for n in /proc/[0-9]*
+do
+ PID=`basename $n`
+ if test "`ls -l $n/fd/* 2>/dev/null|grep /dev/snd` " != " "
+ then
+ KILL=1
+ fi
+
+ if test "`ls -l $n/fd/* 2>/dev/null|grep /dev/mixer` " != " "
+ then
+ KILL=1
+ fi
+done
+
+if ! test -d $OSSLIBDIR/save
+then
+ mkdir $OSSLIBDIR/save
+fi
+
+if test "$KILL " = "1 "
+then
+echo killing
+ rm -f /dev/mixer.old
+ mv /dev/mixer /dev/mixer.old 2>/dev/null
+ #if test -d /dev/snd
+ #then
+ #(cd /;tar cfj $OSSLIBDIR/save/alsadevs.tar.bz2 dev/snd)
+ #fi
+
+ #mv /dev/snd /dev/snd.osssave
+ #fuser -k -s /dev/mixer.old /dev/snd.osssave/*
+fi
+
+# Remove all loaded ALSA modules
+SOUNDDEVS=
+
+if test -f /dev/mixer.old
+then
+ SOUNDDEVS="$SOUNDDEVS /dev/mixer.old"
+fi
+
+if test -d /dev/snd.osssave
+then
+ SOUNDDEVS="$SOUNDDEVS /dev/snd.osssave/*"
+fi
+
+for timeout in 0 1 2 3 4 5 6 7 8 9 10 11
+do
+ if test "`cat /proc/modules|grep ^snd_|sed 's/ .*//'` " = " "
+ then
+ break
+ fi
+
+ if test $timeout -gt 10
+ then
+ echo Cannot unload the ALSA modules. Apparently there is some
+ echo application keeping them busy.
+ echo Please reboot your system and try to start OSS again.
+ ps ax
+ lsmod
+ cat /proc/devices
+ cat /proc/interrupts
+ exit 1
+ fi
+
+ if test "$SOUNDDEVS " != " "
+ then
+ fuser -s -9 $SOUNDDEVS
+ else
+ echo Cannot find any processes using the conflicting sound driver
+ fi
+
+ for n in `cat /proc/modules|grep ^snd_|sed 's/ .*//'`
+ do
+ rmmod $n
+ #rmmod $n >/dev/null 2>&1
+ done
+
+ sleep 1
+done
+
+rmmod snd > /dev/null 2>&1
+
+# Remove soundcore
+rmmod soundcore > /dev/null 2>&1
+
+rm -f /dev/mixer.old
+
+if cat /proc/devices|grep -q '^ *14 '
+then
+
+ echo There still appears to be another sound driver hanging around
+
+ lsmod
+ cat /proc/devices|grep '^ *14 '
+ cat /proc/interrupts
+
+ exit 1
+fi
+
+for n in /dev/sndstat /dev/mixer* /dev/dsp* /dev/midi* /dev/sequencer /dev/music
+do
+ if readlink $n >/dev/null 2>&1
+ then # Symbolic link
+ if readlink $n | grep -q asound
+ then # Link to ALSA devices
+ rm -f $n
+ fi
+ fi
+done
+
+# Disable automatic startup of ALSA during system bootup
+
+if test "`ls /etc/rc.d/rc*/*alsasound*` " != " " > /dev/null 2>&1
+then
+ (cd /;tar cfj $OSSLIBDIR/save/alsarc/tar.bz2 etc/rc.d/rc*/*alsasound*)
+ rm -f /etc/rc.d/rc*/*alsasound*
+fi > /dev/null 2>&1
+
+exit 0
diff --git a/setup/Linux/oss/scripts/restore_drv.sh b/setup/Linux/oss/scripts/restore_drv.sh
new file mode 100644
index 0000000..9046d04
--- /dev/null
+++ b/setup/Linux/oss/scripts/restore_drv.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+if test -f /etc/oss.conf
+then
+ . /etc/oss.conf
+else
+ OSSLIBDIR=/usr/lib/oss
+fi
+
+/usr/sbin/soundoff
+
+rm -rf /lib/modules/`uname -r`/kernel/oss
+
+if test -x /sbin/chkconfig
+then /sbin/chkconfig oss off > /dev/null 2>&1
+else
+ if test -x /sbin/update-rc.d
+ then /usr/sbin/update-rc.d -f oss remove > /dev/null 2>&1
+ fi
+fi
+
+rm -f /etc/init.d/oss
+
+if ! test -d /lib/modules/`uname -r`/kernel/sound
+then
+ if test -f /lib/modules/`uname -r`/sound-preoss.tar.bz2
+ then
+ (cd /lib/modules/`uname -r`; tar xfj sound-preoss.tar.bz2)
+ /sbin/depmod -a
+ fi
+fi
+
+rm -f /lib/modules/`uname -r`/sound-preoss.tar.bz2
+
+if test -f $OSSLIBDIR/sysfiles.list
+then
+ rm -f `cat $OSSLIBDIR/sysfiles.list`
+fi
+
+if test -f $OSSLIBDIR/save/alsadevs.tar.bz2
+then
+ (cd /;tar xfj $OSSLIBDIR/save/alsadevs.tar.bz2)
+fi
+
+if test -f $OSSLIBDIR/save/alsarc/tar.bz2
+then
+ (cd /;tar xfj $OSSLIBDIR/save/alsarc/tar.bz2)
+fi
+
+rm -f /dev/dsp* /dev/midi* /dev/mixer* /dev/sndstat
+
+/sbin/ldconfig
+
+if test -x /sbin/chkconfig
+then
+ /sbin/chkconfig alsasound on > /dev/null 2>&1
+else
+ if test -x /usr/sbin/update-rc.d
+ then
+ /usr/sbin/update-rc.d alsa-utils defaults > /dev/null 2>&1
+ fi
+fi
+
+exit 0
diff --git a/setup/Linux/oss/scripts/setup-alsa.sh b/setup/Linux/oss/scripts/setup-alsa.sh
new file mode 100644
index 0000000..fdcf4ff
--- /dev/null
+++ b/setup/Linux/oss/scripts/setup-alsa.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# This script will restgore selected ALSA modules that were earlier removed by
+# remove_drv.sh
+
+if test -d /proc/asound
+then
+# ALSA is already loaded
+ exit 0
+fi
+
+if ! test -f /lib/modules/`uname -r`/sound-preoss.tar.bz2
+then
+ echo ALSA backup archive /lib/modules/`uname -r`/sound-preoss.tar.bz2 not found. Cannot continue.
+ exit 1
+fi
+
+RESTORE=kernel/sound/soundcore.ko
+
+for n in snd snd-pcm snd-timer snd-page-alloc
+do
+ RESTORE="$RESTORE kernel/sound/core/$n.ko kernel/sound/acore/$n.ko"
+done
+
+(cd /lib/modules/`uname -r` && tar xvfj sound-preoss.tar.bz2 $RESTORE)
+
+if test -d /dev/snd.save && ! test -d /dev/snd
+then
+ mv /dev/snd.save /dev/snd
+fi
+
+exit 0
diff --git a/setup/Linux/oss/scripts/showprocs.sh b/setup/Linux/oss/scripts/showprocs.sh
new file mode 100755
index 0000000..827bb33
--- /dev/null
+++ b/setup/Linux/oss/scripts/showprocs.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+PROCS="`fuser /dev/mixer* /dev/dsp* /dev/audio* /dev/sequencer /dev/music /dev/midi*|sed 's/.* //'|sort|uniq`"
+
+if test "$PROCS " = " "
+then
+ exit 0
+fi
+
+if test "$1 " != "-q "
+then
+echo $PROCS
+echo
+echo "NOTICE!"
+echo "======="
+echo
+echo There are some programs still using OSS devices. You may need to stop them
+echo manually:
+echo
+fi
+
+for pid in $PROCS
+do
+ ps ax|grep "^ *$pid "
+done
+
+echo
+
+exit 0
diff --git a/setup/Linux/oss/soundon.user b/setup/Linux/oss/soundon.user
new file mode 100644
index 0000000..da31b6d
--- /dev/null
+++ b/setup/Linux/oss/soundon.user
@@ -0,0 +1,7 @@
+#!/bin/sh
+#
+# This script can be used to run programs every time OSS is started.
+# By default, this script is disabled, and contains no commands.
+# To enable, add executable permissions to this file, and edit below
+# commands to be run.
+exit 0
diff --git a/setup/Linux/postinst b/setup/Linux/postinst
new file mode 100644
index 0000000..f1ccbf3
--- /dev/null
+++ b/setup/Linux/postinst
@@ -0,0 +1,15 @@
+#!/bin/sh
+OSSLIBDIR=/usr/lib/oss
+if [ -e /tmp/OSS_UPGRADE ]; then rm /tmp/OSS_UPGRADE; fi
+if [ -e /etc/oss.conf ]; then . /etc/oss.conf; else echo "OSSLIBDIR=/usr/lib/oss" > /etc/oss.conf; fi
+echo "Building OSS Modules for Linux-`uname -p` `uname -r`"
+cd "$OSSLIBDIR"/build
+sh install.sh
+if [ -x /usr/bin/update-menus ]; then /usr/bin/update-menus; fi
+echo "Forcing re-detection of installed soundcards"
+ossdetect
+echo "Starting Open Sound System"
+sync
+/usr/sbin/soundoff >> /dev/null 2>&1
+sync
+/usr/sbin/soundon || exit 0
diff --git a/setup/Linux/postrm b/setup/Linux/postrm
new file mode 100644
index 0000000..620f8e2
--- /dev/null
+++ b/setup/Linux/postrm
@@ -0,0 +1,6 @@
+#!/bin/sh
+OSSLIBDIR=/usr/lib/oss
+if [ -e /etc/oss.conf ]; then . /etc/oss.conf; fi
+if [ -e /tmp/OSS_UPGRADE ]; then echo "Upgrading OSS - will not purge $OSSLIBDIR."; else rm -rf "$OSSLIBDIR"/*; fi
+rm -f /usr/lib/libflashsupport.so
+if [ -x /usr/bin/update-menus ]; then /usr/bin/update-menus; fi
diff --git a/setup/Linux/preinst b/setup/Linux/preinst
new file mode 100644
index 0000000..ae93962
--- /dev/null
+++ b/setup/Linux/preinst
@@ -0,0 +1,6 @@
+#!/bin/sh
+if [ -x /etc/init.d/alsa-utils ]; then /etc/init.d/alsa-utils stop || true; fi
+if [ -x /usr/sbin/alsa ]; then /usr/sbin/alsa force-unload || true; fi
+if [ -x /etc/init.d/alsa ]; then /etc/init.d/alsa force-unload || true; fi
+touch /tmp/OSS_UPGRADE
+exit 0
diff --git a/setup/Linux/prerm b/setup/Linux/prerm
new file mode 100644
index 0000000..67fdf0c
--- /dev/null
+++ b/setup/Linux/prerm
@@ -0,0 +1,4 @@
+#!/bin/sh
+OSSLIBDIR=/usr/lib/oss
+if [ -e /etc/oss.conf ]; then . /etc/oss.conf; fi
+sh "$OSSLIBDIR"/scripts/restore_drv.sh || true
diff --git a/setup/Linux/removeoss.sh b/setup/Linux/removeoss.sh
new file mode 100644
index 0000000..0e9d992
--- /dev/null
+++ b/setup/Linux/removeoss.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+if test `whoami` != "root"
+then
+ echo "You must be super-user or logged in as root to uninstall OSS..."
+ exit 0
+fi
+
+if test -f /etc/oss.conf
+then
+ . /etc/oss.conf
+else
+ OSSLIBDIR=/usr/lib/oss
+fi
+
+echo "Uninstalling OSS...."
+echo "Running soundoff...."
+/usr/sbin/soundoff
+echo "Restoring previously install sound drivers..."
+sh "$OSSLIBDIR"/scripts/restore_drv.sh
+echo "Removing OSS Files in MANIFEST"
+cd /
+for i in `cat "$OSSLIBDIR"/MANIFEST`
+do
+# echo "Removing file $i"
+rm -f $i
+done
+
+echo "Removing $OSSLIBDIR directory"
+rm -rf "$OSSLIBDIR"
+
+echo "OSS Uninstalled. However you may need to reboot the system."
diff --git a/setup/Linux/sbin/soundoff b/setup/Linux/sbin/soundoff
new file mode 100755
index 0000000..16ff69c
--- /dev/null
+++ b/setup/Linux/sbin/soundoff
@@ -0,0 +1,69 @@
+#!/bin/sh
+if test -f /etc/oss.conf
+then
+ . /etc/oss.conf
+else
+ OSSLIBDIR=/usr/lib/oss
+fi
+
+if ! test -f /proc/opensound/devfiles
+then
+ echo OSS not loaded.
+ exit 0
+fi
+
+if ! test -f $OSSLIBDIR/etc/installed_drivers
+then
+ echo $OSSLIBDIR/etc/installed_drivers is missing.
+ exit 1
+fi
+
+
+# Save mixer settings automatically if requested
+if test -f $OSSLIBDIR/etc/userdefs && grep -q "autosave_mixer yes" $OSSLIBDIR/etc/userdefs
+then
+ /usr/sbin/savemixer
+fi
+
+# Save legacy devices
+/usr/sbin/ossdevlinks -N
+
+PROGRAMS="`fuser /dev/mixer* /dev/dsp* /dev/midi* /dev/oss/*/* 2>/dev/null`"
+
+if test "$PROGRAMS " != " "
+then
+ echo
+ echo Some applications are still using OSS - cannot unload
+ echo
+
+ for n in $PROGRAMS
+ do
+ if test -f /proc/$n/cmdline
+ then
+ echo $n `cat /proc/$n/cmdline | sed 's/\x00/ /g'`
+ else
+ echo $n Unknown
+ fi
+ done
+
+ echo
+ echo Please stop these applications and run soundoff again
+ exit 2
+fi
+
+for i in 1 2 3
+do
+ for n in `egrep "^osscore" /proc/modules 2>/dev/null | cut -d ' ' -f 4 | sed 's/,/ /g'` `cat $OSSLIBDIR/etc/installed_drivers | sed 's/#.*//'` osscore
+ do
+ /sbin/modprobe -r $n > /dev/null 2>&1
+ done
+done
+
+if ! test -f /proc/opensound/devfiles # OSS gone?
+then
+ exit 0
+fi
+
+echo Cannot unload the OSS driver modules
+
+exit 3
diff --git a/setup/Linux/sbin/soundon b/setup/Linux/sbin/soundon
new file mode 100755
index 0000000..e868fd6
--- /dev/null
+++ b/setup/Linux/sbin/soundon
@@ -0,0 +1,351 @@
+#!/bin/sh
+if test -f /etc/oss.conf
+then
+ . /etc/oss.conf
+else
+ OSSLIBDIR=/usr/lib/oss
+fi
+
+if ! test -d /proc
+then
+ echo soundon script requires procfs to be mounted at /proc!
+ exit 200
+fi
+
+if test -f /proc/opensound/devfiles
+then
+ echo OSS is already loaded.
+ exit 0
+fi
+
+if test -f $OSSLIBDIR/starting
+then
+ echo Previous start of OSS crashed the system
+ echo Please resolve the situation and remove file
+ echo \"$OSSLIBDIR/starting\". Then start OSS by
+ echo running soundon again.
+ exit 1
+fi
+
+NOTIFY=0
+
+LOG=/var/log/soundon.log
+echo "Open Sound System starting" `date` > $LOG
+echo "OSS version: " `cat $OSSLIBDIR/version.dat` >> $LOG 2>&1
+KERNEL_VERSION=`uname -r`
+echo "Kernel version: " $KERNEL_VERSION >> $LOG
+KERNEL_VERMAGIC=`/usr/sbin/ossvermagic -z -s`
+echo "Kernel vermagic: " $KERNEL_VERMAGIC >> $LOG 2>&1
+
+if ! test -f $OSSLIBDIR/etc/installed_drivers
+then
+ echo No $OSSLIBDIR/etc/installed_drivers - running ossdetect >> $LOG
+ /usr/sbin/ossdetect -v >> $LOG
+fi
+
+if ! test -f $OSSLIBDIR/etc/installed_drivers
+then
+ echo Still no $OSSLIBDIR/etc/installed_drivers - cannot continue >> $LOG
+ echo No $OSSLIBDIR/etc/installed_drivers - cannot continue
+ exit 10
+fi
+
+UBUNTU_OVERRIDE=
+POS_UBUNTU_OVERRIDE=
+if test -f /lib/modules/$KERNEL_VERSION/kernel/oss/osscore.ko
+then
+# Verify that vermagic of OSS matches the kernel vermagic
+
+ OSS_VERMAGIC=`/usr/sbin/ossvermagic -z -q /lib/modules/$KERNEL_VERSION/kernel/oss/osscore.ko`
+
+ if ! test "$OSS_VERMAGIC " = "$KERNEL_VERMAGIC "
+ then
+ OSS_ORIG_VERMAGIC="$OSS_VERMAGIC"
+ OSS_VERMAGIC=`/usr/sbin/ossvermagic -z -u -q /lib/modules/$KERNEL_VERSION/kernel/oss/osscore.ko`
+ POS_UBUNTU_OVERRIDE=1
+ fi
+
+ if ! test "$OSS_VERMAGIC " = "$KERNEL_VERMAGIC "
+ then
+ echo "Old vermagic: " $OSS_VERMAGIC >> $LOG
+ rm -rf /lib/modules/$KERNEL_VERSION/kernel/oss
+ echo Previous OSS modules were for a different kernel version - removed
+ echo Previous OSS modules were for a different kernel version - removed >> $LOG
+ elif test "$POS_UBUNTU_OVERRIDE " = "1 "
+ then
+ echo "Vermagic backup check activated for Ubuntu. Backup vermagic: $OSS_VERMAGIC. OSS stored vermagic $OSS_ORIG_VERMAGIC" >> $LOG
+ UBUNTU_OVERRIDE="-u"
+ fi
+fi
+
+if ! test -f /lib/modules/$KERNEL_VERSION/kernel/oss/osscore.ko
+then
+ NOTIFY=1
+ echo Relinking OSS kernel modules for \"$KERNEL_VERMAGIC\"
+ echo This may take few moments - please stand by...
+ echo Relinking OSS kernel modules for $KERNEL_VERMAGIC >> $LOG
+
+ rm -f /var/log/relink.log
+ if ! (cd $OSSLIBDIR/build && sh install.sh > /var/log/relink.log 2>&1)
+ then
+ cat /var/log/relink.log >> $LOG 2>&1
+ cat /var/log/relink.log
+ echo
+ echo Relinking the OSS kernel modules failed
+ rm -f /var/log/relink.log
+ exit 20
+ fi
+
+ cat /var/log/relink.log >> $LOG 2>&1
+ echo Relinking OSS kernel modules finished
+ rm -f /var/log/relink.log
+fi
+
+if ! test -f /lib/modules/$KERNEL_VERSION/kernel/oss/osscore.ko
+then
+ echo
+ echo No /lib/modules/$KERNEL_VERSION/kernel/oss/osscore.ko module >> $LOG
+ echo No /lib/modules/$KERNEL_VERSION/kernel/oss/osscore.ko module in the system
+ exit 30
+fi
+
+OSS_VERMAGIC=`/usr/sbin/ossvermagic -z $UBUNTU_OVERRIDE -q /lib/modules/$KERNEL_VERSION/kernel/oss/osscore.ko`
+echo "OSS vermagic: " $OSS_VERMAGIC >> $LOG
+
+if ! test "$OSS_VERMAGIC " = "$KERNEL_VERMAGIC "
+then
+ echo OSS driver modules do not match the current kernel >> $LOG
+ echo
+ echo Error: OSS driver modules do not match the current kernel
+ echo
+ echo "Kernel vermagic: " $KERNEL_VERMAGIC
+ echo "OSS vermagic: " $OSS_VERMAGIC
+ echo
+ echo The most likely reason is that the kernel development package
+ echo installed in the system is wrong. Please refer to the documentation
+ echo of your Linux distribution for more info about setting up the
+ echo kernel/driver development environment properly.
+ echo
+ exit 40
+fi
+
+if test -f $OSSLIBDIR/etc/license.asc
+then
+ /usr/sbin/ossdetect -l >> $LOG
+fi
+
+if test -d /proc/asound || grep -q '^ *14 ' < /proc/devices
+then
+ if ! sh $OSSLIBDIR/scripts/remove_drv.sh>> $LOG
+ then
+ echo Failed to disable conflicting sound drivers >> $LOG
+ echo Failed to disable conflicting sound drivers
+ echo Reboot and try running soundon again
+ echo
+ echo Also check that you have not compiled sound support statically
+ echo into the kernel.
+ exit 50
+ fi
+fi
+
+echo >> $LOG
+echo '*** Loading OSS kernel modules ***' >> $LOG
+echo >> $LOG
+
+touch $OSSLIBDIR/starting
+sync
+
+OPTIONS=
+if test -f $OSSLIBDIR/conf/osscore.conf
+then
+ OPTIONS="`grep -v -h '^#' $OSSLIBDIR/conf/osscore.conf|sed 's/[ \t]//g'`"
+fi
+
+if ! /sbin/modprobe osscore $OPTIONS
+then
+ echo Loading the osscore module failed
+ echo Loading the osscore module failed >> $LOG
+ dmesg >> $LOG
+ exit 60
+fi
+
+echo "osscore module loaded OK" >> $LOG
+
+for n in `cat $OSSLIBDIR/etc/installed_drivers | sed 's/#.*//'`
+do
+ OPTIONS=
+
+ if test -f $OSSLIBDIR/conf/$n.conf
+ then
+ OPTIONS="`grep -v -h '^#' $OSSLIBDIR/conf/$n.conf|sed 's/[ \t]//g'`"
+ fi
+
+ if ! /sbin/modprobe $n $OPTIONS
+ then
+ echo Loading module $n failed '-' ignored >> $LOG
+ echo Loading module $n failed '-' ignored
+ else
+ echo $n module loaded OK >> $LOG
+ fi
+done
+echo >> $LOG
+echo '*** Finished loading OSS kernel modules ***' >> $LOG
+echo >> $LOG
+
+if ! test -f /proc/opensound/devfiles
+then
+ echo OSS Core module refused to start >> $LOG
+ echo OSS Core module refused to start
+ dmesg >> $LOG
+ exit 70
+fi
+
+/usr/sbin/ossdetect -d >> $LOG 2>&1
+
+# Restore the legacy device links. This is necessary because in some
+# Linux distributions they get lost when the system is booted.
+if test -f $OSSLIBDIR/etc/legacy_devices
+then
+ sh $OSSLIBDIR/etc/legacy_devices >> $LOG 2>&1
+fi
+
+/usr/sbin/ossdevlinks -v >> $LOG 2>&1
+
+echo "+++ ossinfo -v3 +++" >> $LOG
+ossinfo -v3 >> $LOG 2>&1
+echo "+++ /dev/sndstat +++" >> $LOG
+cat /dev/sndstat >> $LOG 2>&1
+echo "+++ dmesg +++" >> $LOG
+dmesg >> $LOG
+echo "+++ lspci +++" >> $LOG
+lspci -vnn >> $LOG 2>&1
+echo "+++ /proc/interrupts +++" >> $LOG
+cat /proc/interrupts >> $LOG 2>&1
+echo "+++ /proc/cpuinfo +++" >> $LOG
+cat /proc/cpuinfo >> $LOG 2>&1
+echo "+++ /proc/opensound/devfiles +++" >> $LOG
+cat /proc/opensound/devfiles >> $LOG 2>&1
+ls -l /dev/dsp* /dev/mixer* /dev/midi* /dev/oss/*/* >> $LOG 2>&1
+
+echo >> $LOG
+/usr/sbin/savemixer -L -v >> $LOG 2>&1
+
+# Setup ALSA emulation
+
+if test -f $OSSLIBDIR/.cuckoo_installed
+then
+# Use kernel based ALSA compatibility
+
+ if ! test -f /lib/modules/$KERNEL_VERSION/kernel/sound/core/snd.ko
+ then
+ sh $OSSLIBDIR/scripts/setup-alsa.sh >> $LOG 2>&1
+ depmod -a
+ fi
+
+ echo "*** Setting up ALSA compatibility ****" >> $LOG
+ modprobe cuckoo >> $LOG 2>&1
+ head -10 /proc/asound/version >> $LOG 2>&1
+ lsmod|grep snd >> $LOG
+ echo "**************************************" >> $LOG
+elif test -f $OSSLIBDIR/.libsalsa_installed
+then
+# Use library based ALSA compatibility
+
+ if test -f $OSSLIBDIR/lib/libsalsa.so.2.0.0
+ then
+ if test "`uname -m` " = "x86_64 "
+ then
+ ln -sf $OSSLIBDIR/lib/libsalsa.so.2.0.0 /usr/lib64/libasound.so.2
+ #ln -sf $OSSLIBDIR/lib/libOSSlib.so /usr/lib64
+ else
+ if test -s /lib/libasound.so.2
+ then
+ ln -sf $OSSLIBDIR/lib/libsalsa.so.2.0.0 /lib/libasound.so.2
+ #ln -sf $OSSLIBDIR/lib/libOSSlib.so /lib
+ fi
+
+ if test -s /usr/lib/libasound.so.2
+ then
+ ln -sf $OSSLIBDIR/lib/libsalsa.so.2.0.0 /usr/lib/libasound.so.2
+ #ln -sf $OSSLIBDIR/lib/libOSSlib.so /usr/lib
+ fi
+ fi
+ fi
+fi
+
+# Setup libOSSlib.so
+if test -f $OSSLIBDIR/lib/libOSSlib.so
+then
+ if test "`uname -m` " = "x86_64 "
+ then
+ ln -sf $OSSLIBDIR/lib/libOSSlib.so /usr/lib64
+ ln -sf $OSSLIBDIR/lib/libossmix.so /usr/lib64
+ else
+ if test -s /lib/libasound.so.2
+ then
+ ln -sf $OSSLIBDIR/lib/libOSSlib.so /lib
+ ln -sf $OSSLIBDIR/lib/libossmix.so /lib
+ fi
+
+ if test -s /usr/lib/libasound.so.2
+ then
+ ln -sf $OSSLIBDIR/lib/libOSSlib.so /usr/lib
+ ln -sf $OSSLIBDIR/lib/libossmix.so /usr/lib
+ fi
+ fi
+fi
+
+# Setup Flash 9 audio support plugin for OSS
+
+if test -d /usr/lib64 && test -f $OSSLIBDIR/lib/libflashsupport_64.so
+then
+ ln -sf $OSSLIBDIR/lib/libflashsupport_64.so /usr/lib64/libflashsupport.so
+fi
+
+if test -d /usr/lib32 && test -f $OSSLIBDIR/lib/libflashsupport_32.so
+then
+ ln -sf $OSSLIBDIR/lib/libflashsupport_32.so /usr/lib32/libflashsupport.so
+fi
+
+if ! test -f /usr/lib/libflashsupport.so && test -f $OSSLIBDIR/lib/libflashsupport_32.so
+then
+ ln -sf $OSSLIBDIR/lib/libflashsupport_32.so /usr/lib/libflashsupport.so
+fi
+
+if test -x $OSSLIBDIR/soundon.user
+then
+ echo Running $OSSLIBDIR/soundon.user >> $LOG
+ $OSSLIBDIR/soundon.user >> $LOG 2>&1
+fi
+
+if test "`ossinfo -g|grep TRIAL` " != " "
+then
+ echo
+ echo "************************************************************"
+ echo "* NOTE! You are using trial version of Open Sound System *"
+ echo "************************************************************"
+ echo
+
+ sleep 1
+fi
+
+if test "`ossinfo -g|grep EXPIRED` " != " "
+then
+ echo
+ echo "****************************************************************"
+ echo "* NOTE! Your Open Sound System evaluation license has expired *"
+ echo "****************************************************************"
+ echo
+
+ sleep 15
+fi
+
+if test "$NOTIFY " = "1 "
+then
+ echo
+ echo OSS started OK
+fi
+
+rm -f $OSSLIBDIR/starting
+
+exit 0
diff --git a/setup/Linux/shlibs b/setup/Linux/shlibs
new file mode 100644
index 0000000..95e6d37
--- /dev/null
+++ b/setup/Linux/shlibs
@@ -0,0 +1 @@
+libsalsa 2 oss-linux
diff --git a/setup/Linux/spec.tmpl b/setup/Linux/spec.tmpl
new file mode 100644
index 0000000..2861496
--- /dev/null
+++ b/setup/Linux/spec.tmpl
@@ -0,0 +1,39 @@
+Summary: Open Sound System sound drivers for Linux
+License: Open Sound System
+Group: System/sound
+Source: oss
+URL: http://www.opensound.com
+Distribution: Open Sound System
+Vendor: 4Front Technologies
+Packager: 4Front Technologies
+BuildRoot: /tmp/prototype
+Requires: gcc, make
+%if 0%{?suse_version}
+Requires: kernel-default-devel
+%else
+Requires: kernel-devel
+%endif
+
+%description
+Open Sound System for Linux (OSS/Linux) is a commercial quality sound driver
+distributed by 4Front Technologies (http://www.opensound.com). OSS provides
+support for practically all sound cards on the market including PnP and
+many PCI ones. Installation and configuration is higly automated and easy to
+perform. To obtain technical support and additional features, you will need to
+order a license key from http://www.opensound.com/order.html
+%prep
+%setup
+%pre
+%post
+echo "Building OSS Modules for Linux-`uname -p` `uname -r`"
+cd OSSLIBDIR/build
+sh install.sh
+echo "Starting Open Sound System"
+/usr/sbin/soundoff >> /dev/null 2>&1
+/usr/sbin/soundon
+exit 0
+%preun
+sh OSSLIBDIR/scripts/restore_drv.sh
+%postun
+rm -rf OSSLIBDIR/*
+rm -f /usr/lib/libflashsupport.so