diff options
| author | cvs2svn <cvs2svn@FreeBSD.org> | 2001-05-27 23:14:28 +0000 | 
|---|---|---|
| committer | cvs2svn <cvs2svn@FreeBSD.org> | 2001-05-27 23:14:28 +0000 | 
| commit | 7b1532323ba008e721d70ac4da35c9e324c27d6c (patch) | |
| tree | 05b07205c79cd5cfb0f5ed46e87c972320592efb | |
| parent | 45c017f9e38e265d9d905746603d4bed5146c3ee (diff) | |
Notes
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 . | 
