summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcvs2svn <cvs2svn@FreeBSD.org>2001-05-27 23:14:28 +0000
committercvs2svn <cvs2svn@FreeBSD.org>2001-05-27 23:14:28 +0000
commit7b1532323ba008e721d70ac4da35c9e324c27d6c (patch)
tree05b07205c79cd5cfb0f5ed46e87c972320592efb
parent45c017f9e38e265d9d905746603d4bed5146c3ee (diff)
Notes
-rw-r--r--lib/libc/string/wcscat.c59
-rw-r--r--lib/libc/string/wcschr.c57
-rw-r--r--lib/libc/string/wcscmp.c66
-rw-r--r--lib/libc/string/wcscpy.c57
-rw-r--r--lib/libc/string/wcscspn.c62
-rw-r--r--lib/libc/string/wcslcat.c79
-rw-r--r--lib/libc/string/wcslcpy.c75
-rw-r--r--lib/libc/string/wcslen.c52
-rw-r--r--lib/libc/string/wcsncat.c62
-rw-r--r--lib/libc/string/wcsncmp.c68
-rw-r--r--lib/libc/string/wcsncpy.c60
-rw-r--r--lib/libc/string/wcspbrk.c62
-rw-r--r--lib/libc/string/wcsrchr.c59
-rw-r--r--lib/libc/string/wcsspn.c63
-rw-r--r--lib/libc/string/wcsstr.c75
-rw-r--r--lib/libc/string/wcswidth.c56
-rw-r--r--lib/libc/string/wmemchr.c57
-rw-r--r--lib/libc/string/wmemcmp.c58
-rw-r--r--lib/libc/string/wmemcpy.c50
-rw-r--r--lib/libc/string/wmemmove.c50
-rw-r--r--lib/libc/string/wmemset.c56
-rw-r--r--sbin/ifconfig/ifieee80211.c520
-rw-r--r--share/examples/isdn/KERNEL78
-rw-r--r--share/examples/isdn/contrib/README42
-rw-r--r--share/examples/isdn/contrib/anleitung.ppp142
-rw-r--r--share/examples/isdn/contrib/answer.c178
-rw-r--r--share/examples/isdn/contrib/answer.sh111
-rw-r--r--share/examples/isdn/contrib/convert.sh86
-rw-r--r--share/examples/isdn/contrib/hplay.c241
-rw-r--r--share/examples/isdn/contrib/i4b-ppp-newbie.txt237
-rw-r--r--share/examples/isdn/contrib/isdnctl111
-rw-r--r--share/examples/isdn/contrib/isdnd_acct137
-rw-r--r--share/examples/isdn/contrib/isdnd_acct.pl258
-rw-r--r--share/examples/isdn/contrib/isdntelmux.c197
-rw-r--r--share/examples/isdn/contrib/mrtg-isp0.sh53
-rw-r--r--share/examples/isdn/v21/Makefile12
-rw-r--r--share/examples/isdn/v21/README50
-rw-r--r--share/man/man4/ieee80211.4234
-rw-r--r--share/man/man7/firewall.7375
-rw-r--r--share/man/man7/tuning.7478
-rw-r--r--sys/dev/pccbb/pccbbdevid.h65
-rw-r--r--sys/dev/sound/pcm/feeder_rate.c192
-rw-r--r--sys/dev/sound/pcm/vchan.h33
-rw-r--r--sys/i4b/capi/README150
-rw-r--r--sys/i4b/capi/capi.h129
-rw-r--r--sys/i4b/capi/capi_l4if.c450
-rw-r--r--sys/i4b/capi/capi_llif.c166
-rw-r--r--sys/i4b/capi/capi_msgs.c948
-rw-r--r--sys/i4b/capi/capi_msgs.h380
-rw-r--r--sys/i4b/capi/iavc/iavc.h586
-rw-r--r--sys/i4b/capi/iavc/iavc_card.c292
-rw-r--r--sys/i4b/capi/iavc/iavc_isa.c297
-rw-r--r--sys/i4b/capi/iavc/iavc_pci.c283
-rw-r--r--usr.sbin/i4b/man/i4bcapi.459
-rw-r--r--usr.sbin/i4b/man/iavc.472
55 files changed, 8925 insertions, 0 deletions
diff --git a/lib/libc/string/wcscat.c b/lib/libc/string/wcscat.c
new file mode 100644
index 000000000000..861822bb092e
--- /dev/null
+++ b/lib/libc/string/wcscat.c
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcscat.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+wchar_t *
+wcscat(s1, s2)
+ wchar_t *s1;
+ const wchar_t *s2;
+{
+ wchar_t *p;
+ wchar_t *q;
+ const wchar_t *r;
+
+ p = s1;
+ while (*p)
+ p++;
+ q = p;
+ r = s2;
+ while (*r)
+ *q++ = *r++;
+ *q = '\0';
+ return s1;
+}
diff --git a/lib/libc/string/wcschr.c b/lib/libc/string/wcschr.c
new file mode 100644
index 000000000000..6eebfbacf63a
--- /dev/null
+++ b/lib/libc/string/wcschr.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcschr.c,v 1.2 2000/12/21 05:07:25 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcschr.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+wchar_t *
+wcschr(s, c)
+ const wchar_t *s;
+ wchar_t c;
+{
+ const wchar_t *p;
+
+ p = s;
+ while (*p) {
+ if (*p == c) {
+ /* LINTED interface specification */
+ return (wchar_t *)p;
+ }
+ p++;
+ }
+ return NULL;
+}
diff --git a/lib/libc/string/wcscmp.c b/lib/libc/string/wcscmp.c
new file mode 100644
index 000000000000..dcf9b57e7357
--- /dev/null
+++ b/lib/libc/string/wcscmp.c
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)strcmp.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD$");
+#endif
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+/*
+ * Compare strings.
+ */
+int
+wcscmp(s1, s2)
+ const wchar_t *s1, *s2;
+{
+
+ while (*s1 == *s2++)
+ if (*s1++ == 0)
+ return (0);
+ /* XXX assumes wchar_t = int */
+ return (*(const unsigned int *)s1 - *(const unsigned int *)--s2);
+}
diff --git a/lib/libc/string/wcscpy.c b/lib/libc/string/wcscpy.c
new file mode 100644
index 000000000000..d05804af1431
--- /dev/null
+++ b/lib/libc/string/wcscpy.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcscpy.c,v 1.2 2000/12/21 04:51:09 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+wchar_t *
+wcscpy(s1, s2)
+ wchar_t *s1;
+ const wchar_t *s2;
+{
+ wchar_t *p;
+ const wchar_t *q;
+
+ *s1 = '\0';
+ p = s1;
+ q = s2;
+ while (*q)
+ *p++ = *q++;
+ *p = '\0';
+
+ return s1;
+}
diff --git a/lib/libc/string/wcscspn.c b/lib/libc/string/wcscspn.c
new file mode 100644
index 000000000000..7309574625c8
--- /dev/null
+++ b/lib/libc/string/wcscspn.c
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcscspn.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscspn.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+size_t
+wcscspn(s, set)
+ const wchar_t *s;
+ const wchar_t *set;
+{
+ const wchar_t *p;
+ const wchar_t *q;
+
+ p = s;
+ while (*p) {
+ q = set;
+ while (*q) {
+ if (*p == *q)
+ goto done;
+ q++;
+ }
+ p++;
+ }
+
+done:
+ return (p - s);
+}
diff --git a/lib/libc/string/wcslcat.c b/lib/libc/string/wcslcat.c
new file mode 100644
index 000000000000..3634bfd5be3a
--- /dev/null
+++ b/lib/libc/string/wcslcat.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from OpenBSD: strlcat.c,v 1.3 2000/11/24 11:10:02 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslcat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <sys/types.h>
+#include <assert.h>
+#include <wchar.h>
+
+/*
+ * Appends src to string dst of size siz (unlike wcsncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns wcslen(initial dst) + wcslen(src); if retval >= siz,
+ * truncation occurred.
+ */
+size_t
+wcslcat(dst, src, siz)
+ wchar_t *dst;
+ const wchar_t *src;
+ size_t siz;
+{
+ wchar_t *d = dst;
+ const wchar_t *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (*d != '\0' && n-- != 0)
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + wcslen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
diff --git a/lib/libc/string/wcslcpy.c b/lib/libc/string/wcslcpy.c
new file mode 100644
index 000000000000..240feb4b5bd3
--- /dev/null
+++ b/lib/libc/string/wcslcpy.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslcpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <sys/types.h>
+#include <assert.h>
+#include <wchar.h>
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns wcslen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+wcslcpy(dst, src, siz)
+ wchar_t *dst;
+ const wchar_t *src;
+ size_t siz;
+{
+ wchar_t *d = dst;
+ const wchar_t *s = src;
+ size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
diff --git a/lib/libc/string/wcslen.c b/lib/libc/string/wcslen.c
new file mode 100644
index 000000000000..8e3039510b8b
--- /dev/null
+++ b/lib/libc/string/wcslen.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcslen.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslen.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+size_t
+wcslen(s)
+ const wchar_t *s;
+{
+ const wchar_t *p;
+
+ p = s;
+ while (*p)
+ p++;
+
+ return p - s;
+}
diff --git a/lib/libc/string/wcsncat.c b/lib/libc/string/wcsncat.c
new file mode 100644
index 000000000000..8d98bdb44293
--- /dev/null
+++ b/lib/libc/string/wcsncat.c
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcsncat.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcsncat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+wchar_t *
+wcsncat(s1, s2, n)
+ wchar_t *s1;
+ const wchar_t *s2;
+ size_t n;
+{
+ wchar_t *p;
+ wchar_t *q;
+ const wchar_t *r;
+
+ p = s1;
+ while (*p)
+ p++;
+ q = p;
+ r = s2;
+ while (*r && n) {
+ *q++ = *r++;
+ n--;
+ }
+ *q = '\0';
+ return s1;
+}
diff --git a/lib/libc/string/wcsncmp.c b/lib/libc/string/wcsncmp.c
new file mode 100644
index 000000000000..bc1abe7ecbbf
--- /dev/null
+++ b/lib/libc/string/wcsncmp.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)strncmp.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD$");
+#endif
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+int
+wcsncmp(s1, s2, n)
+ const wchar_t *s1, *s2;
+ size_t n;
+{
+
+ if (n == 0)
+ return (0);
+ do {
+ if (*s1 != *s2++) {
+ /* XXX assumes wchar_t = int */
+ return (*(const unsigned int *)s1 -
+ *(const unsigned int *)--s2);
+ }
+ if (*s1++ == 0)
+ break;
+ } while (--n != 0);
+ return (0);
+}
diff --git a/lib/libc/string/wcsncpy.c b/lib/libc/string/wcsncpy.c
new file mode 100644
index 000000000000..907344b56771
--- /dev/null
+++ b/lib/libc/string/wcsncpy.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcsncpy.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcsncpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+wchar_t *
+wcsncpy(s1, s2, n)
+ wchar_t *s1;
+ const wchar_t *s2;
+ size_t n;
+{
+ wchar_t *p;
+ const wchar_t *q;
+
+ *s1 = '\0';
+ p = s1;
+ q = s2;
+ while (n && *q) {
+ *p++ = *q++;
+ n--;
+ }
+ *p = '\0';
+
+ return s1;
+}
diff --git a/lib/libc/string/wcspbrk.c b/lib/libc/string/wcspbrk.c
new file mode 100644
index 000000000000..2808ed25a278
--- /dev/null
+++ b/lib/libc/string/wcspbrk.c
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcspbrk.c,v 1.2 2000/12/21 05:07:25 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcspbrk.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+wchar_t *
+wcspbrk(s, set)
+ const wchar_t *s;
+ const wchar_t *set;
+{
+ const wchar_t *p;
+ const wchar_t *q;
+
+ p = s;
+ while (*p) {
+ q = set;
+ while (*q) {
+ if (*p == *q) {
+ /* LINTED interface specification */
+ return (wchar_t *)p;
+ }
+ q++;
+ }
+ p++;
+ }
+ return NULL;
+}
diff --git a/lib/libc/string/wcsrchr.c b/lib/libc/string/wcsrchr.c
new file mode 100644
index 000000000000..4dc9b4bf7bb3
--- /dev/null
+++ b/lib/libc/string/wcsrchr.c
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcsrchr.c,v 1.2 2000/12/21 05:07:25 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcsrchr.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+wchar_t *
+wcsrchr(s, c)
+ const wchar_t *s;
+ wchar_t c;
+{
+ const wchar_t *p;
+
+ p = s;
+ while (*p)
+ p++;
+ while (s <= p) {
+ if (*p == c) {
+ /* LINTED interface specification */
+ return (wchar_t *)p;
+ }
+ p--;
+ }
+ return NULL;
+}
diff --git a/lib/libc/string/wcsspn.c b/lib/libc/string/wcsspn.c
new file mode 100644
index 000000000000..40b583b3eb55
--- /dev/null
+++ b/lib/libc/string/wcsspn.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcsspn.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcsspn.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+size_t
+wcsspn(s, set)
+ const wchar_t *s;
+ const wchar_t *set;
+{
+ const wchar_t *p;
+ const wchar_t *q;
+
+ p = s;
+ while (*p) {
+ q = set;
+ while (*q) {
+ if (*p == *q)
+ break;
+ }
+ if (!*q)
+ goto done;
+ p++;
+ }
+
+done:
+ return (p - s);
+}
diff --git a/lib/libc/string/wcsstr.c b/lib/libc/string/wcsstr.c
new file mode 100644
index 000000000000..1e4cf215ba69
--- /dev/null
+++ b/lib/libc/string/wcsstr.c
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcsstr.c,v 1.2 2000/12/21 05:07:25 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcsstr.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+wchar_t *
+wcsstr(big, little)
+ const wchar_t *big;
+ const wchar_t *little;
+{
+ const wchar_t *p;
+ const wchar_t *q;
+ const wchar_t *r;
+
+ if (!*little) {
+ /* LINTED interface specification */
+ return (wchar_t *)big;
+ }
+ if (wcslen(big) < wcslen(little))
+ return NULL;
+
+ p = big;
+ q = little;
+ while (*p) {
+ q = little;
+ r = p;
+ while (*q) {
+ if (*r != *q)
+ break;
+ q++;
+ r++;
+ }
+ if (!*q) {
+ /* LINTED interface specification */
+ return (wchar_t *)p;
+ }
+ p++;
+ }
+ return NULL;
+}
diff --git a/lib/libc/string/wcswidth.c b/lib/libc/string/wcswidth.c
new file mode 100644
index 000000000000..3ad70c1422a8
--- /dev/null
+++ b/lib/libc/string/wcswidth.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcswidth.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcswidth.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+int
+wcswidth(s, n)
+ const wchar_t *s;
+ size_t n;
+{
+ int w;
+
+ w = 0;
+ while (n && *s) {
+ w += wcwidth(*s);
+ s++;
+ n--;
+ }
+
+ return w;
+}
diff --git a/lib/libc/string/wmemchr.c b/lib/libc/string/wmemchr.c
new file mode 100644
index 000000000000..fa49a7485776
--- /dev/null
+++ b/lib/libc/string/wmemchr.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wmemchr.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemchr.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+wchar_t *
+wmemchr(s, c, n)
+ const wchar_t *s;
+ wchar_t c;
+ size_t n;
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ if (*s == c) {
+ /* LINTED const castaway */
+ return (wchar_t *)s;
+ }
+ s++;
+ }
+ return NULL;
+}
diff --git a/lib/libc/string/wmemcmp.c b/lib/libc/string/wmemcmp.c
new file mode 100644
index 000000000000..158bf09a202e
--- /dev/null
+++ b/lib/libc/string/wmemcmp.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wmemcmp.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemcmp.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+int
+wmemcmp(s1, s2, n)
+ const wchar_t *s1;
+ const wchar_t *s2;
+ size_t n;
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ if (*s1 != *s2) {
+ /* wchar might be unsigned */
+ return *s1 > *s2 ? 1 : -1;
+ }
+ s1++;
+ s2++;
+ }
+ return 0;
+}
diff --git a/lib/libc/string/wmemcpy.c b/lib/libc/string/wmemcpy.c
new file mode 100644
index 000000000000..bb8d05858501
--- /dev/null
+++ b/lib/libc/string/wmemcpy.c
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wmemcpy.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemcpy.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <string.h>
+#include <wchar.h>
+
+wchar_t *
+wmemcpy(d, s, n)
+ wchar_t *d;
+ const wchar_t *s;
+ size_t n;
+{
+
+ return (wchar_t *)memcpy(d, s, n * sizeof(wchar_t));
+}
diff --git a/lib/libc/string/wmemmove.c b/lib/libc/string/wmemmove.c
new file mode 100644
index 000000000000..edf8d1d8290c
--- /dev/null
+++ b/lib/libc/string/wmemmove.c
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wmemmove.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemmove.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <string.h>
+#include <wchar.h>
+
+wchar_t *
+wmemmove(d, s, n)
+ wchar_t *d;
+ const wchar_t *s;
+ size_t n;
+{
+
+ return (wchar_t *)memmove(d, s, n * sizeof(wchar_t));
+}
diff --git a/lib/libc/string/wmemset.c b/lib/libc/string/wmemset.c
new file mode 100644
index 000000000000..08ce087b2931
--- /dev/null
+++ b/lib/libc/string/wmemset.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wmemset.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemset.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <assert.h>
+#include <wchar.h>
+
+wchar_t *
+wmemset(s, c, n)
+ wchar_t *s;
+ wchar_t c;
+ size_t n;
+{
+ size_t i;
+ wchar_t *p;
+
+ p = (wchar_t *)s;
+ for (i = 0; i < n; i++) {
+ *p = c;
+ p++;
+ }
+ return s;
+}
diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c
new file mode 100644
index 000000000000..0566dcd7e9bc
--- /dev/null
+++ b/sbin/ifconfig/ifieee80211.c
@@ -0,0 +1,520 @@
+/*
+ * Copyright 2001 The Aerospace Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*-
+ * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+#include <net/if_ieee80211.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ifconfig.h"
+
+static void set80211(int s, int type, int val, int len, u_int8_t *data);
+static const char *get_string(const char *val, const char *sep,
+ u_int8_t *buf, int *lenp);
+static void print_string(const u_int8_t *buf, int len);
+
+void
+set80211ssid(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int ssid;
+ int len;
+ u_int8_t data[33];
+
+ ssid = 0;
+
+ bzero(data, sizeof(data));
+ len = sizeof(data);
+ get_string(val, NULL, data, &len);
+
+ set80211(s, IEEE80211_IOC_SSID, ssid, len, data);
+}
+
+void
+set80211stationname(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int len;
+ u_int8_t data[33];
+
+ bzero(data, sizeof(data));
+ len = sizeof(data);
+ get_string(val, NULL, data, &len);
+
+ set80211(s, IEEE80211_IOC_STATIONNAME, 0, len, data);
+}
+
+void
+set80211channel(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_CHANNEL, atoi(val), 0, NULL);
+}
+
+void
+set80211authmode(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int mode;
+
+ if(strcasecmp(val, "none") == 0) {
+ mode = IEEE80211_AUTH_NONE;
+ } else if(strcasecmp(val, "open") == 0) {
+ mode = IEEE80211_AUTH_OPEN;
+ } else if(strcasecmp(val, "shared") == 0) {
+ mode = IEEE80211_AUTH_SHARED;
+ } else {
+ err(1, "unknown authmode");
+ }
+
+ set80211(s, IEEE80211_IOC_AUTHMODE, mode, 0, NULL);
+}
+
+void
+set80211powersavemode(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int mode;
+
+ if(strcasecmp(val, "off") == 0) {
+ mode = IEEE80211_POWERSAVE_OFF;
+ } else if(strcasecmp(val, "on") == 0) {
+ mode = IEEE80211_POWERSAVE_ON;
+ } else if(strcasecmp(val, "cam") == 0) {
+ mode = IEEE80211_POWERSAVE_CAM;
+ } else if(strcasecmp(val, "psp") == 0) {
+ mode = IEEE80211_POWERSAVE_PSP;
+ } else if(strcasecmp(val, "psp-cam") == 0) {
+ mode = IEEE80211_POWERSAVE_PSP_CAM;
+ } else {
+ err(1, "unknown powersavemode");
+ }
+
+ set80211(s, IEEE80211_IOC_POWERSAVE, mode, 0, NULL);
+}
+
+void
+set80211powersave(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ if (d == 0)
+ set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF,
+ 0, NULL);
+ else
+ set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON,
+ 0, NULL);
+}
+
+void
+set80211powersavesleep(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL);
+}
+
+void
+set80211wepmode(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int mode;
+
+ if(strcasecmp(val, "off") == 0) {
+ mode = IEEE80211_WEP_OFF;
+ } else if(strcasecmp(val, "on") == 0) {
+ mode = IEEE80211_WEP_ON;
+ } else if(strcasecmp(val, "mixed") == 0) {
+ mode = IEEE80211_WEP_MIXED;
+ } else {
+ err(1, "unknown wep mode");
+ }
+
+ set80211(s, IEEE80211_IOC_WEP, mode, 0, NULL);
+}
+
+void
+set80211wep(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_WEP, d, 0, NULL);
+}
+
+void
+set80211weptxkey(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL);
+}
+
+void
+set80211wepkey(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int key = 0;
+ int len;
+ u_int8_t data[14];
+
+ if(isdigit(val[0]) && val[1] == ':') {
+ key = atoi(val)-1;
+ val += 2;
+ }
+
+ bzero(data, sizeof(data));
+ len = sizeof(data);
+ get_string(val, NULL, data, &len);
+
+ set80211(s, IEEE80211_IOC_WEPKEY, key, len, data);
+}
+
+/*
+ * This function is purly a NetBSD compatability interface. The NetBSD
+ * iterface is too inflexable, but it's there so we'll support it since
+ * it's not all that hard.
+ */
+void
+set80211nwkey(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int txkey;
+ int i, len;
+ u_int8_t data[14];
+
+ set80211(s, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL);
+
+ if(isdigit(val[0]) && val[1] == ':') {
+ txkey = val[0]-'0'-1;
+ val += 2;
+
+ for(i = 0; i < 4; i++) {
+ bzero(data, sizeof(data));
+ len = sizeof(data);
+ val = get_string(val, ",", data, &len);
+
+ set80211(s, IEEE80211_IOC_WEPKEY, i, len, data);
+ }
+ } else {
+ bzero(data, sizeof(data));
+ len = sizeof(data);
+ get_string(val, NULL, data, &len);
+ txkey = 0;
+
+ set80211(s, IEEE80211_IOC_WEPKEY, 0, len, data);
+
+ bzero(data, sizeof(data));
+ for(i = 1; i < 4; i++)
+ set80211(s, IEEE80211_IOC_WEPKEY, i, 0, data);
+ }
+
+ set80211(s, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL);
+}
+
+void
+ieee80211_status (s, info)
+ int s;
+ struct rt_addrinfo *info __unused;
+{
+ int i;
+ int num;
+ struct ieee80211req ireq;
+ u_int8_t data[32];
+ char spacer;
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
+ ireq.i_data = &data;
+
+ ireq.i_type = IEEE80211_IOC_SSID;
+ ireq.i_val = -1;
+ if (ioctl(s, SIOCG80211, &ireq) < 0) {
+ /* If we can't get the SSID, the this isn't an 802.11 device. */
+ return;
+ }
+ printf("\tssid ");
+ print_string(data, ireq.i_len);
+ printf("\n");
+
+ ireq.i_type = IEEE80211_IOC_STATIONNAME;
+ if (ioctl(s, SIOCG80211, &ireq) != -1) {
+ printf("\tstationname ");
+ print_string(data, ireq.i_len);
+ printf("\n");
+ }
+
+ ireq.i_type = IEEE80211_IOC_CHANNEL;
+ if (ioctl(s, SIOCG80211, &ireq) < 0) {
+ goto end;
+ }
+ printf("\tchannel %d", ireq.i_val);
+
+ ireq.i_type = IEEE80211_IOC_AUTHMODE;
+ if (ioctl(s, SIOCG80211, &ireq) != -1) {
+ printf(" authmode");
+ switch (ireq.i_val) {
+ case IEEE80211_AUTH_NONE:
+ printf(" NONE");
+ break;
+ case IEEE80211_AUTH_OPEN:
+ printf(" OPEN");
+ break;
+ case IEEE80211_AUTH_SHARED:
+ printf(" SHARED");
+ break;
+ default:
+ printf(" UNKNOWN");
+ break;
+ }
+ }
+
+ ireq.i_type = IEEE80211_IOC_POWERSAVE;
+ if (ioctl(s, SIOCG80211, &ireq) != -1 &&
+ ireq.i_val != IEEE80211_POWERSAVE_NOSUP ) {
+ printf(" powersavemode");
+ switch (ireq.i_val) {
+ case IEEE80211_POWERSAVE_OFF:
+ printf(" OFF");
+ break;
+ case IEEE80211_POWERSAVE_CAM:
+ printf(" CAM");
+ break;
+ case IEEE80211_POWERSAVE_PSP:
+ printf(" PSP");
+ break;
+ case IEEE80211_POWERSAVE_PSP_CAM:
+ printf(" PSP-CAM");
+ break;
+ }
+
+ ireq.i_type = IEEE80211_IOC_POWERSAVESLEEP;
+ if (ioctl(s, SIOCG80211, &ireq) != -1) {
+ if(ireq.i_val)
+ printf(" powersavesleep %d", ireq.i_val);
+ }
+ }
+
+ printf("\n");
+
+ ireq.i_type = IEEE80211_IOC_WEP;
+ if (ioctl(s, SIOCG80211, &ireq) < 0 ||
+ ireq.i_val == IEEE80211_WEP_NOSUP)
+ goto nowep;
+ else {
+ printf("\twepmode");
+ switch (ireq.i_val) {
+ case IEEE80211_WEP_OFF:
+ printf(" OFF");
+ break;
+ case IEEE80211_WEP_ON:
+ printf(" ON");
+ break;
+ case IEEE80211_WEP_MIXED:
+ printf(" MIXED");
+ break;
+ default:
+ printf(" UNKNOWN");
+ break;
+ }
+
+ /*
+ * If we get here then we've got WEP support so we need
+ * to print WEP status.
+ */
+
+ ireq.i_type = IEEE80211_IOC_WEPTXKEY;
+ if (ioctl(s, SIOCG80211, &ireq) < 0) {
+ warn("WEP support, but no tx key!");
+ goto end;
+ }
+ printf(" weptxkey %d", ireq.i_val+1);
+
+ ireq.i_type = IEEE80211_IOC_NUMWEPKEYS;
+ if (ioctl(s, SIOCG80211, &ireq) < 0) {
+ warn("WEP support, but no NUMWEPKEYS support!");
+ goto end;
+ }
+ num = ireq.i_val;
+
+ printf("\n");
+
+ ireq.i_type = IEEE80211_IOC_WEPKEY;
+ spacer = '\t';
+ for(i = 0; i < num; i++) {
+ ireq.i_val = i;
+ if (ioctl(s, SIOCG80211, &ireq) < 0) {
+ warn("WEP support, but can get keys!");
+ goto end;
+ }
+ if(ireq.i_len == 0 || ireq.i_len > 13)
+ continue;
+ printf("%cwepkey %d:%s", spacer, i+1,
+ ireq.i_len <= 5 ? "64-bit" : "128-bit");
+ if(spacer == '\t')
+ spacer = ' ';
+ }
+
+ printf("\n");
+ }
+nowep:
+
+
+end:
+ return;
+}
+
+static void
+set80211(int s, int type, int val, int len, u_int8_t *data)
+{
+ struct ieee80211req ireq;
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
+ ireq.i_type = type;
+ ireq.i_val = val;
+ ireq.i_len = len;
+ ireq.i_data = data;
+ if(ioctl(s, SIOCS80211, &ireq) < 0)
+ err(1, "SIOCS80211");
+}
+
+static const char *
+get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp)
+{
+ int len;
+ int hexstr;
+ u_int8_t *p;
+
+ len = *lenp;
+ p = buf;
+ hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x');
+ if (hexstr)
+ val += 2;
+ for (;;) {
+ if (*val == '\0')
+ break;
+ if (sep != NULL && strchr(sep, *val) != NULL) {
+ val++;
+ break;
+ }
+ if (hexstr) {
+ if (!isxdigit((u_char)val[0]) ||
+ !isxdigit((u_char)val[1])) {
+ warnx("bad hexadecimal digits");
+ return NULL;
+ }
+ }
+ if (p > buf + len) {
+ if (hexstr)
+ warnx("hexadecimal digits too long");
+ else
+ warnx("strings too long");
+ return NULL;
+ }
+ if (hexstr) {
+#define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
+ *p++ = (tohex((u_char)val[0]) << 4) |
+ tohex((u_char)val[1]);
+#undef tohex
+ val += 2;
+ } else
+ *p++ = *val++;
+ }
+ len = p - buf;
+ /* The string "-" is treated as the empty string. */
+ if (!hexstr && len == 1 && buf[0] == '-')
+ len = 0;
+ if (len < *lenp)
+ memset(p, 0, *lenp - len);
+ *lenp = len;
+ return val;
+}
+
+static void
+print_string(const u_int8_t *buf, int len)
+{
+ int i;
+ int hasspc;
+
+ i = 0;
+ hasspc = 0;
+ for(; i < len; i++) {
+ if (!isprint(buf[i]) && buf[i] != '\0')
+ break;
+ if (isspace(buf[i]))
+ hasspc++;
+ }
+ if (i == len) {
+ if (hasspc || len == 0 || buf[0] == '\0')
+ printf("\"%.*s\"", len, buf);
+ else
+ printf("%.*s", len, buf);
+ } else {
+ printf("0x");
+ for (i = 0; i < len; i++)
+ printf("%02x", buf[i]);
+ }
+}
+
diff --git a/share/examples/isdn/KERNEL b/share/examples/isdn/KERNEL
new file mode 100644
index 000000000000..81bea6e660c0
--- /dev/null
+++ b/share/examples/isdn/KERNEL
@@ -0,0 +1,78 @@
+#---------------------------------------------------------------------------
+#
+# example fragment of a kernel config file to include all
+# parts of isdn4bsd. This file should be appended to your
+# kernel config file and then edited (stripped down) to
+# match your hardware configuration.
+#
+# last edit-date: [Sun May 27 09:56:41 2001]
+#
+# $FreeBSD$
+#
+#---------------------------------------------------------------------------
+
+# Siemens/Infineon chipsets
+device isic 4
+
+# Winbond chipset
+device iwic 4
+
+# AVM Fritz PCI
+device ifpi 4
+
+# Teles 16.3c
+device ihfc 4
+
+# NETjet-S / Teles PCI-TJ
+device itjc 4
+
+# AVM Fritz PnP
+device ifpnp 4
+
+# AVM B1/T1
+device "i4bcapi"
+device iavc 4
+
+# enable some ISA cards within the "isic" driver
+options TEL_S0_8
+options TEL_S0_16
+options TEL_S0_16_3
+options AVM_A1
+options USR_STI
+options ELSA_PCC16
+
+# enable some ISA PnP cards within the "isic" driver
+options TEL_S0_16_3_P
+options CRTX_S0_P
+options DRN_NGO
+options SEDLBAUER
+options ELSA_QS1ISA
+options SIEMENS_ISURF2
+options ASUSCOM_IPAC
+options EICON_DIVA
+
+# enable ELSA Microlink PCI card within the "isic" driver
+options ELSA_QS1PCI
+
+# protocol stack
+device "i4bq921"
+device "i4bq931"
+device "i4b"
+
+# control devices
+device "i4btrc" 4
+device "i4bctl"
+device "i4brbch" 4
+device "i4btel" 2
+
+# IP over raw HDLC
+options IPR_VJ
+device "i4bipr" 4
+
+# kernel sppp/isppp
+device "i4bisppp" 4
+
+# Netgraph interface
+#options NETGRAPH
+#device "i4bing" 4
+
diff --git a/share/examples/isdn/contrib/README b/share/examples/isdn/contrib/README
new file mode 100644
index 000000000000..ae5969f09e84
--- /dev/null
+++ b/share/examples/isdn/contrib/README
@@ -0,0 +1,42 @@
+$FreeBSD$
+
+This directory contains various unsupported contributions to isdn4bsd
+---------------------------------------------------------------------
+
+anleitung.ppp Anleitung für syncPPP Internet-Zugang und
+ Anrufbeantworter / FreeBSD 2.2.x / Teles.S0/16.3-Karte
+ (stefan@asterix.webaffairs.net)
+
+answer.c answering machine in C by David Wetzel
+ (dave@turbocat.de)
+
+answer.sh a much better replacement for answer, tell and record
+ from Stefan Esser (se@freebsd.org)
+
+convert.sh convert recorded message to WAV format, optionally
+ send it via mail. from Stefan Herrmann
+ (stefan@asterix.webaffairs.net)
+
+hplay.c isdn4bsd telephony output driver for the "rsynth"
+ package to play synthetic speech to a telephone
+ connection
+
+i4b-ppp-newbie.txt setup PPP for isdn4bsd for newbies text from
+ Dominik Brettnacher <domi@saargate.de> (german)
+
+isdnctl This script can control the state of your ISDN line.
+ It counts how many scripts/users currently use the
+ ISDN line and uses "ifconfig down" if noone uses it
+ any more. Alexander Langer <alex@big.endian.de>
+
+isdnd_acct the barebones isdnd accounting script
+
+isdnd_acct.pl enhanced accounting from Joachim Kuebart
+ (joki@kuebart.stuttgart.netsurf.de)
+
+isdntelmux.c a "record while play" program contributed by
+ Michael Reifenberger (Michael@Reifenberger.com)
+
+mrtg-isp0.sh shell script and mrtg config entry to display
+ callout and callback statistics with mrtg
+ (www.mrtg.org) using the budget file statistics
diff --git a/share/examples/isdn/contrib/anleitung.ppp b/share/examples/isdn/contrib/anleitung.ppp
new file mode 100644
index 000000000000..01466e2f4880
--- /dev/null
+++ b/share/examples/isdn/contrib/anleitung.ppp
@@ -0,0 +1,142 @@
+$FreeBSD$
+
+i4b Anleitung für syncPPP Internet-Zugang und Anrufbeantworter
+unter FreeBSD 2.2.x mit Teles.S0/16.3-Karte
+===============================================================
+
+by Stefan Herrmann <stefan@asterix.webaffairs.net>
+
+
+Installation
+------------
+1) Neues Verzeichnis "/usr/src/i4b" anlegen.
+
+2) Ins Verzeichnis "/usr/src/i4b" wechseln und Sourcen entpacken.
+
+3) Ins Verzeichnis "FreeBSD" wechseln und den Befehl "sh install.sh ausführen:
+ z.B. "root@asterix[0]/usr/src/i4b/FreeBSD # sh install.sh"
+
+ Wenn auf eine neuere Version von i4b gewechselt wird, zuerst
+ "sh uninstall.sh" ausführen, dann erst "sh install.sh"
+
+4) Dann ins Verzeichnis "/usr/src/i4b" (zurück-)wechseln und die Befehle
+ "make depend", "make" und "make install" ausführen.
+
+5) Nun muß der kernel mit neuen Optionen versehen werden. Dazu wird an die
+ Kernel-Konfigurationsdatei im Verzeichnis "/sys/i386/conf" folgendes ans
+ Ende hinzugefügt:
+
+# i4b passive ISDN cards support (isic - I4b Siemens Isdn Chipset driver)
+# note that the ``options'' and ``device'' lines must BOTH be defined !
+
+# Teles S0/16.3
+options "TEL_S0_16_3"
+device isic0 at isa? port 0xd80 net irq 5 flags 0x04 vector isicintr
+
+# i4b passive cards D channel handling
+# Q.921
+pseudo-device "i4bq921"
+# Q.931
+pseudo-device "i4bq931"
+
+# common passive and active layer 4
+# layer 4
+pseudo-device "i4b"
+
+# userland driver to do ISDN tracing (for passive cards oly)
+pseudo-device "i4btrc" 4
+# userland driver to control the whole thing
+pseudo-device "i4bctl"
+# userland driver for access to raw B channel
+pseudo-device "i4brbch" 4
+# userland driver for telephony
+pseudo-device "i4btel" 2
+# network driver for IP over raw HDLC ISDN
+pseudo-device "i4bipr" 4
+# enable VJ header compression detection for ipr i/f
+options IPR_VJ
+# network driver for sync PPP over ISDN
+pseudo-device "i4bisppp" 4
+pseudo-device sppp 4
+
+6) Danach wird der kernel durch Eingabe der Befehle "make depend", "make" und
+ "make install" im Verzeichniss "/usr/src/sys/compile/<CONFIG>" neu
+ übersetzt und installiert.
+
+7) Nach dem Booten kann man dann mit dem Befehl "dmesg" überprüfen, ob die
+ Karte korrekt erkannt wurde und alle erforderlichen Treiber installiert
+ sind.
+
+
+Konfiguration
+-------------
+8) Die Konfiguration von i4b wird hauptsächlich im Verzeichnis "/etc/isdn"
+ druchgeführt, dort sucht der isdnd beim Start auch seine Konfigurations-
+ datei "isdnd.rc". Da vorgenanntes Verzeichnis nach der Installation aber
+ noch leer ist, kopiert man zuerst die Beispieldateien aus dem Verzeichnis
+ "/etc/isdn/samples" nach "/etc/isdn".
+
+9) Die Datei "isdnd.rc" enthält schon recht aussagekräftige Kommentare zu den
+ einzelnen Optionen, weitere Informationen erhält man mit "man isdnd.rc" und
+ "man isdnd".
+
+10) Für syncPPP und Anrufbeantworter sind nur die Sektionen "SYSTEM",
+ "telephone answering" und "example for sPPP" notwendig, die Sektion
+ "IP over ISDN example" kann dafür also entfernt werden.
+
+11) Für den automatisierten Start des isp0 Interfaces und des isdnd erstellt
+ man nun ein Start-Skript. Dazu kopiert man die Datei
+ "/usr/src/i4b/etc/rc.isdn-PPP" nach "/etc/rc.isdn" und paßt sie
+ entsprechend an. Man beachte hierbei auch die FAQ "/usr/src/i4b/FAQ", die
+ Tips für die richtige Eintragung der IP-Adressen bereithält.
+
+12) Der Anrufbeantworter wird dadurch aktiviert, daß das entsprechende
+ Programm, das in "/etc/isdn/isdnd.rc" hinter dem Eintrag "answerprog = "
+ steht, aufgerufen wird. Wird dort kein Pfad angegeben, wird das Programm
+ im Verzeichniss "/etc/isdn" erwartet. Beispiele solcher Programme findet
+ man wiederum im Verzeichnis "/etc/isdn/samples". Sie nennen sich
+
+ "answer" Nur Ansagetext abspielen, keine Aufzeichnungsmöglichkeit.
+ "record" Ansage wird abgespielt, nach Piep-Ton kann gesprochen
+ werden.
+ "tell" Als Ansagetext wird die anrufende Nummer gesprochen, keine
+ Aufzeichnung.
+ "tell-record" Anrufende Nummer als Ansagetext, nach Piep-Ton kann ge-
+ sprochen werden.
+ "isdntel.sh" Ansagetext und Aufzeichnung; mittels dem Programm "isdntel"
+ hat man die Kontrolle übe die Aufzeichnungen im Ver-
+ zeichniss "/var/isdn". Siehe auch "man isdntel" und
+ "man isdntelctl".
+
+ Diese Programme müssen an die eigenen Wünsche angepaßt werden. Leider gibt es
+ kein mitgeliefertes Programm, mit dem man so auch den Ansagetext aufsprechen
+ kann. Das ist aber nicht allzuschlimm, da man nur das Programm "record" dafür
+ etwas anpassen muß (Ansagetexte beep und msg auskommentieren). Damit die Anrufe
+ aufgezeichnet werden können, muß zuerst noch das Verzeichnis "/var/isdn"
+ angelegt werden. Dort werden dann alle Aufzeichnungen obiger Programme gespeichert.
+
+13) Man sollte sich auch noch die man-Pages der Programme "isdnd", "isdnctl",
+ "isdnd_acct", "isdndebug" und "isdntrace" zu Gemüte führen.
+
+
+Betrieb
+-------
+14) Der syncPPP Zugang zum Provider wird einfach mit dem Aufruf von
+ "/etc/rc.isdn" initialisiert. Jegliche Aktivitäten ins Internet (also z.B.
+ ein "ping 141.1.1.1") starten die Verbindung. Wenn in "/etc/isdn/isdnd.rc"
+ beim Eintrag "unitlengthsrc = " "rate" angegeben wurde, wird die Verbindung
+ kurz bevor die nächste Einheit begonnen wird, beendet. Informationen über
+ die Einheiten werden aus der Datei "/etc/isdn/isdnd.rates" ausgelesen
+ (Beispiele sind in "/etc/isdn/samples").
+
+ Mit "/etc/rc.isdn [restart|stop]" kann i4b entweder neu gestartet (z.B. zum
+ Einlesen der geänderten Konfiguration aus "isdnd.rc") oder beendet werden.
+
+15) Für den Anrufbeantworter muß nur der "isdnd" gestartet sein. Ein
+ ankommender Anruf wird dann automatisch angenommen (je nach den Einträgen
+ in "/etc/isdn/isdnd.rc").
+
+16) Informationen über die Verbindung erhält man sowohl in "/var/log/messages",
+ also auch in "/var/log/isdnd.log" (so der isdnd mit der Option "-l"
+ gestartet wird) bzw. auf dem aktuellen tty (wenn der isdnd mit der Option
+ "-f" gestartet wird).
diff --git a/share/examples/isdn/contrib/answer.c b/share/examples/isdn/contrib/answer.c
new file mode 100644
index 000000000000..da19aa946fd7
--- /dev/null
+++ b/share/examples/isdn/contrib/answer.c
@@ -0,0 +1,178 @@
+// $FreeBSD$
+// changed ".g711a" to ".al" (-hm)
+// Tue Mar 3 02:42:14 MET 1998 dave@turbocat.de
+// started
+
+#define BLK_SIZE 2048
+#define SOX "/usr/local/bin/sox"
+#define ALAWULAW "/usr/local/bin/alaw2ulaw"
+
+#include <stdio.h>
+#include <time.h>
+
+ FILE *device;
+ FILE *logfile;
+ char srcNum[30];
+ char destNum[30];
+ char argbuf[255];
+ char tmpBuf[1024] = "";
+
+
+void writeToPhone (char *path)
+{
+ char buf[BLK_SIZE];
+ FILE *srcfile;
+ int i = 0;
+ int readcount = 0;
+
+ srcfile = fopen(path,"r");
+ if (srcfile) {
+ for (i=0;i<BLK_SIZE;i++) {
+ buf[i] = '\0';
+ }
+ readcount = BLK_SIZE;
+ i = 0;
+ do {
+ readcount = fread(buf,1, BLK_SIZE, srcfile);
+ fwrite(buf, 1, readcount, device);
+ i = readcount + i;
+// fprintf(logfile,"%d read (%d)\n",i,readcount);
+ } while (readcount == BLK_SIZE);
+
+ fclose(srcfile);
+ } else {
+ fprintf(logfile,"Can't open file '%s'\n",path);
+ }
+}
+
+void readFromPhone (char *path)
+{
+ char buf[BLK_SIZE];
+ FILE *destfile;
+ int i = 0;
+ int readcount = 0;
+
+ destfile = fopen(path,"a");
+ if (destfile) {
+ for (i=0;i<BLK_SIZE;i++) {
+ buf[i] = '\0';
+ }
+ readcount = BLK_SIZE;
+ i = 0;
+ do {
+ readcount = fread(buf,1, BLK_SIZE, device);
+ fwrite(buf, 1, readcount, destfile);
+ i = readcount + i;
+// fprintf(logfile,"%d read (%d)\n",i,readcount);
+ } while (readcount == BLK_SIZE);
+
+ fclose(destfile);
+ } else {
+ fprintf(logfile,"Can't open file '%s'\n",path);
+ }
+}
+
+void usage (void)
+{
+ fprintf(stderr,"Usage: answer -D device -d destination -s source\n");
+ exit(1);
+}
+
+const char * argWithName (const char* aName)
+{
+ // '-D /dev/null -d 82834 -s 3305682834'
+ int i = 0;
+ int optionSeen = 0;
+ int startpos = 0;
+
+ for (i = 0; i < sizeof(tmpBuf);i++) {
+ tmpBuf[i] = '\0';
+ }
+
+ for (i = 0; i<strlen(argbuf);i++) {
+ if (optionSeen) {
+ for (;(i<strlen(argbuf) && (argbuf[i] != ' '));i++) {
+ }
+ i++;
+ startpos = i;
+
+ for (;(i<strlen(argbuf) && (argbuf[i] != ' '));i++) {
+ }
+ strncpy(tmpBuf,&argbuf[startpos], i-startpos);
+
+ return tmpBuf;
+ }
+ if (0 == strncmp(aName,&argbuf[i], strlen(aName))) {
+ optionSeen = 1;
+ }
+ }
+
+ usage();
+ return NULL;
+}
+
+int main (int argc, const char *argv[]) {
+
+ int i,pos = 0;
+ extern char *optarg;
+ extern int optind;
+ int bflag, ch;
+ char timeStr[50];
+ char outfileName[1024] = "";
+ char cmdStr[2048] = "";
+ time_t now;
+
+ now=time(NULL);
+
+ strftime(timeStr,40,I4B_TIME_FORMAT,localtime(&now));
+
+ logfile = fopen("/var/log/answer.log","a");
+
+ fprintf(logfile,"%s Started\n",timeStr);
+
+ pos=0;
+ for (i=1;i<argc;i++) {
+ sprintf(&argbuf[strlen(argbuf)],"%s ",argv[i]);
+ }
+ if (strlen(argbuf) > 2) {
+ argbuf[strlen(argbuf)-1] = '\0';
+ }
+
+
+ device = fopen(argWithName("-D"),"r+");
+ strcpy(destNum, argWithName("-d"));
+ strcpy(srcNum, argWithName("-s"));
+
+ fprintf(logfile,"device '%s'\n", argWithName("-D"));
+ fprintf(logfile,"srcNum '%s'\n", srcNum);
+ fprintf(logfile,"destNum '%s'\n", destNum);
+
+
+ if (device) {
+
+ strftime(timeStr,40,I4B_TIME_FORMAT,localtime(&now));
+
+ sprintf(outfileName,"/var/isdn/%s_%s_%s", timeStr, srcNum, destNum);
+
+ writeToPhone ("/usr/local/lib/isdn/msg.al");
+ readFromPhone (outfileName);
+
+ sprintf(cmdStr,"/bin/cat %s | %s | %s -t raw -U -b -r 8000 - -t .au %s.snd", outfileName, ALAWULAW, SOX, outfileName);
+ fprintf(logfile,"%s\n",cmdStr);
+ system(cmdStr);
+ unlink(outfileName);
+
+ fclose(device);
+ } else {
+ fprintf(logfile,"Can't open file '%s'\n",argWithName("-D"));
+ }
+
+ now=time(NULL);
+
+ strftime(timeStr,40,I4B_TIME_FORMAT,localtime(&now));
+
+ fprintf(logfile,"%s Done\n",timeStr);
+ fclose(logfile);
+ exit(0); // insure the process exit status is 0
+ return 0; // ...and make main fit the ANSI spec.
+}
diff --git a/share/examples/isdn/contrib/answer.sh b/share/examples/isdn/contrib/answer.sh
new file mode 100644
index 000000000000..34073d359923
--- /dev/null
+++ b/share/examples/isdn/contrib/answer.sh
@@ -0,0 +1,111 @@
+#!/bin/sh
+#---------------------------------------------------------------------------
+#
+# answer script for i4b isdnd
+# ---------------------------
+#
+# last edit-date: [Fri May 25 15:21:05 2001]
+#
+# $FreeBSD$
+#
+#---------------------------------------------------------------------------
+VARDIR=/var/isdn
+LIBDIR=/usr/local/lib/isdn
+LOGFILE=/tmp/answer.log
+
+NCALLFILE=$VARDIR/ncall
+DATE=`date +%d%H`
+
+progname=${0##*/}
+set -- $@ # have to split argument string !!!
+
+# ----------------------------------------------------------------------
+
+usage ()
+{
+ echo "usage: $progname -D device -d dest -s src"
+ exit 1
+}
+
+ncall ()
+{
+ nfile=$1
+ [ -f $nfile ] && read n < $nfile || n=0
+ echo $(($n + 1)) > $nfile
+ printf "%.4d" $n
+}
+
+# ----------------------------------------------------------------------
+
+while getopts "D:d:s:" opt
+do
+ case $opt
+ in
+D) DEVICE=$OPTARG ;;
+d) DEST=$OPTARG ;;
+s) SRC=$OPTARG ;;
+ esac
+done
+
+[ -c "$DEVICE" -a -n "$DEST" -a -n "$SRC" ] || usage;
+
+shift $(($OPTIND - 1))
+
+# ----------------------------------------------------------------------
+
+NCALL=`ncall $NCALLFILE`
+
+echo "$progname: device $DEVICE destination $DEST source $SRC " >>$LOGFILE
+
+{
+ echo "Date: "`date`
+ echo "From: \"$SRC\""
+ echo "To: \"$DEST\""
+ echo
+} >> $VARDIR/I.$NCALL.$DATE
+
+# ----------------------------------------------------------------------
+
+tellnumber ()
+{
+ number=$1
+ digits=`echo $number | sed -e 's/\(.\)/\1 /g'`
+
+ files=""
+ for digit in $digits
+ do
+ files="$files $LIBDIR/$digit.al"
+ done
+ cat $files
+}
+
+# ----------------------------------------------------------------------
+
+do_answer ()
+{
+ [ -f $LIBDIR/beep.al ] && cat $LIBDIR/beep.al
+ [ -f $LIBDIR/msg.al ] && cat $LIBDIR/msg.al
+ [ -f $LIBDIR/beep.al ] && cat $LIBDIR/beep.al
+} > $DEVICE
+
+do_record ()
+{
+ cat $DEVICE > $VARDIR/R.$NCALL.$DATE
+}
+
+do_tell ()
+{
+ [ -f $LIBDIR/beep.al ] && cat $LIBDIR/beep.al
+ [ -f $LIBDIR/msg.al ] && cat $LIBDIR/msg.al
+ tellnumber $SRC
+ [ -f $LIBDIR/beep.al ] && cat $LIBDIR/beep.al
+} > $DEVICE
+
+# ----------------------------------------------------------------------
+
+case $progname
+in
+answer) do_answer ;;
+record) do_answer; do_record ;;
+tell) do_tell ;;
+esac
diff --git a/share/examples/isdn/contrib/convert.sh b/share/examples/isdn/contrib/convert.sh
new file mode 100644
index 000000000000..b4a6e7d8d852
--- /dev/null
+++ b/share/examples/isdn/contrib/convert.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+#
+# convert recorded message to WAV format, optionally send it via mail
+#
+# by: Stefan Herrmann <stefan@asterix.webaffairs.net>
+# Date: Fr 22 Mai 1998 14:18:40 CEST
+#
+# $FreeBSD$
+
+CAT=/bin/cat
+RM=/bin/rm
+SOX=/usr/local/bin/sox
+ALAW2ULAW=/usr/local/bin/alaw2ulaw
+MAIL=/usr/bin/mail
+GZIP=/usr/bin/gzip
+ZIP=/usr/local/bin/zip
+UUENCODE=/usr/bin/uuencode
+
+inputfile=""
+outfilename=""
+mailto=""
+iF=0
+oF=0
+mF=0
+
+set -- `getopt i:o:m: $*`
+
+if test $? != 0
+then
+ echo 'Usage: r2w -i <input file> -o <outfile name>.wav -m <email address>'
+ exit 1
+fi
+
+for i
+do
+ case "$i"
+ in
+ -i)
+ inputfile=$2
+ iF=1
+ shift
+ shift
+ ;;
+ -o)
+ outfilename=$2
+ oF=1
+ shift
+ shift
+ ;;
+ -m)
+ mailto=$2
+ mF=1
+ shift
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+done
+
+if [ $iF -eq 0 -o $oF -eq 0 ]
+then
+ echo 'Usage: r2w -i <input file> -o <outfile name>.wav -m <email address>'
+ exit 1
+fi
+
+if [ $iF -eq 1 -a $oF -eq 1 ]
+then
+ echo
+ echo "converting $inputfile to $outfilename.wav ..."
+
+ $CAT $inputfile | $ALAW2ULAW | $SOX -t raw -U -b -r 8000 - -t .wav $outfilename.wav
+fi
+
+if [ $iF -eq 1 -a $oF -eq 1 -a $mF -eq 1 ]
+then
+ echo "... and sending it via email to $mailto ..."
+ $UUENCODE $outfilename.wav message.wav | $MAIL -s"new message $outfilename" $mailto && $RM $outfilename.wav
+ # only usefull when sending over the internet
+ #$GZIP -c $outfilename.wav | $UUENCODE message.zip | $MAIL -s"Nachricht vom ISDN Anrufbeantworter" $mailto && $RM $outfilename.wav
+fi
+
+echo "done."
+echo
diff --git a/share/examples/isdn/contrib/hplay.c b/share/examples/isdn/contrib/hplay.c
new file mode 100644
index 000000000000..10660ac7b7b1
--- /dev/null
+++ b/share/examples/isdn/contrib/hplay.c
@@ -0,0 +1,241 @@
+/*---------------------------------------------------------------------------*
+ *
+ * rsynth driver to output to
+ * - an open isdn4bsd telephone connection or
+ * - an output file or
+ * - the /dev/audio device
+ * ----------------------------------------------------------------
+ *
+ * tested with rsynth-2.0
+ *
+ * written by Hellmuth Michaelis (hm@kts.org)
+ *
+ * last edit-date: [Fri May 25 15:21:33 2001]
+ *
+ * $FreeBSD$
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <config.h>
+#include <useconfig.h>
+#include <stdio.h>
+#include <math.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/signal.h>
+#include <sys/ioctl.h>
+
+#include <machine/i4b_tel_ioctl.h>
+
+#include "proto.h"
+#include "getargs.h"
+#include "hplay.h"
+#include "l2u.h"
+
+#define SAMP_RATE 8000
+long samp_rate = SAMP_RATE;
+
+char *prog = "hplay";
+
+static int use_audio = 1;
+static int use_isdn = 0;
+static int unit_no = 0;
+
+static int audio_fd = -1;
+static int isdn_fd = -1;
+static int file_fd = -1;
+
+char *audio_dev = "/dev/dsp";
+char *isdn_dev = "/dev/i4btel";
+static char *ulaw_file = NULL;
+
+int
+audio_init(int argc, char *argv[])
+{
+ char dev[64];
+ int format = CVT_ALAW2ULAW;
+
+ prog = argv[0];
+
+ argc = getargs("FreeBSD audio/i4b/file output driver",argc, argv,
+ "a", NULL, &use_audio, "use /dev/audio (default)",
+ "i", NULL, &use_isdn, "use /dev/i4btel",
+ "u", "%d", &unit_no, "/dev/i4btel unit number (def = 0)",
+ "f", "", &ulaw_file, "u-law output to file",
+ NULL);
+
+ if(help_only)
+ return argc;
+
+ if(ulaw_file)
+ {
+ if(strcmp(ulaw_file, "-") == 0)
+ {
+ file_fd = 1; /* stdout */
+ }
+ else
+ {
+ file_fd = open(ulaw_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if(file_fd < 0)
+ fprintf(stderr, "ERROR: cannot open %s, error = %s\n", ulaw_file, strerror(errno));
+ }
+ }
+
+ if(use_isdn)
+ {
+ sprintf(dev, "%s%d", isdn_dev, unit_no);
+
+ if((isdn_fd = open(dev, O_WRONLY)) < 0)
+ {
+ fprintf(stderr, "ERROR: cannot open %s, error = %s\n", dev, strerror(errno));
+ }
+
+ if((ioctl(isdn_fd, I4B_TEL_SETAUDIOFMT, &format)) < 0)
+ {
+ fprintf(stderr, "ioctl I4B_TEL_SETAUDIOFMT failed: %s", strerror(errno));
+ }
+ }
+
+ if(use_audio)
+ {
+ audio_fd = open(audio_dev, O_WRONLY | O_NDELAY);
+ if(audio_fd < 0)
+ {
+ fprintf(stderr, "ERROR: cannot open %s, error = %s\n", audio_dev, strerror(errno));
+ }
+ }
+
+ return argc;
+}
+
+void
+audio_term()
+{
+ int format = CVT_NONE;
+
+ if(isdn_fd >= 0)
+ {
+ if((ioctl(isdn_fd, I4B_TEL_SETAUDIOFMT, &format)) < 0)
+ {
+ fprintf(stderr, "ioctl I4B_TEL_SETAUDIOFMT failed: %s", strerror(errno));
+ }
+ close(isdn_fd);
+ isdn_fd = -1;
+ }
+
+ if(audio_fd >= 0)
+ {
+#if 0
+ ioctl(audio_fd, SNDCTL_DSP_SYNC, &dummy);
+#endif
+ close(audio_fd);
+ audio_fd = -1;
+ }
+
+ if(file_fd >= 0)
+ {
+ close(file_fd);
+ file_fd = -1;
+ }
+}
+
+void
+audio_play(int n, short *data)
+{
+ int ret;
+ unsigned char *p;
+
+ if (n > 0)
+ {
+ unsigned char *converted = (unsigned char *) malloc(n);
+ int i;
+
+ if(converted == NULL)
+ {
+ fprintf(stderr, "Could not allocate memory for conversion\n");
+ exit(3);
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ converted[i] = short2ulaw(data[i]);
+ }
+
+ if (isdn_fd >= 0)
+ {
+ p = converted;
+ errno = 0;
+
+ while((ret = write(isdn_fd, p, n)) != n)
+ {
+ if(!errno)
+ {
+ p += ret;
+ if(p > (converted + n))
+ break;
+ }
+ else
+ {
+ fprintf(stderr, "write /dev/i4btel ERROR: ret (%d) != n (%d), error = %s\n", ret, n, strerror(errno));
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < n; i++)
+ converted[i] = (data[i] - 32768) / 256;
+
+ if(audio_fd >= 0)
+ {
+ p = converted;
+
+ errno = 0;
+
+ while((ret = write(audio_fd, p, n)) != n)
+ {
+ if(!errno)
+ {
+ p += ret;
+ if(p > (converted + n))
+ break;
+ }
+ else
+ {
+ fprintf(stderr, "write /dev/dsp ERROR: ret (%d) != n (%d), error = %s\n", ret, n, strerror(errno));
+ break;
+ }
+ }
+ }
+
+ if(file_fd >= 0)
+ {
+ int ret;
+ p = converted;
+
+ errno = 0;
+
+ while((ret = write(file_fd, p, n)) != n)
+ {
+ if(!errno)
+ {
+ p += ret;
+ if(p > (converted + n))
+ break;
+ }
+ else
+ {
+ fprintf(stderr, "write file ERROR: ret (%d) != n (%d), error = %s\n", ret, n, strerror(errno));
+ break;
+ }
+ }
+ }
+
+ free(converted);
+ }
+}
+
+/* EOF */
diff --git a/share/examples/isdn/contrib/i4b-ppp-newbie.txt b/share/examples/isdn/contrib/i4b-ppp-newbie.txt
new file mode 100644
index 000000000000..7d6c4b0870ae
--- /dev/null
+++ b/share/examples/isdn/contrib/i4b-ppp-newbie.txt
@@ -0,0 +1,237 @@
+$FreeBSD$
+
+ PPP mit isdn4bsd
+ _________________________________________________________________
+
+ Version 1.01
+ Datum: 22.02.1999
+ Autor: [1]Dominik Brettnacher <domi@saargate.de>
+
+ - Anmerkungen und Verbesserungsvorschläge sind willkommen -
+
+ 1. vorab
+ Dieser Text soll Neulingen helfen, sich mittels isdn4bsd und BSD
+ per PPP z.B. bei ihrem Provider einwählen zu können.
+ isdn4bsd bringt einiges an Dokumentation und
+ Konfigurationsbeispielen mit, jedoch ist es nicht immer leicht,
+ die entsprechenden Hinweise gut miteinander zu kombinieren, so daß
+ am Schluß das dabei herauskommt, was man haben möchte.
+ 2. Wo bekomme ich isdn4bsd?
+ hier solle es keine allzu großen Probleme geben: isdn4bsd ist auf
+ dem FTP-Server [2]ftp.consol.de erhältlich. Man beachte dabei, daß
+ man sich nicht, wie üblich, als anonymous, sondern als isdn4bsd
+ einloggen muß. Benutzer von Browsern geben als Adresse
+ [3]ftp://isdn4bsd@ftp.consol.de und als Passwort ihre
+ eMail-Adresse an.
+ Wertvolle Informationen findet man in der Datei README.
+ 3. Welche ISDN-Karten werden unterstützt?
+ Informationen darüber findet man in der README-Datei.
+ 4. Ich benutze einen externen ISDN-Adapter - was nun?
+ Externe Adapter benötigen keine direkte Unterstützung, weil sie
+ über die serielle Schnittstelle angesteuert werden. Man kann also
+ das normale PPP benutzen. man ppp hilft hier sicher weiter.
+ 5. isdn4bsd installieren
+ Wie man isdn4bsd installiert, steht in der Datei
+ FreeBSD/INSTALLATION (für NetBSD und OpenBSD analog). Eine
+ Beispielkonfiguration des Kernel sieht so aus:
+[...]
+#
+# i4b passive ISDN cards support (isic - I4b Siemens Isdn Chipset driver)
+# note that the ``options'' and ``device'' lines must BOTH be defined !
+#
+# Non-PnP Cards:
+# --------------
+#
+# AVM A1 or AVM Fritz!Card
+options "AVM_A1"
+device isic0 at isa? port 0x300 net irq 15 flags 4 vector isicintr
+#
+# ISDN Protocol Stack
+# -------------------
+#
+# Q.921 / layer 2 - i4b passive cards D channel handling
+pseudo-device "i4bq921"
+#
+# Q.931 / layer 3 - i4b passive cards D channel handling
+pseudo-device "i4bq931"
+#
+# layer 4 - i4b common passive and active card handling
+pseudo-device "i4b"
+#
+# ISDN devices
+# ------------
+#
+# userland driver to do ISDN tracing (for passive cards only)
+pseudo-device "i4btrc" 4
+#
+# userland driver to control the whole thing
+pseudo-device "i4bctl"
+#
+# userland driver for access to raw B channel
+#pseudo-device "i4brbch" 4
+#
+# userland driver for telephony
+#pseudo-device "i4btel" 2
+#
+# network driver for IP over raw HDLC ISDN
+#pseudo-device "i4bipr" 4
+# enable VJ header compression detection for ipr i/f
+#options IPR_VJ
+#
+# network driver for sync PPP over ISDN
+pseudo-device "i4bisppp" 1
+pseudo-device sppp 1
+#
+#---------------------------------------------------------------------------
+[...]
+ Nachdem ein neuer Kernel kompiliert und das System neugestartet
+ wurde, kann es weiter gehen.
+ 6. Konfiguration isdnd.rc
+ Die für ISDN wichtigste Konfigurationsdatei ist
+ /etc/isdn/isdnd.rc. Mit man isdnd.rc erhält man Informationen über
+ die Einstellungen, die man dort vornehmen kann. Im Folgenden ein
+ Beispiel:
+
+
+#==============================================================================
+# SYSTEM section: isdnd global configuration parameters
+#==============================================================================
+system
+
+# accounting
+# ----------
+
+acctall = on # generate info for everything
+acctfile = /var/log/isdnd.acct # name & location of accounting file
+useacctfile = yes # generate accouting info to file
+
+# monitor
+# -------
+
+monitor-allowed = no # global switch: monitor on/off
+monitor-port = 451 # default monitor TCP port
+
+# Monitor rights are granted due to the most specific host/net spec, i.e. in
+# the example below host 192.168.1.2 will have the rights specified on that
+# line, even so it belongs to net 192.168.1.0/24 as well.
+#
+# A monitor specification may either be:
+#
+# - the name of a local (UNIX-domain) socket; this MUST start with a "/"
+monitor = "/var/run/isdn-monitor"
+monitor-access = fullcmd
+monitor-access = channelstate, logevents
+monitor-access = callin, callout
+
+# ratesfile
+# ---------
+
+ratesfile = /etc/isdn/isdnd.rates # name & location of rates file
+
+# regular expression pattern matching
+# -----------------------------------
+
+#regexpr = "connected.*KTS" # look for matches in log messages
+#regprog = connectKTS # execute program when match is found
+
+# realtime priority section
+# -------------------------
+
+rtprio = 25 # modify isdnd's process priority
+
+###############################################################################
+entry
+name = lf
+usrdevicename = isp
+usrdeviceunit = 0
+isdncontroller = 0
+isdnchannel = -1
+local-phone-incoming = 012345678
+remote-phone-incoming = 876543210
+local-phone-dialout = 012345678
+remote-phone-dialout = 876543210
+remdial-handling = first
+dialin-reaction = accept
+dialout-type = normal
+b1protocol = hdlc
+idletime-incoming = 240
+idletime-outgoing = 30
+earlyhangup = 5
+ratetype = 0
+unitlength = 90
+unitlengthsrc = rate
+dialretries = 3
+dialrandincr = on
+recoverytime = 25
+
+connectprog = is-up
+disconnectprog = is-down
+
+ Wichtig sind hier für den Neuling die vier *-phone-* Einträge, die
+ jeweils die lokale Rufnummer und die der Gegenstelle für ein- und
+ ausgehende Verbindungen angeben.
+
+ 7. ISDN-Verbindungen aufbauen
+ um ISDN-Verbindungen aufzubauen, bedarf es einiger Befehle, die
+ beim Systemstart aufgerufen werden. Man kann sie zum Beispiel am
+ Ende von /etc/rc.local unterbringen. Hier gibt es aber durchaus
+ noch andere Lösungen:
+ [...]
+ # start ISDN
+ echo -n 'ppp / ISDN...'
+ echo -n 'isdnd...'
+ /usr/local/bin/isdnd
+ echo -n 'ifconfig...'
+ ifconfig isp0 link1 0.0.0.0 1.1.1.1 netmask 0xffffff00
+ ifconfig isp0 down
+ echo -n 'sppp...'
+ spppcontrol isp0 myauthproto=pap myauthname="xxx"
+ myauthsecret="xxx" hisauthproto=none
+ echo -n 'ifconfig...'
+ ifconfig isp0 up
+ echo -n 'setting routes...'
+ route add default -interface isp0
+ echo '.'
+ Ändern muß man hier eventuell die Zieladresse des Providers (im
+ Beispiel 1.1.1.1). Man bekommt diese entweder vom Provider, oder
+ aber man muß einen Versuch daransetzen, sie selbst herauszufinden.
+ Wie das funktioniert, steht in der Datei FAQ des isdn4bsd-Paketes.
+ Auch am Aufruf von spppcontrol (Vorsicht: spppcontrol bis
+ hisauthproto=none ist eine Zeile!) muß noch etwas umgestellt
+ werden:
+ + myauthproto steht für das Authentifizierungsprotokoll.
+ Möglich sind pap oder chap.
+ + myauthname ist der PPP-Benutzername.
+ + myauthsecret ist das PPP-Kennwort.
+ Wenn man nun die Befehle in /etc/rc.local ausführt, kann man mit
+ einem ping auf eine beliebige Adresse außerhalb des lokalen Netzes
+ eine Verbindung öffnen. Sie wird automatisch nach einiger
+ Inaktivität (siehe isdnd.rc) wieder geschlossen.
+
+ 8. Es funktioniert nicht - was kann ich tun?
+ Es gibt einige Möglichkeiten zur Fehlerdiagnose:
+ + dmesg gibt Aufschluß darüber, ob die Karte richtig erkannt
+ wurde.
+ + ifconfig (siehe rc.local) kann mit dem Parameter debug
+ aufgerufen werden und gibt dann einiges an Informationen aus.
+ + die Nachrichten in /var/log/messages können außerdem
+ hilfreich sein
+
+ 9. wer kann mir helfen?
+ + die erste Adresse für ISDN-Probleme ist die Mailingliste
+ [4]freebsd-isdn@freebsd.org - man bestellt sie, indem man
+ eine Mail mit dem Text subscribe freebsd-isdn an
+ [5]majordomo@freebsd.org schickt.
+ + auch die deutschsprachige Mailingliste kann hilfreich sein.
+ Mit einer Mail an [6]majordomo@de.freebsd.org, die im Text
+ subscribe de-bsd-questions enthält bestellt man sie.
+ _________________________________________________________________
+
+References
+
+ 1. mailto:domi@saargate.de
+ 2. ftp://isdn4bsd@ftp.consol.de/
+ 3. ftp://isdn4bsd@ftp.consol.de/
+ 4. mailto:freebsd-isdn@freebsd.org
+ 5. mailto:majordomo@freebsd.org
+ 6. mailto:majordomo@de.freebsd.org
diff --git a/share/examples/isdn/contrib/isdnctl b/share/examples/isdn/contrib/isdnctl
new file mode 100644
index 000000000000..f9de44fbb834
--- /dev/null
+++ b/share/examples/isdn/contrib/isdnctl
@@ -0,0 +1,111 @@
+#!/bin/sh
+
+# isdnctl
+# Control the ISDN line based on usage
+#
+# This script can control the state of your ISDN line. It counts
+# how many scripts/users currently use the ISDN line and uses
+# "ifconfig down" if noone uses it any more.
+# I use this script for cronjobs that fetch mail and news and run cvsup.
+# If I'm still using the line, the script won't close the connection,
+# but if not, it saves a lot of phone costs.
+#
+# ----------------------------------------------------------------------------
+# "THE BEER-WARE LICENSE" (Revision 42, (c) Poul-Henning Kamp):
+# Alexander Langer <alex@big.endian.de> wrote this file. As long as you retain
+# this notice you can do whatever you want with this stuff. If we meet some
+# day, and you think this stuff is worth it, you can buy me a beer in return.
+#
+# Alexander Langer
+# ----------------------------------------------------------------------------
+#
+# $FreeBSD$
+#
+
+
+usage () {
+ echo "Usage: $0 [-i interface] [-f /path/to/users.file] [up|down|show]"
+}
+
+# Defaults
+INTERFACE=isp0
+USERSFILE=
+
+# Getopt stuff
+args=`getopt i:f: $*`
+if [ $? != 0 ]; then
+ usage
+ exit 2
+ fi
+set -- $args
+for i; do
+ case "$i" in
+ -i)
+ INTERFACE="$2"
+ shift; shift
+ ;;
+ -f)
+ USERSFILE="$2"
+ shift; shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+done
+
+if [ -z $USERSFILE ]; then
+ USERSFILE=/var/run/isdn.users.$INTERFACE
+fi
+
+if [ -z $1 ]; then
+ usage
+ exit 2
+fi
+
+# Does Usersfile exist?
+if [ ! -f $USERSFILE ]; then
+ # Try to create it
+ if ! /sbin/ifconfig $INTERFACE | grep "^$INTERFACE.*<UP," > /dev/null; then
+ echo "0" > $USERSFILE || exit 1
+ else
+ echo "1" > $USERSFILE || exit 1
+ fi
+elif [ ! -w $USERSFILE ]; then
+ echo "Error: $USERSFILE not writeable!"
+ exit 1
+fi
+
+if ! /sbin/ifconfig $INTERFACE | grep "^$INTERFACE.*<UP," > /dev/null; then
+ if ! cat $USERSFILE | grep '^0$' > /dev/null ; then
+ echo "Interface down, removing number from file";
+ echo "0" > $USERSFILE
+ fi;
+fi;
+
+case "$1" in
+ show)
+ echo "`cat $USERSFILE` users online"
+ ;;
+ up)
+ expr `cat $USERSFILE` + 1 > $USERSFILE
+ /sbin/ifconfig $INTERFACE up
+ echo "`cat $USERSFILE` users online"
+ ;;
+ down)
+ if cat $USERSFILE | grep '^0$' > /dev/null ; then
+ echo "Already down"
+ exit 0
+ fi
+ expr `cat $USERSFILE` - 1 > $USERSFILE
+ if cat $USERSFILE | grep '^0$' > /dev/null ; then
+ echo "`cat $USERSFILE` users online, interface down"
+ /sbin/ifconfig $INTERFACE down
+ exit 0
+ fi
+ echo "`cat $USERSFILE` users online"
+ ;;
+esac
+
+exit 0
diff --git a/share/examples/isdn/contrib/isdnd_acct b/share/examples/isdn/contrib/isdnd_acct
new file mode 100644
index 000000000000..21223b7cd0f4
--- /dev/null
+++ b/share/examples/isdn/contrib/isdnd_acct
@@ -0,0 +1,137 @@
+#!/usr/bin/perl
+#---------------------------------------------------------------------------
+#
+# Copyright (c) 1996, 1998 Hellmuth Michaelis. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#---------------------------------------------------------------------------
+#
+# accounting report script for the isdnd daemon accounting info
+# -------------------------------------------------------------
+#
+# last edit-date: [Fri May 25 15:28:20 2001]
+#
+# $FreeBSD$
+#
+#---------------------------------------------------------------------------
+
+# where the isdnd accounting file resides
+$ACCT_FILE = "/var/log/isdnd.acct";
+
+# the charge for a unit, currently 0,12 DM
+$UNIT_PRICE = 0.12;
+
+# open accounting file
+open(IN, $ACCT_FILE) ||
+ die "ERROR, cannot open $ACCT_FILE !\n";
+
+# set first thru flag
+$first = 1;
+
+# process file line by line
+while (<IN>)
+{
+ # remove ( and ) from length and bytecounts
+ tr/()//d;
+
+ # split line into pieces
+ ($from_d, $from_h, $dash, $to_d, $to_h, $name, $units, $secs, $byte)
+ = split(/ /, $_);
+
+ # get starting date
+ if($first)
+ {
+ $from = "$from_d $from_h";
+ $first = 0;
+ }
+
+ # split bytecount
+ ($inb, $outb) = split(/\//, $byte);
+
+ # process fields
+ $a_secs{$name} += $secs;
+ $a_calls{$name}++;
+ $a_units{$name} += $units;
+ $a_charge{$name} += $units * $UNIT_PRICE;
+ $a_inbytes{$name} += $inb;
+ $a_outbytes{$name} += $outb;
+ $a_bytes{$name} = $a_bytes{$name} + $inb + $outb;
+}
+
+# close accouting file
+close(IN);
+
+# write header
+print "\n";
+print " ISDN Accounting Report ($from -> $to_d $to_h)\n";
+print " =====================================================================\n";
+
+#write the sum for each interface/name
+foreach $name (sort(keys %a_secs))
+{
+ $o_secs = $a_secs{$name};
+ $gt_secs += $o_secs;
+ $o_calls = $a_calls{$name};
+ $gt_calls += $o_calls;
+ $o_units = $a_units{$name};
+ $gt_units += $o_units;
+ $o_charge = $a_charge{$name};
+ $gt_charge += $o_charge;
+ $o_inbytes = $a_inbytes{$name};
+ $gt_inbytes += $o_inbytes;
+ $o_outbytes = $a_outbytes{$name};
+ $gt_outbytes += $o_outbytes;
+ $o_bytes = $a_bytes{$name};
+ $gt_bytes += $o_bytes;
+ write;
+}
+
+$o_secs = $gt_secs;
+$o_calls = $gt_calls;
+$o_units = $gt_units;
+$o_charge = $gt_charge;
+$o_inbytes = $gt_inbytes;
+$o_outbytes = $gt_outbytes;
+$o_bytes = $gt_bytes;
+$name = "Total";
+
+print "======= ====== ===== ===== ======== ============ ============ ============\n";
+write;
+
+print "\n\n";
+exit;
+
+# top of page header
+format top =
+
+Name charge units calls secs inbytes outbytes bytes
+------- ------ ----- ----- -------- ------------ ------------ ------------
+.
+
+# record template
+format STDOUT =
+@<<<<<< @##.## @#### @#### @####### @########### @########### @###########
+$name, $o_charge, $o_units, $o_calls, $o_secs, $o_inbytes, $o_outbytes, $o_bytes
+.
+
+# EOF
diff --git a/share/examples/isdn/contrib/isdnd_acct.pl b/share/examples/isdn/contrib/isdnd_acct.pl
new file mode 100644
index 000000000000..03062160104d
--- /dev/null
+++ b/share/examples/isdn/contrib/isdnd_acct.pl
@@ -0,0 +1,258 @@
+#!/usr/bin/perl
+#
+#ich habe zwei vielleicht n?tzliche Erweiterungen an isdn_pacct
+#gemacht:
+#
+# 1) Man kann den Namen der Accounting-Datei angeben. Ich
+# habe Accounting-Files nach Telekom-Rechnung aufgeteilt
+# und kann diese so sehr sch?n nachvollziehen.
+#
+# 2) Die Abrechnung wird nach Einheitenl?ngen aufgelistet.
+# Leider wird zur Zeit immer Nahzone verwendet (isdnd.rates
+# wird ausgelesen), und Feiertage stehen als erstes auf
+# der TODO-Liste. Wenn man dieses Feature durch einen
+# Switch anschaltet, kann man es sogar unauff?llig in die
+# Distribution aufnehmen.
+#
+# Mir hilft diese Abrechnung, an mir zu arbeite und mehr
+# Tests und Zug?nge nachts durchzuf?hren... Aber die meisten
+# Einheiten werden immer noch im 90s-Takt verbraucht :-(
+#
+# $FreeBSD$
+#
+#---------------------------------------------------------------------------
+#
+# Copyright (c) 1994, 1996 Hellmuth Michaelis. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Hellmuth Michaelis
+# 4. Neither the name of the author nor the names of any co-contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#---------------------------------------------------------------------------
+#
+# accounting script for the isdn daemon accounting info
+# -----------------------------------------------------
+#
+# last edit-date: [Fri May 25 15:22:26 2001]
+#
+# -hm my first perl program :-)
+# -hm sorting the output
+# -hm adding grand total
+#
+#---------------------------------------------------------------------------
+
+sub wday {
+ local ($y, $m, $d) = @_;
+ local ($nday, @mon);
+
+ @mon = (0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337);
+# M A M J J A S O N D J F
+
+ if ($m > 2) {
+ $m -= 3;
+ } else {
+ $m += 9;
+ $y--;
+ }
+ if ($y < 1600) {
+ return -1;
+ }
+ $y -= 1600;
+ $nday = $y * 365 + $mon[$m] + $d +
+ int($y / 4) - int($y / 100) + int($y / 400);
+ ($nday + 2) % 7;
+}
+
+# where the isdnd accounting file resides
+if ($#ARGV == 0) {
+ $ACCT_FILE = $ARGV[0];
+} else {
+ $ACCT_FILE = "/var/log/isdnd.acct";
+}
+
+# $PERIOD_FILE = "/usr/local/etc/isdnd.periods";
+# # read periods that need to be separately listed
+# if (open(IN, $PERIOD_FILE)) {
+# while (<IN>) {
+# chop;
+# ($start, $end) = split(/ /);
+# push(@p_start, $start);
+# push(@p_end, $end);
+# }
+# close(IN);
+# }
+
+$RATES_FILE = "/etc/isdn/isdnd.rates";
+if (open(IN, $RATES_FILE)) {
+ while(<IN>) {
+ chop;
+ if (! /^ra0/) {
+ next;
+ }
+ ($ra0, $day, $rest) = split(/[ \t]+/, $_, 3);
+ @periods = split(/[ \t]+/, $rest);
+ foreach $period (@periods) {
+ ($h_start, $m_start, $h_end, $m_end, $secs) =
+ $period =~ /(.+)\.(.+)-(.+)\.(.+):(.+)/;
+ for ($h = int($h_start); $h < $h_end; $h++) {
+ $secs{$day, $h} = $secs;
+ }
+ }
+ }
+ close(IN);
+}
+
+# the charge for a unit, currently 0,12 DM
+$UNIT_PRICE = 0.12;
+
+# open accounting file
+open(IN, $ACCT_FILE) ||
+ die "ERROR, cannot open $ACCT_FILE !\n";
+
+# set first thru flag
+$first = 1;
+
+# process file line by line
+while (<IN>)
+{
+ # remove ( and ) from length and bytecounts
+ tr/()//d;
+
+ # split line into pieces
+ ($from_d, $from_h, $dash, $to_d, $to_h, $name, $units, $secs, $byte)
+ = split(/ /, $_);
+
+ # get starting date
+ if($first)
+ {
+ $from = "$from_d $from_h";
+ $first = 0;
+ }
+
+ # split bytecount
+ ($inb, $outb) = split(/\//, $byte);
+
+ # if user wants to account time periods, put this to the right
+ # slot(s)
+ ($hour, $minute, $second) = split(/:/, $from_h);
+ ($day, $mon, $year) = split(/\./, $from_d);
+ $day = &wday('19' . $year, $mon, $day);
+ if ($secs{$day, int($hour)}) {
+ $secs = $secs{$day, int($hour)};
+ # process fields
+ $p_secs{$name, $secs} += $secs;
+ $p_calls{$name, $secs}++;
+ $p_units{$name, $secs} += $units;
+ $p_charge{$name, $secs} += $units * $UNIT_PRICE;
+ $p_inbytes{$name, $secs} += $inb;
+ $p_outbytes{$name, $secs} += $outb;
+ $p_bytes{$name, $secs} = $p_bytes{$name, $secs} + $inb + $outb;
+ }
+
+ # process fields
+ $a_secs{$name} += $secs;
+ $a_calls{$name}++;
+ $a_units{$name} += $units;
+ $a_charge{$name} += $units * $UNIT_PRICE;
+ $a_inbytes{$name} += $inb;
+ $a_outbytes{$name} += $outb;
+ $a_bytes{$name} = $a_bytes{$name} + $inb + $outb;
+}
+
+# close accouting file
+close(IN);
+
+# write header
+print "\n";
+print " ISDN Accounting Report ($from -> $to_d $to_h)\n";
+print " =================================================================\n";
+
+#write the sum for each interface/name
+foreach $n (sort(keys %a_secs))
+{
+ $o_secs = $a_secs{$n};
+ $gt_secs += $o_secs;
+ $o_calls = $a_calls{$n};
+ $gt_calls += $o_calls;
+ $o_units = $a_units{$n};
+ $gt_units += $o_units;
+ $o_charge = $a_charge{$n};
+ $gt_charge += $o_charge;
+ $o_inbytes = $a_inbytes{$n};
+ $gt_inbytes += $o_inbytes;
+ $o_outbytes = $a_outbytes{$n};
+ $gt_outbytes += $o_outbytes;
+ $o_bytes = $a_bytes{$n};
+ $gt_bytes = $o_bytes;
+ $name = $n;
+ write;
+
+ foreach $i (keys %p_secs) {
+ ($nam, $secs) = split(/$;/, $i);
+ if ($nam ne $n) {
+ next;
+ }
+ $o_secs = $p_secs{$i};
+ $o_calls = $p_calls{$i};
+ $o_units = $p_units{$i};
+ $o_charge = $p_charge{$i};
+ $o_inbytes = $p_inbytes{$i};
+ $o_outbytes = $p_outbytes{$i};
+ $o_bytes = $p_bytes{$i};
+ $name = sprintf(' %5.1fs', $secs / 10);
+ write;
+ }
+}
+
+$o_secs = $gt_secs;
+$o_calls = $gt_calls;
+$o_units = $gt_units;
+$o_charge = $gt_charge;
+$o_inbytes = $gt_inbytes;
+$o_outbytes = $gt_outbytes;
+$o_bytes = $gt_bytes;
+$name = "Total";
+
+print "======= ====== ===== ===== ======== ============ ============ ============\n";
+write;
+
+print "\n\n";
+exit;
+
+# top of page header
+format top =
+
+Name charge units calls secs inbytes outbytes bytes
+------- ------ ----- ----- -------- ------------ ------------ ------------
+.
+
+# record template
+format STDOUT =
+@<<<<<< @##.## @#### @#### @####### @########### @########### @###########
+$name, $o_charge, $o_units, $o_calls, $o_secs, $o_inbytes, $o_outbytes, $o_bytes
+.
+
+# EOF
diff --git a/share/examples/isdn/contrib/isdntelmux.c b/share/examples/isdn/contrib/isdntelmux.c
new file mode 100644
index 000000000000..318ebfcb937e
--- /dev/null
+++ b/share/examples/isdn/contrib/isdntelmux.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 1999 Michael Reifenberger (Michael@Reifenberger.com).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4btemux - record while playing
+ * ===============================
+ *
+ * $FreeBSD$
+ *
+ *----------------------------------------------------------------------------*/
+
+#include<stdio.h>
+#include<stdarg.h>
+#include<signal.h>
+#include<errno.h>
+#include<string.h>
+#include<stdlib.h>
+#include<unistd.h>
+#include<fcntl.h>
+#include<ctype.h>
+#include<sys/stat.h>
+#include<sys/wait.h>
+#include<sys/ioctl.h>
+#include<sys/types.h>
+#include<sys/time.h>
+#include<sys/param.h>
+#include<machine/i4b_tel_ioctl.h>
+
+// DECL DEFS
+#define BUFLEN 2048
+#define MAXBLOCKS_DEFAULT 23
+
+// DECL VARS
+int ibytes = 0;
+int obytes = 0;
+int maxbytes = (BUFLEN * MAXBLOCKS_DEFAULT);
+
+int xfd = -1, xact = 0;
+int ifd = -1, iact = 0;
+int ofd = -1;
+FILE *dfp = NULL;
+int opt_dbg = 0;
+int maxfd = 0;
+fd_set set;
+struct timeval timeout;
+char nambuf[PATH_MAX];
+int ch;
+
+// DECL FUNC
+void ifd_hdlr( void);
+void xfd_hdlr( void);
+void usage( void);
+void dbg( char *fmt, ... );
+
+// DEF FUNC
+int main (int argc, char **argv) {
+ int dummy;
+ int x = -1;
+
+ dfp = stderr;
+ while( ( ch = getopt( argc, argv, "x:i:o:b:D:")) != -1 ){
+ switch(ch){
+ case 'b':
+ x = atoi(optarg);
+ maxbytes = x * BUFLEN;
+ break;
+ case 'i':
+ ifd = open( optarg, O_RDONLY );
+ iact = 1;
+ break;
+ case 'o':
+ ofd = open( optarg, O_WRONLY|O_TRUNC|O_CREAT );
+ break;
+ case 'x':
+ xfd = open( optarg, O_RDWR );
+ xact = 1;
+ break;
+ case 'D':
+ opt_dbg = 1;
+ if( (dfp = fopen( optarg, "w" )) < 0) {
+ dfp = stderr;
+ dbg("Err for opening %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case '?':
+ default:
+ usage();
+ break;
+ }
+ }
+ if( ( xfd < 0 ) || ( ifd < 0 ) || ( ofd < 0 ) ) {
+ dbg("Err opening one ore more Files.\n");
+ dbg("xfd: %d, ifd: %d, ofd: %d\n", xfd, ifd, ofd );
+ usage();
+ }
+
+ if((x = ioctl(xfd, I4B_TEL_EMPTYINPUTQUEUE, &dummy)) < 0){
+ dbg("Err I4B_TEL_EMPTYINPUTQUEUE\n");
+ }
+
+ while( (iact == 1) || ( (obytes < maxbytes) && (xact == 1) ) ){
+ FD_ZERO( &set);
+ if( iact == 1){
+ FD_SET( ifd, &set);
+ if( ifd > maxfd)
+ maxfd = ifd;
+ dbg("FSET ifd\n");
+ }
+ if( xact == 1){
+ FD_SET( xfd, &set);
+ if( xfd > maxfd)
+ maxfd = xfd;
+ dbg("FSET xfd\n");
+ }
+ x=select( maxfd+1, &set, NULL, NULL, NULL);
+ if( x > 0){
+ if( (iact == 1) && FD_ISSET( ifd, &set) ){
+ ifd_hdlr();
+ }
+ if( (xact == 1) && FD_ISSET( xfd, &set) ){
+ xfd_hdlr();
+ }
+ }
+ }
+ dbg("exit0\n");
+ return(0);
+}
+
+void ifd_hdlr( void) {
+ int x;
+ unsigned char buf[BUFLEN];
+
+ x = read( ifd, buf, BUFLEN);
+ dbg("ifd read %d bytes\n", x);
+ if( x > 0 ){
+ write( xfd, buf, x);
+ ibytes += x;
+ dbg("xfd %d bytes written to %d\n", x, ibytes);
+ } else {
+ iact = 0;
+ }
+}
+
+void xfd_hdlr( void) {
+ int x;
+ unsigned char buf[BUFLEN];
+
+ x = read( xfd, buf, BUFLEN);
+ dbg("xfd read %d bytes\n", x);
+ if( x > 0){
+ write( ofd, buf, x);
+ obytes += x;
+ dbg("ofd %d bytes written to %d\n", x, obytes);
+ } else {
+ xact = 0;
+ }
+}
+
+void usage( void) {
+ fprintf(dfp, "isdntelmux V.1\n");
+ fprintf(dfp, "usage: isdntelmux -x device -i ifile -o ofile [-b blocks]\n");
+ exit(1);
+}
+
+void dbg( char *fmt, ... ) {
+ va_list ap;
+
+ if( opt_dbg == 0 )
+ return;
+ va_start( ap, fmt );
+ vfprintf( dfp, fmt, ap);
+ va_end(ap);
+}
diff --git a/share/examples/isdn/contrib/mrtg-isp0.sh b/share/examples/isdn/contrib/mrtg-isp0.sh
new file mode 100644
index 000000000000..bdc9671883ac
--- /dev/null
+++ b/share/examples/isdn/contrib/mrtg-isp0.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+#---------------------------------------------------------------------------
+#
+# collect callout and callback statistics for the isp0 i/f
+#
+# enable budget callout and callback restrictions and file
+# rotation in the isdnd.rc file.
+#
+# last edit-date: [Fri May 25 15:22:45 2001]
+#
+# $FreeBSD$
+#
+#---------------------------------------------------------------------------
+#
+#---------------------------------------------------------------------------
+# this is the entry for mrtg in mrtg.cfg
+#---------------------------------------------------------------------------
+# Target[ernie.cstat.isp0]: `/usr/local/etc/mrtg/util/mrtg-isp0.sh`
+# MaxBytes[ernie.cstat.isp0]: 10
+# AbsMax[ernie.cstat.isp0]: 200
+# Title[ernie.cstat.isp0]: isp0: callouts / callbacks
+# PageTop[ernie.cstat.isp0]: <H1> isp0: callouts /callbacks </H1>
+# Options[ernie.cstat.isp0]: gauge, nopercent, integer
+# YLegend[ernie.cstat.isp0]: co / cb
+# ShortLegend[ernie.cstat.isp0]: n
+# Legend1[ernie.cstat.isp0]: callouts
+# Legend2[ernie.cstat.isp0]: callbacks
+# LegendI[ernie.cstat.isp0]: callouts:
+# LegendO[ernie.cstat.isp0]: callbacks:
+# WithPeak[ernie.cstat.isp0]: ymwd
+#
+#---------------------------------------------------------------------------
+# this is the shell script run by mrtg
+#---------------------------------------------------------------------------
+if [ -r /var/log/isdn/callouts.isp0 ]
+then
+ cat /var/log/isdn/callouts.isp0 | awk '{print $3}'
+else
+ echo 0
+fi
+
+if [ -r /var/log/isdn/callbacks.isp0 ]
+then
+ cat /var/log/isdn/callbacks.isp0 | awk '{print $3}'
+else
+ echo 0
+fi
+
+uptime | cut -c 12-18
+uname -nsr
+
+exit 0
+
diff --git a/share/examples/isdn/v21/Makefile b/share/examples/isdn/v21/Makefile
new file mode 100644
index 000000000000..3c499966276b
--- /dev/null
+++ b/share/examples/isdn/v21/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+PROG= v21modem
+NOMAN= 1
+LDADD= -lutil -lm
+CFLAGS+= -g -Wall
+
+.if !defined(BSDTYPE)
+BSDTYPE!=uname
+.endif
+
+.include <bsd.prog.mk>
diff --git a/share/examples/isdn/v21/README b/share/examples/isdn/v21/README
new file mode 100644
index 000000000000..52f553c31307
--- /dev/null
+++ b/share/examples/isdn/v21/README
@@ -0,0 +1,50 @@
+
+ V.21 Modem for ISDN4BSD.
+
+INTRODUCTION:
+
+The modem is implemented in software and is rather simple minded.
+
+It works with my Telebit TB2500 and Zyxel 2864I modems.
+
+There are plenty of knobs and handles which can be adjusted and I have
+no real idea what to set them to for best all-round performance.
+
+The carrier detect timer may be a bit short tempered, and this is
+probably why the dialing modem needs to be told to talk V.21 up
+front. If this code were mode tolerant of loss of carrier auto
+negotiation might work.
+
+When you get carrier ("CONNECT 300"), you must press a key before the
+login banner gets printed. See the comments in "input_byte" why this
+is.
+
+THE KERNEL PART:
+
+Implementes a crude "send these tones" facility, but it is enough to
+take most of the real-time worries out of doing FSK modulation in
+software. If suitably extended, the code could also be used to
+send DTMF tones and other similar signals.
+
+INSTALLATION:
+
+The program is started from /etc/isdn/isdnd.rc:
+
+entry
+ name = I4BTEL
+ usrdevicename = tel
+ usrdeviceunit = 0
+ isdncontroller = 0
+ isdnchannel = -1
+ local-phone-incoming = 2934812934
+ remote-phone-incoming = *
+ dialin-reaction = answer
+ answerprog = v21modem
+ b1protocol = raw
+ idletime-incoming = 5
+
+
+Poul-Henning (phk@freebsd.org)
+19991212
+
+$FreeBSD$
diff --git a/share/man/man4/ieee80211.4 b/share/man/man4/ieee80211.4
new file mode 100644
index 000000000000..546311c64035
--- /dev/null
+++ b/share/man/man4/ieee80211.4
@@ -0,0 +1,234 @@
+.\" Copyright (c) 2001
+.\" The Aerospace Corporation. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 23, 2001
+.Dt IEEE80211 4
+.Os FreeBSD 4.3
+.Sh NAME
+.Nm ieee80211
+.Nd standard interface to IEEE 802.11 devices
+.Sh SYNOPSIS
+.Fd #include <net/if_ieee80211.h>
+.Sh DESCRIPTION
+This section describes the interface standard interface to configuration
+and status information on IEEE 802.11 devices. Most devices support
+options not configurable by this interface. They must be set by their
+respective, specific control program. The interface is via one
+of the following
+.Xr ioctl 2
+calls on a socket:
+.Bl -tag -width SIOCG80211
+.It Dv SIOCG80211
+Get configuration or status information.
+.It Dv SIOCS80211
+Set configuration information.
+.El
+These requests are made via a modified
+.Ar ifreq
+structure. This structure is defined as follows:
+.Bd -literal
+struct ieee80211req {
+ char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */
+ u_int16_t i_type; /* req type */
+ int16_t i_val; /* Index or simple value */
+ int16_t i_len; /* Index or simple value */
+ void *i_data; /* Extra data */
+};
+.Ed
+.Pp
+For
+.Dv SIOCG80211
+the following values of
+.Ar i_type
+are valid:
+.Bl -tag -width IEEE80211_IOC_POWERSAVESLEEP
+.It Dv IEEE80211_IOC_SSID
+Returns the requested SSID by copying it into the buffer pointed to by
+.Ar i_data
+and setting
+.Ar i_len
+to the length. If
+.Ar i_val
+is >= 0 then the request refers to the configured value for that slot.
+Generally, 0 is the only valid value, but some interfaces support more
+SSIDs. If
+.Ar i_val
+is -1 then the request refers to the currently active value.
+.It Dv IEEE80211_IOC_NUMSSIDS
+Returns the number of SSIDs this card supports. In most cases, this is
+1, but some devices such as
+.Xr an 4
+support more.
+.It Dv IEEE80211_IOC_WEP
+Returns the current WEP status in
+.Ar i_val .
+Valid values are
+.Dv IEEE80211_WEP_NOSUP ,
+.Dv IEEE80211_WEP_ON ,
+.Dv IEEE80211_WEP_OFF ,
+and
+.Dv IEEE80211_WEP_MIXED .
+Respectively, these values mean unsupported, mandatory for all devices,
+off, and on, but not required for all devices.
+.It Dv IEEE80211_IOC_WEPKEY
+Returns the requested WEP key via
+.Ar i_data
+and it's length via
+.Ar i_len .
+If the device does not support returning the WEP key or the user is not
+root then the key may be returned as all zeros. Technically this is a
+valid key, but it's the kind of key an idiot would put on his luggage so
+we use it as a special value. Generally, only four WEP keys are
+allowed, but some devices support more. If so, the first four (0-3) are
+the standard keys stored in volatile storage and the others are device
+specific.
+.It Dv IEEE80211_IOC_NUMWEPKEYS
+Returns the number of WEP keys supported by this device, generally 4.
+A device that does not support WEP may either report 0 or simply return
+.Dv EINVAL .
+.It Dv IEEE80211_IOC_WEPTXKEY
+Returns the WEP key used for transmission.
+.It Dv IEEE80211_IOC_AUTHMODE
+Returns the current authentication mode in
+.Ar i_val .
+Valid values are
+.Dv IEEE80211_AUTH_NONE ,
+.Dv IEEE80211_AUTH_OPEN ,
+and
+.Dv IEEE80211_AUTH_SHARED .
+.It Dv IEEE80211_IOC_STATIONNAME
+Returns the station name via
+.Ar i_data
+and its length via
+.Ar i_len .
+While all known devices seem to support this is some way or another,
+they all do it differently and it appears to not have anything to do
+with the actual IEEE 802.11 standard so making up an answer may be
+necessary for future devices.
+.It Dv IEEE80211_IOC_CHANNEL
+Returns the current direct sequence spread spectrum channel in use.
+.It Dv IEEE80211_IOC_POWERSAVE
+Returns the current powersaving mode. Valid values are
+.Dv IEEE80211_POWERSAVE_NOSUP ,
+.Dv IEEE80211_POWERSAVE_OFF ,
+.Dv IEEE80211_POWERSAVE_ON ,
+.Dv IEEE80211_POWERSAVE_CAM ,
+.Dv IEEE80211_POWERSAVE_PSP ,
+and
+.Dv IEEE80211_POWERSAVE_PSP_CAM .
+Currently,
+.Dv IEEE80211_POWERSAVE_ON
+is defined to be equal to
+.Dv IEEE80211_POWERSAVE_CAM ,
+but this may be incorrect.
+.It Dv IEEE80211_IOC_POWERSAVESLEEP
+Returns the powersave sleep time in msec in
+.Ar i_val .
+.El
+.Pp
+For
+.Dv SIOCS80211
+the following values of
+.Ar i_type
+are valid:
+.Bl -tag -width IEEE80211_IOC_POWERSAVESLEEP
+.It Dv IEEE80211_IOC_SSID
+Set the desired SSID for infrastructure and ad-hoc modes to value given
+by
+.Ar i_data
+and
+.Ar i_len .
+The length should be no longer then 32 characters.
+.It Dv IEEE80211_IOC_WEP
+Set the current WEP mode to the value given in
+.Ar i_val .
+Valid values are the same as those for this value above. Devices which
+do not support all modes may choose to either return
+.Dv EINVAL
+or choose a reasonable alternate (supported) setting.
+.It Dv IEEE80211_IOC_WEPKEY
+Set the WEP key indicated by
+.Ar i_val
+to the value given by
+.Ar i_data
+and
+.Ar i_len .
+Generally, valid values of
+.Ar i_len
+are 0, 5, and 13 though not all devices with WEP support have support
+for 13-byte keys.
+.It Dv IEEE80211_IOC_WEPTXKEY
+Set the WEP key used for transmission to the value in
+.Ar i_val .
+Not all values which are valid for setting keys may be valid for setting
+transmit keys due to strange device interfaces.
+.It Dv IEEE80211_IOC_AUTHMODE
+Set the current authorization mode to the value given in
+.Ar i_val .
+Valid values are given above. No all devices support this.
+.It Dv IEEE80211_IOC_STATIONNAME
+Set the station name to the value given by
+.Ar i_data
+and
+.Ar i_len .
+The standard does not appear to deal with this feature so the range of
+valid values may vary from device to device.
+.It Dv IEEE80211_IOC_CHANNEL
+Set the desired ad-hoc channel to the value given by
+.Ar i_val .
+On some devices this has an impact on infrastructure mode as well.
+Valid values are 1-14, but 0 should be allowed and should return the
+device to the default value. May devices support this directly by
+converting any invalid value to the default value.
+.It Dv IEEE80211_IOC_POWERSAVE
+Set the current powersaving mode to the value given in
+.Ar i_val .
+Valid values are the same as those for this value above. Devices which
+do not support all modes may choose to either return
+.Dv EINVAL
+or choose a reasonable alternate (supported) setting. Most devices only
+support CAM mode.
+.It Dv IEEE80211_IOC_POWERSAVESLEEP
+Set the powersave sleep time in msec to the value in
+.Ar i_val .
+.El
+.Sh SEE ALSO
+.Xr ioctl 2 ,
+.Xr an 4 ,
+.Xr ray 4 ,
+.Xr wi 4 ,
+.Xr ancontrol 8 ,
+.Xr ifconfig 8 ,
+.Xr raycontrol 8 ,
+.Xr wicontrol 8 ,
+.Sh HISTORY
+The
+.Nm ieee80211
+manual appeared in
+.Fx 4.3 .
diff --git a/share/man/man7/firewall.7 b/share/man/man7/firewall.7
new file mode 100644
index 000000000000..043af5aa3547
--- /dev/null
+++ b/share/man/man7/firewall.7
@@ -0,0 +1,375 @@
+.\" Copyright (c) 2001, Matthew Dillon. Terms and conditions are those of
+.\" the BSD Copyright as specified in the file "/usr/src/COPYRIGHT" in
+.\" the source tree.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd May 26, 2001
+.Dt FIREWALL 7
+.Os FreeBSD
+.Sh NAME
+.Nm firewall
+.Nd simple firewalls under FreeBSD
+.Sh FIREWALL BASICS
+A Firewall is most commonly used to protect an internal network
+from an outside network by preventing the outside network from
+making arbitrary connections into the internal network. Firewalls
+are also used to prevent outside entities from spoofing internal
+IP addresses and to isolate services such as NFS or SMBFS (Windows
+file sharing) within LAN segments.
+.Pp
+The
+.Fx
+firewalling system also has the capability to limit bandwidth using
+.Xr dummynet 4 .
+This feature can be useful when you need to guarentee a certain
+amount of bandwidth for a critical purpose. For example, if you
+are doing video conferencing over the internet via your
+office T1 (1.5 MBits), you may wish to bandwidth-limit all other
+T1 traffic to 1 MBit in order to reserve at least 0.5 MBits
+for your video conferencing connections. Similarly if you are
+running a popular web or ftp site from a colocation facility
+you might want to limit bandwidth to prevent excessive band
+width charges from your provider.
+.Pp
+Finally,
+.Fx
+firewalls may be used to divert packets or change the next-hop
+address for packets to help route them to the correct destination.
+Packet diversion is most often used to support NAT (network
+address translation), which allows an internal network using
+a private IP space to make connections to the outside for browsing
+or other purposes.
+.Pp
+Constructing a firewall may appear to be trivial, but most people
+get them wrong. The most common mistake is to create an exclusive
+firewall rather then an inclusive firewall. An exclusive firewall
+allows all packets through except for those matching a set of rules.
+An inclusive firewall allows only packets matching the rulset
+through. Inclusive firewalls are much, much safer then exclusive
+firewalls but a tad more difficult to build properly. The
+second most common mistake is to blackhole everything except the
+particular port you want to let through. TCP/IP needs to be able
+to get certain types of ICMP errors to function properly - for
+example, to implement MTU discovery. Also, a number of common
+system daemons make reverse connections to the
+.Sy auth
+service in an attempt to authenticate the user making a connection.
+Auth is rather dangerous but the proper implementation is to return
+a TCP reset for the connection attempt rather then simply blackholing
+the packet. We cover these and other quirks involved with constructing
+a firewall in the sample firewall section below.
+.Sh IPFW KERNEL CONFIGURATION
+To use the ip firewall features of
+.Fx
+you must create a custom kernel with the
+.Sy IPFIREWALL
+option set. The kernel defaults its firewall to deny all
+packets by default, which means that if you do not load in
+a permissive ruleset via
+.Em /etc/rc.conf ,
+rebooting into your new kernel will take the network offline
+and will prevent you from being able to access it if you
+are not sitting at the console. It is also quite common to
+update a kernel to a new release and reboot before updating
+the binaries. This can result in an incompatibility between
+the
+.Xr ipfw 8
+program and the kernel which prevents it from running in the
+boot sequence, also resulting in an inaccessible machine.
+Because of these problems the
+.Sy IPFIREWALL_DEFAULT_TO_ACCEPT
+kernel option is also available which changes the default firewall
+to pass through all packets. Note, however, that this is a very
+dangerous option to set because it means your firewall is disabled
+during booting. You should use this option while getting up to
+speed with
+.Fx
+firewalling, but get rid of it once you understand how it all works
+to close the loophole. There is a third option called
+.Sy IPDIVERT
+which allows you to use the firewall to divert packets to a user program
+and is necessary if you wish to use
+.Xr natd 8
+to give private internal networks access to the outside world.
+If you want to be able to limit the bandwidth used by certain types of
+traffic, the
+.Sy DUMMYNET
+option must be used to enable
+.Em ipfw pipe
+rules.
+.Pp
+.Sh SAMPLE IPFW-BASED FIREWALL
+Here is an example ipfw-based firewall taken from a machine with three
+interface cards. fxp0 is connected to the 'exposed' LAN. Machines
+on this LAN are dual-homed with both internal 10. IP addresses and
+internet-routed IP addresses. In our example, 192.100.5.x represents
+the internet-routed IP block while 10.x.x.x represents the internal
+networks. While it isn't relevant to the example, 10.0.1.x is
+assigned as the internal address block for the LAN on fxp0, 10.0.2.x
+for the LAN on fxp1, and 10.0.3.x for the LAN on fxp2.
+.Pp
+In this example we want to isolate all three LANs from the internet
+as well as isolate them from each other, and we want to give all
+internal addresses access to the internet through a NAT gateway running
+on this machine. To make the NAT gateway work, the firewall machine
+is given two internet-exposed addresses on fxp0 in addition to an
+internal 10. address on fxp0: one exposed address (not shown)
+represents the machine's official address, and the second exposed
+address (192.100.5.5 in our example) represents the NAT gateway
+rendezvous IP. We make the example more complex by giving the machines
+on the exposed LAN internal 10.0.0.x addresses as well as exposed
+addresses. The idea here is that you can bind internal services
+to internal addresses even on exposed machines and still protect
+those services from the internet. The only services you run on
+exposed IP addresses would be the ones you wish to expose to the
+internet.
+.Pp
+It is important to note that the 10.0.0.x network in our example
+is not protected by our firewall. You must make sure that your
+internet router protects this network from outside spoofing.
+Also, in our example, we pretty much give the exposed hosts free
+reign on our internal network when operating services through
+internal IP addresses (10.0.0.x). This is somewhat of security
+risk... what if an exposed host is compromised? To remove the
+risk and force everything coming in via LAN0 to go through
+the firewall, remove rules 01010 and 01011.
+.Pp
+Finally, note that the use of internal addresses represents a
+big piece of our firewall protection mechanism. With proper
+spoofing safeguards in place, nothing outside can directly
+access an internal (LAN1 or LAN2) host.
+.Bd -literal
+# /etc/rc.conf
+#
+firewall_enable="YES"
+firewall_type="/etc/ipfw.conf"
+
+# temporary port binding range let
+# through the firewall.
+#
+# NOTE: heavily loaded services running through the firewall may require
+# a larger port range for local-size binding. 4000-10000 or 4000-30000
+# might be a better choice.
+ip_portrange_first=4000
+ip_portrange_last=5000
+...
+.Ed
+.Pp
+.Bd -literal
+# /etc/ipfw.conf
+#
+# FIREWALL: the firewall machine / nat gateway
+# LAN0 10.0.0.X and 192.100.5.X (dual homed)
+# LAN1 10.0.1.X
+# LAN2 10.0.2.X
+# sw: ethernet switch (unmanaged)
+#
+# 192.100.5.x represents IP addresses exposed to the internet
+# (i.e. internet routeable). 10.x.x.x represent internal IPs
+# (not exposed)
+#
+# [LAN1]
+# ^
+# |
+# FIREWALL -->[LAN2]
+# |
+# [LAN0]
+# |
+# +--> exposed host A
+# +--> exposed host B
+# +--> exposed host C
+# |
+# INTERNET (secondary firewall)
+# ROUTER
+# |
+# [internet]
+#
+# NOT SHOWN: The INTERNET ROUTER must contain rules to disallow
+# all packets with source IP addresses in the 10. block in order
+# to protect the dual-homed 10.0.0.x block. Exposed hosts are
+# not otherwise protected in this example - they should only bind
+# exposed services to exposed IPs but can safely bind internal
+# services to internal IPs.
+#
+# The NAT gateway works by taking packets sent from internal
+# IP addresses to external IP addresses and routing them to natd, which
+# is listening on port 8668. This is handled by rule 00300. Data coming
+# back to natd from the outside world must also be routed to natd using
+# rule 00301. To make the example interesting, we note that we do
+# NOT have to run internal requests to exposed hosts through natd
+# (rule 00290) because those exposed hosts know about our
+# 10. network. This can reduce the load on natd. Also note that we
+# of course do not have to route internal<->internal traffic through
+# natd since those hosts know how to route our 10. internal network.
+# The natd command we run from /etc/rc.local is shown below. See
+# also the in-kernel version of natd, ipnat.
+#
+# natd -s -u -a 208.161.114.67
+#
+#
+add 00290 skipto 1000 ip from 10.0.0.0/8 to 192.100.5.0/24
+add 00300 divert 8668 ip from 10.0.0.0/8 to not 10.0.0.0/8
+add 00301 divert 8668 ip from not 10.0.0.0/8 to 192.100.5.5
+
+# Short cut the rules to avoid running high bandwidths through
+# the entire rule set. Allow established tcp connections through,
+# and shortcut all outgoing packets under the assumption that
+# we need only firewall incoming packets.
+#
+# Allowing established tcp connections through creates a small
+# hole but may be necessary to avoid overloading your firewall.
+# If you are worried, you can move the rule to after the spoof
+# checks.
+#
+add 01000 allow tcp from any to any established
+add 01001 allow all from any to any out via fxp0
+add 01001 allow all from any to any out via fxp1
+add 01001 allow all from any to any out via fxp2
+
+# Spoof protection. This depends on how well you trust your
+# internal networks. Packets received via fxp1 MUST come from
+# 10.0.1.x. Packets received via fxp2 MUST come from 10.0.2.x.
+# Packets received via fxp0 cannot come from the LAN1 or LAN2
+# blocks. We can't protect 10.0.0.x here, the internet router
+# must do that for us.
+#
+add 01500 deny all from not 10.0.1.0/24 in via fxp1
+add 01500 deny all from not 10.0.2.0/24 in via fxp2
+add 01501 deny all from 10.0.1.0/24 in via fxp0
+add 01501 deny all from 10.0.2.0/24 in via fxp0
+
+# In this example rule set there are no restrictions between
+# internal hosts, even those on the exposed LAN (as long as
+# they use an internal IP address). This represents a
+# potential security hole (what if an exposed host is
+# compromised?). If you want full restrictions to apply
+# between the three LANs, firewalling them off from each
+# other for added security, remove these two rules.
+#
+# If you want to isolate LAN1 and LAN2, but still want
+# to give exposed hosts free reign with each other, get
+# rid of rule 01010 and keep rule 01011.
+#
+# (commented out, uncomment for less restrictive firewall)
+#add 01010 allow all from 10.0.0.0/8 to 10.0.0.0/8
+#add 01011 allow all from 192.100.5.0/24 to 192.100.5.0/24
+#
+
+# SPECIFIC SERVICES ALLOWED FROM SPECIFIC LANS
+#
+# If using a more restrictive firewall, allow specific LANs
+# access to specific services running on the firewall itself.
+# In this case we assume LAN1 needs access to filesharing running
+# on the firewall. If using a less restrictive firewall
+# (allowing rule 01010), you don't need these rules.
+#
+add 01012 allow tcp from 10.0.1.0/8 to 10.0.1.1 139
+add 01012 allow udp from 10.0.1.0/8 to 10.0.1.1 137,138
+
+# GENERAL SERVICES ALLOWED TO CROSS INTERNAL AND EXPOSED LANS
+#
+# We allow specific UDP services through: DNS lookups, ntalk, and ntp.
+# Note that internal services are protected by virtue of having
+# spoof-proof internal IP addresses (10. net), so these rules
+# really only apply to services bound to exposed IPs. We have
+# to allow UDP fragments or larger fragmented UDP packets will
+# not survive the firewall.
+#
+# If we want to expose high-numbered temporary service ports
+# for things like DNS lookup responses we can use a port range,
+# in this example 4000-65535, and we set to /etc/rc.conf variables
+# on all exposed machines to make sure they bind temporary ports
+# to the exposed port range (see rc.conf example above)
+#
+add 02000 allow udp from any to any 4000-65535,domain,ntalk,ntp
+add 02500 allow udp from any to any frag
+
+# Allow similar services for TCP. Again, these only apply to
+# services bound to exposed addresses. NOTE: we allow 'auth'
+# through but do not actually run an identd server on any exposed
+# port. This allows the machine being authed to respond with a
+# TCP RESET. Throwing the packet away would result in delays
+# when connecting to remote services that do reverse ident lookups.
+#
+# Note that we do not allow tcp fragments through, and that we do
+# not allow fragments in general (except for UDP fragments). We
+# expect the TCP mtu discovery protocol to work properly so there
+# should be no TCP fragments.
+#
+add 03000 allow tcp from any to any http,https
+add 03000 allow tcp from any to any 4000-65535,ssh,smtp,domain,ntalk
+add 03000 allow tcp from any to any auth,pop3,ftp,ftp-data
+
+# It is important to allow certain ICMP types through:
+#
+# 0 Echo Reply
+# 3 Destination Unreachable
+# 4 Source Quench (typically not allowed)
+# 5 Redirect (typically not allowed - can be dangerous!)
+# 8 Echo
+# 11 Time Exceeded
+# 12 Parameter Problem
+# 13 Timestamp
+# 14 Timestamp Reply
+#
+# Sometimes people need to allow ICMP REDIRECT packets, which is
+# type 5, but if you allow it make sure that your internet router
+# disallows it.
+
+add 04000 allow icmp from any to any icmptypes 0,5,8,11,12,13,14
+
+# log any remaining fragments that get through. Might be useful,
+# otherwise don't bother. Have a final deny rule as a safety to
+# guarentee that your firewall is inclusive no matter how the kernel
+# is configured.
+#
+add 05000 deny log ip from any to any frag
+add 06000 deny all from any to any
+.Ed
+.Sh PORT BINDING INTERNAL AND EXTERNAL SERVICES
+We've mentioned multi-homing hosts and binding services to internal or
+external addresses but we haven't really explained it. When you have a
+host with multiple IP addresses assigned to it, you can bind services run
+on that host to specific IPs or interfaces rather then all IPs. Take
+the firewall machine for example: With three interfaces
+and two exposed IP addresses
+on one of those interfaces, the firewall machine is known by 5 different
+IP addresses (10.0.0.1, 10.0.1.1, 10.0.2.1, 192.100.5.5, and say
+192.100.5.1). If the firewall is providing file sharing services to the
+windows LAN segment (say it is LAN1), you can use samba's 'bind interfaces'
+directive to specifically bind it to just the LAN1 IP address. That
+way the file sharing services will not be made available to other LAN
+segments. The same goes for NFS. If LAN2 has your UNIX engineering
+workstations, you can tell nfsd to bind specifically to 10.0.2.1. You
+can specify how to bind virtually every service on the machine and you
+can use a light
+.Xr jail 8
+to indirectly bind services that do not otherwise give you the option.
+.Sh SEE ALSO
+.Pp
+.Xr config 8 ,
+.Xr dummynet 4 ,
+.Xr ipfw 8 ,
+.Xr ipnat 1 ,
+.Xr ipnat 5 ,
+.Xr jail 8 ,
+.Xr natd 8 ,
+.Xr nfsd 8 ,
+.Xr rc.conf 5 ,
+.Xr samba 7 [ /usr/ports/net/samba ]
+.Xr smb.conf 5 [ /usr/ports/net/samba ]
+.Sh ADDITIONAL READING
+.Pp
+.Xr ipf 5 ,
+.Xr ipf 8 ,
+.Xr ipfstat 8
+.Sh HISTORY
+The
+.Nm
+manual page was originally written by
+.An Matthew Dillon
+and first appeared
+in
+.Fx 4.3 ,
+May 2001.
diff --git a/share/man/man7/tuning.7 b/share/man/man7/tuning.7
new file mode 100644
index 000000000000..8c7630e4953b
--- /dev/null
+++ b/share/man/man7/tuning.7
@@ -0,0 +1,478 @@
+.\" Copyright (c) 2001, Matthew Dillon. Terms and conditions are those of
+.\" the BSD Copyright as specified in the file "/usr/src/COPYRIGHT" in
+.\" the source tree.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd May 25, 2001
+.Dt TUNING 7
+.Os FreeBSD
+.Sh NAME
+.Nm tuning
+.Nd performance tuning under FreeBSD
+.Sh SYSTEM SETUP - DISKLABEL, NEWFS, TUNEFS, SWAP
+.Pp
+When using
+.Xr disklabel 8
+to lay out your filesystems on a hard disk it is important to remember
+that hard drives can transfer data much more quickly from outer tracks
+then they can from inner tracks. To take advantage of this you should
+try to pack your smaller filesystems and swap closer to the outer tracks,
+follow with the larger filesystems, and end with the largest filesystems.
+It is also important to size system standard filesystems such that you
+will not be forced to resize them later as you scale the machine up.
+I usually create, in order, a 128M root, 1G swap, 128M /var, 128M /var/tmp,
+3G /usr, and use any remaining space for /home.
+.Pp
+You should typically size your swap space to approximately 2x main memory.
+If you do not have a lot of ram, though, you will generally want a lot
+more swap. It is not recommended that you configure any less than
+256M of swap on a system and you should keep in mind future memory
+expansion when sizing the swap partition.
+The kernel's VM paging algorithms are tuned to perform best when there is
+at least 2x swap versus main memory. Configuring too little swap can lead
+to inefficiencies in the VM page scanning code as well as create issues
+later on if you add more memory to your machine. Finally, on larger systems
+with multiple SCSI disks (or multiple IDE disks operating on different
+controllers), we strongly recommend that you configure swap on each drive
+(up to four drives). The swap partitions on the drives should be
+approximately the same size. The kernel can handle arbitrary sizes but
+internal data structures scale to 4 times the largest swap partition. Keeping
+the swap partitions near the same size will allow the kernel to optimally
+stripe swap space across the N disks. Don't worry about overdoing it a
+little, swap space is the saving grace of
+.Ux
+and even if you don't normally use much swap, it can give you more time to
+recover from a runaway program before being forced to reboot.
+.Pp
+How you size your
+.Em /var
+partition depends heavily on what you intend to use the machine for. This
+partition is primarily used to hold mailboxes, the print spool, and log
+files. Some people even make
+.Em /var/log
+its own partition (but except for extreme cases it isn't worth the waste
+of a partition id). If your machine is intended to act as a mail
+or print server,
+or you are running a heavily visited web server, you should consider
+creating a much larger partition - perhaps a gig or more. It is very easy
+to underestimate log file storage requirements.
+.Pp
+Sizing
+.Em /var/tmp
+depends on the kind of temporary file usage you think you will need. 128M is
+the minimum we recommend. Also note that you usually want to make
+.Em /tmp
+a softlink to
+.Em /var/tmp .
+Dedicating a partition for temporary file storage is important for
+two reasons: First, it reduces the possibility of filesystem corruption
+in a crash, and second it reduces the chance of a runaway process that
+fills up [/var]/tmp from blowing up more critical subsystems (mail,
+logging, etc). Filling up [/var]/tmp is a very common problem to have.
+.Pp
+In the old days there were differences between /tmp and /var/tmp,
+but the introduction of /var (and /var/tmp) led to massive confusion
+by program writers so today programs halfhazardly use one or the
+other and thus no real distinction can be made between the two. So
+it makes sense to have just one temporary directory. You can do the
+softlink either way. The one thing you do not want to do is leave /tmp
+on the root partition where it might cause root to fill up or possibly
+corrupt root in a crash/reboot situation.
+.Pp
+The
+.Em /usr
+partition holds the bulk of the files required to support the system and
+a subdirectory within it called
+.Em /usr/local
+holds the bulk of the files installed from the
+.Xr ports 7
+hierarchy. If you do not use ports all that much and do not intend to keep
+system source (/usr/src) on the machine, you can get away with
+a 1 gigabyte /usr partition. However, if you install a lot of ports
+(especially window managers and linux-emulated binaries), we recommend
+at least a 2 gigabyte /usr and if you also intend to keep system source
+on the machine, we recommend a 3 gigabyte /usr. Do not underestimate the
+amount of space you will need in this partition, it can creep up and
+surprise you!
+.Pp
+The
+.Em /home
+partition is typically used to hold user-specific data. I usually size it
+to the remainder of the disk.
+.Pp
+Why partition at all? Why not create one big
+.Em /
+partition and be done with it? Then I don't have to worry about undersizing
+things! Well, there are several reasons this isn't a good idea. First,
+each partition has different operational characteristics and separating them
+allows the filesystem to tune itself to those characteristics. For example,
+the root and /usr partitions are read-mostly, with very little writing, while
+a lot of reading and writing could occur in /var and /var/tmp. By properly
+partitioning your system, fragmentation introduced in the smaller more
+heavily write-loaded partitions will not bleed over into the mostly-read
+partitions. Additionally, keeping the write-loaded partitions closer to
+the edge of the disk (i.e. before the really big partitions instead of after
+in the partition table) will increase I/O performance in the partitions
+where you need it the most. Now it is true that you might also need I/O
+performance in the larger partitions, but they are so large that shifting
+them more towards the edge of the disk will not lead to a significnat
+performance improvement whereas moving /var to the edge can have a huge impact.
+Finally, there are safety concerns. Having a small neat root partition that
+is essentially read-only gives it a greater chance of surviving a bad crash
+intact.
+.Pp
+Properly partitioning your system also allows you to tune
+.Xr newfs 8 ,
+and
+.Xr tunefs 8
+parameters. Tuning
+.Fn newfs
+requires more experience but can lead to significant improvements in
+performance. There are three parameters that are relatively safe to
+tune:
+.Em blocksize ,
+.Em bytes/inode ,
+and
+.Em cylinders/group .
+.Pp
+.Fx
+performs best when using 8K or 16K filesystem block sizes. The default
+filesystem block size is 8K. For larger partitions it is usually a good
+idea to use a 16K block size. This also requires you to specify a larger
+fragment size. We recommend always using a fragment size that is 1/8
+the block size (less testing has been done on other fragment size factors).
+The
+.Fn newfs
+options for this would be
+.Em newfs -f 2048 -b 16384 ...
+Using a larger block size can cause fragmentation of the buffer cache and
+lead to lower performance.
+.Pp
+If a large partition is intended to be used to hold fewer, larger files, such
+as a database files, you can increase the
+.Em bytes/inode
+ratio which reduces the number if inodes (maximum number of files and
+directories that can be created) for that partition. Decreasing the number
+of inodes in a filesystem can greatly reduce
+.Xr fsck 8
+recovery times after a crash. Do not use this option
+unless you are actually storing large files on the partition, because if you
+overcompensate you can wind up with a filesystem that has lots of free
+space remaining but cannot accomodate any more files. Using
+32768, 65536, or 262144 bytes/inode is recommended. You can go higher but
+it will have only incremental effects on fsck recovery times. For
+example,
+.Em newfs -i 32768 ...
+.Pp
+Finally, increasing the
+.Em cylinders/group
+ratio has the effect of packing the inodes closer together. This can increase
+directory performance and also decrease fsck times. If you use this option
+at all, we recommend maxing it out. Use
+.Em newfs -c 999
+and newfs will error out and tell you what the maximum is, then use that.
+.Pp
+.Xr tunefs 8
+may be used to further tune a filesystem. This command can be run in
+single-user mode without having to reformat the filesystem. However, this
+is possibly the most abused program in the system. Many people attempt to
+increase available filesystem space by setting the min-free percentage to 0.
+This can lead to severe filesystem fragmentation and we do not recommend
+that you do this. Really the only tunefs option worthwhile here is turning on
+.Em softupdates
+with
+.Em tunefs -n enable /filesystem.
+(Note: In 5.x softupdates can be turned on using the -U option to newfs).
+Softupdates drastically improves meta-data performance, mainly file
+creation and deletion. We recommend turning softupdates on on all of your
+filesystems. There are two downsides to softupdates that you should be
+aware of: First, softupdates guarentees filesystem consistency in the
+case of a crash but could very easily be several seconds (even a minute!)
+behind updating the physical disk. If you crash you may lose more work
+then otherwise. Secondly, softupdates delays the freeing of filesystem
+blocks. If you have a filesystem (such as the root filesystem) which is
+close to full, doing a major update of it, e.g.
+.Em make installworld,
+can run it out of space and cause the update to fail.
+.Sh STRIPING DISKS
+In larger systems you can stripe partitions from several drives together
+to create a much larger overall partition. Striping can also improve
+the performance of a filesystem by splitting I/O operations across two
+or more disks. The
+.Xr vinum 8
+and
+.Xr ccd 4
+utilities may be used to create simple striped filesystems. Generally
+speaking, striping smaller partitions such as the root and /var/tmp,
+or essentially read-only partitions such as /usr is a complete waste of
+time. You should only stripe partitions that require serious I/O performance...
+typically /var, /home, or custom partitions used to hold databases and web
+pages. Choosing the proper stripe size is also
+important. Filesystems tend to store meta-data on power-of-2 boundries
+and you usually want to reduce seeking rather then increase seeking. This
+means you want to use a large off-center stripe size such as 1152 sectors
+so sequential I/O does not seek both disks and so meta-data is distributed
+across both disks rather then concentrated on a single disk. If
+you really need to get sophisticated, we recommend using a real hardware
+raid controller from the list of
+.Fx
+supported controllers.
+.Sh SYSCTL TUNING
+.Pp
+There are several hundred
+.Xr sysctl 8
+variables in the system, including many that appear to be candidates for
+tuning but actually aren't. In this document we will only cover the ones
+that have the greatest effect on the system.
+.Pp
+The
+.Em kern.ipc.shm_use_phys
+sysctl defaults to 0 (off) and may be set to 0 (off) or 1 (on). Setting
+this parameter to 1 will cause all SysV shared memory segments to be
+mapped to unpageable physical ram. This feature only has an effect if you
+are either (A) mapping small amounts of shared memory across many (hundreds)
+of processes, or (B) mapping large amounts of shared memory across any
+number of processes. This feature allows the kernel to remove a great deal
+of internal memory management page-tracking overhead at the cost of wiring
+the shared memory into core, making it unswappable.
+.Pp
+The
+.Em vfs.vmiodirenable
+sysctl defaults to 0 (off) (though soon it will default to 1) and may be
+set to 0 (off) or 1 (on). This parameter controls how directories are cached
+by the system. Most directories are small and use but a single fragment
+(typically 1K) in the filesystem and even less (typically 512 bytes) in
+the buffer cache. However, when operating in the default mode the buffer
+cache will only cache a fixed number of directories even if you have a huge
+amount of memory. Turning on this sysctl allows the buffer cache to use
+the VM Page Cache to cache the directories. The advantage is that all of
+memory is now available for caching directories. The disadvantage is that
+the minimum in-core memory used to cache a directory is the physical page
+size (typically 4K) rather then 512 bytes. We recommend turning this option
+on if you are running any services which manipulate large numbers of files.
+Such services can include web caches, large mail systems, and news systems.
+Turning on this option will generally not reduce performance even with the
+wasted memory but you should experiment to find out.
+.Pp
+There are various buffer-cache and VM page cache related sysctls. We do
+not recommend messing around with these at all. As of
+.Fx 4.3 ,
+the VM system does an extremely good job tuning itself.
+.Pp
+The
+.Em net.inet.tcp.sendspace
+and
+.Em net.inet.tcp.recvspace
+sysctls are of particular interest if you are running network intensive
+applications. This controls the amount of send and receive buffer space
+allowed for any given TCP connection. The default is 16K. You can often
+improve bandwidth utilization by increasing the default at the cost of
+eating up more kernel memory for each connection. We do not recommend
+increasing the defaults if you are serving hundreds or thousands of
+simultanious connections because it is possible to quickly run the system
+out of memory due to stalled connections building up. But if you need
+high bandwidth over a fewer number of connections, especially if you have
+gigabit ethernet, increasing these defaults can make a huge difference.
+You can adjust the buffer size for incoming and outgoing data separately.
+For example, if your machine is primarily doing web serving you may want
+to decrease the recvspace in order to be able to increase the sendspace
+without eating too much kernel memory. Note that the route table, see
+.Xr route 8 ,
+can be used to introduce route-specific send and receive buffer size
+defaults. As an additional mangagement tool you can use pipes in your
+firewall rules, see
+.Xr ipfw 8 ,
+to limit the bandwidth going to or from particular IP blocks or ports.
+For example, if you have a T1 you might want to limit your web traffic
+to 70% of the T1's bandwidth in order to leave the remainder available
+for mail and interactive use. Normally a heavily loaded web server
+will not introduce significant latencies into other services even if
+the network link is maxed out, but enforcing a limit can smooth things
+out and lead to longer term stability. Many people also enforce artificial
+bandwidth limitations in order to ensure that they are not charged for
+using too much bandwidth.
+.Pp
+We recommend that you turn on (set to 1) and leave on the
+.Em net.inet.tcp.always_keepalive
+control. The default is usually off. This introduces a small amount of
+additional network bandwidth but guarentees that dead tcp connections
+will eventually be recognized and cleared. Dead tcp connections are a
+particular problem on systems accesed by users operating over dialups,
+because users often disconnect their modems without properly closing active
+connections.
+.Pp
+The
+.Em kern.ipc.somaxconn
+sysctl limits the size of the listen queue for accepting new tcp connections.
+The default value of 128 is typically too low for robust handling of new
+connections in a heavily loaded web server environment. For such environments,
+we recommend increasing this value to 1024 or higher. The service daemon
+may itself limit the listen queue size (e.g. sendmail, apache) but will
+often have a directive in its configuration file to adjust the queue size up.
+Larger listen queue also do a better job of fending of denial of service
+attacks.
+.Sh KERNEL CONFIG TUNING
+.Pp
+There are a number of kernel options that you may have to fiddle with in
+a large scale system. In order to change these options you need to be
+able to compile a new kernel from source. The
+.Xr config 8
+manual page and the handbook are good starting points for learning how to
+do this. Generally the first thing you do when creating your own custom
+kernel is to strip out all the drivers and services you don't use. Removing
+things like
+.Em INET6
+and drivers you don't have will reduce the size of your kernel, sometimes
+by a megabyte or more, leaving more memory available for applications.
+.Pp
+The
+.Em maxusers
+kernel option defaults to an incredibly low value. For most modern machines,
+you probably want to increase this value to 64, 128, or 256. We do not
+recommend going above 256 unless you need a huge number of file descriptors.
+Network buffers are also affected but can be controlled with a separate
+kernel option. Do not increase maxusers just to get more network mbufs.
+.Pp
+.Em NMBCLUSTERS
+may be adjusted to increase the number of network mbufs the system is
+willing to allocate. Each cluster represents approximately 2K of memory,
+so a value of 1024 represents 2M of kernel memory reserved for network
+buffers. You can do a simple calculation to figure out how many you need.
+If you have a web server which maxes out at 1000 simultanious connections,
+and each connection eats a 16K receive and 16K send buffer, you need
+approximate 32MB worth of network buffers to deal with it. A good rule of
+thumb is to multiply by 2, so 32MBx2 = 64MB/2K = 32768. So for this case
+you would want to se NMBCLUSTERS to 32768. We recommend values between
+1024 and 4096 for machines with moderates amount of memory, and between 4096
+and 32768 for machines with greater amounts of memory. Under no circumstances
+should you specify an arbitrarily high value for this parameter, it could
+lead to a boot-time crash. The -m option to
+.Xr netstat 1
+may be used to observe network cluster use.
+.Pp
+More and more programs are using the
+.Fn sendfile
+system call to transmit files over the network. The
+.Em NSFBUFS
+kernel parameter controls the number of filesystem buffers
+.Fn sendfile
+is allowed to use to perform its work. This parameter nominally scales
+with
+.Em maxusers
+so you should not need to mess with this parameter except under extreme
+circumstances.
+.Pp
+.Em SCSI_DELAY
+and
+.Em IDE_DELAY
+may be used to reduce system boot times. The defaults are fairly high and
+can be responsible for 15+ seconds of delay in the boot process. Reducing
+SCSI_DELAY to 5 seconds usually works (especially with modern drives).
+Reducing IDE_DELAY also works but you have to be a little more careful.
+.Pp
+There are a number of
+.Em XXX_CPU
+options that can be commented out. If you only want the kernel to run
+on a Pentium class cpu, you can easily remove
+.Em I386_CPU
+and
+.Em I486_CPU,
+but only remove
+.Em I586_CPU
+if you are sure your cpu is being recognized as a Pentium II or better.
+Some clones may be recognized as a pentium or even a 486 and not be able
+to boot without those options. If it works, great! The operating system
+will be able to better-use higher-end cpu features for mmu, task switching,
+timebase, and even device operations. Additionally, higher-end cpus support
+4MB MMU pages which the kernel uses to map the kernel itself into memory,
+which increases its efficiency under heavy syscall loads.
+.Sh IDE WRITE CACHING
+As of
+.Fx 4.3 ,
+IDE write caching is turned off by default. This will reduce write bandwidth
+to IDE disks but is considered necessary due to serious data consistency
+issues introduced by hard drive vendors. Basically the problem is that
+IDE drives lie about when a write completes. With IDE write caching turned
+on, IDE hard drives will not only write data to disk out of order, they
+will sometimes delay some of the blocks indefinitely when under heavy disk
+loads. A crash or power failure can result in serious filesystem
+corruption. So our default is to be safe. If you are willing to risk
+filesystem corruption, you can return to the old behavior by setting the
+hw.ata.wc
+kernel variable back to 1. This must be done from the boot loader at boot
+time. Please see
+.Xr ata 4 ,
+and
+.Xr loader 8 .
+.Pp
+There is a new experimental feature for IDE hard drives called hw.ata.tags
+(you also set this in the bootloader) which allows write caching to be safely
+turned on. This brings SCSI tagging features to IDE drives. As of this
+writing only IBM DPTA and DTLA drives support the feature.
+.Sh CPU, MEMORY, DISK, NETWORK
+The type of tuning you do depends heavily on where your system begins to
+bottleneck as load increases. If your system runs out of cpu (idle times
+are pepetually 0%) then you need to consider upgrading the cpu or moving to
+an SMP motherboard (multiple cpu's), or perhaps you need to revisit the
+programs that are causing the load and try to optimize them. If your system
+is paging to swap a lot you need to consider adding more memory. If your
+system is saturating the disk you typically see high cpu idle times and
+total disk saturation.
+.Xr systat 1
+can be used to monitor this. There are many solutions to saturated disks:
+increasing memory for caching, mirroring disks, distributing operations across
+several machines, and so forth. If disk performance is an issue and you
+are using IDE drives, switching to SCSI can help a great deal. While modern
+IDE drives compare with SCSI in raw sequential bandwidth, the moment you
+start seeking around the disk SCSI drives usually win.
+.Pp
+Finally, you might run out of network suds. The first line of defense for
+improving network performance is to make sure you are using switches instead
+of hubs, especially these days where switches are almost as cheap. Hubs
+have severe problems under heavy loads due to collision backoff and one bad
+host can severely degrade the entire LAN. Second, optimize the network path
+as much as possible. For example, in
+.Xr firewall 7
+we describe a firewall protecting internal hosts with a topology where
+the externally visible hosts are not routed through it. Use 100BaseT rather
+then 10BaseT, or use 1000BaseT rather then 100BaseT, depending on your needs.
+Most bottlenecks occur at the WAN link (e.g. modem, T1, DSL, whatever).
+If expanding the link is not an option it may be possible to use ipfw's
+.Sy DUMMYNET
+feature to implement peak shaving or other forms of traffic shaping to
+prevent the overloaded service (such as web services) from effecting other
+services (such as email), or vise versa. In home installations this could
+be used to give interactive traffic (your browser, ssh logins) priority
+over services you export from your box (web services, email).
+.Sh SEE ALSO
+.Pp
+.Xr ata 4 ,
+.Xr boot 8 ,
+.Xr ccd 4 ,
+.Xr config 8 ,
+.Xr disklabel 8 ,
+.Xr firewall 7 ,
+.Xr fsck 8 ,
+.Xr hier 7 ,
+.Xr ifconfig 8 ,
+.Xr ipfw 8 ,
+.Xr loader 8 ,
+.Xr login.conf 5 ,
+.Xr netstat 1 ,
+.Xr newfs 8 ,
+.Xr ports 7 ,
+.Xr route 8 ,
+.Xr sysctl 8 ,
+.Xr systat 1 ,
+.Xr tunefs 8 ,
+.Xr vinum 8
+.Sh HISTORY
+The
+.Nm
+manual page was originally written by
+.An Matthew Dillon
+and first appeared
+in
+.Fx 4.3 ,
+May 2001.
diff --git a/sys/dev/pccbb/pccbbdevid.h b/sys/dev/pccbb/pccbbdevid.h
new file mode 100644
index 000000000000..3fe28c3946a5
--- /dev/null
+++ b/sys/dev/pccbb/pccbbdevid.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2001 M. Warner Losh. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/* Vendor/Device IDs */
+#define PCI_DEVICE_ID_PCIC_CLPD6729 0x11001013ul
+#define PCI_DEVICE_ID_PCIC_CLPD6832 0x11101013ul
+#define PCI_DEVICE_ID_PCIC_CLPD6833 0x11131013ul
+#define PCI_DEVICE_ID_PCIC_OZ6729 0x67291217ul
+#define PCI_DEVICE_ID_PCIC_OZ6730 0x673A1217ul
+#define PCI_DEVICE_ID_PCIC_OZ6832 0x68321217ul /* Also 6833 */
+#define PCI_DEVICE_ID_PCIC_OZ6860 0x68361216ul /* Also 6836? */
+#define PCI_DEVICE_ID_PCIC_OZ6872 0x68721217ul /* Also 6812 */
+#define PCI_DEVICE_ID_PCIC_OZ6912 /* Unknown */
+#define PCI_DEVICE_ID_PCIC_OZ6922 /* Unknown */
+#define PCI_DEVICE_ID_PCIC_OZ6933 /* Unknown */
+#define PCI_DEVICE_ID_RICOH_RL5C465 0x04651180ul
+#define PCI_DEVICE_ID_RICOH_RL5C466 0x04661180ul
+#define PCI_DEVICE_ID_RICOH_RL5C475 0x04751180ul
+#define PCI_DEVICE_ID_RICOH_RL5C476 0x04761180ul
+#define PCI_DEVICE_ID_RICOH_RL5C477 0x04771180ul
+#define PCI_DEVICE_ID_RICOH_RL5C478 0x04781180ul
+#define PCI_DEVICE_ID_PCIC_TI1031 0xac13104cul
+#define PCI_DEVICE_ID_PCIC_TI1130 0xac12104cul
+#define PCI_DEVICE_ID_PCIC_TI1131 0xac15104cul
+#define PCI_DEVICE_ID_PCIC_TI1211 0xac1e104cul
+#define PCI_DEVICE_ID_PCIC_TI1220 0xac17104cul
+#define PCI_DEVICE_ID_PCIC_TI1221 0xac19104cul
+#define PCI_DEVICE_ID_PCIC_TI1225 0xac1c104cul
+#define PCI_DEVICE_ID_PCIC_TI1250 0xac16104cul
+#define PCI_DEVICE_ID_PCIC_TI1251 0xac1d104cul
+#define PCI_DEVICE_ID_PCIC_TI1251B 0xac1f104cul
+#define PCI_DEVICE_ID_PCIC_TI1410 0xac50104cul
+#define PCI_DEVICE_ID_PCIC_TI1420 0xac51104cul
+#define PCI_DEVICE_ID_PCIC_TI1450 0xac1b104cul
+#define PCI_DEVICE_ID_PCIC_TI1451 0xac52104cul
+#define PCI_DEVICE_ID_PCIC_TI4451 0xac42104cul
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC95 0x06031179ul
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC95B 0x060a1179ul
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC97 0x060f1179ul
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC100 0x06171179ul
diff --git a/sys/dev/sound/pcm/feeder_rate.c b/sys/dev/sound/pcm/feeder_rate.c
new file mode 100644
index 000000000000..264f64353aad
--- /dev/null
+++ b/sys/dev/sound/pcm/feeder_rate.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <dev/sound/pcm/sound.h>
+
+#include "feeder_if.h"
+
+MALLOC_DEFINE(M_RATEFEEDER, "ratefeed", "pcm rate feeder");
+
+#define FEEDBUFSZ 8192
+#undef FEEDER_DEBUG
+
+struct feed_rate_info {
+ u_int32_t src, dst;
+ int srcpos, srcinc;
+ int16_t *buffer;
+ u_int16_t alpha;
+};
+
+static int
+feed_rate_setup(struct pcm_feeder *f)
+{
+ struct feed_rate_info *info = f->data;
+
+ info->srcinc = (info->src << 16) / info->dst;
+ /* srcinc is 16.16 fixed point increment for srcpos for each dstpos */
+ info->srcpos = 0;
+ return 0;
+}
+
+static int
+feed_rate_set(struct pcm_feeder *f, int what, int value)
+{
+ struct feed_rate_info *info = f->data;
+
+ switch(what) {
+ case FEEDRATE_SRC:
+ info->src = value;
+ break;
+ case FEEDRATE_DST:
+ info->dst = value;
+ break;
+ default:
+ return -1;
+ }
+ return feed_rate_setup(f);
+}
+
+static int
+feed_rate_get(struct pcm_feeder *f, int what)
+{
+ struct feed_rate_info *info = f->data;
+
+ switch(what) {
+ case FEEDRATE_SRC:
+ return info->src;
+ case FEEDRATE_DST:
+ return info->dst;
+ default:
+ return -1;
+ }
+ return -1;
+}
+
+static int
+feed_rate_init(struct pcm_feeder *f)
+{
+ struct feed_rate_info *info;
+
+ info = malloc(sizeof(*info), M_RATEFEEDER, M_WAITOK | M_ZERO);
+ if (info == NULL)
+ return ENOMEM;
+ info->buffer = malloc(FEEDBUFSZ, M_RATEFEEDER, M_WAITOK | M_ZERO);
+ if (info->buffer == NULL) {
+ free(info, M_RATEFEEDER);
+ return ENOMEM;
+ }
+ info->src = DSP_DEFAULT_SPEED;
+ info->dst = DSP_DEFAULT_SPEED;
+ info->alpha = 0;
+ f->data = info;
+ return feed_rate_setup(f);
+}
+
+static int
+feed_rate_free(struct pcm_feeder *f)
+{
+ struct feed_rate_info *info = f->data;
+
+ if (info) {
+ if (info->buffer)
+ free(info->buffer, M_RATEFEEDER);
+ free(info, M_RATEFEEDER);
+ }
+ f->data = NULL;
+ return 0;
+}
+
+static int
+feed_rate(struct pcm_feeder *f, struct pcm_channel *c, u_int8_t *b, u_int32_t count, void *source)
+{
+ struct feed_rate_info *info = f->data;
+ int16_t *destbuf = (int16_t *)b;
+ int fetch, v, alpha, hidelta, spos, dpos;
+
+ /*
+ * at this point:
+ * info->srcpos is 24.8 fixed offset into the fetchbuffer. 0 <= srcpos <= 0xff
+ *
+ * our input and output are always AFMT_S16LE stereo. this simplifies things.
+ */
+
+ /*
+ * we start by fetching enough source data into our buffer to generate
+ * about as much as was requested. we put it at offset 2 in the
+ * buffer so that we can interpolate from the last samples in the
+ * previous iteration- when we finish we will move our last samples
+ * to the start of the buffer.
+ */
+ spos = 0;
+ dpos = 0;
+
+ /* fetch is in bytes */
+ fetch = (count * info->srcinc) >> 16;
+ fetch = min(fetch, FEEDBUFSZ - 4) & ~3;
+ if (fetch == 0)
+ return 0;
+ fetch = FEEDER_FEED(f->source, c, ((u_int8_t *)info->buffer) + 4, fetch, source);
+ fetch /= 2;
+
+ alpha = info->alpha;
+ hidelta = min(info->srcinc >> 16, 1) * 2;
+ while ((spos + hidelta + 1) < fetch) {
+ v = (info->buffer[spos] * (0xffff - alpha)) + (info->buffer[spos + hidelta] * alpha);
+ destbuf[dpos++] = v >> 16;
+
+ v = (info->buffer[spos + 1] * (0xffff - alpha)) + (info->buffer[spos + hidelta + 1] * alpha);
+ destbuf[dpos++] = v >> 16;
+
+ alpha += info->srcinc;
+ spos += (alpha >> 16) * 2;
+ alpha &= 0xffff;
+
+ }
+ info->alpha = alpha & 0xffff;
+ info->buffer[0] = info->buffer[spos - hidelta];
+ info->buffer[1] = info->buffer[spos - hidelta + 1];
+
+ count = dpos * 2;
+ return count;
+}
+
+static struct pcm_feederdesc feeder_rate_desc[] = {
+ {FEEDER_RATE, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
+ {0},
+};
+static kobj_method_t feeder_rate_methods[] = {
+ KOBJMETHOD(feeder_init, feed_rate_init),
+ KOBJMETHOD(feeder_free, feed_rate_free),
+ KOBJMETHOD(feeder_set, feed_rate_set),
+ KOBJMETHOD(feeder_get, feed_rate_get),
+ KOBJMETHOD(feeder_feed, feed_rate),
+ { 0, 0 }
+};
+FEEDER_DECLARE(feeder_rate, 2, NULL);
+
+
diff --git a/sys/dev/sound/pcm/vchan.h b/sys/dev/sound/pcm/vchan.h
new file mode 100644
index 000000000000..7e057ce43c89
--- /dev/null
+++ b/sys/dev/sound/pcm/vchan.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2001 Cameron Grant <gandalf@vilnya.demon.co.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+int vchan_create(struct pcm_channel *parent);
+int vchan_destroy(struct pcm_channel *c);
+int vchan_initsys(struct snddev_info *d);
+
+
diff --git a/sys/i4b/capi/README b/sys/i4b/capi/README
new file mode 100644
index 000000000000..91685258e161
--- /dev/null
+++ b/sys/i4b/capi/README
@@ -0,0 +1,150 @@
+$FreeBSD$
+
+Message-ID: <3AF56886.7D92609A@cubical.fi>
+Date: Sun, 06 May 2001 18:06:47 +0300
+From: Juha-Matti Liukkonen <jml@cubical.fi>
+Organization: Cubical Solutions Ltd
+
+Please find the attached diff and tarball for our support software for
+CAPI 2.0 and AVM's active T1 and T1-B (primary rate) and B1 (basic rate)
+ISDN adapters for isdn4bsd. The implementation has been made from
+scratch by us, based on reverse engineering of the Linux driver provided
+by AVM GmbH and available in ftp.avm.de. Cubical Solutions Ltd offers
+this implementation for the BSD community free of charge and assuming
+absolutely no liabilities whatsoever. Feel free to modify the
+implementation any way you see fit, but please retain our one-liner
+copyright statement somewhere in the comment headers in the capi and
+iavc driver modules.
+
+That said, the attached tarball is i4b-00.96.00-beta with our
+modifications integrated, and the diff contains all modifications we
+have made to the original (including the new capi files). Our mods add
+pseudo-device i4bcapi, which attaches to i4b layer 4, and device iavc0,
+which implements a link layer driver for AVM's active B1 and T1 adapters
+for i4bcapi. There are also a couple of related improvements to isdnd,
+and a number of modifications to isdnd and layer 4 to implement support
+for up to 30 channels per adapter (for primary rate use).
+
+We have developed the software explicitly for our telephony application,
+to be used with AVM's T1 adapters, and the implementation has been
+tested primarily with this functionality in mind. There may be
+interesting side effects with eg. the ipr and isppp drivers; we do not
+use them and therefore their testing has been cursory at best. The
+i4btel driver works well with the T1 (our primary use), and the i4brbch
+driver has been verified to work with T1, T1-B and B1 adapters (ftp'd
+some files over a dialup PPP connection with each adapter). Only the PCI
+versions of the adapters (equipped with the AMCC DMA controller) are
+supported, although the basics (PIO mode communication) for the older
+ISA model support is in place, so only the bus attachment modules should
+be required to support the older hardware.
+
+All of the AVM active adapters use downloadable firmware, which is not
+included in the attached package. The firmware files (t1.t4, t1b.t4,
+b1.t4) can be found from ftp.avm.de in adapter specific subdirectories,
+or from the CDs provided with the adapters (in directory
+'cardware/firmware').
+
+Our primary development platform is our own embedded build (we call it
+'ebsd') based on FreeBSD 4.2-RELEASE. The implementation has also been
+tested on standard FreeBSD 4.2-RELEASE system. The implementation should
+not contain any FreeBSD (or even FreeBSD release) specific issues, but
+it has not been tested or even compiled on any other platforms;
+specifically, only the FreeBSD overinstall.sh script is modified to
+install the capi/iavc support in the kernel source tree.
+
+This code is not under active development here since the functionality
+we use (i4btel, T1) has been working since the beginning of March. We
+are also not planning on any further development (no need seen at this
+point), but I am naturally interested on whatever bugs and development
+ideas pop up on the community and will keep a keen eye on the isdn
+mailing list. I personally may be available for consultation, debugging
+and possibly development projects, but with notable reservations on my
+time (the current IT industry recession seems to be pushing even more
+work for us, which tends to keep us pretty busy these days).
+
+Here are some specific technical notes:
+
+* isdnd supports new keyword 'firmware=</path/to/file>' in section
+'controller'. This keyword is supported for all controller types, and
+causes I4B_CTRL_DOWNLOAD ioctl to be invoked with the specified file as
+an argument. In systems equipped with both active and passive adapters,
+and the passive cards being detected first, dummy 'controller' entries
+are required for the passive cards to get the correct firmwares to
+correct adapters. (I hope you did not have other uses for this ioctl in
+mind?)
+
+* isdnd supports new keyword 'clone=<entry name>' in section 'entry'.
+This causes the entry to be copied from the existing named entry. At
+least entry specific 'name' and 'usrdeviceunit' values should be
+specified after a 'clone'. (Makes configuring 30 or 60 entries way much
+easier.)
+
+* a bug in i4btel driver read routine corrected. The conditions in the
+while() clause caused the receive queue to be referenced before checking
+if a channel is connected, leading to kernel panic (do a 'dd
+if=/dev/i4btel0 of=/dev/null' on an unconnected tel device, panic will
+follow). Correction was to reorder the while clause conditions to check
+for connectedness first.
+
+* isdnd and i4b layer 4 support up to CHANNELS_MAX (=30) channels per
+adapter. The msg_ctrl_info_req_t message reports the number of channels
+provided by the adapter, the number is stored in the nbchan field of the
+controller state structure. The fixed stateb1 and stateb2 entries in
+controller state stuctures are replaced with an array, and all fixed
+references there are replaced with loops up to nbchan. Passive stack
+layer 1 and 2 are not modified, layer 3 sets this field to fixed value 2
+for all adapters (but it could be delegated to the layer 1 driver's
+attach request).
+
+* the i4bcapi driver maps i4b channels to logical channels identified
+with PLCI/NCCI values in the CAPI protocol using the sc_bchan[] array.
+The PLCI/NCCI handling is merged in the channel mapping and is greatly
+simplified from the reference state machine model, because in practice
+there can be only one PLCI/NCCI per channel active at any given time.
+
+* the i4bcapi driver does not provide any kind of user level interface
+(such as the /dev/capi20 interface provided by the linux driver), but
+could relatively easily be extended to do so (and if done, interface
+compatibility with the linux implementation would probably be a good
+goal).
+
+* there are some gritty details in the iavc driver, inherited from the
+linux code. Despite us being a legitimate company in the telecom
+business, AVM failed to produce any programming reference material for
+us (at least in a reasonable time frame), so some guesswork remains due
+to classic reverse engineering process (particularly there are a few
+magic numbers in the card initialization sequence whose meaning I do not
+know).
+
+* pseudo-devices i4bq931, i4bq921 and some passive stack layer 1 driver
+(such as iwic) are required to compile, as the required ctrl_desc[]
+array is in layer 3, which requires layer 2, which requires layer 1.
+Some architectural cleanup would come in handy here, but we did not want
+to start making any major changes (and we use iwic in test setups
+anyway, so we simply always compile it in).
+
+To summarize: unpack, overinstall, add the following lines (with the
+usual passive stack configuration including at least one L1 driver) to
+your kernel configuration file:
+
+pseudo-device "i4bcapi"
+device iavc0
+
+...and the following to your isdnd.rc:
+
+controller
+firmware = /usr/lib/isdn/b1.t4
+
+...compile your new kernel, make sure the firmware file is in
+/usr/lib/isdn, and your B1 adapter should boot up and Just Work (tm). If
+you have multiple adapters, you need a 'controller' section for each to
+have them loaded and booted on isdnd startup.
+
+Have fun -- and let me know if there are any complications, or if I can
+be of further assistance,
+
+ - Juha
+--
+Juha-Matti Liukkonen, Cubical Solutions Ltd
+Phone: +358(0)405280142
+Email: jml@cubical.fi
diff --git a/sys/i4b/capi/capi.h b/sys/i4b/capi/capi.h
new file mode 100644
index 000000000000..185d2f7a5f8e
--- /dev/null
+++ b/sys/i4b/capi/capi.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * capi/capi.h The CAPI device interface.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _I4B_CAPI_H_
+#define _I4B_CAPI_H_
+
+/*
+// CAPI driver context: B channels and controller softcs.
+*/
+
+#define INVALID -1
+
+enum capi_b_state {
+ B_FREE, /* channel free, ncci invalid */
+ B_CONNECT_CONF, /* wait for CONNECT_CONF */
+ B_CONNECT_IND, /* IND got, wait for appl RESP */
+ B_CONNECT_ACTIVE_IND, /* wait for CONNECT_ACTIVE_IND */
+ B_CONNECT_B3_CONF, /* wait for CONNECT_B3_CONF */
+ B_CONNECT_B3_IND, /* wait for CONNECT_B3_IND */
+ B_CONNECT_B3_ACTIVE_IND, /* wait for CONNECT_B3_ACTIVE_IND */
+ B_CONNECTED, /* channel connected & in use */
+ B_DISCONNECT_CONF, /* wait for DISCONNECT_CONF */
+ B_DISCONNECT_B3_CONF, /* wait for DISCONNECT_B3_CONF */
+ B_DISCONNECT_IND, /* wait for DISCONNECT_IND */
+};
+
+typedef struct capi_bchan
+{
+ /* Channel state */
+
+ int ncci;
+#define CAPI_CTRL_MASK 0x000000ff
+#define CAPI_PLCI_MASK 0x0000ffff
+#define CAPI_NCCI_MASK 0xffff0000
+ u_int16_t msgid;
+ int busy;
+ enum capi_b_state state;
+
+ struct ifqueue tx_queue;
+ struct ifqueue rx_queue;
+ int rxcount;
+ int txcount;
+
+ /* The rest is needed for i4b integration */
+
+ int bprot;
+ int cdid;
+
+ struct mbuf *in_mbuf;
+ isdn_link_t capi_isdn_linktab;
+ drvr_link_t *capi_drvr_linktab;
+} capi_bchan_t;
+
+enum capi_c_state {
+ C_DOWN, /* controller uninitialized */
+ C_READY, /* controller initialized but not listening */
+ C_UP, /* controller listening */
+};
+
+typedef struct capi_softc {
+ int sc_unit; /* index in capi_sc[] */
+ int ctrl_unit; /* index in isdn_ctrl_tab[] */
+ int card_type; /* CARD_TYPEC_xxx, filled by ll driver */
+ int sc_nbch; /* number of b channels on this controller */
+ int sc_enabled; /* is daemon connected TRUE/FALSE */
+ int sc_msgid; /* next CAPI message id */
+ char sc_profile[64];/* CAPI profile data */
+ enum capi_c_state sc_state;
+
+ capi_bchan_t sc_bchan[MAX_BCHAN];
+
+ /* Link layer driver context holder and methods */
+
+ void *ctx;
+
+ int (*load)(struct capi_softc *, int, u_int8_t *);
+ int (*reg_appl)(struct capi_softc *, int, int);
+ int (*rel_appl)(struct capi_softc *, int);
+ int (*send)(struct capi_softc *, struct mbuf *);
+} capi_softc_t;
+
+extern capi_softc_t *capi_sc[];
+extern int ncapi;
+
+/*
+// CAPI upcalls for the link layer.
+*/
+
+#define I4BCAPI_APPLID 1
+
+extern int capi_ll_attach(capi_softc_t *);
+extern int capi_ll_control(capi_softc_t *, int op, int arg);
+
+#define CAPI_CTRL_READY 0 /* ctrl ready, value=TRUE/FALSE */
+#define CAPI_CTRL_PROFILE 1 /* set CAPI profile */
+#define CAPI_CTRL_NEW_NCCI 2 /* new ncci value, assign bchan */
+#define CAPI_CTRL_FREE_NCCI 3 /* free ncci value, clear bchan */
+
+extern int capi_ll_receive(capi_softc_t *, struct mbuf *);
+
+extern int capi_start_tx(capi_softc_t *, int bchan);
+
+#endif /* _I4B_CAPI_H_ */
diff --git a/sys/i4b/capi/capi_l4if.c b/sys/i4b/capi/capi_l4if.c
new file mode 100644
index 000000000000..9cb05f221781
--- /dev/null
+++ b/sys/i4b/capi/capi_l4if.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * capi/capi_l4if.c The CAPI i4b L4/device interface.
+ *
+ * $FreeBSD$
+ */
+
+#include "i4bcapi.h"
+#if NI4BCAPI > 0
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_cause.h>
+
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+#include <i4b/capi/capi.h>
+#include <i4b/capi/capi_msgs.h>
+
+static void n_connect_request(u_int cdid);
+static void n_connect_response(u_int cdid, int response, int cause);
+static void n_disconnect_request(u_int cdid, int cause);
+static void n_alert_request(u_int cdid);
+static void n_mgmt_command(int unit, int cmd, void *parm);
+static int n_download(int unit, int, struct isdn_dr_prot *);
+
+capi_softc_t *capi_sc[MAX_CONTROLLERS] = { NULL, };
+int ncapi = 0;
+
+/*
+// i4b_capi_{ret,set}_linktab
+// i4b driver glue.
+//
+// i4b_capi_bch_config
+// Called by i4b driver to flush + {en,dis}able a channel.
+//
+// i4b_capi_bch_start_tx
+// Called by i4b driver to transmit a queued mbuf.
+//
+// i4b_capi_bch_stat
+// Called by i4b driver to obtain statistics information.
+*/
+
+static isdn_link_t *
+i4b_capi_ret_linktab(int unit, int channel)
+{
+ capi_softc_t *sc = capi_sc[unit];
+ return &sc->sc_bchan[channel].capi_isdn_linktab;
+}
+
+static void
+i4b_capi_set_linktab(int unit, int channel, drvr_link_t *dlt)
+{
+ capi_softc_t *sc = capi_sc[unit];
+ sc->sc_bchan[channel].capi_drvr_linktab = dlt;
+}
+
+static void
+i4b_capi_bch_config(int unit, int chan, int bprot, int activate)
+{
+ capi_softc_t *sc = capi_sc[unit];
+
+ i4b_Bcleanifq(&sc->sc_bchan[chan].tx_queue);
+ sc->sc_bchan[chan].tx_queue.ifq_maxlen = IFQ_MAXLEN;
+ sc->sc_bchan[chan].txcount = 0;
+
+ /* The telephony drivers use rx_queue for receive. */
+
+ i4b_Bcleanifq(&sc->sc_bchan[chan].rx_queue);
+ sc->sc_bchan[chan].rx_queue.ifq_maxlen = IFQ_MAXLEN;
+ sc->sc_bchan[chan].rxcount = 0;
+
+ /* HDLC frames are put to in_mbuf */
+
+ i4b_Bfreembuf(sc->sc_bchan[chan].in_mbuf);
+ sc->sc_bchan[chan].in_mbuf = NULL;
+
+ /* Because of the difference, we need to remember the protocol. */
+
+ sc->sc_bchan[chan].bprot = bprot;
+ sc->sc_bchan[chan].busy = 0;
+}
+
+static void
+i4b_capi_bch_start_tx(int unit, int chan)
+{
+ capi_softc_t *sc = capi_sc[unit];
+ int s;
+
+ s = SPLI4B();
+
+ if (sc->sc_bchan[chan].state != B_CONNECTED) {
+ splx(s);
+ printf("capi%d: start_tx on unconnected channel\n", sc->sc_unit);
+ return;
+ }
+
+ if (sc->sc_bchan[chan].busy) {
+ splx(s);
+ return;
+ }
+
+ capi_start_tx(sc, chan);
+
+ splx(s);
+}
+
+static void
+i4b_capi_bch_stat(int unit, int chan, bchan_statistics_t *bsp)
+{
+ capi_softc_t *sc = capi_sc[unit];
+ int s = SPLI4B();
+
+ bsp->outbytes = sc->sc_bchan[chan].txcount;
+ bsp->inbytes = sc->sc_bchan[chan].rxcount;
+
+ sc->sc_bchan[chan].txcount = 0;
+ sc->sc_bchan[chan].rxcount = 0;
+
+ splx(s);
+}
+
+int capi_start_tx(capi_softc_t *sc, int chan)
+{
+ struct mbuf *m_b3;
+ int sent = 0;
+
+ _IF_DEQUEUE(&sc->sc_bchan[chan].tx_queue, m_b3);
+ while (m_b3) {
+ struct mbuf *m = m_b3->m_next;
+
+ sc->sc_bchan[chan].txcount += m_b3->m_len;
+ capi_data_b3_req(sc, chan, m_b3);
+ sent++;
+
+ m_b3 = m;
+ }
+
+ if (sc->sc_bchan[chan].capi_drvr_linktab) {
+ /* Notify i4b driver of activity, and if the queue is drained. */
+
+ if (sent)
+ (*sc->sc_bchan[chan].capi_drvr_linktab->bch_activity)(
+ sc->sc_bchan[chan].capi_drvr_linktab->unit, ACT_TX);
+
+ if (IF_QEMPTY(&sc->sc_bchan[chan].tx_queue))
+ (*sc->sc_bchan[chan].capi_drvr_linktab->bch_tx_queue_empty)(
+ sc->sc_bchan[chan].capi_drvr_linktab->unit);
+ }
+
+ return sent;
+}
+
+/*
+// capi_ll_attach
+// Called by a link layer driver at boot time.
+*/
+
+int
+capi_ll_attach(capi_softc_t *sc)
+{
+ int i;
+
+ if (ncapi == (sizeof(capi_sc) / sizeof(capi_sc[0]))) {
+ printf("capi%d: too many units, increase MAX_CONTROLLERS\n", ncapi);
+ return (ENXIO);
+ }
+
+ /* Unit type and subtype; sc is partly filled by ll driver */
+
+ ctrl_desc[nctrl].unit = ncapi;
+ ctrl_desc[nctrl].ctrl_type = CTRL_CAPI;
+ ctrl_desc[nctrl].card_type = sc->card_type;
+
+ /* L4 callbacks */
+
+ ctrl_types[CTRL_CAPI].get_linktab = i4b_capi_ret_linktab;
+ ctrl_types[CTRL_CAPI].set_linktab = i4b_capi_set_linktab;
+
+ ctrl_desc[nctrl].N_CONNECT_REQUEST = n_connect_request;
+ ctrl_desc[nctrl].N_CONNECT_RESPONSE = n_connect_response;
+ ctrl_desc[nctrl].N_DISCONNECT_REQUEST = n_disconnect_request;
+ ctrl_desc[nctrl].N_ALERT_REQUEST = n_alert_request;
+ ctrl_desc[nctrl].N_DOWNLOAD = n_download;
+ ctrl_desc[nctrl].N_DIAGNOSTICS = NULL; /* XXX todo */
+ ctrl_desc[nctrl].N_MGMT_COMMAND = n_mgmt_command;
+
+ /* Unit state */
+
+ sc->sc_enabled = FALSE;
+ sc->sc_state = C_DOWN;
+ sc->sc_msgid = 0;
+
+ ctrl_desc[nctrl].dl_est = DL_DOWN;
+ ctrl_desc[nctrl].nbch = sc->sc_nbch;
+
+ for (i = 0; i < sc->sc_nbch; i++) {
+ ctrl_desc[nctrl].bch_state[i] = BCH_ST_FREE;
+ sc->sc_bchan[i].ncci = INVALID;
+ sc->sc_bchan[i].msgid = 0;
+ sc->sc_bchan[i].busy = 0;
+ sc->sc_bchan[i].state = B_FREE;
+
+ memset(&sc->sc_bchan[i].tx_queue, 0, sizeof(struct ifqueue));
+ memset(&sc->sc_bchan[i].rx_queue, 0, sizeof(struct ifqueue));
+ sc->sc_bchan[i].tx_queue.ifq_maxlen = IFQ_MAXLEN;
+ sc->sc_bchan[i].rx_queue.ifq_maxlen = IFQ_MAXLEN;
+
+#if defined (__FreeBSD__) && __FreeBSD__ > 4
+ mtx_init(&sc->sc_bchan[i].tx_queue.ifq_mtx, "i4b_capi_tx", MTX_DEF);
+ mtx_init(&sc->sc_bchan[i].rx_queue.ifq_mtx, "i4b_capi_rx", MTX_DEF);
+#endif
+
+ sc->sc_bchan[i].txcount = 0;
+ sc->sc_bchan[i].rxcount = 0;
+
+ sc->sc_bchan[i].cdid = CDID_UNUSED;
+ sc->sc_bchan[i].bprot = BPROT_NONE;
+ sc->sc_bchan[i].in_mbuf = NULL;
+
+ sc->sc_bchan[i].capi_drvr_linktab = NULL;
+
+ sc->sc_bchan[i].capi_isdn_linktab.unit = ncapi;
+ sc->sc_bchan[i].capi_isdn_linktab.channel = i;
+ sc->sc_bchan[i].capi_isdn_linktab.bch_config = i4b_capi_bch_config;
+ sc->sc_bchan[i].capi_isdn_linktab.bch_tx_start = i4b_capi_bch_start_tx;
+ sc->sc_bchan[i].capi_isdn_linktab.bch_stat = i4b_capi_bch_stat;
+ sc->sc_bchan[i].capi_isdn_linktab.tx_queue = &sc->sc_bchan[i].tx_queue;
+ sc->sc_bchan[i].capi_isdn_linktab.rx_queue = &sc->sc_bchan[i].rx_queue;
+ sc->sc_bchan[i].capi_isdn_linktab.rx_mbuf = &sc->sc_bchan[i].in_mbuf;
+ }
+
+ ctrl_desc[nctrl].tei = -1;
+
+ /* Up the controller index and store the softc */
+
+ sc->sc_unit = ncapi;
+ capi_sc[ncapi++] = sc;
+ sc->ctrl_unit = nctrl++;
+
+ printf("capi%d: card type %d attached\n", sc->sc_unit, sc->card_type);
+
+ return(0);
+}
+
+/*
+// n_mgmt_command
+// i4b L4 management command.
+*/
+
+static void
+n_mgmt_command(int unit, int op, void *arg)
+{
+ capi_softc_t *sc = capi_sc[unit];
+
+ printf("capi%d: mgmt command %d\n", sc->sc_unit, op);
+
+ switch(op) {
+ case CMR_DOPEN:
+ sc->sc_enabled = TRUE;
+ break;
+
+ case CMR_DCLOSE:
+ sc->sc_enabled = FALSE;
+ break;
+
+ case CMR_SETTRACE:
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*
+// n_connect_request
+// i4b L4 wants to connect. We assign a B channel to the call,
+// send a CAPI_CONNECT_REQ, and set the channel to B_CONNECT_CONF.
+*/
+
+static void
+n_connect_request(u_int cdid)
+{
+ call_desc_t *cd = cd_by_cdid(cdid);
+ capi_softc_t *sc;
+ int bch, s;
+
+ if (!cd) {
+ printf("capi?: invalid cdid %d\n", cdid);
+ return;
+ }
+
+ sc = capi_sc[ctrl_desc[cd->controller].unit];
+ bch = cd->channelid;
+
+ s = SPLI4B();
+
+ if ((bch < 0) || (bch >= sc->sc_nbch))
+ for (bch = 0; bch < sc->sc_nbch; bch++)
+ if (sc->sc_bchan[bch].state == B_FREE)
+ break;
+
+ if (bch == sc->sc_nbch) {
+ splx(s);
+ printf("capi%d: no free B channel\n", sc->sc_unit);
+ return;
+ }
+
+ cd->channelid = bch;
+
+ capi_connect_req(sc, cd);
+ splx(s);
+}
+
+/*
+// n_connect_response
+// i4b L4 answers a call. We send a CONNECT_RESP with the proper
+// Reject code, and set the channel to B_CONNECT_B3_IND or B_FREE,
+// depending whether we answer or not.
+*/
+
+static void
+n_connect_response(u_int cdid, int response, int cause)
+{
+ call_desc_t *cd = cd_by_cdid(cdid);
+ capi_softc_t *sc;
+ int bch, s;
+
+ if (!cd) {
+ printf("capi?: invalid cdid %d\n", cdid);
+ return;
+ }
+
+ sc = capi_sc[ctrl_desc[cd->controller].unit];
+ bch = cd->channelid;
+
+ T400_stop(cd);
+
+ cd->response = response;
+ cd->cause_out = cause;
+
+ s = SPLI4B();
+ capi_connect_resp(sc, cd);
+ splx(s);
+}
+
+/*
+// n_disconnect_request
+// i4b L4 wants to disconnect. We send a DISCONNECT_REQ and
+// set the channel to B_DISCONNECT_CONF.
+*/
+
+static void
+n_disconnect_request(u_int cdid, int cause)
+{
+ call_desc_t *cd = cd_by_cdid(cdid);
+ capi_softc_t *sc;
+ int bch, s;
+
+ if (!cd) {
+ printf("capi?: invalid cdid %d\n", cdid);
+ return;
+ }
+
+ sc = capi_sc[ctrl_desc[cd->controller].unit];
+ bch = cd->channelid;
+
+ cd->cause_out = cause;
+
+ s = SPLI4B();
+ capi_disconnect_req(sc, cd);
+ splx(s);
+}
+
+/*
+// n_alert_request
+// i4b L4 wants to alert an incoming call. We send ALERT_REQ.
+*/
+
+static void
+n_alert_request(u_int cdid)
+{
+ call_desc_t *cd = cd_by_cdid(cdid);
+ capi_softc_t *sc;
+ int s;
+
+ if (!cd) {
+ printf("capi?: invalid cdid %d\n", cdid);
+ return;
+ }
+
+ sc = capi_sc[ctrl_desc[cd->controller].unit];
+
+ s = SPLI4B();
+ capi_alert_req(sc, cd);
+ splx(s);
+}
+
+/*
+// n_download
+// L4 -> firmware download
+*/
+
+static int
+n_download(int unit, int numprotos, struct isdn_dr_prot *protocols)
+{
+ capi_softc_t *sc = capi_sc[unit];
+
+ if (sc->load) {
+ (*capi_sc[unit]->load)(sc, protocols[0].bytecount,
+ protocols[0].microcode);
+ }
+
+ return(0);
+}
+
+#endif /* NI4BCAPI > 0 */
diff --git a/sys/i4b/capi/capi_llif.c b/sys/i4b/capi/capi_llif.c
new file mode 100644
index 000000000000..a02286143f7f
--- /dev/null
+++ b/sys/i4b/capi/capi_llif.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * capi/capi_llif.c The i4b CAPI link layer interface.
+ *
+ * $FreeBSD$
+ */
+
+#include "i4bcapi.h"
+#if NI4BCAPI > 0
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_cause.h>
+
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+#include <i4b/capi/capi.h>
+#include <i4b/capi/capi_msgs.h>
+
+/*
+// capi_ll_control
+// CAPI link layer control routine. Called by a link layer
+// driver when its state changes.
+*/
+
+int
+capi_ll_control(capi_softc_t *sc, int op, int arg)
+{
+ switch (op) {
+ case CAPI_CTRL_READY:
+ if (arg) {
+ sc->sc_state = C_READY;
+
+ /*
+ * Register our CAPI ApplId and send CAPI_LISTEN_REQ
+ * with CIP Mask value 1 (match all).
+ */
+
+ sc->reg_appl(sc, I4BCAPI_APPLID, sc->sc_nbch);
+ capi_listen_req(sc, 0x10007);
+
+ } else {
+ sc->sc_state = C_DOWN;
+ /* XXX go through cds and notify L4 of pdeact? XXX */
+ }
+ break;
+
+ case CAPI_CTRL_PROFILE:
+ bcopy((char*) arg, &sc->sc_profile, sizeof(sc->sc_profile));
+ break;
+
+ case CAPI_CTRL_NEW_NCCI:
+ case CAPI_CTRL_FREE_NCCI:
+ /* We ignore the controller's NCCI notifications. */
+ break;
+
+ default:
+ printf("capi%d: unknown control %d\n", sc->sc_unit, op);
+ }
+
+ return 0;
+}
+
+/*
+// i4b_capi_handlers
+// Array of message-handler pairs used to dispatch CAPI
+// messages sent to I4BCAPI_APPLID.
+*/
+
+static struct capi_cmdtab {
+ u_int16_t cmd;
+ void (*handler)(capi_softc_t *, struct mbuf *);
+} i4b_capi_handlers[] = {
+ { CAPI_LISTEN_CONF, capi_listen_conf },
+ { CAPI_INFO_IND, capi_info_ind },
+ { CAPI_ALERT_CONF, capi_alert_conf },
+ { CAPI_CONNECT_CONF, capi_connect_conf },
+ { CAPI_CONNECT_IND, capi_connect_ind },
+ { CAPI_CONNECT_ACTIVE_IND, capi_connect_active_ind },
+ { CAPI_CONNECT_B3_CONF, capi_connect_b3_conf },
+ { CAPI_CONNECT_B3_IND, capi_connect_b3_ind },
+ { CAPI_CONNECT_B3_ACTIVE_IND, capi_connect_b3_active_ind },
+ { CAPI_DATA_B3_CONF, capi_data_b3_conf },
+ { CAPI_DATA_B3_IND, capi_data_b3_ind },
+ { CAPI_DISCONNECT_B3_IND, capi_disconnect_b3_ind },
+ { CAPI_DISCONNECT_CONF, capi_disconnect_conf },
+ { CAPI_DISCONNECT_IND, capi_disconnect_ind },
+ { 0, 0 }
+};
+
+/*
+// capi_ll_receive
+// CAPI link layer receive upcall. Called by a link layer
+// driver to dispatch incoming CAPI messages.
+*/
+
+int
+capi_ll_receive(capi_softc_t *sc, struct mbuf *m)
+{
+ u_int8_t *p = mtod(m, u_int8_t*);
+ u_int16_t len, applid, msgid, cmd;
+
+ capimsg_getu16(p + 0, &len);
+ capimsg_getu16(p + 2, &applid);
+ capimsg_getu16(p + 4, &cmd);
+ capimsg_getu16(p + 6, &msgid);
+
+#if 0
+ printf("capi%d: ll_receive hdr %04x %04x %04x %04x\n", sc->sc_unit,
+ len, applid, cmd, msgid);
+#endif
+
+ if (applid == I4BCAPI_APPLID) {
+ struct capi_cmdtab *e;
+ for (e = i4b_capi_handlers; e->cmd && e->cmd != cmd; e++);
+ if (e->cmd) (*e->handler)(sc, m);
+ else printf("capi%d: unknown message %04x\n", sc->sc_unit, cmd);
+
+ } else {
+ /* XXX we could handle arbitrary ApplIds here XXX */
+ printf("capi%d: message %04x for unknown applid %d\n", sc->sc_unit,
+ cmd, applid);
+ }
+
+ if (m->m_next) {
+ i4b_Bfreembuf(m->m_next);
+ m->m_next = NULL;
+ }
+ i4b_Dfreembuf(m);
+ return(0);
+}
+
+#endif /* NI4BCAPI > 0*/
diff --git a/sys/i4b/capi/capi_msgs.c b/sys/i4b/capi/capi_msgs.c
new file mode 100644
index 000000000000..a2ce023a20ea
--- /dev/null
+++ b/sys/i4b/capi/capi_msgs.c
@@ -0,0 +1,948 @@
+/*
+ * Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * capi/capi_msgs.c The CAPI i4b message handlers.
+ *
+ * $FreeBSD$
+ */
+
+#include "i4bcapi.h"
+#if NI4BCAPI > 0
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_cause.h>
+
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/layer4/i4b_l4.h>
+
+#include <i4b/capi/capi.h>
+#include <i4b/capi/capi_msgs.h>
+
+/*
+// Administrative messages:
+// ------------------------
+*/
+
+void capi_listen_req(capi_softc_t *sc, u_int32_t CIP)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 18);
+ u_int8_t *msg;
+ u_int16_t msgid;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for listen_req\n", sc->sc_unit);
+ return;
+ }
+
+ msgid = sc->sc_msgid++;
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, I4BCAPI_APPLID);
+ msg = capimsg_setu16(msg, CAPI_LISTEN_REQ);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, 1); /* Controller */
+ msg = capimsg_setu32(msg, 0); /* Info mask */
+ msg = capimsg_setu32(msg, CIP);
+ msg = capimsg_setu32(msg, 0);
+ msg = capimsg_setu8(msg, 0);
+ msg = capimsg_setu8(msg, 0);
+
+ sc->send(sc, m);
+}
+
+void capi_listen_conf(capi_softc_t *sc, struct mbuf *m_in)
+{
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ u_int16_t Info;
+
+ capimsg_getu16(msg + 12, &Info);
+
+ if (Info == 0) {
+ /* We are now listening. */
+
+ sc->sc_state = C_UP;
+ ctrl_desc[sc->ctrl_unit].dl_est = DL_UP;
+
+ i4b_l4_l12stat(sc->ctrl_unit, 1, 1);
+ i4b_l4_l12stat(sc->ctrl_unit, 2, 1);
+
+ } else {
+ /* XXX sc->sc_state = C_DOWN ? XXX */
+ printf("capi%d: can't listen, info=%04x\n", sc->sc_unit, Info);
+ }
+}
+
+void capi_info_ind(capi_softc_t *sc, struct mbuf *m_in)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 4);
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ u_int16_t applid, msgid;
+ u_int32_t PLCI;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for info_resp\n", sc->sc_unit);
+ return;
+ }
+
+ msg = capimsg_getu16(msg + 2, &applid);
+ msg = capimsg_getu16(msg + 2, &msgid);
+ msg = capimsg_getu32(msg, &PLCI);
+
+ /* i4b_l4_info_ind() */
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, applid);
+ msg = capimsg_setu16(msg, CAPI_INFO_RESP);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, PLCI);
+
+ sc->send(sc, m);
+}
+
+void capi_alert_req(capi_softc_t *sc, call_desc_t *cd)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 5);
+ u_int8_t *msg;
+ u_int16_t msgid;
+ u_int32_t PLCI;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for alert_req\n", sc->sc_unit);
+ return;
+ }
+
+ msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
+ PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, I4BCAPI_APPLID);
+ msg = capimsg_setu16(msg, CAPI_ALERT_REQ);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, PLCI);
+ msg = capimsg_setu8(msg, 0);
+
+ sc->send(sc, m);
+}
+
+void capi_alert_conf(capi_softc_t *sc, struct mbuf *m_in)
+{
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ u_int16_t Info;
+
+ msg = capimsg_getu16(msg + 12, &Info);
+
+ if (Info) {
+ printf("capi%d: can't alert, info=%04x\n", sc->sc_unit, Info);
+ }
+}
+
+/*
+// Outgoing call setup:
+// --------------------
+//
+// CAPI_CONNECT_REQ -->
+// <-- CAPI_CONNECT_CONF
+// (notify Layer 4)
+// <-- CAPI_CONNECT_ACTIVE_IND
+// CAPI_CONNECT_ACTIVE_RESP -->
+// CAPI_CONNECT_B3_REQ -->
+// <-- CAPI_CONNECT_B3_CONF
+// <-- CAPI_CONNECT_B3_ACTIVE_IND
+// CAPI_CONNECT_B3_ACTIVE_RESP -->
+// (notify Layer 4)
+*/
+
+void capi_connect_req(capi_softc_t *sc, call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_int8_t *msg;
+ u_int16_t msgid;
+ int slen = strlen(cd->src_telno);
+ int dlen = strlen(cd->dst_telno);
+
+ m = i4b_Dgetmbuf(8 + 18 + slen + dlen);
+ if (!m) {
+ printf("capi%d: can't get mbuf for connect_req\n", sc->sc_unit);
+ return;
+ }
+
+ cd->crflag = CRF_ORIG;
+
+ sc->sc_bchan[cd->channelid].cdid = cd->cdid;
+ sc->sc_bchan[cd->channelid].bprot = cd->bprot;
+ sc->sc_bchan[cd->channelid].state = B_CONNECT_CONF;
+ msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
+ ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_RSVD;
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, I4BCAPI_APPLID);
+ msg = capimsg_setu16(msg, CAPI_CONNECT_REQ);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, 1); /* Controller */
+
+ switch (cd->bprot) {
+ case BPROT_NONE:
+ msg = capimsg_setu16(msg, 0x0010); /* Telephony */
+ break;
+
+ case BPROT_RHDLC:
+ msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
+ break;
+
+ default:
+ msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
+ }
+
+ msg = capimsg_setu8(msg, 1 + dlen);
+ msg = capimsg_setu8(msg, 0x80);
+ strncpy(msg, cd->dst_telno, dlen);
+
+ msg = capimsg_setu8(msg + dlen, 2 + slen);
+ msg = capimsg_setu8(msg, 0x00);
+ msg = capimsg_setu8(msg, 0x80); /* Presentation and screening indicator */
+ strncpy(msg, cd->src_telno, slen);
+
+ msg = capimsg_setu8(msg + slen, 0); /* Called & */
+ msg = capimsg_setu8(msg, 0); /* Calling party subaddress */
+
+ msg = capimsg_setu8(msg, 15); /* B protocol */
+ if (cd->bprot == BPROT_NONE)
+ msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
+ else
+ msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
+ msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
+ msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
+ msg = capimsg_setu8(msg, 0); /* B1 parameters */
+ msg = capimsg_setu8(msg, 0); /* B2 parameters */
+ msg = capimsg_setu8(msg, 0); /* B3 parameters */
+
+ msg = capimsg_setu8(msg, 0); /* Bearer Capability */
+ msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
+ msg = capimsg_setu8(msg, 0); /* High Layer Compatibility */
+ msg = capimsg_setu8(msg, 0); /* Additional Info */
+
+ sc->send(sc, m);
+}
+
+void capi_connect_conf(capi_softc_t *sc, struct mbuf *m_in)
+{
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ call_desc_t *cd;
+ u_int16_t msgid;
+ u_int32_t PLCI;
+ u_int16_t Info;
+ int bch;
+
+ msg = capimsg_getu16(msg + 6, &msgid);
+ msg = capimsg_getu32(msg, &PLCI);
+ msg = capimsg_getu16(msg, &Info);
+
+ for (bch = 0; bch < sc->sc_nbch; bch++)
+ if ((sc->sc_bchan[bch].state == B_CONNECT_CONF) &&
+ (sc->sc_bchan[bch].msgid == msgid))
+ break;
+
+ if ((bch == sc->sc_nbch) ||
+ (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
+ printf("capi%d: can't find channel for connect_conf PLCI %x\n",
+ sc->sc_unit, PLCI);
+ return;
+ }
+
+ if (Info == 0) {
+ sc->sc_bchan[bch].state = B_CONNECT_ACTIVE_IND;
+ sc->sc_bchan[bch].ncci = PLCI;
+
+ i4b_l4_proceeding_ind(cd);
+
+ } else {
+ SET_CAUSE_TV(cd->cause_out, CAUSET_I4B, CAUSE_I4B_L1ERROR);
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+
+ sc->sc_bchan[bch].state = B_FREE;
+ ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_FREE;
+
+ printf("capi%d: can't connect out, info=%04x\n", sc->sc_unit, Info);
+ }
+}
+
+void capi_connect_active_ind(capi_softc_t *sc, struct mbuf *m_in)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 4);
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ call_desc_t *cd;
+ u_int16_t applid, msgid;
+ u_int32_t PLCI;
+ int bch;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for active_ind\n", sc->sc_unit);
+ return;
+ }
+
+ msg = capimsg_getu16(msg + 2, &applid);
+ msg = capimsg_getu16(msg + 2, &msgid);
+ msg = capimsg_getu32(msg, &PLCI);
+
+ for (bch = 0; bch < sc->sc_nbch; bch++)
+ if ((sc->sc_bchan[bch].state == B_CONNECT_ACTIVE_IND) &&
+ (sc->sc_bchan[bch].ncci == PLCI))
+ break;
+
+ if ((bch == sc->sc_nbch) ||
+ (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
+ printf("capi%d: can't find channel for active_resp, PLCI %x\n",
+ sc->sc_unit, PLCI);
+ return;
+ }
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, applid);
+ msg = capimsg_setu16(msg, CAPI_CONNECT_ACTIVE_RESP);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, PLCI);
+
+ sc->send(sc, m);
+
+ if (cd->crflag == CRF_ORIG) {
+ capi_connect_b3_req(sc, cd);
+
+ } else {
+ sc->sc_bchan[bch].state = B_CONNECT_B3_IND;
+ }
+}
+
+void capi_connect_b3_req(capi_softc_t *sc, call_desc_t *cd)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 5);
+ u_int8_t *msg;
+ u_int16_t msgid;
+ u_int32_t PLCI;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for connect_b3_req\n", sc->sc_unit);
+ return;
+ }
+
+ sc->sc_bchan[cd->channelid].state = B_CONNECT_B3_CONF;
+ msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
+ PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, I4BCAPI_APPLID);
+ msg = capimsg_setu16(msg, CAPI_CONNECT_B3_REQ);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, PLCI);
+ msg = capimsg_setu8(msg, 0); /* NCPI */
+
+ sc->send(sc, m);
+}
+
+void capi_connect_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
+{
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ call_desc_t *cd;
+ u_int16_t msgid;
+ u_int32_t NCCI;
+ u_int16_t Info;
+ int bch;
+
+ msg = capimsg_getu16(msg + 6, &msgid);
+ msg = capimsg_getu32(msg, &NCCI);
+ msg = capimsg_getu16(msg, &Info);
+
+ for (bch = 0; bch < sc->sc_nbch; bch++)
+ if ((sc->sc_bchan[bch].state == B_CONNECT_B3_CONF) &&
+ (sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
+ break;
+
+ if ((bch == sc->sc_nbch) ||
+ (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
+ printf("capi%d: can't find channel for connect_b3_conf NCCI %x\n",
+ sc->sc_unit, NCCI);
+ return;
+ }
+
+ if (Info == 0) {
+ sc->sc_bchan[bch].ncci = NCCI;
+ sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
+
+ } else {
+ SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_OOO); /* XXX */
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+
+ ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_RSVD;
+
+ printf("capi%d: can't connect_b3 out, info=%04x\n", sc->sc_unit, Info);
+
+ capi_disconnect_req(sc, cd);
+ }
+}
+
+void capi_connect_b3_active_ind(capi_softc_t *sc, struct mbuf *m_in)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 4);
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ call_desc_t *cd;
+ u_int16_t applid, msgid;
+ u_int32_t NCCI;
+ int bch;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for b3_active_ind\n", sc->sc_unit);
+ return;
+ }
+
+ msg = capimsg_getu16(msg + 2, &applid);
+ msg = capimsg_getu16(msg + 2, &msgid);
+ msg = capimsg_getu32(msg, &NCCI);
+
+ for (bch = 0; bch < sc->sc_nbch; bch++)
+ if ((sc->sc_bchan[bch].state == B_CONNECT_B3_ACTIVE_IND) &&
+ (sc->sc_bchan[bch].ncci == NCCI))
+ break;
+
+ if ((bch == sc->sc_nbch) ||
+ (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
+ printf("capi%d: can't find channel for b3_active_resp NCCI %x\n",
+ sc->sc_unit, NCCI);
+ return;
+ }
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, I4BCAPI_APPLID);
+ msg = capimsg_setu16(msg, CAPI_CONNECT_B3_ACTIVE_RESP);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, NCCI);
+
+ sc->send(sc, m);
+
+ sc->sc_bchan[bch].state = B_CONNECTED;
+ i4b_l4_connect_active_ind(cd);
+}
+
+/*
+// Incoming call setup:
+// --------------------
+//
+// <-- CAPI_CONNECT_IND
+// (consult Layer 4)
+// CAPI_CONNECT_RESP -->
+// <-- CAPI_CONNECT_ACTIVE_IND
+// CAPI_CONNECT_ACTIVE_RESP -->
+// <-- CAPI_CONNECT_B3_IND
+// CAPI_CONNECT_B3_RESP -->
+// <-- CAPI_CONNECT_B3_ACTIVE_IND
+// CAPI_CONNECT_B3_ACTIVE_RESP -->
+// (notify Layer 4)
+*/
+
+void capi_connect_ind(capi_softc_t *sc, struct mbuf *m_in)
+{
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ call_desc_t *cd;
+ u_int16_t applid, msgid;
+ u_int32_t PLCI;
+ u_int16_t CIP;
+ u_int8_t x, y, z;
+ int bch;
+
+ if ((cd = reserve_cd()) == NULL) {
+ printf("capi%d: can't get cd for connect_ind\n", sc->sc_unit);
+ return;
+ }
+
+ cd->controller = sc->ctrl_unit;
+ cd->channelexcl = FALSE;
+
+ for (bch = 0; bch < sc->sc_nbch; bch++)
+ if (sc->sc_bchan[bch].state == B_FREE) break;
+ sc->sc_bchan[bch].state = B_CONNECT_IND;
+ cd->channelid = bch; /* XXX CHAN_ANY XXX */
+
+ cd->crflag = CRF_DEST;
+ cd->cr = get_rand_cr(sc->sc_unit);
+ cd->scr_ind = SCR_NONE;
+ cd->prs_ind = PRS_NONE;
+ cd->bprot = BPROT_NONE;
+ cd->ilt = NULL;
+ cd->dlt = NULL;
+ cd->display[0] = '\0';
+ cd->datetime[0] = '\0';
+
+ msg = capimsg_getu16(msg + 2, &applid);
+ msg = capimsg_getu16(msg + 2, &msgid);
+ msg = capimsg_getu32(msg, &PLCI);
+ msg = capimsg_getu16(msg, &CIP);
+
+ cd->event = (int) msgid; /* XXX overload */
+ cd->Q931state = (int) PLCI; /* XXX overload */
+
+ switch (CIP) {
+ case 0x0010:
+ case 0x0001: cd->bprot = BPROT_NONE; break;
+ case 0x0002: cd->bprot = BPROT_RHDLC; break;
+ default:
+ NDBGL4(L4_CAPIDBG, "capi%d: unknown CIP = %d", sc->sc_unit, CIP);
+ cd->bprot = BPROT_NONE;
+ }
+
+ msg = capimsg_getu8(msg, &x); /* Called party struct len */
+ if (x) {
+ msg = capimsg_getu8(msg, &y); /* Numbering plan */
+ z = x - 1;
+ if (z >= TELNO_MAX) z = (TELNO_MAX-1);
+ strncpy(cd->dst_telno, msg, z);
+ msg += x;
+ x = z;
+ }
+ cd->dst_telno[x] = '\0';
+
+ msg = capimsg_getu8(msg, &x); /* Calling party struct len */
+ if (x) {
+ msg = capimsg_getu8(msg, &y); /* Numbering plan */
+ msg = capimsg_getu8(msg, &y); /* Screening/Presentation */
+ if ((y & 0x80) == 0) { /* screening used */
+ cd->scr_ind = (y & 3) + SCR_USR_NOSC;
+ cd->prs_ind = ((y >> 5) & 3) + PRS_ALLOWED;
+ }
+ z = x - 2;
+ if (z >= TELNO_MAX) z = (TELNO_MAX-1);
+ strncpy(cd->src_telno, msg, z);
+ msg += x;
+ x = z;
+ }
+ cd->src_telno[x] = '\0';
+
+ i4b_l4_connect_ind(cd);
+}
+
+void capi_connect_resp(capi_softc_t *sc, call_desc_t *cd)
+{
+ struct mbuf *m;
+ u_int8_t *msg;
+ u_int16_t msgid;
+ u_int32_t PLCI;
+ int dlen = strlen(cd->dst_telno);
+
+ m = i4b_Dgetmbuf(8 + 11 + dlen);
+ if (!m) {
+ printf("capi%d: can't get mbuf for connect_resp\n", sc->sc_unit);
+ return;
+ }
+
+ msgid = (u_int16_t) cd->event;
+ PLCI = (u_int32_t) cd->Q931state;
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, I4BCAPI_APPLID);
+ msg = capimsg_setu16(msg, CAPI_CONNECT_RESP);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, PLCI);
+
+ switch (cd->response) {
+ case SETUP_RESP_ACCEPT:
+ sc->sc_bchan[cd->channelid].cdid = cd->cdid;
+ sc->sc_bchan[cd->channelid].ncci = PLCI;
+ sc->sc_bchan[cd->channelid].state = B_CONNECT_ACTIVE_IND;
+ ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_USED;
+ msg = capimsg_setu16(msg, 0); /* Accept the call */
+ break;
+
+ case SETUP_RESP_REJECT:
+ sc->sc_bchan[cd->channelid].state = B_FREE;
+ ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_FREE;
+ msg = capimsg_setu16(msg, 2); /* Reject, normal call clearing */
+ break;
+
+ case SETUP_RESP_DNTCRE:
+ sc->sc_bchan[cd->channelid].state = B_FREE;
+ ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_FREE;
+ msg = capimsg_setu16(msg, 1); /* Ignore */
+ break;
+
+ default:
+ sc->sc_bchan[cd->channelid].state = B_FREE;
+ ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_FREE;
+ msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_CALLREJ));
+ }
+
+ msg = capimsg_setu8(msg, 15); /* B protocol */
+ if (cd->bprot == BPROT_NONE)
+ msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
+ else
+ msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
+ msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
+ msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
+ msg = capimsg_setu8(msg, 0); /* B1 parameters */
+ msg = capimsg_setu8(msg, 0); /* B2 parameters */
+ msg = capimsg_setu8(msg, 0); /* B3 parameters */
+
+ msg = capimsg_setu8(msg, 1 + dlen);
+ msg = capimsg_setu8(msg, 0x80); /* Numbering plan */
+ strncpy(msg, cd->dst_telno, dlen);
+ msg = capimsg_setu8(msg + dlen, 0); /* Connected subaddress */
+ msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
+ msg = capimsg_setu8(msg, 0); /* Additional Info */
+
+ sc->send(sc, m);
+}
+
+void capi_connect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 7);
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ u_int16_t applid, msgid;
+ u_int32_t NCCI;
+ int bch;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for connect_b3_resp\n", sc->sc_unit);
+ return;
+ }
+
+ msg = capimsg_getu16(msg + 2, &applid);
+ msg = capimsg_getu16(msg + 2, &msgid);
+ msg = capimsg_getu32(msg, &NCCI);
+
+ for (bch = 0; bch < sc->sc_nbch; bch++)
+ if ((sc->sc_bchan[bch].state == B_CONNECT_B3_IND) &&
+ (sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
+ break;
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, applid);
+ msg = capimsg_setu16(msg, CAPI_CONNECT_B3_RESP);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, NCCI);
+
+ if (bch == sc->sc_nbch) {
+ printf("capi%d: can't get cd for connect_b3_resp NCCI %x\n",
+ sc->sc_unit, NCCI);
+ msg = capimsg_setu16(msg, 8); /* Reject, destination OOO */
+
+ } else {
+ sc->sc_bchan[bch].ncci = NCCI;
+ sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
+ msg = capimsg_setu16(msg, 0); /* Accept */
+ }
+
+ msg = capimsg_setu8(msg, 0); /* NCPI */
+
+ sc->send(sc, m);
+}
+
+/*
+// Data transfer:
+// --------------
+*/
+
+void capi_data_b3_req(capi_softc_t *sc, int chan, struct mbuf *m_b3)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 14);
+ u_int8_t *msg;
+ u_int16_t msgid;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for data_b3_req\n", sc->sc_unit);
+ return;
+ }
+
+ msgid = sc->sc_bchan[chan].msgid = sc->sc_msgid++;
+ sc->sc_bchan[chan].busy = 1;
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, I4BCAPI_APPLID);
+ msg = capimsg_setu16(msg, CAPI_DATA_B3_REQ);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, sc->sc_bchan[chan].ncci);
+ msg = capimsg_setu32(msg, (u_int32_t) m_b3->m_data); /* Pointer */
+ msg = capimsg_setu16(msg, m_b3->m_len);
+ msg = capimsg_setu16(msg, chan);
+ msg = capimsg_setu16(msg, 0); /* Flags */
+
+ m->m_next = m_b3;
+
+ sc->send(sc, m);
+}
+
+void capi_data_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
+{
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ u_int32_t NCCI;
+ u_int16_t handle;
+ u_int16_t Info;
+
+ msg = capimsg_getu32(msg + 8, &NCCI);
+ msg = capimsg_getu16(msg, &handle);
+ msg = capimsg_getu16(msg, &Info);
+
+ if (Info == 0) {
+ sc->sc_bchan[handle].busy = 0;
+ capi_start_tx(sc, handle);
+
+ } else {
+ printf("capi%d: data_b3_conf NCCI %x handle %x info=%04x\n",
+ sc->sc_unit, NCCI, handle, Info);
+ }
+}
+
+void capi_data_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 14);
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ u_int16_t applid, msgid;
+ u_int32_t NCCI;
+ u_int16_t handle;
+ int bch;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for data_b3_resp\n", sc->sc_unit);
+ return;
+ }
+
+ msg = capimsg_getu16(msg + 2, &applid);
+ msg = capimsg_getu16(msg + 2, &msgid);
+ msg = capimsg_getu32(msg, &NCCI);
+ msg = capimsg_getu16(msg + 6, &handle);
+
+ for (bch = 0; bch < sc->sc_nbch; bch++)
+ if ((sc->sc_bchan[bch].state == B_CONNECTED) &&
+ (sc->sc_bchan[bch].ncci == NCCI))
+ break;
+
+ if (bch == sc->sc_nbch) {
+ printf("capi%d: can't find channel for data_b3_ind NCCI %x\n",
+ sc->sc_unit, NCCI);
+
+ } else {
+ if (sc->sc_bchan[bch].bprot == BPROT_RHDLC) {
+ /* HDLC drivers use rx_mbuf */
+
+ sc->sc_bchan[bch].in_mbuf = m_in->m_next;
+ sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
+ m_in->m_next = NULL; /* driver frees */
+
+ (*sc->sc_bchan[bch].capi_drvr_linktab->bch_rx_data_ready)(
+ sc->sc_bchan[bch].capi_drvr_linktab->unit);
+
+ } else {
+ /* Telephony drivers use rx_queue */
+
+ if (!_IF_QFULL(&sc->sc_bchan[bch].rx_queue)) {
+ _IF_ENQUEUE(&sc->sc_bchan[bch].rx_queue, m_in->m_next);
+ sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
+ m_in->m_next = NULL; /* driver frees */
+ }
+
+ (*sc->sc_bchan[bch].capi_drvr_linktab->bch_rx_data_ready)(
+ sc->sc_bchan[bch].capi_drvr_linktab->unit);
+ }
+ }
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, I4BCAPI_APPLID);
+ msg = capimsg_setu16(msg, CAPI_DATA_B3_RESP);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, NCCI);
+ msg = capimsg_setu16(msg, handle);
+
+ sc->send(sc, m);
+}
+
+/*
+// Connection teardown:
+// --------------------
+*/
+
+void capi_disconnect_req(capi_softc_t *sc, call_desc_t *cd)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 5);
+ u_int8_t *msg;
+ u_int16_t msgid;
+ u_int32_t PLCI;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for disconnect_req\n", sc->sc_unit);
+ return;
+ }
+
+ sc->sc_bchan[cd->channelid].state = B_DISCONNECT_CONF;
+ ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_RSVD;
+ msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
+ PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, I4BCAPI_APPLID);
+ msg = capimsg_setu16(msg, CAPI_DISCONNECT_REQ);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, PLCI);
+ msg = capimsg_setu8(msg, 0); /* Additional Info */
+
+ sc->send(sc, m);
+}
+
+void capi_disconnect_conf(capi_softc_t *sc, struct mbuf *m_in)
+{
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ call_desc_t *cd;
+ u_int32_t PLCI;
+ int bch;
+
+ msg = capimsg_getu32(msg + 8, &PLCI);
+
+ for (bch = 0; bch < sc->sc_nbch; bch++)
+ if ((sc->sc_bchan[bch].state == B_DISCONNECT_CONF) &&
+ ((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
+ break;
+
+ if (bch == sc->sc_nbch) {
+ printf("capi%d: can't find channel for disconnect_conf PLCI %x\n",
+ sc->sc_unit, PLCI);
+ return;
+ }
+
+ cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
+ if (!cd) {
+ printf("capi%d: can't find cd for disconnect_conf PLCI %x\n",
+ sc->sc_unit, PLCI);
+ } else {
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+ }
+
+ sc->sc_bchan[bch].state = B_FREE;
+ ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_FREE;
+}
+
+void capi_disconnect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 4);
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ u_int16_t applid, msgid;
+ u_int32_t NCCI;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for disconnect_b3_resp\n", sc->sc_unit);
+ return;
+ }
+
+ msg = capimsg_getu16(msg + 2, &applid);
+ msg = capimsg_getu16(msg + 2, &msgid);
+ msg = capimsg_getu32(msg, &NCCI);
+
+ /* XXX update bchan state? XXX */
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, applid);
+ msg = capimsg_setu16(msg, CAPI_DISCONNECT_B3_RESP);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, NCCI);
+
+ sc->send(sc, m);
+}
+
+void capi_disconnect_ind(capi_softc_t *sc, struct mbuf *m_in)
+{
+ struct mbuf *m = i4b_Dgetmbuf(8 + 4);
+ u_int8_t *msg = mtod(m_in, u_int8_t*);
+ call_desc_t *cd;
+ u_int16_t applid, msgid;
+ u_int32_t PLCI;
+ u_int16_t Reason;
+ int bch;
+
+ if (!m) {
+ printf("capi%d: can't get mbuf for disconnect_resp\n", sc->sc_unit);
+ return;
+ }
+
+ msg = capimsg_getu16(msg + 2, &applid);
+ msg = capimsg_getu16(msg + 2, &msgid);
+ msg = capimsg_getu32(msg, &PLCI);
+ msg = capimsg_getu16(msg, &Reason);
+
+ for (bch = 0; bch < sc->sc_nbch; bch++)
+ if ((sc->sc_bchan[bch].state != B_FREE) &&
+ ((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
+ break;
+
+ if (bch < sc->sc_nbch) {
+ /* We may not have a bchan assigned if call was ignored. */
+
+ cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
+ sc->sc_bchan[bch].state = B_DISCONNECT_IND;
+ } else cd = NULL;
+
+ if (cd) {
+ if ((Reason & 0xff00) == 0x3400) {
+ SET_CAUSE_TV(cd->cause_in, CAUSET_Q850, (Reason & 0x7f));
+ } else {
+ SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_NORMAL);
+ }
+
+ i4b_l4_disconnect_ind(cd);
+ freecd_by_cd(cd);
+
+ sc->sc_bchan[bch].state = B_FREE;
+ ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_FREE;
+ }
+
+ msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
+ msg = capimsg_setu16(msg, applid);
+ msg = capimsg_setu16(msg, CAPI_DISCONNECT_RESP);
+ msg = capimsg_setu16(msg, msgid);
+
+ msg = capimsg_setu32(msg, PLCI);
+
+ sc->send(sc, m);
+}
+
+#endif /* NI4BCAPI > 0 */
diff --git a/sys/i4b/capi/capi_msgs.h b/sys/i4b/capi/capi_msgs.h
new file mode 100644
index 000000000000..3cdce35991d6
--- /dev/null
+++ b/sys/i4b/capi/capi_msgs.h
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * capi/capi_msgs.h The CAPI i4b message and handler declarations.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _I4B_CAPI_MSGS_H_
+#define _I4B_CAPI_MSGS_H_
+
+/* CAPI commands */
+
+#define CAPI_ALERT 0x01
+#define CAPI_CONNECT 0x02
+#define CAPI_CONNECT_ACTIVE 0x03
+#define CAPI_CONNECT_B3 0x82
+#define CAPI_CONNECT_B3_ACTIVE 0x83
+#define CAPI_CONNECT_B3_T90_ACTIVE 0x88
+#define CAPI_DATA_B3 0x86
+#define CAPI_DISCONNECT_B3 0x84
+#define CAPI_DISCONNECT 0x04
+#define CAPI_FACILITY 0x80
+#define CAPI_INFO 0x08
+#define CAPI_LISTEN 0x05
+#define CAPI_MANUFACTURER 0xff
+#define CAPI_RESET_B3 0x87
+#define CAPI_SELECT_B_PROTOCOL 0x41
+
+/* CAPI subcommands */
+
+#define CAPI_REQ 0x80
+#define CAPI_CONF 0x81
+#define CAPI_IND 0x82
+#define CAPI_RESP 0x83
+
+/* CAPI combined commands */
+
+#define CAPICMD(cmd,subcmd) (((subcmd)<<8)|(cmd))
+
+#define CAPI_DISCONNECT_REQ CAPICMD(CAPI_DISCONNECT,CAPI_REQ)
+#define CAPI_DISCONNECT_CONF CAPICMD(CAPI_DISCONNECT,CAPI_CONF)
+#define CAPI_DISCONNECT_IND CAPICMD(CAPI_DISCONNECT,CAPI_IND)
+#define CAPI_DISCONNECT_RESP CAPICMD(CAPI_DISCONNECT,CAPI_RESP)
+
+#define CAPI_ALERT_REQ CAPICMD(CAPI_ALERT,CAPI_REQ)
+#define CAPI_ALERT_CONF CAPICMD(CAPI_ALERT,CAPI_CONF)
+
+#define CAPI_CONNECT_REQ CAPICMD(CAPI_CONNECT,CAPI_REQ)
+#define CAPI_CONNECT_CONF CAPICMD(CAPI_CONNECT,CAPI_CONF)
+#define CAPI_CONNECT_IND CAPICMD(CAPI_CONNECT,CAPI_IND)
+#define CAPI_CONNECT_RESP CAPICMD(CAPI_CONNECT,CAPI_RESP)
+
+#define CAPI_CONNECT_ACTIVE_REQ CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_REQ)
+#define CAPI_CONNECT_ACTIVE_CONF CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_CONF)
+#define CAPI_CONNECT_ACTIVE_IND CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_IND)
+#define CAPI_CONNECT_ACTIVE_RESP CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_RESP)
+
+#define CAPI_SELECT_B_PROTOCOL_REQ CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_REQ)
+#define CAPI_SELECT_B_PROTOCOL_CONF CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_CONF)
+
+#define CAPI_CONNECT_B3_REQ CAPICMD(CAPI_CONNECT_B3,CAPI_REQ)
+#define CAPI_CONNECT_B3_CONF CAPICMD(CAPI_CONNECT_B3,CAPI_CONF)
+#define CAPI_CONNECT_B3_IND CAPICMD(CAPI_CONNECT_B3,CAPI_IND)
+#define CAPI_CONNECT_B3_RESP CAPICMD(CAPI_CONNECT_B3,CAPI_RESP)
+
+#define CAPI_CONNECT_B3_ACTIVE_REQ CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_REQ)
+#define CAPI_CONNECT_B3_ACTIVE_CONF CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_CONF)
+#define CAPI_CONNECT_B3_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_IND)
+#define CAPI_CONNECT_B3_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_RESP)
+
+#define CAPI_CONNECT_B3_T90_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_IND)
+#define CAPI_CONNECT_B3_T90_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_RESP)
+
+#define CAPI_DATA_B3_REQ CAPICMD(CAPI_DATA_B3,CAPI_REQ)
+#define CAPI_DATA_B3_CONF CAPICMD(CAPI_DATA_B3,CAPI_CONF)
+#define CAPI_DATA_B3_IND CAPICMD(CAPI_DATA_B3,CAPI_IND)
+#define CAPI_DATA_B3_RESP CAPICMD(CAPI_DATA_B3,CAPI_RESP)
+
+#define CAPI_DISCONNECT_B3_REQ CAPICMD(CAPI_DISCONNECT_B3,CAPI_REQ)
+#define CAPI_DISCONNECT_B3_CONF CAPICMD(CAPI_DISCONNECT_B3,CAPI_CONF)
+#define CAPI_DISCONNECT_B3_IND CAPICMD(CAPI_DISCONNECT_B3,CAPI_IND)
+#define CAPI_DISCONNECT_B3_RESP CAPICMD(CAPI_DISCONNECT_B3,CAPI_RESP)
+
+#define CAPI_RESET_B3_REQ CAPICMD(CAPI_RESET_B3,CAPI_REQ)
+#define CAPI_RESET_B3_CONF CAPICMD(CAPI_RESET_B3,CAPI_CONF)
+#define CAPI_RESET_B3_IND CAPICMD(CAPI_RESET_B3,CAPI_IND)
+#define CAPI_RESET_B3_RESP CAPICMD(CAPI_RESET_B3,CAPI_RESP)
+
+#define CAPI_LISTEN_REQ CAPICMD(CAPI_LISTEN,CAPI_REQ)
+#define CAPI_LISTEN_CONF CAPICMD(CAPI_LISTEN,CAPI_CONF)
+
+#define CAPI_MANUFACTURER_REQ CAPICMD(CAPI_MANUFACTURER,CAPI_REQ)
+#define CAPI_MANUFACTURER_CONF CAPICMD(CAPI_MANUFACTURER,CAPI_CONF)
+#define CAPI_MANUFACTURER_IND CAPICMD(CAPI_MANUFACTURER,CAPI_IND)
+#define CAPI_MANUFACTURER_RESP CAPICMD(CAPI_MANUFACTURER,CAPI_RESP)
+
+#define CAPI_FACILITY_REQ CAPICMD(CAPI_FACILITY,CAPI_REQ)
+#define CAPI_FACILITY_CONF CAPICMD(CAPI_FACILITY,CAPI_CONF)
+#define CAPI_FACILITY_IND CAPICMD(CAPI_FACILITY,CAPI_IND)
+#define CAPI_FACILITY_RESP CAPICMD(CAPI_FACILITY,CAPI_RESP)
+
+#define CAPI_INFO_REQ CAPICMD(CAPI_INFO,CAPI_REQ)
+#define CAPI_INFO_CONF CAPICMD(CAPI_INFO,CAPI_CONF)
+#define CAPI_INFO_IND CAPICMD(CAPI_INFO,CAPI_IND)
+#define CAPI_INFO_RESP CAPICMD(CAPI_INFO,CAPI_RESP)
+
+/* CAPI message access helpers */
+
+/*
+ * CAPI message header:
+ * word Length
+ * word ApplId
+ * byte Command
+ * byte Subcommand
+ * word MsgId
+ *
+ * Note that in the following, Controller/PLCI/NCCI is coded as follows:
+ * bits 0..6 = controller, bit 7 = ext/int, bits 8..15 = PLCI, and
+ * bits 16..31 = NCCI value.
+ *
+ * ALERT_REQ, 01 80:
+ * dword PLCI
+ * struct Additional Info
+ *
+ * ALERT_CONF, 01 81:
+ * dword PLCI
+ * word Info (0 = OK, other = cause)
+ *
+ * CONNECT_REQ, 02 80:
+ * dword controller
+ * word CIP
+ * struct Called party number
+ * struct Calling party number
+ * struct Called party subaddress
+ * struct Calling party subaddress
+ * struct Bearer Capability
+ * struct Low Layer Compatibility
+ * struct High Layer Compatibility
+ * struct Additional Info
+ *
+ * CONNECT_CONF, 02 81:
+ * dword PLCI
+ * word Info (0 = OK, other = cause)
+ *
+ * CONNECT_IND, 02 82:
+ * dword PLCI
+ * word CIP
+ * struct Called party number
+ * struct Calling party number
+ * struct Called party subaddress
+ * struct Calling party subaddress
+ * struct Bearer Capability
+ * struct Low Layer Compatibility
+ * struct High Layer Compatibility
+ * struct Additional Info
+ * struct Second Calling party number
+ *
+ * CONNECT_RESP, 02 83:
+ * dword PLCI
+ * word Reject (0 = accept, 1 = ignore, 2 = reject/normal clearing)
+ * struct B protocol
+ * struct Connected number
+ * struct Connected subaddress
+ * struct Low Layer Compatibility
+ * struct Additional Info
+ *
+ * CONNECT_ACTIVE_IND, 03 82:
+ * dword PLCI
+ * struct Connected number
+ * struct Connected subaddress
+ * struct Low Layer Compatibility
+ *
+ * CONNECT_ACTIVE_RESP, 03 83:
+ * dword PLCI
+ *
+ * CONNECT_B3_REQ, 82 80:
+ * dword PLCI
+ * struct NCPI
+ *
+ * CONNECT_B3_CONF, 82 81:
+ * dword NCCI
+ * word Info (0 = connected, other = cause)
+ *
+ * CONNECT_B3_IND, 82 82:
+ * dword NCCI
+ * struct NCPI
+ *
+ * CONNECT_B3_RESP, 82 83:
+ * dword NCCI
+ * word Reject (0 = accept, 2 = reject/normal clearing)
+ * struct NCPI
+ *
+ * CONNECT_B3_ACTIVE_IND, 83 82:
+ * dword NCCI
+ * struct NCPI
+ *
+ * CONNECT_B3_ACTIVE_RESP, 83 83:
+ * dword NCCI
+ *
+ * DATA_B3_REQ, 86 80:
+ * dword NCCI
+ * dword Data pointer
+ * word Data length
+ * word Data handle (packet id)
+ * word Flags (02 = more)
+ *
+ * DATA_B3_CONF, 86 81:
+ * dword NCCI
+ * word Data handle (packet id)
+ * word Info (0 = OK, other = cause)
+ *
+ * DATA_B3_IND, 86 82:
+ * dword NCCI
+ * dword Data pointer
+ * word Data length
+ * word Data handle (packet id)
+ * word Flags (02 = more)
+ *
+ * DATA_B3_RESP, 86 83:
+ * dword NCCI
+ * word Data handle (packet id)
+ *
+ * DISCONNECT_B3_REQ, 84 80:
+ * dword NCCI
+ * struct NCPI
+ *
+ * DISCONNECT_B3_CONF, 84 81:
+ * dword NCCI
+ * word Info (0 = OK, other = cause)
+ *
+ * DISCONNECT_B3_IND, 84 82:
+ * dword NCCI
+ * word Reason
+ * struct NCPI
+ *
+ * DISCONNECT_B3_RESP, 84 83:
+ * dword NCCI
+ *
+ * DISCONNECT_REQ, 04 80:
+ * dword PLCI
+ * struct Additional Info
+ *
+ * DISCONNECT_CONF, 04 81:
+ * dword PLCI
+ * word Info (0 = OK, other = cause)
+ *
+ * DISCONNECT_IND, 04 82:
+ * dword PLCI
+ * word Reason
+ *
+ * DISCONNECT_RESP, 04 83:
+ * dword PLCI
+ *
+ * LISTEN_REQ, 05 80:
+ * dword Controller
+ * dword Info mask (bits 0..9 used)
+ * dword CIP Mask (bit 0 = any match)
+ * dword CIP Mask 2 (bit 0 = any match)
+ * struct Calling party number
+ * struct Calling party subaddress
+ *
+ * LISTEN_CONF, 05 81:
+ * dword Controller
+ * word Info (0 = OK, other = cause)
+ *
+ * INFO_REQ, 08 80:
+ * dword Controller/PLCI
+ * struct Called party number
+ * struct Additional Info
+ *
+ * INFO_CONF, 08 81:
+ * dword Controller/PLCI
+ * word Info (0 = OK, other = cause)
+ *
+ * INFO_IND, 08 82:
+ * dword Controller/PLCI
+ * word Info number
+ * struct Info element
+ *
+ * INFO_RESP, 08 83:
+ * dword Controller/PLCI
+ */
+
+#define CAPIMSG_LEN(msg) (msg[0]|(msg[1]<<8))
+#define CAPIMSG_DATALEN(msg) (msg[16]|(msg[17]<<8))
+
+static __inline u_int8_t* capimsg_getu8(u_int8_t *msg, u_int8_t *val)
+{
+ *val = *msg;
+ return (msg + 1);
+}
+
+static __inline u_int8_t* capimsg_getu16(u_int8_t *msg, u_int16_t *val)
+{
+ *val = (msg[0]|(msg[1]<<8));
+ return (msg + 2);
+}
+
+static __inline u_int8_t* capimsg_getu32(u_int8_t *msg, u_int32_t *val)
+{
+ *val = (msg[0]|(msg[1]<<8)|(msg[2]<<16)|(msg[3]<<24));
+ return (msg + 4);
+}
+
+static __inline u_int8_t* capimsg_setu8(u_int8_t *msg, u_int8_t val)
+{
+ msg[0] = val;
+ return (msg + 1);
+}
+
+static __inline u_int8_t* capimsg_setu16(u_int8_t *msg, u_int16_t val)
+{
+ msg[0] = (val & 0xff);
+ msg[1] = (val >> 8) & 0xff;
+ return (msg + 2);
+}
+
+static __inline u_int8_t* capimsg_setu32(u_int8_t *msg, u_int32_t val)
+{
+ msg[0] = (val & 0xff);
+ msg[1] = (val >> 8) & 0xff;
+ msg[2] = (val >> 16) & 0xff;
+ msg[3] = (val >> 24) & 0xff;
+ return (msg + 4);
+}
+
+/*
+// CAPI message handlers called by higher layers
+*/
+
+extern void capi_listen_req(capi_softc_t *sc, u_int32_t CIP);
+extern void capi_alert_req(capi_softc_t *sc, call_desc_t *cd);
+extern void capi_connect_req(capi_softc_t *sc, call_desc_t *cd);
+extern void capi_connect_b3_req(capi_softc_t *sc, call_desc_t *cd);
+extern void capi_connect_resp(capi_softc_t *sc, call_desc_t *cd);
+extern void capi_data_b3_req(capi_softc_t *sc, int chan, struct mbuf *m);
+extern void capi_disconnect_req(capi_softc_t *sc, call_desc_t *cd);
+
+/*
+// CAPI message handlers called by the receive routine
+*/
+
+extern void capi_listen_conf(capi_softc_t *sc, struct mbuf *m);
+extern void capi_info_ind(capi_softc_t *sc, struct mbuf *m);
+extern void capi_alert_conf(capi_softc_t *sc, struct mbuf *m);
+extern void capi_connect_conf(capi_softc_t *sc, struct mbuf *m);
+extern void capi_connect_active_ind(capi_softc_t *sc, struct mbuf *m);
+extern void capi_connect_b3_conf(capi_softc_t *sc, struct mbuf *m);
+extern void capi_connect_b3_active_ind(capi_softc_t *sc, struct mbuf *m);
+extern void capi_connect_ind(capi_softc_t *sc, struct mbuf *m);
+extern void capi_connect_b3_ind(capi_softc_t *sc, struct mbuf *m);
+extern void capi_data_b3_conf(capi_softc_t *sc, struct mbuf *m);
+extern void capi_data_b3_ind(capi_softc_t *sc, struct mbuf *m);
+extern void capi_disconnect_conf(capi_softc_t *sc, struct mbuf *m);
+extern void capi_disconnect_b3_ind(capi_softc_t *sc, struct mbuf *m);
+extern void capi_disconnect_ind(capi_softc_t *sc, struct mbuf *m);
+
+#endif /* _I4B_CAPI_MSGS_H_ */
diff --git a/sys/i4b/capi/iavc/iavc.h b/sys/i4b/capi/iavc/iavc.h
new file mode 100644
index 000000000000..a38ad70c39a9
--- /dev/null
+++ b/sys/i4b/capi/iavc/iavc.h
@@ -0,0 +1,586 @@
+/*
+ * Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * capi/iavc/iavc.h The AVM ISDN controllers' common declarations.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _CAPI_IAVC_H_
+#define _CAPI_IAVC_H_
+
+/* max 4 units supported per machine */
+
+#define IAVC_MAXUNIT 4
+
+/*
+// iavc_softc_t
+// The software context of one AVM T1 controller.
+*/
+
+#define IAVC_IO_BASES 1
+
+typedef struct i4b_info {
+ struct resource * io_base[IAVC_IO_BASES];
+ int io_rid [IAVC_IO_BASES];
+ struct resource * irq;
+ int irq_rid;
+ struct resource * mem;
+ int mem_rid;
+} i4b_info_t;
+
+typedef struct iavc_softc {
+ capi_softc_t sc_capi;
+ int sc_unit;
+ int sc_cardtyp;
+
+ u_int32_t sc_membase;
+ bus_space_handle_t sc_mem_bh;
+ bus_space_tag_t sc_mem_bt;
+ u_int32_t sc_iobase;
+ bus_space_handle_t sc_io_bh;
+ bus_space_tag_t sc_io_bt;
+
+ int sc_state;
+#define IAVC_DOWN 0
+#define IAVC_POLL 1
+#define IAVC_INIT 2
+#define IAVC_UP 3
+ int sc_blocked;
+ int sc_dma;
+ int sc_t1;
+ int sc_intr;
+
+ u_int32_t sc_csr;
+
+ char sc_sendbuf[128+2048];
+ char sc_recvbuf[128+2048];
+ int sc_recvlen;
+
+ struct ifqueue sc_txq;
+
+ i4b_info_t sc_resources;
+} iavc_softc_t;
+
+extern iavc_softc_t iavc_sc[];
+
+#define iavc_find_sc(unit) (&iavc_sc[(unit)])
+
+/*
+// {b1,b1dma,t1}_{detect,reset}
+// Routines to detect and manage the specific type of card.
+*/
+
+extern int b1_detect(iavc_softc_t *sc);
+extern void b1_disable_irq(iavc_softc_t *sc);
+extern void b1_reset(iavc_softc_t *sc);
+
+extern int b1dma_detect(iavc_softc_t *sc);
+extern void b1dma_reset(iavc_softc_t *sc);
+
+extern int t1_detect(iavc_softc_t *sc);
+extern void t1_disable_irq(iavc_softc_t *sc);
+extern void t1_reset(iavc_softc_t *sc);
+
+/*
+// AMCC_{READ,WRITE}
+// Routines to access the memory mapped registers of the
+// S5933 DMA controller.
+*/
+
+static __inline u_int32_t AMCC_READ(iavc_softc_t *sc, int off)
+{
+ return bus_space_read_4(sc->sc_mem_bt, sc->sc_mem_bh, off);
+}
+
+static __inline void AMCC_WRITE(iavc_softc_t *sc, int off, u_int32_t value)
+{
+ bus_space_write_4(sc->sc_mem_bt, sc->sc_mem_bh, off, value);
+}
+
+/*
+// amcc_{put,get}_{byte,word}
+// Routines to access the DMA buffers byte- or wordwise.
+*/
+
+static __inline u_int8_t* amcc_put_byte(u_int8_t *buf, u_int8_t value)
+{
+ *buf++ = value;
+ return buf;
+}
+
+static __inline u_int8_t* amcc_get_byte(u_int8_t *buf, u_int8_t *value)
+{
+ *value = *buf++;
+ return buf;
+}
+
+static __inline u_int8_t* amcc_put_word(u_int8_t *buf, u_int32_t value)
+{
+ *buf++ = (value & 0xff);
+ *buf++ = (value >> 8) & 0xff;
+ *buf++ = (value >> 16) & 0xff;
+ *buf++ = (value >> 24) & 0xff;
+ return buf;
+}
+
+static __inline u_int8_t* amcc_get_word(u_int8_t *buf, u_int32_t *value)
+{
+ *value = *buf++;
+ *value |= (*buf++ << 8);
+ *value |= (*buf++ << 16);
+ *value |= (*buf++ << 24);
+ return buf;
+}
+
+/*
+// Controller LLI message numbers.
+*/
+
+#define SEND_POLL 0x72
+#define SEND_INIT 0x11
+#define SEND_REGISTER 0x12
+#define SEND_DATA_B3_REQ 0x13
+#define SEND_RELEASE 0x14
+#define SEND_MESSAGE 0x15
+#define SEND_CONFIG 0x71
+#define SEND_POLLACK 0x73
+
+#define RECEIVE_POLL 0x32
+#define RECEIVE_INIT 0x27
+#define RECEIVE_MESSAGE 0x21
+#define RECEIVE_DATA_B3_IND 0x22
+#define RECEIVE_START 0x23
+#define RECEIVE_STOP 0x24
+#define RECEIVE_NEW_NCCI 0x25
+#define RECEIVE_FREE_NCCI 0x26
+#define RECEIVE_RELEASE 0x26
+#define RECEIVE_TASK_READY 0x31
+#define RECEIVE_DEBUGMSG 0x71
+#define RECEIVE_POLLDWORD 0x75
+
+/* Operation constants */
+
+#define WRITE_REGISTER 0x00
+#define READ_REGISTER 0x01
+
+/* Port offsets in I/O space */
+
+#define B1_READ 0x00
+#define B1_WRITE 0x01
+#define B1_INSTAT 0x02
+#define B1_OUTSTAT 0x03
+#define B1_ANALYSE 0x04
+#define B1_REVISION 0x05
+#define B1_RESET 0x10
+
+#define T1_FASTLINK 0x00
+#define T1_SLOWLINK 0x08
+
+#define T1_READ B1_READ
+#define T1_WRITE B1_WRITE
+#define T1_INSTAT B1_INSTAT
+#define T1_OUTSTAT B1_OUTSTAT
+#define T1_IRQENABLE 0x05
+#define T1_FIFOSTAT 0x06
+#define T1_RESETLINK 0x10
+#define T1_ANALYSE 0x11
+#define T1_IRQMASTER 0x12
+#define T1_IDENT 0x17
+#define T1_RESETBOARD 0x1f
+
+#define T1F_IREADY 0x01
+#define T1F_IHALF 0x02
+#define T1F_IFULL 0x04
+#define T1F_IEMPTY 0x08
+#define T1F_IFLAGS 0xf0
+
+#define T1F_OREADY 0x10
+#define T1F_OHALF 0x20
+#define T1F_OEMPTY 0x40
+#define T1F_OFULL 0x80
+#define T1F_OFLAGS 0xf0
+
+#define FIFO_OUTBSIZE 256
+#define FIFO_INPBSIZE 512
+
+#define HEMA_VERSION_ID 0
+#define HEMA_PAL_ID 0
+
+/*
+// S5933 DMA controller register offsets in memory, and bitmasks.
+*/
+
+#define AMCC_RXPTR 0x24
+#define AMCC_RXLEN 0x28
+#define AMCC_TXPTR 0x2c
+#define AMCC_TXLEN 0x30
+
+#define AMCC_INTCSR 0x38
+#define EN_READ_TC_INT 0x00008000
+#define EN_WRITE_TC_INT 0x00004000
+#define EN_TX_TC_INT EN_READ_TC_INT
+#define EN_RX_TC_INT EN_WRITE_TC_INT
+#define AVM_FLAG 0x30000000
+
+#define ANY_S5933_INT 0x00800000
+#define READ_TC_INT 0x00080000
+#define WRITE_TC_INT 0x00040000
+#define TX_TC_INT READ_TC_INT
+#define RX_TC_INT WRITE_TC_INT
+#define MASTER_ABORT_INT 0x00100000
+#define TARGET_ABORT_INT 0x00200000
+#define BUS_MASTER_INT 0x00200000
+#define ALL_INT 0x000c0000
+
+#define AMCC_MCSR 0x3c
+#define A2P_HI_PRIORITY 0x00000100
+#define EN_A2P_TRANSFERS 0x00000400
+#define P2A_HI_PRIORITY 0x00001000
+#define EN_P2A_TRANSFERS 0x00004000
+#define RESET_A2P_FLAGS 0x04000000
+#define RESET_P2A_FLAGS 0x02000000
+
+/*
+// (B1IO_WAIT_MAX * B1IO_WAIT_DLY) is the max wait in us for the card
+// to become ready after an I/O operation. The default is 1 ms.
+*/
+
+#define B1IO_WAIT_MAX 1000
+#define B1IO_WAIT_DLY 1
+
+/*
+// b1io_outp
+// Diagnostic output routine, returns the written value via
+// the device's analysis register.
+//
+// b1io_rx_full
+// Returns nonzero if data is readable from the card via the
+// I/O ports.
+//
+// b1io_tx_empty
+// Returns nonzero if data can be written to the card via the
+// I/O ports.
+*/
+
+static __inline u_int8_t b1io_outp(iavc_softc_t *sc, int off, u_int8_t val)
+{
+ bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, off, val);
+ DELAY(1);
+ return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_ANALYSE);
+}
+
+static __inline int b1io_rx_full(iavc_softc_t *sc)
+{
+ u_int8_t val = bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_INSTAT);
+ return (val & 0x01);
+}
+
+static __inline int b1io_tx_empty(iavc_softc_t *sc)
+{
+ u_int8_t val = bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_OUTSTAT);
+ return (val & 0x01);
+}
+
+/*
+// b1io_{get,put}_{byte,word}
+// Routines to read and write the device I/O registers byte- or
+// wordwise.
+//
+// b1io_{get,put}_slice
+// Routines to read and write sequential bytes to the device
+// I/O registers.
+*/
+
+static __inline u_int8_t b1io_get_byte(iavc_softc_t *sc)
+{
+ int spin = 0;
+ while (!b1io_rx_full(sc) && spin < B1IO_WAIT_MAX) {
+ spin++; DELAY(B1IO_WAIT_DLY);
+ }
+ if (b1io_rx_full(sc))
+ return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_READ);
+ printf("iavc%d: rx not completed\n", sc->sc_unit);
+ return 0xff;
+}
+
+static __inline int b1io_put_byte(iavc_softc_t *sc, u_int8_t val)
+{
+ int spin = 0;
+ while (!b1io_tx_empty(sc) && spin < B1IO_WAIT_MAX) {
+ spin++; DELAY(B1IO_WAIT_DLY);
+ }
+ if (b1io_tx_empty(sc)) {
+ bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, B1_WRITE, val);
+ return 0;
+ }
+ printf("iavc%d: tx not emptied\n", sc->sc_unit);
+ return -1;
+}
+
+static __inline int b1io_save_put_byte(iavc_softc_t *sc, u_int8_t val)
+{
+ int spin = 0;
+ while (!b1io_tx_empty(sc) && spin < B1IO_WAIT_MAX) {
+ spin++; DELAY(B1IO_WAIT_DLY);
+ }
+ if (b1io_tx_empty(sc)) {
+ b1io_outp(sc, B1_WRITE, val);
+ return 0;
+ }
+ printf("iavc%d: tx not emptied\n", sc->sc_unit);
+ return -1;
+}
+
+static __inline u_int32_t b1io_get_word(iavc_softc_t *sc)
+{
+ u_int32_t val = 0;
+ val |= b1io_get_byte(sc);
+ val |= (b1io_get_byte(sc) << 8);
+ val |= (b1io_get_byte(sc) << 16);
+ val |= (b1io_get_byte(sc) << 24);
+ return val;
+}
+
+static __inline void b1io_put_word(iavc_softc_t *sc, u_int32_t val)
+{
+ b1io_put_byte(sc, (val & 0xff));
+ b1io_put_byte(sc, (val >> 8) & 0xff);
+ b1io_put_byte(sc, (val >> 16) & 0xff);
+ b1io_put_byte(sc, (val >> 24) & 0xff);
+}
+
+static __inline int b1io_get_slice(iavc_softc_t *sc, u_int8_t *dp)
+{
+ int len, i;
+ len = i = b1io_get_word(sc);
+ while (i--) *dp++ = b1io_get_byte(sc);
+ return len;
+}
+
+static __inline void b1io_put_slice(iavc_softc_t *sc, u_int8_t *dp, int len)
+{
+ b1io_put_word(sc, len);
+ while (len--) b1io_put_byte(sc, *dp++);
+}
+
+/*
+// b1io_{read,write}_reg
+// Routines to read and write the device registers via the I/O
+// ports.
+*/
+
+static __inline u_int32_t b1io_read_reg(iavc_softc_t *sc, int reg)
+{
+ b1io_put_byte(sc, READ_REGISTER);
+ b1io_put_word(sc, reg);
+ return b1io_get_word(sc);
+}
+
+static __inline u_int32_t b1io_write_reg(iavc_softc_t *sc, int reg, u_int32_t val)
+{
+ b1io_put_byte(sc, WRITE_REGISTER);
+ b1io_put_word(sc, reg);
+ b1io_put_word(sc, val);
+ return b1io_get_word(sc);
+}
+
+/*
+// t1io_outp
+// I/O port write operation for the T1, which does not seem
+// to have the analysis port.
+*/
+
+static __inline void t1io_outp(iavc_softc_t *sc, int off, u_int8_t val)
+{
+ bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, off, val);
+}
+
+static __inline u_int8_t t1io_inp(iavc_softc_t *sc, int off)
+{
+ return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, off);
+}
+
+static __inline int t1io_isfastlink(iavc_softc_t *sc)
+{
+ return ((bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, T1_IDENT) & ~0x82) == 1);
+}
+
+static __inline u_int8_t t1io_fifostatus(iavc_softc_t *sc)
+{
+ return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, T1_FIFOSTAT);
+}
+
+static __inline int t1io_get_slice(iavc_softc_t *sc, u_int8_t *dp)
+{
+ int len, i;
+ len = i = b1io_get_word(sc);
+ if (t1io_isfastlink(sc)) {
+ int status;
+ while (i) {
+ status = t1io_fifostatus(sc) & (T1F_IREADY|T1F_IHALF);
+ if (i >= FIFO_INPBSIZE) status |= T1F_IFULL;
+
+ switch (status) {
+ case T1F_IREADY|T1F_IHALF|T1F_IFULL:
+ bus_space_read_multi_1(sc->sc_io_bt, sc->sc_io_bh,
+ T1_READ, dp, FIFO_INPBSIZE);
+ dp += FIFO_INPBSIZE;
+ i -= FIFO_INPBSIZE;
+ break;
+
+ case T1F_IREADY|T1F_IHALF:
+ bus_space_read_multi_1(sc->sc_io_bt, sc->sc_io_bh,
+ T1_READ, dp, i);
+ dp += i;
+ i = 0;
+ break;
+
+ default:
+ *dp++ = b1io_get_byte(sc);
+ i--;
+ }
+ }
+ } else { /* not fastlink */
+ if (i--) *dp++ = b1io_get_byte(sc);
+ }
+ return len;
+}
+
+static __inline void t1io_put_slice(iavc_softc_t *sc, u_int8_t *dp, int len)
+{
+ int i = len;
+ b1io_put_word(sc, i);
+ if (t1io_isfastlink(sc)) {
+ int status;
+ while (i) {
+ status = t1io_fifostatus(sc) & (T1F_OREADY|T1F_OHALF);
+ if (i >= FIFO_OUTBSIZE) status |= T1F_OFULL;
+
+ switch (status) {
+ case T1F_OREADY|T1F_OHALF|T1F_OFULL:
+ bus_space_write_multi_1(sc->sc_io_bt, sc->sc_io_bh,
+ T1_WRITE, dp, FIFO_OUTBSIZE);
+ dp += FIFO_OUTBSIZE;
+ i -= FIFO_OUTBSIZE;
+ break;
+
+ case T1F_OREADY|T1F_OHALF:
+ bus_space_write_multi_1(sc->sc_io_bt, sc->sc_io_bh,
+ T1_WRITE, dp, i);
+ dp += i;
+ i = 0;
+ break;
+
+ default:
+ b1io_put_byte(sc, *dp++);
+ i--;
+ }
+ }
+ } else {
+ while (i--) b1io_put_byte(sc, *dp++);
+ }
+}
+
+/*
+// An attempt to bring it all together:
+// ------------------------------------
+//
+// iavc_{read,write}_reg
+// Routines to access the device registers via the I/O port.
+//
+// iavc_{read,write}_port
+// Routines to access the device I/O ports.
+//
+// iavc_tx_empty, iavc_rx_full
+// Routines to check when the device has drained the last written
+// byte, or produced a full byte to read.
+//
+// iavc_{get,put}_byte
+// Routines to read/write byte values to the device via the I/O port.
+//
+// iavc_{get,put}_word
+// Routines to read/write 32-bit words to the device via the I/O port.
+//
+// iavc_{get,put}_slice
+// Routines to read/write {length, data} pairs to the device via the
+// ubiquituous I/O port. Uses the HEMA FIFO on a T1.
+*/
+
+#define iavc_read_reg(sc, reg) b1io_read_reg(sc, reg)
+#define iavc_write_reg(sc, reg, val) b1io_write_reg(sc, reg, val)
+
+#define iavc_read_port(sc, port) \
+ bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, (port))
+#define iavc_write_port(sc, port, val) \
+ bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, (port), (val))
+
+#define iavc_tx_empty(sc) b1io_tx_empty(sc)
+#define iavc_rx_full(sc) b1io_rx_full(sc)
+
+#define iavc_get_byte(sc) b1io_get_byte(sc)
+#define iavc_put_byte(sc, val) b1io_put_byte(sc, val)
+#define iavc_get_word(sc) b1io_get_word(sc)
+#define iavc_put_word(sc, val) b1io_put_word(sc, val)
+
+static __inline u_int32_t iavc_get_slice(iavc_softc_t *sc, u_int8_t *dp)
+{
+ if (sc->sc_t1) return t1io_get_slice(sc, dp);
+ else return b1io_get_slice(sc, dp);
+}
+
+static __inline void iavc_put_slice(iavc_softc_t *sc, u_int8_t *dp, int len)
+{
+ if (sc->sc_t1) t1io_put_slice(sc, dp, len);
+ else b1io_put_slice(sc, dp, len);
+}
+
+/*
+// iavc_handle_intr
+// Interrupt handler, called by the bus specific interrupt routine
+// in iavc_<bustype>.c module.
+//
+// iavc_load
+// CAPI callback. Resets device and loads firmware.
+//
+// iavc_register
+// CAPI callback. Registers an application id.
+//
+// iavc_release
+// CAPI callback. Releases an application id.
+//
+// iavc_send
+// CAPI callback. Sends a CAPI message. A B3_DATA_REQ message has
+// m_next point to a data mbuf.
+*/
+
+extern void iavc_handle_intr(iavc_softc_t *);
+extern int iavc_load(capi_softc_t *, int, u_int8_t *);
+extern int iavc_register(capi_softc_t *, int, int);
+extern int iavc_release(capi_softc_t *, int);
+extern int iavc_send(capi_softc_t *, struct mbuf *);
+
+extern void b1isa_setup_irq(struct iavc_softc *sc);
+
+#endif /* _CAPI_IAVC_H_ */
diff --git a/sys/i4b/capi/iavc/iavc_card.c b/sys/i4b/capi/iavc/iavc_card.c
new file mode 100644
index 000000000000..831dc6870424
--- /dev/null
+++ b/sys/i4b/capi/iavc/iavc_card.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * capi/iavc/iavc_card.c
+ * The AVM ISDN controllers' card specific support routines.
+ *
+ * $FreeBSD$
+ */
+
+#include "iavc.h"
+#include "i4bcapi.h"
+#include "pci.h"
+
+#if (NIAVC > 0) && (NI4BCAPI > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <machine/clock.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/capi/capi.h>
+
+#include <i4b/capi/iavc/iavc.h>
+
+/*
+// AVM B1 (active BRI, PIO mode)
+*/
+
+int b1_detect(iavc_softc_t *sc)
+{
+ if ((iavc_read_port(sc, B1_INSTAT) & 0xfc) ||
+ (iavc_read_port(sc, B1_OUTSTAT) & 0xfc))
+ return (1);
+
+ b1io_outp(sc, B1_INSTAT, 0x02);
+ b1io_outp(sc, B1_OUTSTAT, 0x02);
+ if ((iavc_read_port(sc, B1_INSTAT) & 0xfe) != 2 ||
+ (iavc_read_port(sc, B1_OUTSTAT) & 0xfe) != 2)
+ return (2);
+
+ b1io_outp(sc, B1_INSTAT, 0x00);
+ b1io_outp(sc, B1_OUTSTAT, 0x00);
+ if ((iavc_read_port(sc, B1_INSTAT) & 0xfe) ||
+ (iavc_read_port(sc, B1_OUTSTAT) & 0xfe))
+ return (3);
+
+ return (0); /* found */
+}
+
+void b1_disable_irq(iavc_softc_t *sc)
+{
+ b1io_outp(sc, B1_INSTAT, 0x00);
+}
+
+void b1_reset(iavc_softc_t *sc)
+{
+ b1io_outp(sc, B1_RESET, 0);
+ DELAY(55*2*1000);
+
+ b1io_outp(sc, B1_RESET, 1);
+ DELAY(55*2*1000);
+
+ b1io_outp(sc, B1_RESET, 0);
+ DELAY(55*2*1000);
+}
+
+/*
+// Newer PCI-based B1's, and T1's, supports DMA
+*/
+
+int b1dma_detect(iavc_softc_t *sc)
+{
+ AMCC_WRITE(sc, AMCC_MCSR, 0);
+ DELAY(10*1000);
+ AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000);
+ DELAY(10*1000);
+ AMCC_WRITE(sc, AMCC_MCSR, 0);
+ DELAY(42*1000);
+
+ AMCC_WRITE(sc, AMCC_RXLEN, 0);
+ AMCC_WRITE(sc, AMCC_TXLEN, 0);
+ sc->sc_csr = 0;
+ AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
+
+ if (AMCC_READ(sc, AMCC_INTCSR) != 0)
+ return 1;
+
+ AMCC_WRITE(sc, AMCC_RXPTR, 0xffffffff);
+ AMCC_WRITE(sc, AMCC_TXPTR, 0xffffffff);
+ if ((AMCC_READ(sc, AMCC_RXPTR) != 0xfffffffc) ||
+ (AMCC_READ(sc, AMCC_TXPTR) != 0xfffffffc))
+ return 2;
+
+ AMCC_WRITE(sc, AMCC_RXPTR, 0);
+ AMCC_WRITE(sc, AMCC_TXPTR, 0);
+ if ((AMCC_READ(sc, AMCC_RXPTR) != 0) ||
+ (AMCC_READ(sc, AMCC_TXPTR) != 0))
+ return 3;
+
+ iavc_write_port(sc, 0x10, 0x00);
+ iavc_write_port(sc, 0x07, 0x00);
+
+ iavc_write_port(sc, 0x02, 0x02);
+ iavc_write_port(sc, 0x03, 0x02);
+
+ if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x02) ||
+ (iavc_read_port(sc, 0x03) != 0x03))
+ return 4;
+
+ iavc_write_port(sc, 0x02, 0x00);
+ iavc_write_port(sc, 0x03, 0x00);
+
+ if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x00) ||
+ (iavc_read_port(sc, 0x03) != 0x01))
+ return 5;
+
+ return (0); /* found */
+}
+
+void b1dma_reset(iavc_softc_t *sc)
+{
+ int s = SPLI4B();
+
+ sc->sc_csr = 0;
+ AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
+ AMCC_WRITE(sc, AMCC_MCSR, 0);
+ AMCC_WRITE(sc, AMCC_RXLEN, 0);
+ AMCC_WRITE(sc, AMCC_TXLEN, 0);
+
+ iavc_write_port(sc, 0x10, 0x00); /* XXX magic numbers from */
+ iavc_write_port(sc, 0x07, 0x00); /* XXX the linux driver */
+
+ splx(s);
+
+ AMCC_WRITE(sc, AMCC_MCSR, 0);
+ DELAY(10 * 1000);
+ AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000);
+ DELAY(10 * 1000);
+ AMCC_WRITE(sc, AMCC_MCSR, 0);
+ DELAY(42 * 1000);
+}
+
+/*
+// AVM T1 (active PRI)
+*/
+
+/* XXX how do these differ from b1io_{read,write}_reg()? XXX */
+
+static int b1dma_tx_empty(int iobase)
+{ return inb(iobase + 3) & 1; }
+
+static int b1dma_rx_full(int iobase)
+{ return inb(iobase + 2) & 1; }
+
+static int b1dma_tolink(iavc_softc_t *sc, void *buf, int len)
+{
+ volatile int spin;
+ char *s = (char*) buf;
+ while (len--) {
+ spin = 0;
+ while (!b1dma_tx_empty(sc->sc_iobase) && spin < 100000)
+ spin++;
+ if (!b1dma_tx_empty(sc->sc_iobase))
+ return -1;
+ t1io_outp(sc, 1, *s++);
+ }
+ return 0;
+}
+
+static int b1dma_fromlink(iavc_softc_t *sc, void *buf, int len)
+{
+ volatile int spin;
+ char *s = (char*) buf;
+ while (len--) {
+ spin = 0;
+ while (!b1dma_rx_full(sc->sc_iobase) && spin < 100000)
+ spin++;
+ if (!b1dma_rx_full(sc->sc_iobase))
+ return -1;
+ *s++ = t1io_inp(sc, 0);
+ }
+ return 0;
+}
+
+static int WriteReg(iavc_softc_t *sc, u_int32_t reg, u_int8_t val)
+{
+ u_int8_t cmd = 0;
+ if (b1dma_tolink(sc, &cmd, 1) == 0 &&
+ b1dma_tolink(sc, &reg, 4) == 0) {
+ u_int32_t tmp = val;
+ return b1dma_tolink(sc, &tmp, 4);
+ }
+ return -1;
+}
+
+static u_int8_t ReadReg(iavc_softc_t *sc, u_int32_t reg)
+{
+ u_int8_t cmd = 1;
+ if (b1dma_tolink(sc, &cmd, 1) == 0 &&
+ b1dma_tolink(sc, &reg, 4) == 0) {
+ u_int32_t tmp;
+ if (b1dma_fromlink(sc, &tmp, 4) == 0)
+ return (u_int8_t) tmp;
+ }
+ return 0xff;
+}
+
+int t1_detect(iavc_softc_t *sc)
+{
+ int ret = b1dma_detect(sc);
+ if (ret) return ret;
+
+ if ((WriteReg(sc, 0x80001000, 0x11) != 0) ||
+ (WriteReg(sc, 0x80101000, 0x22) != 0) ||
+ (WriteReg(sc, 0x80201000, 0x33) != 0) ||
+ (WriteReg(sc, 0x80301000, 0x44) != 0))
+ return 6;
+
+ if ((ReadReg(sc, 0x80001000) != 0x11) ||
+ (ReadReg(sc, 0x80101000) != 0x22) ||
+ (ReadReg(sc, 0x80201000) != 0x33) ||
+ (ReadReg(sc, 0x80301000) != 0x44))
+ return 7;
+
+ if ((WriteReg(sc, 0x80001000, 0x55) != 0) ||
+ (WriteReg(sc, 0x80101000, 0x66) != 0) ||
+ (WriteReg(sc, 0x80201000, 0x77) != 0) ||
+ (WriteReg(sc, 0x80301000, 0x88) != 0))
+ return 8;
+
+ if ((ReadReg(sc, 0x80001000) != 0x55) ||
+ (ReadReg(sc, 0x80101000) != 0x66) ||
+ (ReadReg(sc, 0x80201000) != 0x77) ||
+ (ReadReg(sc, 0x80301000) != 0x88))
+ return 9;
+
+ return 0; /* found */
+}
+
+void t1_disable_irq(iavc_softc_t *sc)
+{
+ iavc_write_port(sc, T1_IRQMASTER, 0x00);
+}
+
+void t1_reset(iavc_softc_t *sc)
+{
+ b1_reset(sc);
+ iavc_write_port(sc, B1_INSTAT, 0x00);
+ iavc_write_port(sc, B1_OUTSTAT, 0x00);
+ iavc_write_port(sc, T1_IRQMASTER, 0x00);
+ iavc_write_port(sc, T1_RESETBOARD, 0x0f);
+}
+
+#endif
diff --git a/sys/i4b/capi/iavc/iavc_isa.c b/sys/i4b/capi/iavc/iavc_isa.c
new file mode 100644
index 000000000000..96ea1c91bc96
--- /dev/null
+++ b/sys/i4b/capi/iavc/iavc_isa.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2001 Hellmuth Michaelis. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "iavc.h"
+#include "i4bcapi.h"
+
+#if (NIAVC > 0) && (NI4BCAPI > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <machine/clock.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <isa/isavar.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/capi/capi.h>
+
+#include <i4b/capi/iavc/iavc.h>
+
+/* ISA driver linkage */
+
+static void iavc_isa_intr(iavc_softc_t *sc);
+static int iavc_isa_probe(device_t dev);
+static int iavc_isa_attach(device_t dev);
+
+static device_method_t iavc_isa_methods[] =
+{
+ DEVMETHOD(device_probe, iavc_isa_probe),
+ DEVMETHOD(device_attach, iavc_isa_attach),
+ { 0, 0 }
+};
+
+static driver_t iavc_isa_driver =
+{
+ "iavc",
+ iavc_isa_methods,
+ 0
+};
+
+static devclass_t iavc_isa_devclass;
+
+DRIVER_MODULE(iavc, isa, iavc_isa_driver, iavc_isa_devclass, 0, 0);
+
+#define B1_IOLENGTH 0x20
+
+static int b1_irq_table[] =
+{0, 0, 0, 192, 32, 160, 96, 224, 0, 64, 80, 208, 48, 0, 0, 112};
+/* 3 4 5 6 7 9 10 11 12 15 */
+
+/*---------------------------------------------------------------------------*
+ * device probe
+ *---------------------------------------------------------------------------*/
+
+static int
+iavc_isa_probe(device_t dev)
+{
+ struct iavc_softc *sc;
+ int ret = ENXIO;
+ int unit = device_get_unit(dev);
+
+ if(isa_get_vendorid(dev)) /* no PnP probes here */
+ return ENXIO;
+
+ /* check max unit range */
+
+ if (unit >= IAVC_MAXUNIT)
+ {
+ printf("iavc%d: too many units\n", unit);
+ return(ENXIO);
+ }
+
+ sc = iavc_find_sc(unit); /* get softc */
+
+ sc->sc_unit = unit;
+
+ if (!(sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0UL, ~0UL, B1_IOLENGTH, RF_ACTIVE)))
+ {
+ printf("iavc%d: can't allocate io region\n", unit);
+ return(ENXIO);
+ }
+
+ sc->sc_iobase = rman_get_start(sc->sc_resources.io_base[0]);
+
+ switch(sc->sc_iobase)
+ {
+ case 0x150:
+ case 0x250:
+ case 0x300:
+ case 0x340:
+ break;
+ default:
+ printf("iavc%d: ERROR, invalid i/o base addr 0x%x configured!\n", sc->sc_unit, sc->sc_iobase);
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ sc->sc_resources.io_rid[0],
+ sc->sc_resources.io_base[0]);
+ return(ENXIO);
+ }
+
+ sc->sc_io_bt = rman_get_bustag(sc->sc_resources.io_base[0]);
+ sc->sc_io_bh = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ /* setup characteristics */
+
+ sc->sc_t1 = FALSE;
+ sc->sc_dma = FALSE;
+
+ sc->sc_capi.card_type = CARD_TYPEC_AVM_B1_ISA;
+ sc->sc_capi.sc_nbch = 2;
+
+ b1_reset(sc);
+ DELAY(100);
+
+ ret = b1_detect(sc);
+
+ if(ret)
+ {
+ printf("iavc%d: no card ? b1_detect returns 0x02x\n", sc->sc_unit, ret);
+ return(ENXIO);
+ }
+
+ DELAY(100);
+
+ b1_reset(sc);
+
+ DELAY(100);
+
+ if(bootverbose)
+ {
+ printf("iavc%d: class = 0x%02x, rev = 0x%02x\n", sc->sc_unit,
+ iavc_read_port(sc, B1_ANALYSE),
+ iavc_read_port(sc, B1_REVISION));
+ }
+
+ device_set_desc(dev, "AVM B1 ISA");
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * attach
+ *---------------------------------------------------------------------------*/
+static int
+iavc_isa_attach(device_t dev)
+{
+ struct iavc_softc *sc;
+ void *ih = 0;
+ int unit = device_get_unit(dev);
+ int irq;
+
+ sc = iavc_find_sc(unit); /* get softc */
+
+ sc->sc_resources.irq_rid = 0;
+
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0UL, ~0UL, 1, RF_ACTIVE)))
+ {
+ printf("iavc%d: can't allocate irq\n",unit);
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ sc->sc_resources.io_rid[0],
+ sc->sc_resources.io_base[0]);
+ return(ENXIO);
+ }
+
+ irq = rman_get_start(sc->sc_resources.irq);
+
+ if(b1_irq_table[irq] == 0)
+ {
+ printf("iavc%d: ERROR, illegal irq %d configured!\n",unit, irq);
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ sc->sc_resources.io_rid[0],
+ sc->sc_resources.io_base[0]);
+ bus_release_resource(dev, SYS_RES_IRQ,
+ sc->sc_resources.irq_rid,
+ sc->sc_resources.irq);
+ return(ENXIO);
+ }
+
+ memset(&sc->sc_txq, 0, sizeof(struct ifqueue));
+ sc->sc_txq.ifq_maxlen = sc->sc_capi.sc_nbch * 4;
+
+#if defined (__FreeBSD__) && __FreeBSD__ > 4
+ mtx_init(&sc->sc_txq.ifq_mtx, "i4b_ivac_isa", MTX_DEF);
+#endif
+
+ sc->sc_intr = FALSE;
+ sc->sc_state = IAVC_DOWN;
+ sc->sc_blocked = FALSE;
+
+ /* setup capi link */
+
+ sc->sc_capi.load = iavc_load;
+ sc->sc_capi.reg_appl = iavc_register;
+ sc->sc_capi.rel_appl = iavc_release;
+ sc->sc_capi.send = iavc_send;
+ sc->sc_capi.ctx = (void*) sc;
+
+ if (capi_ll_attach(&sc->sc_capi))
+ {
+ printf("iavc%d: capi attach failed\n", unit);
+ return(ENXIO);
+ }
+
+ /* setup the interrupt */
+
+ if(bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
+ (void(*)(void*))iavc_isa_intr,
+ sc, &ih))
+ {
+ printf("iavc%d: irq setup failed\n", unit);
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ sc->sc_resources.io_rid[0],
+ sc->sc_resources.io_base[0]);
+ bus_release_resource(dev, SYS_RES_IRQ,
+ sc->sc_resources.irq_rid,
+ sc->sc_resources.irq);
+ return(ENXIO);
+ }
+
+ /* the board is now ready to be loaded */
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * setup interrupt
+ *---------------------------------------------------------------------------*/
+void
+b1isa_setup_irq(struct iavc_softc *sc)
+{
+ int irq = rman_get_start(sc->sc_resources.irq);
+
+ if(bootverbose)
+ printf("iavc%d: using irq %d\n", sc->sc_unit, irq);
+
+ /* enable the interrupt */
+
+ b1io_outp(sc, B1_INSTAT, 0x00);
+ b1io_outp(sc, B1_RESET, b1_irq_table[irq]);
+ b1io_outp(sc, B1_INSTAT, 0x02);
+}
+
+/*---------------------------------------------------------------------------*
+ * IRQ handler
+ *---------------------------------------------------------------------------*/
+static void
+iavc_isa_intr(struct iavc_softc *sc)
+{
+ iavc_handle_intr(sc);
+}
+
+#endif
diff --git a/sys/i4b/capi/iavc/iavc_pci.c b/sys/i4b/capi/iavc/iavc_pci.c
new file mode 100644
index 000000000000..5579a3c27b7a
--- /dev/null
+++ b/sys/i4b/capi/iavc/iavc_pci.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * capi/iavc/iavc_pci.c
+ * The AVM ISDN controllers' PCI bus attachment handling.
+ *
+ * $FreeBSD$
+ */
+
+#include "iavc.h"
+#include "i4bcapi.h"
+#include "pci.h"
+
+#if (NIAVC > 0) && (NI4BCAPI > 0) && (NPCI > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <machine/clock.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <pci/pcireg.h>
+#include <pci/pcivar.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_l3l4.h>
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/capi/capi.h>
+
+#include <i4b/capi/iavc/iavc.h>
+
+/* PCI device ids */
+
+#define PCI_AVM_VID 0x1244
+#define PCI_AVMT1_DID 0x1200
+#define PCI_AVMB1_DID 0x0700
+
+/* PCI driver linkage */
+
+static void iavc_pci_intr(iavc_softc_t *sc);
+static int iavc_pci_probe(device_t dev);
+static int iavc_pci_attach(device_t dev);
+
+static device_method_t iavc_pci_methods[] =
+{
+ DEVMETHOD(device_probe, iavc_pci_probe),
+ DEVMETHOD(device_attach, iavc_pci_attach),
+ { 0, 0 }
+};
+
+static driver_t iavc_pci_driver =
+{
+ "iavc",
+ iavc_pci_methods,
+ 0
+};
+
+static devclass_t iavc_pci_devclass;
+
+DRIVER_MODULE(iavc, pci, iavc_pci_driver, iavc_pci_devclass, 0, 0);
+
+/* Driver soft contexts */
+
+iavc_softc_t iavc_sc[IAVC_MAXUNIT];
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+
+static int
+iavc_pci_probe(device_t dev)
+{
+ u_int16_t did = pci_get_device(dev);
+ u_int16_t vid = pci_get_vendor(dev);
+
+ if ((vid == PCI_AVM_VID) && (did == PCI_AVMT1_DID)) {
+ device_set_desc(dev, "AVM T1 PCI");
+ } else if ((vid == PCI_AVM_VID) && (did == PCI_AVMB1_DID)) {
+ device_set_desc(dev, "AVM B1 PCI");
+ } else {
+ return(ENXIO);
+ }
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ *---------------------------------------------------------------------------*/
+
+static int
+iavc_pci_attach(device_t dev)
+{
+ struct iavc_softc *sc;
+ void *ih = 0;
+ u_int16_t did = pci_get_device(dev);
+ int unit = device_get_unit(dev), ret;
+
+ /* check max unit range */
+
+ if (unit >= IAVC_MAXUNIT) {
+ printf("iavc%d: too many units\n", unit);
+ return(ENXIO);
+ }
+
+ sc = iavc_find_sc(unit); /* get softc */
+
+ sc->sc_unit = unit;
+
+ /* use the i/o mapped base address */
+
+ sc->sc_resources.io_rid[0] = 0x14;
+
+ if (!(sc->sc_resources.io_base[0] =
+ bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->sc_resources.io_rid[0],
+ 0UL, ~0UL, 1, RF_ACTIVE))) {
+ printf("iavc%d: can't allocate io region\n", unit);
+ return(ENXIO);
+ }
+
+ sc->sc_iobase = rman_get_start(sc->sc_resources.io_base[0]);
+ sc->sc_io_bt = rman_get_bustag(sc->sc_resources.io_base[0]);
+ sc->sc_io_bh = rman_get_bushandle(sc->sc_resources.io_base[0]);
+
+ /* use the memory mapped DMA controller */
+
+ sc->sc_resources.mem_rid = 0x10;
+
+ if (!(sc->sc_resources.mem =
+ bus_alloc_resource(dev, SYS_RES_MEMORY,
+ &sc->sc_resources.mem_rid,
+ 0UL, ~0UL, 1, RF_ACTIVE))) {
+ printf("iavc%d: can't allocate memory region\n", unit);
+ return(ENXIO);
+ }
+
+ sc->sc_membase = rman_get_start(sc->sc_resources.mem);
+ sc->sc_mem_bt = rman_get_bustag(sc->sc_resources.mem);
+ sc->sc_mem_bh = rman_get_bushandle(sc->sc_resources.mem);
+
+ /* do some detection */
+
+ sc->sc_t1 = FALSE;
+ sc->sc_dma = FALSE;
+ b1dma_reset(sc);
+
+ if (did == PCI_AVMT1_DID) {
+ sc->sc_capi.card_type = CARD_TYPEC_AVM_T1_PCI;
+ sc->sc_capi.sc_nbch = 30;
+ ret = t1_detect(sc);
+ if (ret) {
+ if (ret < 6) {
+ printf("iavc%d: no card detected?\n", sc->sc_unit);
+ } else {
+ printf("iavc%d: black box not on\n", sc->sc_unit);
+ }
+ return(ENXIO);
+ } else {
+ sc->sc_dma = TRUE;
+ sc->sc_t1 = TRUE;
+ }
+
+ } else if (did == PCI_AVMB1_DID) {
+ sc->sc_capi.card_type = CARD_TYPEC_AVM_B1_PCI;
+ sc->sc_capi.sc_nbch = 2;
+ ret = b1dma_detect(sc);
+ if (ret) {
+ ret = b1_detect(sc);
+ if (ret) {
+ printf("iavc%d: no card detected?\n", sc->sc_unit);
+ return(ENXIO);
+ }
+ } else {
+ sc->sc_dma = TRUE;
+ }
+ }
+
+ if (sc->sc_dma) b1dma_reset(sc);
+#if 0
+ if (sc->sc_t1) t1_reset(sc);
+ else b1_reset(sc);
+#endif
+
+ /* of course we need an interrupt */
+
+ sc->sc_resources.irq_rid = 0x00;
+
+ if(!(sc->sc_resources.irq =
+ bus_alloc_resource(dev, SYS_RES_IRQ,
+ &sc->sc_resources.irq_rid,
+ 0UL, ~0UL, 1, RF_SHAREABLE|RF_ACTIVE))) {
+ printf("iavc%d: can't allocate irq\n",unit);
+ return(ENXIO);
+ }
+
+ /* finalize our own context */
+
+ memset(&sc->sc_txq, 0, sizeof(struct ifqueue));
+ sc->sc_txq.ifq_maxlen = sc->sc_capi.sc_nbch * 4;
+
+#if defined (__FreeBSD__) && __FreeBSD__ > 4
+ mtx_init(&sc->sc_txq.ifq_mtx, "i4b_ivac_pci", MTX_DEF);
+#endif
+
+ sc->sc_intr = FALSE;
+ sc->sc_state = IAVC_DOWN;
+ sc->sc_blocked = FALSE;
+
+ /* setup capi link */
+
+ sc->sc_capi.load = iavc_load;
+ sc->sc_capi.reg_appl = iavc_register;
+ sc->sc_capi.rel_appl = iavc_release;
+ sc->sc_capi.send = iavc_send;
+ sc->sc_capi.ctx = (void*) sc;
+
+ if (capi_ll_attach(&sc->sc_capi)) {
+ printf("iavc%d: capi attach failed\n", unit);
+ return(ENXIO);
+ }
+
+ /* setup the interrupt */
+
+ if(bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
+ (void(*)(void*))iavc_pci_intr,
+ sc, &ih)) {
+ printf("iavc%d: irq setup failed\n", unit);
+ return(ENXIO);
+ }
+
+ /* the board is now ready to be loaded */
+
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * IRQ handler
+ *---------------------------------------------------------------------------*/
+
+static void
+iavc_pci_intr(struct iavc_softc *sc)
+{
+ iavc_handle_intr(sc);
+}
+
+#endif
diff --git a/usr.sbin/i4b/man/i4bcapi.4 b/usr.sbin/i4b/man/i4bcapi.4
new file mode 100644
index 000000000000..cca62c060536
--- /dev/null
+++ b/usr.sbin/i4b/man/i4bcapi.4
@@ -0,0 +1,59 @@
+.\"
+.\" Copyright (c) 2001 Hellmuth Michaelis. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.\" last edit-date: [Fri May 25 09:38:45 2001]
+.\"
+.Dd May 21, 2001
+.Dt I4BCAPI 4
+.Os
+.Sh NAME
+.Nm i4bcapi
+.Nd CAPI driver for the isdn4bsd kernel part
+.Sh SYNOPSIS
+.Cd "device \*[q]i4bcapi\*[q]"
+.Sh DESCRIPTION
+.Nm
+is a CAPI driver for the
+.Em isdn4bsd
+package.
+It sits between layer\~4 of isdn4bsd and a driver for an active
+ISDN card; currently only the
+.Xr iavc 4
+driver for the AVM B1 and T1 family of active cards is supported.
+.Sh STANDARDS
+CAPI 2.0
+.Pq Pa http://www.capi.org/
+.Sh SEE ALSO
+.Xr iavc 4
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+device driver was written by
+.An Juha-Matti Liukkonen Aq jml@cubical.fi
+(Cubical Solutions Ltd, Finland).
+This manpage was written by
+.An Hellmuth Michaelis Aq hm@FreeBSD.org .
diff --git a/usr.sbin/i4b/man/iavc.4 b/usr.sbin/i4b/man/iavc.4
new file mode 100644
index 000000000000..575859bac1d6
--- /dev/null
+++ b/usr.sbin/i4b/man/iavc.4
@@ -0,0 +1,72 @@
+.\"
+.\" Copyright (c) 2001 Hellmuth Michaelis. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.\" last edit-date: [Fri May 25 09:45:35 2001]
+.\"
+.Dd May 22, 2001
+.Dt IAVC 4
+.Os
+.Sh NAME
+.Nm iavc
+.Nd isdn4bsd AVM B1/T1 driver
+.Sh SYNOPSIS
+.Cd "device iavc"
+.Pp
+NOTE:
+For the B1 ISA card
+.Pp
+.Bd -literal -offset indent
+hint.iavc.0.at="isa"
+hint.iavc.0.port="0x150"
+hint.iavc.0.irq="5"
+.Ed
+.Pp
+must be added to
+.Pa /boot/device.hints
+.Sh DESCRIPTION
+The
+.Nm
+driver is used to access the AVM family of active cards to the
+.Xr i4bcapi 4
+driver and the
+.Em isdn4bsd
+package.
+Currently the AVM B1 PCI, the AVM B1 ISA and the AVM T1 PCI
+cards are supported.
+.Sh STANDARDS
+CAPI 2.0
+.Pq Pa http://www.capi.org/
+.Sh SEE ALSO
+.Xr i4bcapi 4
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+device driver was written by
+.An Juha-Matti Liukkonen Aq jml@cubical.fi
+(Cubical Solutions Ltd, Finland).
+This manpage was written by
+.An Hellmuth Michaelis Aq hm@FreeBSD.org .