diff options
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, ®, 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, ®, 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 . |
