summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcvs2svn <cvs2svn@FreeBSD.org>2000-10-30 14:49:27 +0000
committercvs2svn <cvs2svn@FreeBSD.org>2000-10-30 14:49:27 +0000
commit4cc01a5a9b96095be1eaab76a18ffdf868f4ee96 (patch)
tree0990600be3b5b619add9593e2dc7e95fd6ad5cd8
parent5c6ab3f47bc128e9725b235983fdaf82204ca86c (diff)
Notes
-rw-r--r--etc/rc.firewall6257
-rw-r--r--lib/csu/alpha/crti.S51
-rw-r--r--lib/csu/alpha/crtn.S43
-rw-r--r--sys/crypto/rijndael/rijndael.h3
-rw-r--r--sys/dev/awi/awi_wep.c528
-rw-r--r--sys/dev/awi/awi_wicfg.c625
-rw-r--r--sys/dev/usb/uscanner.c658
-rw-r--r--sys/i4b/layer1/i4b_l1lib.c76
-rw-r--r--sys/i4b/layer1/ifpi/i4b_ifpi_isac.c666
-rw-r--r--sys/i4b/layer1/ifpi/i4b_ifpi_l1.c244
-rw-r--r--sys/i4b/layer1/ifpi/i4b_ifpi_l1fsm.c517
-rw-r--r--sys/i4b/layer1/ifpnp/i4b_ifpnp_isac.c666
-rw-r--r--sys/i4b/layer1/ifpnp/i4b_ifpnp_l1.c244
-rw-r--r--sys/i4b/layer1/ifpnp/i4b_ifpnp_l1fsm.c517
-rw-r--r--sys/net/if_ieee80211.h171
15 files changed, 5266 insertions, 0 deletions
diff --git a/etc/rc.firewall6 b/etc/rc.firewall6
new file mode 100644
index 000000000000..df2d7a23c8f6
--- /dev/null
+++ b/etc/rc.firewall6
@@ -0,0 +1,257 @@
+############
+# Setup system for IPv6 firewall service.
+# $FreeBSD$
+
+# Suck in the configuration variables.
+if [ -z "${source_rc_confs_defined}" ]; then
+ if [ -r /etc/defaults/rc.conf ]; then
+ . /etc/defaults/rc.conf
+ source_rc_confs
+ elif [ -r /etc/rc.conf ]; then
+ . /etc/rc.conf
+ fi
+fi
+
+############
+# Define the firewall type in /etc/rc.conf. Valid values are:
+# open - will allow anyone in
+# client - will try to protect just this machine
+# simple - will try to protect a whole network
+# closed - totally disables IP services except via lo0 interface
+# UNKNOWN - disables the loading of firewall rules.
+# filename - will load the rules in the given filename (full path required)
+#
+# For ``client'' and ``simple'' the entries below should be customized
+# appropriately.
+
+############
+#
+# If you don't know enough about packet filtering, we suggest that you
+# take time to read this book:
+#
+# Building Internet Firewalls
+# Brent Chapman and Elizabeth Zwicky
+#
+# O'Reilly & Associates, Inc
+# ISBN 1-56592-124-0
+# http://www.ora.com/
+#
+# For a more advanced treatment of Internet Security read:
+#
+# Firewalls & Internet Security
+# Repelling the wily hacker
+# William R. Cheswick, Steven M. Bellowin
+#
+# Addison-Wesley
+# ISBN 0-201-6337-4
+# http://www.awl.com/
+#
+
+if [ -n "${1}" ]; then
+ ipv6_firewall_type="${1}"
+fi
+
+############
+# Set quiet mode if requested
+#
+case ${ipv6_firewall_quiet} in
+[Yy][Ee][Ss])
+ fw6cmd="/sbin/ip6fw -q"
+ ;;
+*)
+ fw6cmd="/sbin/ip6fw"
+ ;;
+esac
+
+############
+# Flush out the list before we begin.
+#
+${fw6cmd} -f flush
+
+############
+# If you just configured ipfw in the kernel as a tool to solve network
+# problems or you just want to disallow some particular kinds of traffic
+# then you will want to change the default policy to open. You can also
+# do this as your only action by setting the ipv6_firewall_type to ``open''.
+#
+# ${fw6cmd} add 65000 pass all from any to any
+
+############
+# Only in rare cases do you want to change these rules
+#
+${fw6cmd} add 100 pass all from any to any via lo0
+#
+# ND
+#
+# DAD
+${fw6cmd} add pass ipv6-icmp from ff02::/16 to ::
+${fw6cmd} add pass ipv6-icmp from :: to ff02::/16
+# RS, RA, NS, NA, redirect...
+${fw6cmd} add pass ipv6-icmp from fe80::/10 to fe80::/10
+${fw6cmd} add pass ipv6-icmp from fe80::/10 to ff02::/16
+
+
+# Prototype setups.
+#
+case ${ipv6_firewall_type} in
+[Oo][Pp][Ee][Nn])
+ ${fw6cmd} add 65000 pass all from any to any
+ ;;
+
+[Cc][Ll][Ii][Ee][Nn][Tt])
+ ############
+ # This is a prototype setup that will protect your system somewhat
+ # against people from outside your own network.
+ ############
+
+ # set these to your network and prefixlen and ip
+ #
+ # This needs more work
+ #
+ net="3ffe:505:2:1::"
+ prefixlen="64"
+ ip="3ffe:505:2:1::1"
+
+ # Allow any traffic to or from my own net.
+ ${fw6cmd} add pass all from ${ip} to ${net}/${prefixlen}
+ ${fw6cmd} add pass all from ${net}/${prefixlen} to ${ip}
+
+ # Allow TCP through if setup succeeded
+ ${fw6cmd} add pass tcp from any to any established
+
+ # Allow IP fragments to pass through
+ ${fw6cmd} add pass all from any to any frag
+
+ # Allow setup of incoming email
+ ${fw6cmd} add pass tcp from any to ${ip} 25 setup
+
+ # Allow setup of outgoing TCP connections only
+ ${fw6cmd} add pass tcp from ${ip} to any setup
+
+ # Disallow setup of all other TCP connections
+ ${fw6cmd} add deny tcp from any to any setup
+
+ # Allow DNS queries out in the world
+ ${fw6cmd} add pass udp from any 53 to ${ip}
+ ${fw6cmd} add pass udp from ${ip} to any 53
+
+ # Allow NTP queries out in the world
+ ${fw6cmd} add pass udp from any 123 to ${ip}
+ ${fw6cmd} add pass udp from ${ip} to any 123
+
+ # Everything else is denied by default, unless the
+ # IPFIREWALL_DEFAULT_TO_ACCEPT option is set in your kernel
+ # config file.
+ ;;
+
+[Ss][Ii][Mm][Pp][Ll][Ee])
+ ############
+ # This is a prototype setup for a simple firewall. Configure this
+ # machine as a named server and ntp server, and point all the machines
+ # on the inside at this machine for those services.
+ ############
+
+ # set these to your outside interface network and prefixlen and ip
+ oif="ed0"
+ onet="3ffe:505:2:1::"
+ oprefixlen="64"
+ oip="3ffe:505:2:1::1"
+
+ # set these to your inside interface network and prefixlen and ip
+ iif="ed1"
+ inet="3ffe:505:2:2::"
+ iprefixlen="64"
+ iip="3ffe:505:2:2::1"
+
+ # Stop spoofing
+ ${fw6cmd} add deny all from ${inet}/${iprefixlen} to any in via ${oif}
+ ${fw6cmd} add deny all from ${onet}/${oprefixlen} to any in via ${iif}
+
+ # Stop site-local on the outside interface
+ ${fw6cmd} add deny all from ff02::/16 to any via ${oif}
+ ${fw6cmd} add deny all from any to ff02::/16 via ${oif}
+
+ # Disallow "internal" addresses to appear on the wire.
+ ${fw6cmd} add deny all from ::ffff:0.0.0.0/96 to any via ${oif}
+ ${fw6cmd} add deny all from any to ::ffff:0.0.0.0/96 via ${oif}
+
+ # Disallow packets to malicious IPv4 compatible prefix.
+ ${fw6cmd} add deny all from ::224.0.0.0/100 to any via ${oif}
+ ${fw6cmd} add deny all from any to ::224.0.0.0/100 via ${oif}
+ ${fw6cmd} add deny all from ::127.0.0.0/104 to any via ${oif}
+ ${fw6cmd} add deny all from any to ::127.0.0.0/104 via ${oif}
+ ${fw6cmd} add deny all from ::0.0.0.0/104 to any via ${oif}
+ ${fw6cmd} add deny all from any to ::0.0.0.0/104 via ${oif}
+ ${fw6cmd} add deny all from ::255.0.0.0/104 to any via ${oif}
+ ${fw6cmd} add deny all from any to ::255.0.0.0/104 via ${oif}
+
+ ${fw6cmd} add deny all from ::0.0.0.0/96 to any via ${oif}
+ ${fw6cmd} add deny all from any to ::0.0.0.0/96 via ${oif}
+
+ # Disallow packets to malicious 6to4 prefix.
+ ${fw6cmd} add deny all from 2002:e000::/20 to any via ${oif}
+ ${fw6cmd} add deny all from any to 2002:e000::/20 via ${oif}
+ ${fw6cmd} add deny all from 2002:7f00::/24 to any via ${oif}
+ ${fw6cmd} add deny all from any to 2002:7f00::/24 via ${oif}
+ ${fw6cmd} add deny all from 2002:0000::/24 to any via ${oif}
+ ${fw6cmd} add deny all from any to 2002:0000::/24 via ${oif}
+ ${fw6cmd} add deny all from 2002:ff00::/24 to any via ${oif}
+ ${fw6cmd} add deny all from any to 2002:ff00::/24 via ${oif}
+
+ ${fw6cmd} add deny all from 2002:0a00::/24 to any via ${oif}
+ ${fw6cmd} add deny all from any to 2002:0a00::/24 via ${oif}
+ ${fw6cmd} add deny all from 2002:ac10::/28 to any via ${oif}
+ ${fw6cmd} add deny all from any to 2002:ac10::/28 via ${oif}
+ ${fw6cmd} add deny all from 2002:c0a8::/32 to any via ${oif}
+ ${fw6cmd} add deny all from any to 2002:c0a8::/32 via ${oif}
+
+ ${fw6cmd} add deny all from ff05::/32 to any via ${oif}
+ ${fw6cmd} add deny all from any to ff05::/32 via ${oif}
+
+ # Allow TCP through if setup succeeded
+ ${fw6cmd} add pass tcp from any to any established
+
+ # Allow IP fragments to pass through
+ ${fw6cmd} add pass all from any to any frag
+
+ # Allow setup of incoming email
+ ${fw6cmd} add pass tcp from any to ${oip} 25 setup
+
+ # Allow access to our DNS
+ ${fw6cmd} add pass tcp from any to ${oip} 53 setup
+ ${fw6cmd} add pass udp from any to ${oip} 53
+ ${fw6cmd} add pass udp from ${oip} 53 to any
+
+ # Allow access to our WWW
+ ${fw6cmd} add pass tcp from any to ${oip} 80 setup
+
+ # Reject&Log all setup of incoming connections from the outside
+ ${fw6cmd} add deny log tcp from any to any in via ${oif} setup
+
+ # Allow setup of any other TCP connection
+ ${fw6cmd} add pass tcp from any to any setup
+
+ # Allow DNS queries out in the world
+ ${fw6cmd} add pass udp from any 53 to ${oip}
+ ${fw6cmd} add pass udp from ${oip} to any 53
+
+ # Allow NTP queries out in the world
+ ${fw6cmd} add pass udp from any 123 to ${oip}
+ ${fw6cmd} add pass udp from ${oip} to any 123
+
+ # RIPng
+ #${fw6cmd} add pass udp from fe80::/10 521 to ff02::9 521
+
+ # Everything else is denied by default, unless the
+ # IPFIREWALL_DEFAULT_TO_ACCEPT option is set in your kernel
+ # config file.
+ ;;
+
+[Uu][Nn][Kk][Nn][Oo][Ww][Nn])
+ ;;
+*)
+ if [ -r "${ipv6_firewall_type}" ]; then
+ ${fw6cmd} ${ipv6_firewall_flags} ${ipv6_firewall_type}
+ fi
+ ;;
+esac
diff --git a/lib/csu/alpha/crti.S b/lib/csu/alpha/crti.S
new file mode 100644
index 000000000000..3f58a0b433c7
--- /dev/null
+++ b/lib/csu/alpha/crti.S
@@ -0,0 +1,51 @@
+/*-
+ * Copyright 2000 David O'Brien, John D. Polstra.
+ * 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 ``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$
+ */
+
+ .section .init,"ax",@progbits
+ .align 5
+ .globl _init
+_init:
+ ldgp $29,0($27)
+$_init..ng:
+ lda $30,-16($30)
+ stq $26,0($30)
+ stq $15,8($30)
+ mov $30,$15
+ .align 5
+
+ .section .fini,"ax",@progbits
+ .align 5
+ .globl _fini
+_fini:
+ ldgp $29,0($27)
+$_fini..ng:
+ lda $30,-16($30)
+ stq $26,0($30)
+ stq $15,8($30)
+ mov $30,$15
+ .align 5
+
diff --git a/lib/csu/alpha/crtn.S b/lib/csu/alpha/crtn.S
new file mode 100644
index 000000000000..63024ffe2452
--- /dev/null
+++ b/lib/csu/alpha/crtn.S
@@ -0,0 +1,43 @@
+/*-
+ * Copyright 2000 David O'Brien, John D. Polstra.
+ * 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 ``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$
+ */
+
+ .section .init,"ax",@progbits
+ ldgp $29,0($26)
+ mov $15,$30
+ ldq $26,0($30)
+ ldq $15,8($30)
+ lda $30,16($30)
+ ret $31,($26),1
+
+
+ .section .fini,"ax",@progbits
+ ldgp $29,0($26)
+ mov $15,$30
+ ldq $26,0($30)
+ ldq $15,8($30)
+ lda $30,16($30)
+ ret $31,($26),1
diff --git a/sys/crypto/rijndael/rijndael.h b/sys/crypto/rijndael/rijndael.h
new file mode 100644
index 000000000000..8f2cc895b433
--- /dev/null
+++ b/sys/crypto/rijndael/rijndael.h
@@ -0,0 +1,3 @@
+/* $KAME: rijndael.h,v 1.2 2000/10/02 17:14:27 itojun Exp $ */
+
+#include <crypto/rijndael/rijndael-api-fst.h>
diff --git a/sys/dev/awi/awi_wep.c b/sys/dev/awi/awi_wep.c
new file mode 100644
index 000000000000..a8f76ec793e0
--- /dev/null
+++ b/sys/dev/awi/awi_wep.c
@@ -0,0 +1,528 @@
+/* $NetBSD: awi_wep.c,v 1.4 2000/08/14 11:28:03 onoe Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Atsushi Onoe.
+ *
+ * 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.
+ */
+
+/*
+ * WEP support framework for the awi driver.
+ *
+ * No actual encryption capability is provided here, but any can be added
+ * to awi_wep_algo table below.
+ *
+ * Note that IEEE802.11 specification states WEP uses RC4 with 40bit key,
+ * which is a proprietary encryption algorithm available under license
+ * from RSA Data Security Inc. Using another algorithm, includes null
+ * encryption provided here, the awi driver cannot be able to communicate
+ * with other stations.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/sockio.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 4
+#include <sys/bus.h>
+#else
+#include <sys/device.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#ifdef __FreeBSD__
+#include <net/ethernet.h>
+#include <net/if_arp.h>
+#else
+#include <net/if_ether.h>
+#endif
+#include <net/if_media.h>
+#include <net/if_ieee80211.h>
+
+#include <machine/cpu.h>
+#include <machine/bus.h>
+#ifdef __FreeBSD__
+#endif
+
+#ifdef __NetBSD__
+#include <dev/ic/am79c930reg.h>
+#include <dev/ic/am79c930var.h>
+#include <dev/ic/awireg.h>
+#include <dev/ic/awivar.h>
+
+#include <crypto/arc4/arc4.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <dev/awi/am79c930reg.h>
+#include <dev/awi/am79c930var.h>
+#include <dev/awi/awireg.h>
+#include <dev/awi/awivar.h>
+
+#include <crypto/rc4/rc4.h>
+static __inline int
+arc4_ctxlen(void)
+{
+ return sizeof(struct rc4_state);
+}
+
+static __inline void
+arc4_setkey(void *ctx, u_int8_t *key, int keylen)
+{
+ rc4_init(ctx, key, keylen);
+}
+
+static __inline void
+arc4_encrypt(void *ctx, u_int8_t *dst, u_int8_t *src, int len)
+{
+ rc4_crypt(ctx, src, dst, len);
+}
+#endif
+
+static void awi_crc_init __P((void));
+static u_int32_t awi_crc_update __P((u_int32_t crc, u_int8_t *buf, int len));
+
+static int awi_null_ctxlen __P((void));
+static void awi_null_setkey __P((void *ctx, u_int8_t *key, int keylen));
+static void awi_null_copy __P((void *ctx, u_int8_t *dst, u_int8_t *src, int len));
+
+/* XXX: the order should be known to wiconfig/user */
+
+static struct awi_wep_algo awi_wep_algo[] = {
+/* 0: no wep */
+ { "no" }, /* dummy for no wep */
+
+/* 1: normal wep (arc4) */
+ { "arc4", arc4_ctxlen, arc4_setkey,
+ arc4_encrypt, arc4_encrypt },
+
+/* 2: debug wep (null) */
+ { "null", awi_null_ctxlen, awi_null_setkey,
+ awi_null_copy, awi_null_copy },
+ /* dummy for wep without encryption */
+};
+
+int
+awi_wep_setnwkey(sc, nwkey)
+ struct awi_softc *sc;
+ struct ieee80211_nwkey *nwkey;
+{
+ int i, len, error;
+ u_int8_t keybuf[AWI_MAX_KEYLEN];
+
+ if (nwkey->i_defkid <= 0 ||
+ nwkey->i_defkid > IEEE80211_WEP_NKID)
+ return EINVAL;
+ error = 0;
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ if (nwkey->i_key[i].i_keydat == NULL)
+ continue;
+ len = nwkey->i_key[i].i_keylen;
+ if (len > sizeof(keybuf)) {
+ error = EINVAL;
+ break;
+ }
+ error = copyin(nwkey->i_key[i].i_keydat, keybuf, len);
+ if (error)
+ break;
+ error = awi_wep_setkey(sc, i, keybuf, len);
+ if (error)
+ break;
+ }
+ if (error == 0) {
+ sc->sc_wep_defkid = nwkey->i_defkid - 1;
+ error = awi_wep_setalgo(sc, nwkey->i_wepon);
+ if (error == 0 && sc->sc_enabled) {
+ awi_stop(sc);
+ error = awi_init(sc);
+ }
+ }
+ return error;
+}
+
+int
+awi_wep_getnwkey(sc, nwkey)
+ struct awi_softc *sc;
+ struct ieee80211_nwkey *nwkey;
+{
+ int i, len, error, suerr;
+ u_int8_t keybuf[AWI_MAX_KEYLEN];
+
+ nwkey->i_wepon = awi_wep_getalgo(sc);
+ nwkey->i_defkid = sc->sc_wep_defkid + 1;
+ /* do not show any keys to non-root user */
+#ifdef __FreeBSD__
+ suerr = suser(curproc);
+#else
+ suerr = suser(curproc->p_ucred, &curproc->p_acflag);
+#endif
+ error = 0;
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ if (nwkey->i_key[i].i_keydat == NULL)
+ continue;
+ if (suerr) {
+ error = suerr;
+ break;
+ }
+ len = sizeof(keybuf);
+ error = awi_wep_getkey(sc, i, keybuf, &len);
+ if (error)
+ break;
+ if (nwkey->i_key[i].i_keylen < len) {
+ error = ENOSPC;
+ break;
+ }
+ nwkey->i_key[i].i_keylen = len;
+ error = copyout(keybuf, nwkey->i_key[i].i_keydat, len);
+ if (error)
+ break;
+ }
+ return error;
+}
+
+int
+awi_wep_getalgo(sc)
+ struct awi_softc *sc;
+{
+
+ if (sc->sc_wep_algo == NULL)
+ return 0;
+ return sc->sc_wep_algo - awi_wep_algo;
+}
+
+int
+awi_wep_setalgo(sc, algo)
+ struct awi_softc *sc;
+ int algo;
+{
+ struct awi_wep_algo *awa;
+ int ctxlen;
+
+ awi_crc_init(); /* XXX: not belongs here */
+ if (algo < 0 || algo > sizeof(awi_wep_algo)/sizeof(awi_wep_algo[0]))
+ return EINVAL;
+ awa = &awi_wep_algo[algo];
+ if (awa->awa_name == NULL)
+ return EINVAL;
+ if (awa->awa_ctxlen == NULL) {
+ awa = NULL;
+ ctxlen = 0;
+ } else
+ ctxlen = awa->awa_ctxlen();
+ if (sc->sc_wep_ctx != NULL) {
+ free(sc->sc_wep_ctx, M_DEVBUF);
+ sc->sc_wep_ctx = NULL;
+ }
+ if (ctxlen) {
+ sc->sc_wep_ctx = malloc(ctxlen, M_DEVBUF, M_NOWAIT);
+ if (sc->sc_wep_ctx == NULL)
+ return ENOMEM;
+ }
+ sc->sc_wep_algo = awa;
+ return 0;
+}
+
+int
+awi_wep_setkey(sc, kid, key, keylen)
+ struct awi_softc *sc;
+ int kid;
+ unsigned char *key;
+ int keylen;
+{
+
+ if (kid < 0 || kid >= IEEE80211_WEP_NKID)
+ return EINVAL;
+ if (keylen < 0 || keylen + IEEE80211_WEP_IVLEN > AWI_MAX_KEYLEN)
+ return EINVAL;
+ sc->sc_wep_keylen[kid] = keylen;
+ if (keylen > 0)
+ memcpy(sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, key, keylen);
+ return 0;
+}
+
+int
+awi_wep_getkey(sc, kid, key, keylen)
+ struct awi_softc *sc;
+ int kid;
+ unsigned char *key;
+ int *keylen;
+{
+
+ if (kid < 0 || kid >= IEEE80211_WEP_NKID)
+ return EINVAL;
+ if (*keylen < sc->sc_wep_keylen[kid])
+ return ENOSPC;
+ *keylen = sc->sc_wep_keylen[kid];
+ if (*keylen > 0)
+ memcpy(key, sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, *keylen);
+ return 0;
+}
+
+struct mbuf *
+awi_wep_encrypt(sc, m0, txflag)
+ struct awi_softc *sc;
+ struct mbuf *m0;
+ int txflag;
+{
+ struct mbuf *m, *n, *n0;
+ struct ieee80211_frame *wh;
+ struct awi_wep_algo *awa;
+ int left, len, moff, noff, keylen, kid;
+ u_int32_t iv, crc;
+ u_int8_t *key, *ivp;
+ void *ctx;
+ u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
+
+ n0 = NULL;
+ awa = sc->sc_wep_algo;
+ if (awa == NULL)
+ goto fail;
+ ctx = sc->sc_wep_ctx;
+ m = m0;
+ left = m->m_pkthdr.len;
+ MGET(n, M_DONTWAIT, m->m_type);
+ n0 = n;
+ if (n == NULL)
+ goto fail;
+ M_COPY_PKTHDR(n, m);
+ len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
+ if (txflag) {
+ n->m_pkthdr.len += len;
+ } else {
+ n->m_pkthdr.len -= len;
+ left -= len;
+ }
+ n->m_len = MHLEN;
+ if (n->m_pkthdr.len >= MINCLSIZE) {
+ MCLGET(n, M_DONTWAIT);
+ if (n->m_flags & M_EXT)
+ n->m_len = n->m_ext.ext_size;
+ }
+ len = sizeof(struct ieee80211_frame);
+ memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
+ left -= len;
+ moff = len;
+ noff = len;
+ if (txflag) {
+ kid = sc->sc_wep_defkid;
+ wh = mtod(n, struct ieee80211_frame *);
+ wh->i_fc[1] |= IEEE80211_FC1_WEP;
+ iv = random();
+ /*
+ * store IV, byte order is not the matter since it's random.
+ * assuming IEEE80211_WEP_IVLEN is 3
+ */
+ ivp = mtod(n, u_int8_t *) + noff;
+ ivp[0] = (iv >> 16) & 0xff;
+ ivp[1] = (iv >> 8) & 0xff;
+ ivp[2] = iv & 0xff;
+ ivp[3] = kid & 0x03; /* clear pad and keyid */
+ noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
+ } else {
+ ivp = mtod(m, u_int8_t *) + moff;
+ moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
+ kid = ivp[IEEE80211_WEP_IVLEN] & 0x03;
+ }
+ key = sc->sc_wep_key[kid];
+ keylen = sc->sc_wep_keylen[kid];
+ /* assuming IEEE80211_WEP_IVLEN is 3 */
+ key[0] = ivp[0];
+ key[1] = ivp[1];
+ key[2] = ivp[2];
+ awa->awa_setkey(ctx, key, IEEE80211_WEP_IVLEN + keylen);
+
+ /* encrypt with calculating CRC */
+ crc = ~0;
+ while (left > 0) {
+ len = m->m_len - moff;
+ if (len == 0) {
+ m = m->m_next;
+ moff = 0;
+ continue;
+ }
+ if (len > n->m_len - noff) {
+ len = n->m_len - noff;
+ if (len == 0) {
+ MGET(n->m_next, M_DONTWAIT, n->m_type);
+ if (n->m_next == NULL)
+ goto fail;
+ n = n->m_next;
+ n->m_len = MLEN;
+ if (left >= MINCLSIZE) {
+ MCLGET(n, M_DONTWAIT);
+ if (n->m_flags & M_EXT)
+ n->m_len = n->m_ext.ext_size;
+ }
+ noff = 0;
+ continue;
+ }
+ }
+ if (len > left)
+ len = left;
+ if (txflag) {
+ awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff,
+ mtod(m, caddr_t) + moff, len);
+ crc = awi_crc_update(crc, mtod(m, caddr_t) + moff, len);
+ } else {
+ awa->awa_decrypt(ctx, mtod(n, caddr_t) + noff,
+ mtod(m, caddr_t) + moff, len);
+ crc = awi_crc_update(crc, mtod(n, caddr_t) + noff, len);
+ }
+ left -= len;
+ moff += len;
+ noff += len;
+ }
+ crc = ~crc;
+ if (txflag) {
+ LE_WRITE_4(crcbuf, crc);
+ if (n->m_len >= noff + sizeof(crcbuf))
+ n->m_len = noff + sizeof(crcbuf);
+ else {
+ n->m_len = noff;
+ MGET(n->m_next, M_DONTWAIT, n->m_type);
+ if (n->m_next == NULL)
+ goto fail;
+ n = n->m_next;
+ n->m_len = sizeof(crcbuf);
+ noff = 0;
+ }
+ awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
+ sizeof(crcbuf));
+ } else {
+ n->m_len = noff;
+ for (noff = 0; noff < sizeof(crcbuf); noff += len) {
+ len = sizeof(crcbuf) - noff;
+ if (len > m->m_len - moff)
+ len = m->m_len - moff;
+ if (len > 0)
+ awa->awa_decrypt(ctx, crcbuf + noff,
+ mtod(m, caddr_t) + moff, len);
+ m = m->m_next;
+ moff = 0;
+ }
+ if (crc != LE_READ_4(crcbuf))
+ goto fail;
+ }
+ m_freem(m0);
+ return n0;
+
+ fail:
+ m_freem(m0);
+ m_freem(n0);
+ return NULL;
+}
+
+/*
+ * CRC 32 -- routine from RFC 2083
+ */
+
+/* Table of CRCs of all 8-bit messages */
+static u_int32_t awi_crc_table[256];
+static int awi_crc_table_computed = 0;
+
+/* Make the table for a fast CRC. */
+static void
+awi_crc_init()
+{
+ u_int32_t c;
+ int n, k;
+
+ if (awi_crc_table_computed)
+ return;
+ for (n = 0; n < 256; n++) {
+ c = (u_int32_t)n;
+ for (k = 0; k < 8; k++) {
+ if (c & 1)
+ c = 0xedb88320UL ^ (c >> 1);
+ else
+ c = c >> 1;
+ }
+ awi_crc_table[n] = c;
+ }
+ awi_crc_table_computed = 1;
+}
+
+/*
+ * Update a running CRC with the bytes buf[0..len-1]--the CRC
+ * should be initialized to all 1's, and the transmitted value
+ * is the 1's complement of the final running CRC
+ */
+
+static u_int32_t
+awi_crc_update(crc, buf, len)
+ u_int32_t crc;
+ u_int8_t *buf;
+ int len;
+{
+ u_int8_t *endbuf;
+
+ for (endbuf = buf + len; buf < endbuf; buf++)
+ crc = awi_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
+ return crc;
+}
+
+/*
+ * Null -- do nothing but copy.
+ */
+
+static int
+awi_null_ctxlen()
+{
+
+ return 0;
+}
+
+static void
+awi_null_setkey(ctx, key, keylen)
+ void *ctx;
+ u_char *key;
+ int keylen;
+{
+}
+
+static void
+awi_null_copy(ctx, dst, src, len)
+ void *ctx;
+ u_char *dst;
+ u_char *src;
+ int len;
+{
+
+ memcpy(dst, src, len);
+}
diff --git a/sys/dev/awi/awi_wicfg.c b/sys/dev/awi/awi_wicfg.c
new file mode 100644
index 000000000000..80882ba3035a
--- /dev/null
+++ b/sys/dev/awi/awi_wicfg.c
@@ -0,0 +1,625 @@
+/* $NetBSD: awi_wicfg.c,v 1.3 2000/07/06 17:22:25 onoe Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Atsushi Onoe.
+ *
+ * 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.
+ */
+
+/*
+ * WaveLAN compatible configuration support routines for the awi driver.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/sockio.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 4
+#include <sys/bus.h>
+#else
+#include <sys/device.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#ifdef __FreeBSD__
+#include <net/ethernet.h>
+#include <net/if_arp.h>
+#else
+#include <net/if_ether.h>
+#endif
+#include <net/if_media.h>
+#include <net/if_ieee80211.h>
+
+#include <machine/cpu.h>
+#include <machine/bus.h>
+#ifdef __FreeBSD__
+#endif
+
+#ifdef __NetBSD__
+#include <dev/ic/am79c930reg.h>
+#include <dev/ic/am79c930var.h>
+#include <dev/ic/awireg.h>
+#include <dev/ic/awivar.h>
+
+#include <dev/pcmcia/if_wi_ieee.h> /* XXX */
+#endif
+#ifdef __FreeBSD__
+#include <dev/awi/am79c930reg.h>
+#include <dev/awi/am79c930var.h>
+
+#undef _KERNEL /* XXX */
+#include <i386/include/if_wavelan_ieee.h> /* XXX */
+#define _KERNEL /* XXX */
+#include <dev/awi/awireg.h>
+#include <dev/awi/awivar.h>
+#endif
+
+static int awi_cfgget __P((struct ifnet *ifp, u_long cmd, caddr_t data));
+static int awi_cfgset __P((struct ifnet *ifp, u_long cmd, caddr_t data));
+
+int
+awi_wicfg(ifp, cmd, data)
+ struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ int error;
+
+ switch (cmd) {
+ case SIOCGWAVELAN:
+ error = awi_cfgget(ifp, cmd, data);
+ break;
+ case SIOCSWAVELAN:
+#ifdef __FreeBSD__
+ error = suser(curproc);
+#else
+ error = suser(curproc->p_ucred, &curproc->p_acflag);
+#endif
+ if (error)
+ break;
+ error = awi_cfgset(ifp, cmd, data);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+static int
+awi_cfgget(ifp, cmd, data)
+ struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ int i, error, keylen;
+ char *p;
+ struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct wi_ltv_keys *keys;
+ struct wi_key *k;
+ struct wi_req wreq;
+#ifdef WICACHE
+ struct wi_sigcache wsc;
+ struct awi_bss *bp;
+#endif /* WICACHE */
+
+ error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
+ if (error)
+ return error;
+ switch (wreq.wi_type) {
+ case WI_RID_SERIALNO:
+ memcpy(wreq.wi_val, sc->sc_banner, AWI_BANNER_LEN);
+ wreq.wi_len = (AWI_BANNER_LEN + 1) / 2;
+ break;
+ case WI_RID_NODENAME:
+ strcpy((char *)&wreq.wi_val[1], hostname);
+ wreq.wi_val[0] = strlen(hostname);
+ wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
+ break;
+ case WI_RID_OWN_SSID:
+ p = sc->sc_ownssid;
+ wreq.wi_val[0] = p[1];
+ memcpy(&wreq.wi_val[1], p + 2, p[1]);
+ wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
+ break;
+ case WI_RID_CURRENT_SSID:
+ if (ifp->if_flags & IFF_RUNNING) {
+ p = sc->sc_bss.essid;
+ wreq.wi_val[0] = p[1];
+ memcpy(&wreq.wi_val[1], p + 2, p[1]);
+ } else {
+ wreq.wi_val[0] = 0;
+ wreq.wi_val[1] = '\0';
+ }
+ wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
+ break;
+ case WI_RID_DESIRED_SSID:
+ p = sc->sc_mib_mac.aDesired_ESS_ID;
+ wreq.wi_val[0] = p[1];
+ memcpy(&wreq.wi_val[1], p + 2, p[1]);
+ wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
+ break;
+ case WI_RID_CURRENT_BSSID:
+ if (ifp->if_flags & IFF_RUNNING)
+ memcpy(wreq.wi_val, sc->sc_bss.bssid, ETHER_ADDR_LEN);
+ else
+ memset(wreq.wi_val, 0, ETHER_ADDR_LEN);
+ wreq.wi_len = ETHER_ADDR_LEN / 2;
+ break;
+ case WI_RID_CHANNEL_LIST:
+ if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
+ wreq.wi_val[0] = sc->sc_scan_min;
+ wreq.wi_val[1] = sc->sc_scan_max;
+ wreq.wi_len = 2;
+ } else {
+ wreq.wi_val[0] = 0;
+ for (i = sc->sc_scan_min; i <= sc->sc_scan_max; i++)
+ wreq.wi_val[0] |= 1 << (i - 1);
+ wreq.wi_len = 1;
+ }
+ break;
+ case WI_RID_OWN_CHNL:
+ wreq.wi_val[0] = sc->sc_ownch;
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_CURRENT_CHAN:
+ if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
+ wreq.wi_val[0] = sc->sc_bss.pattern;
+ else
+ wreq.wi_val[0] = sc->sc_bss.chanset;
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_COMMS_QUALITY:
+ wreq.wi_val[0] = 0; /* quality */
+ wreq.wi_val[1] = sc->sc_bss.rssi; /* signal */
+ wreq.wi_val[2] = 0; /* noise */
+ wreq.wi_len = 3;
+ break;
+ case WI_RID_PROMISC:
+ wreq.wi_val[0] = sc->sc_mib_mac.aPromiscuous_Enable;
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_PORTTYPE:
+ if (sc->sc_mib_local.Network_Mode)
+ wreq.wi_val[0] = 1;
+ else if (!sc->sc_no_bssid)
+ wreq.wi_val[0] = 2;
+ else
+ wreq.wi_val[0] = 3;
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_MAC_NODE:
+ memcpy(wreq.wi_val, sc->sc_mib_addr.aMAC_Address,
+ ETHER_ADDR_LEN);
+ wreq.wi_len = ETHER_ADDR_LEN / 2;
+ break;
+ case WI_RID_TX_RATE:
+ case WI_RID_CUR_TX_RATE:
+ wreq.wi_val[0] = sc->sc_tx_rate / 10;
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_RTS_THRESH:
+ wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aRTS_Threshold);
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_CREATE_IBSS:
+ wreq.wi_val[0] = sc->sc_start_bss;
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_SYSTEM_SCALE:
+ wreq.wi_val[0] = 1; /* low density ... not supported */
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_PM_ENABLED:
+ wreq.wi_val[0] = sc->sc_mib_local.Power_Saving_Mode_Dis ? 0 : 1;
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_MAX_SLEEP:
+ wreq.wi_val[0] = 0; /* not implemented */
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_WEP_AVAIL:
+ wreq.wi_val[0] = 1;
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_ENCRYPTION:
+ wreq.wi_val[0] = awi_wep_getalgo(sc);
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_TX_CRYPT_KEY:
+ wreq.wi_val[0] = sc->sc_wep_defkid;
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_DEFLT_CRYPT_KEYS:
+ keys = (struct wi_ltv_keys *)&wreq;
+ /* do not show keys to non-root user */
+#ifdef __FreeBSD__
+ error = suser(curproc);
+#else
+ error = suser(curproc->p_ucred, &curproc->p_acflag);
+#endif
+ if (error) {
+ memset(keys, 0, sizeof(*keys));
+ error = 0;
+ break;
+ }
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ k = &keys->wi_keys[i];
+ keylen = sizeof(k->wi_keydat);
+ error = awi_wep_getkey(sc, i, k->wi_keydat, &keylen);
+ if (error)
+ break;
+ k->wi_keylen = keylen;
+ }
+ wreq.wi_len = sizeof(*keys) / 2;
+ break;
+ case WI_RID_MAX_DATALEN:
+ wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aMax_Frame_Length);
+ wreq.wi_len = 1;
+ break;
+ case WI_RID_IFACE_STATS:
+ /* not implemented yet */
+ wreq.wi_len = 0;
+ break;
+#ifdef WICACHE
+ case WI_RID_READ_CACHE:
+ for (bp = TAILQ_FIRST(&sc->sc_scan), i = 0;
+ bp != NULL && i < MAXWICACHE;
+ bp = TAILQ_NEXT(bp, list), i++) {
+ memcpy(wsc.macsrc, bp->esrc, ETHER_ADDR_LEN);
+ /*XXX*/
+ memcpy(&wsc.ipsrc, bp->bssid, sizeof(wsc.ipsrc));
+ wsc.signal = bp->rssi;
+ wsc.noise = 0;
+ wsc.quality = 0;
+ memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i,
+ &wsc, sizeof(wsc));
+ }
+ wreq.wi_len = sizeof(wsc) * i / 2;
+ break;
+#endif /* WICACHE */
+ default:
+ error = EINVAL;
+ break;
+ }
+ if (error == 0) {
+ wreq.wi_len++;
+ error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
+ }
+ return error;
+}
+
+static int
+awi_cfgset(ifp, cmd, data)
+ struct ifnet *ifp;
+ u_long cmd;
+ caddr_t data;
+{
+ int i, error, rate, oregion;
+ u_int8_t *phy_rates;
+ struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct wi_ltv_keys *keys;
+ struct wi_key *k;
+ struct wi_req wreq;
+
+ error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
+ if (error)
+ return error;
+ if (wreq.wi_len-- < 1)
+ return EINVAL;
+ switch (wreq.wi_type) {
+ case WI_RID_SERIALNO:
+ case WI_RID_NODENAME:
+ error = EPERM;
+ break;
+ case WI_RID_OWN_SSID:
+ if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
+ error = EINVAL;
+ break;
+ }
+ if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
+ error = EINVAL;
+ break;
+ }
+ memset(sc->sc_ownssid, 0, AWI_ESS_ID_SIZE);
+ sc->sc_ownssid[0] = IEEE80211_ELEMID_SSID;
+ sc->sc_ownssid[1] = wreq.wi_val[0];
+ memcpy(&sc->sc_ownssid[2], &wreq.wi_val[1], wreq.wi_val[0]);
+ if (!sc->sc_mib_local.Network_Mode &&
+ !sc->sc_no_bssid && sc->sc_start_bss)
+ error = ENETRESET;
+ break;
+ case WI_RID_CURRENT_SSID:
+ error = EPERM;
+ break;
+ case WI_RID_DESIRED_SSID:
+ if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
+ error = EINVAL;
+ break;
+ }
+ if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
+ error = EINVAL;
+ break;
+ }
+ memset(sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
+ sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
+ sc->sc_mib_mac.aDesired_ESS_ID[1] = wreq.wi_val[0];
+ memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], &wreq.wi_val[1],
+ wreq.wi_val[0]);
+ if (sc->sc_mib_local.Network_Mode || !sc->sc_no_bssid)
+ error = ENETRESET;
+ break;
+ case WI_RID_CURRENT_BSSID:
+ error = EPERM;
+ break;
+ case WI_RID_CHANNEL_LIST:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ oregion = sc->sc_mib_phy.aCurrent_Reg_Domain;
+ if (wreq.wi_val[0] == oregion)
+ break;
+ sc->sc_mib_phy.aCurrent_Reg_Domain = wreq.wi_val[0];
+ error = awi_init_region(sc);
+ if (error) {
+ sc->sc_mib_phy.aCurrent_Reg_Domain = oregion;
+ break;
+ }
+ error = ENETRESET;
+ break;
+ case WI_RID_OWN_CHNL:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ if (wreq.wi_val[0] < sc->sc_scan_min ||
+ wreq.wi_val[0] > sc->sc_scan_max) {
+ error = EINVAL;
+ break;
+ }
+ sc->sc_ownch = wreq.wi_val[0];
+ if (!sc->sc_mib_local.Network_Mode)
+ error = ENETRESET;
+ break;
+ case WI_RID_CURRENT_CHAN:
+ error = EPERM;
+ break;
+ case WI_RID_COMMS_QUALITY:
+ error = EPERM;
+ break;
+ case WI_RID_PROMISC:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ if (ifp->if_flags & IFF_PROMISC) {
+ if (wreq.wi_val[0] == 0) {
+ ifp->if_flags &= ~IFF_PROMISC;
+ error = ENETRESET;
+ }
+ } else {
+ if (wreq.wi_val[0] != 0) {
+ ifp->if_flags |= IFF_PROMISC;
+ error = ENETRESET;
+ }
+ }
+ break;
+ case WI_RID_PORTTYPE:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ switch (wreq.wi_val[0]) {
+ case 1:
+ sc->sc_mib_local.Network_Mode = 1;
+ sc->sc_no_bssid = 0;
+ error = ENETRESET;
+ break;
+ case 2:
+ sc->sc_mib_local.Network_Mode = 0;
+ sc->sc_no_bssid = 0;
+ error = ENETRESET;
+ break;
+ case 3:
+ if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
+ error = EINVAL;
+ break;
+ }
+ sc->sc_mib_local.Network_Mode = 0;
+ sc->sc_no_bssid = 1;
+ error = ENETRESET;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+ case WI_RID_MAC_NODE:
+ /* XXX: should be implemented? */
+ error = EPERM;
+ break;
+ case WI_RID_TX_RATE:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
+ switch (wreq.wi_val[0]) {
+ case 1:
+ case 2:
+ case 5:
+ case 11:
+ rate = wreq.wi_val[0] * 10;
+ if (rate == 50)
+ rate += 5; /*XXX*/
+ break;
+ case 3:
+ case 6:
+ case 7:
+ /* auto rate */
+ phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
+ rate = AWI_RATE_1MBIT;
+ for (i = 0; i < phy_rates[1]; i++) {
+ if (AWI_80211_RATE(phy_rates[2 + i]) > rate)
+ rate = AWI_80211_RATE(phy_rates[2 + i]);
+ }
+ break;
+ default:
+ rate = 0;
+ error = EINVAL;
+ break;
+ }
+ if (error)
+ break;
+ for (i = 0; i < phy_rates[1]; i++) {
+ if (rate == AWI_80211_RATE(phy_rates[2 + i]))
+ break;
+ }
+ if (i == phy_rates[1]) {
+ error = EINVAL;
+ break;
+ }
+ sc->sc_tx_rate = rate;
+ break;
+ case WI_RID_CUR_TX_RATE:
+ error = EPERM;
+ break;
+ case WI_RID_RTS_THRESH:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ LE_WRITE_2(&sc->sc_mib_mac.aRTS_Threshold, wreq.wi_val[0]);
+ error = ENETRESET;
+ break;
+ case WI_RID_CREATE_IBSS:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ sc->sc_start_bss = wreq.wi_val[0] ? 1 : 0;
+ error = ENETRESET;
+ break;
+ case WI_RID_SYSTEM_SCALE:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ if (wreq.wi_val[0] != 1)
+ error = EINVAL; /* not supported */
+ break;
+ case WI_RID_PM_ENABLED:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ if (wreq.wi_val[0] != 0)
+ error = EINVAL; /* not implemented */
+ break;
+ case WI_RID_MAX_SLEEP:
+ error = EINVAL; /* not implemented */
+ break;
+ case WI_RID_WEP_AVAIL:
+ error = EPERM;
+ break;
+ case WI_RID_ENCRYPTION:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ error = awi_wep_setalgo(sc, wreq.wi_val[0]);
+ if (error)
+ break;
+ error = ENETRESET;
+ break;
+ case WI_RID_TX_CRYPT_KEY:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ if (wreq.wi_val[0] >= IEEE80211_WEP_NKID) {
+ error = EINVAL;
+ break;
+ }
+ sc->sc_wep_defkid = wreq.wi_val[1];
+ break;
+ case WI_RID_DEFLT_CRYPT_KEYS:
+ if (wreq.wi_len != sizeof(*keys) / 2) {
+ error = EINVAL;
+ break;
+ }
+ keys = (struct wi_ltv_keys *)&wreq;
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ k = &keys->wi_keys[i];
+ error = awi_wep_setkey(sc, i, k->wi_keydat,
+ k->wi_keylen);
+ if (error)
+ break;
+ }
+ break;
+ case WI_RID_MAX_DATALEN:
+ if (wreq.wi_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ if (wreq.wi_val[0] < 350 || wreq.wi_val[0] > 2304) {
+ error = EINVAL;
+ break;
+ }
+ LE_WRITE_2(&sc->sc_mib_mac.aMax_Frame_Length, wreq.wi_val[0]);
+ break;
+ case WI_RID_IFACE_STATS:
+ error = EPERM;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ if (error == ENETRESET) {
+ if (sc->sc_enabled) {
+ awi_stop(sc);
+ error = awi_init(sc);
+ } else
+ error = 0;
+ }
+ return error;
+}
diff --git a/sys/dev/usb/uscanner.c b/sys/dev/usb/uscanner.c
new file mode 100644
index 000000000000..4a87c475d61d
--- /dev/null
+++ b/sys/dev/usb/uscanner.c
@@ -0,0 +1,658 @@
+/* $NetBSD: uscanner.c,v 1.6 2000/10/13 18:16:36 augustss Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology
+ * and Nick Hibma (n_hibma@qubesoft.com).
+ *
+ * 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/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/device.h>
+#elif defined(__FreeBSD__)
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/filio.h>
+#endif
+#include <sys/tty.h>
+#include <sys/file.h>
+#include <sys/select.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/poll.h>
+#include <sys/conf.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+
+#include <dev/usb/usbdevs.h>
+
+#ifdef USCANNER_DEBUG
+#define DPRINTF(x) if (uscannerdebug) logprintf x
+#define DPRINTFN(n,x) if (uscannerdebug>(n)) logprintf x
+int uscannerdebug = 0;
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n,x)
+#endif
+
+/* Table of scanners that may work with this driver. */
+static const struct scanner_id {
+ uint16_t vendor;
+ uint16_t product;
+} scanner_ids [] = {
+ /* Acer Peripherals */
+ { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_320U },
+ { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_640U },
+ { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_620U },
+ { USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_C310U },
+
+ /* AGFA */
+ { USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1212U },
+ { USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1212U2 },
+ { USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANTOUCH },
+
+ /* Kye */
+ { USB_VENDOR_KYE, USB_PRODUCT_KYE_VIVIDPRO },
+
+ /* HP */
+ { USB_VENDOR_HP, USB_PRODUCT_HP_3300C },
+ { USB_VENDOR_HP, USB_PRODUCT_HP_4100C },
+ { USB_VENDOR_HP, USB_PRODUCT_HP_4200C },
+ { USB_VENDOR_HP, USB_PRODUCT_HP_S20 },
+ { USB_VENDOR_HP, USB_PRODUCT_HP_5200C },
+ { USB_VENDOR_HP, USB_PRODUCT_HP_5300C },
+ { USB_VENDOR_HP, USB_PRODUCT_HP_6200C },
+ { USB_VENDOR_HP, USB_PRODUCT_HP_6300C },
+
+ /* Avision */
+ { USB_VENDOR_AVISION, USB_PRODUCT_AVISION_1200U },
+
+ /* Microtek */
+ { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_X6U },
+ { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_336CX },
+ { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_336CX2 },
+ { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_C6 },
+ { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6USL },
+ { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6USL2 },
+ { USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6UL },
+
+ /* Mustek */
+ { USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200CU },
+ { USB_VENDOR_NATIONAL, USB_PRODUCT_NATIONAL_BEARPAW },
+ { USB_VENDOR_NATIONAL, USB_PRODUCT_MUSTEK_600CU },
+ { USB_VENDOR_NATIONAL, USB_PRODUCT_MUSTEK_1200USB },
+ { USB_VENDOR_NATIONAL, USB_PRODUCT_MUSTEK_1200UB },
+
+ /* Primax */
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2X300 },
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E300 },
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2300 },
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E3002 },
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_9600 },
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_600U },
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_19200 },
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_1200U },
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G600 },
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_636I },
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2600 },
+ { USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E600 },
+
+ /* Epson */
+ { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_636 },
+ { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_610 },
+ { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1200 },
+ { USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1600 },
+
+ /* UMAX */
+ { USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1220U },
+ { USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1236U },
+ { USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2000U },
+ { USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2200U },
+
+ /* Visioneer */
+ { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_5300 },
+ { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_7600 },
+ { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_6100 },
+ { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_6200 },
+ { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_8100 },
+ { USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_8600 },
+
+ { 0, 0 }
+};
+
+#define USCANNER_BUFFERSIZE 1024
+
+struct uscanner_softc {
+ USBBASEDEVICE sc_dev; /* base device */
+ usbd_device_handle sc_udev;
+ usbd_interface_handle sc_iface;
+
+ usbd_pipe_handle sc_bulkin_pipe;
+ int sc_bulkin;
+ usbd_xfer_handle sc_bulkin_xfer;
+ void *sc_bulkin_buffer;
+ int sc_bulkin_bufferlen;
+ int sc_bulkin_datalen;
+
+ usbd_pipe_handle sc_bulkout_pipe;
+ int sc_bulkout;
+ usbd_xfer_handle sc_bulkout_xfer;
+ void *sc_bulkout_buffer;
+ int sc_bulkout_bufferlen;
+ int sc_bulkout_datalen;
+
+ u_char sc_state;
+#define USCANNER_OPEN 0x01 /* opened */
+
+ int sc_refcnt;
+ u_char sc_dying;
+};
+
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+cdev_decl(uscanner);
+#elif defined(__FreeBSD__)
+d_open_t uscanneropen;
+d_close_t uscannerclose;
+d_read_t uscannerread;
+d_write_t uscannerwrite;
+d_poll_t uscannerpoll;
+
+#define USCANNER_CDEV_MAJOR 156
+
+Static struct cdevsw uscanner_cdevsw = {
+ /* open */ uscanneropen,
+ /* close */ uscannerclose,
+ /* read */ uscannerread,
+ /* write */ uscannerwrite,
+ /* ioctl */ noioctl,
+ /* poll */ uscannerpoll,
+ /* mmap */ nommap,
+ /* strategy */ nostrategy,
+ /* name */ "uscanner",
+ /* maj */ USCANNER_CDEV_MAJOR,
+ /* dump */ nodump,
+ /* psize */ nopsize,
+ /* flags */ 0,
+ /* bmaj */ -1
+};
+#endif
+
+Static int uscanner_do_read(struct uscanner_softc *, struct uio *, int);
+Static int uscanner_do_write(struct uscanner_softc *, struct uio *, int);
+Static void uscanner_do_close(struct uscanner_softc *);
+
+#define USCANNERUNIT(n) (minor(n))
+
+USB_DECLARE_DRIVER(uscanner);
+
+USB_MATCH(uscanner)
+{
+ USB_MATCH_START(uscanner, uaa);
+ int i;
+
+ if (uaa->iface != NULL)
+ return UMATCH_NONE;
+
+ for (i = 0; scanner_ids[i].vendor != 0; i++) {
+ if (scanner_ids[i].vendor == uaa->vendor &&
+ scanner_ids[i].product == uaa->product) {
+ return (UMATCH_VENDOR_PRODUCT);
+ }
+ }
+
+ return (UMATCH_NONE);
+}
+
+USB_ATTACH(uscanner)
+{
+ USB_ATTACH_START(uscanner, sc, uaa);
+ usb_interface_descriptor_t *id = 0;
+ usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL;
+ char devinfo[1024];
+ int i;
+ usbd_status err;
+
+ usbd_devinfo(uaa->device, 0, devinfo);
+ USB_ATTACH_SETUP;
+ printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
+
+ sc->sc_udev = uaa->device;
+
+ err = usbd_set_config_no(uaa->device, 1, 0); /* XXX */
+ if (err) {
+ printf("%s: setting config no failed\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
+ }
+
+ /* XXX We only check the first interface */
+ err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
+ if (!err && sc->sc_iface)
+ id = usbd_get_interface_descriptor(sc->sc_iface);
+ if (err || id == 0) {
+ printf("%s: could not get interface descriptor, err=%d,id=%p\n",
+ USBDEVNAME(sc->sc_dev), err, id);
+ USB_ATTACH_ERROR_RETURN;
+ }
+
+ /* Find the two first bulk endpoints */
+ for (i = 0 ; i < id->bNumEndpoints; i++) {
+ ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
+ if (ed == 0) {
+ printf("%s: could not read endpoint descriptor\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
+ }
+
+ if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
+ && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
+ ed_bulkin = ed;
+ } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
+ && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
+ ed_bulkout = ed;
+ }
+
+ if (ed_bulkin && ed_bulkout) /* found all we need */
+ break;
+ }
+
+ /* Verify that we goething sensible */
+ if (ed_bulkin == NULL || ed_bulkout == NULL) {
+ printf("%s: bulk-in and/or bulk-out endpoint not found\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
+ }
+
+ sc->sc_bulkin = ed_bulkin->bEndpointAddress;
+ sc->sc_bulkout = ed_bulkout->bEndpointAddress;
+
+#ifdef __FreeBSD__
+ /* the main device, ctrl endpoint */
+ make_dev(&uscanner_cdevsw, USBDEVUNIT(sc->sc_dev),
+ UID_ROOT, GID_OPERATOR, 0644, "%s", USBDEVNAME(sc->sc_dev));
+#endif
+
+ USB_ATTACH_SUCCESS_RETURN;
+}
+
+int
+uscanneropen(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ struct uscanner_softc *sc;
+ int unit = USCANNERUNIT(dev);
+ usbd_status err;
+
+ USB_GET_SC_OPEN(uscanner, unit, sc);
+
+ DPRINTFN(5, ("uscanneropen: flag=%d, mode=%d, unit=%d\n",
+ flag, mode, unit));
+
+ if (sc->sc_dying)
+ return (ENXIO);
+
+ if (sc->sc_state & USCANNER_OPEN)
+ return (EBUSY);
+
+ sc->sc_bulkin_buffer = malloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK);
+ sc->sc_bulkout_buffer = malloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK);
+ /* No need to check buffers for NULL since we have WAITOK */
+
+ sc->sc_bulkin_bufferlen = USCANNER_BUFFERSIZE;
+ sc->sc_bulkout_bufferlen = USCANNER_BUFFERSIZE;
+
+ /* We have decided on which endpoints to use, now open the pipes */
+ err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin,
+ USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
+ if (err) {
+ printf("%s: cannot open bulk-in pipe (addr %d)\n",
+ USBDEVNAME(sc->sc_dev), sc->sc_bulkin);
+ uscanner_do_close(sc);
+ return (EIO);
+ }
+ err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout,
+ USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
+ if (err) {
+ printf("%s: cannot open bulk-out pipe (addr %d)\n",
+ USBDEVNAME(sc->sc_dev), sc->sc_bulkout);
+ uscanner_do_close(sc);
+ return (EIO);
+ }
+
+ sc->sc_bulkin_xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (sc->sc_bulkin_xfer == NULL) {
+ uscanner_do_close(sc);
+ return (ENOMEM);
+ }
+ sc->sc_bulkout_xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (sc->sc_bulkout_xfer == NULL) {
+ uscanner_do_close(sc);
+ return (ENOMEM);
+ }
+
+ return (0); /* success */
+}
+
+int
+uscannerclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag;
+ int mode;
+ struct proc *p;
+{
+ struct uscanner_softc *sc;
+
+ USB_GET_SC(uscanner, USCANNERUNIT(dev), sc);
+
+ DPRINTFN(5, ("uscannerclose: flag=%d, mode=%d, unit=%d\n",
+ flag, mode, USCANNERUNIT(dev)));
+
+#ifdef DIAGNOSTIC
+ if (!(sc->sc_state & USCANNER_OPEN)) {
+ printf("uscannerclose: not open\n");
+ return (EINVAL);
+ }
+#endif
+
+ uscanner_do_close(sc);
+
+ return 0;
+}
+
+void
+uscanner_do_close(struct uscanner_softc *sc)
+{
+ if (sc->sc_bulkin_xfer) {
+ usbd_free_xfer(sc->sc_bulkin_xfer);
+ sc->sc_bulkin_xfer = NULL;
+ }
+ if (sc->sc_bulkout_xfer) {
+ usbd_free_xfer(sc->sc_bulkout_xfer);
+ sc->sc_bulkout_xfer = NULL;
+ }
+
+ if (sc->sc_bulkin_pipe) {
+ usbd_abort_pipe(sc->sc_bulkin_pipe);
+ usbd_close_pipe(sc->sc_bulkin_pipe);
+ sc->sc_bulkin_pipe = NULL;
+ }
+ if (sc->sc_bulkout_pipe) {
+ usbd_abort_pipe(sc->sc_bulkout_pipe);
+ usbd_close_pipe(sc->sc_bulkout_pipe);
+ sc->sc_bulkout_pipe = NULL;
+ }
+
+ if (sc->sc_bulkin_buffer) {
+ free(sc->sc_bulkin_buffer, M_USBDEV);
+ sc->sc_bulkin_buffer = NULL;
+ }
+ if (sc->sc_bulkout_buffer) {
+ free(sc->sc_bulkout_buffer, M_USBDEV);
+ sc->sc_bulkout_buffer = NULL;
+ }
+
+ sc->sc_state &= ~USCANNER_OPEN;
+}
+
+Static int
+uscanner_do_read(sc, uio, flag)
+ struct uscanner_softc *sc;
+ struct uio *uio;
+ int flag;
+{
+ u_int32_t n, tn;
+ usbd_status err;
+ int error = 0;
+
+ DPRINTFN(5, ("%s: uscannerread\n", USBDEVNAME(sc->sc_dev)));
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ while ((n = min(sc->sc_bulkin_bufferlen, uio->uio_resid)) != 0) {
+ DPRINTFN(1, ("uscannerread: start transfer %d bytes\n",n));
+ tn = n;
+
+ err = usbd_bulk_transfer(
+ sc->sc_bulkin_xfer, sc->sc_bulkin_pipe,
+ sc->sc_state & USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
+ sc->sc_bulkin_buffer, &tn,
+ "uscannerrb");
+ if (err) {
+ if (err == USBD_INTERRUPTED)
+ error = EINTR;
+ else if (err == USBD_TIMEOUT)
+ error = ETIMEDOUT;
+ else
+ error = EIO;
+ break;
+ }
+ DPRINTFN(1, ("uscannerread: got %d bytes\n", tn));
+ error = uiomove(sc->sc_bulkin_buffer, tn, uio);
+ if (error || tn < n)
+ break;
+ }
+
+ return (error);
+}
+
+int
+uscannerread(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct uscanner_softc *sc;
+ int error;
+
+ USB_GET_SC(uscanner, USCANNERUNIT(dev), sc);
+
+ sc->sc_refcnt++;
+ error = uscanner_do_read(sc, uio, flag);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+
+ return (error);
+}
+
+Static int
+uscanner_do_write(sc, uio, flag)
+ struct uscanner_softc *sc;
+ struct uio *uio;
+ int flag;
+{
+ u_int32_t n;
+ int error = 0;
+ usbd_status err;
+
+ DPRINTFN(5, ("%s: uscanner_do_write\n", USBDEVNAME(sc->sc_dev)));
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ while ((n = min(sc->sc_bulkout_bufferlen, uio->uio_resid)) != 0) {
+ error = uiomove(sc->sc_bulkout_buffer, n, uio);
+ if (error)
+ break;
+ DPRINTFN(1, ("uscanner_do_write: transfer %d bytes\n", n));
+ err = usbd_bulk_transfer(
+ sc->sc_bulkout_xfer, sc->sc_bulkout_pipe,
+ 0, USBD_NO_TIMEOUT,
+ sc->sc_bulkout_buffer, &n,
+ "uscannerwb");
+ if (err) {
+ if (err == USBD_INTERRUPTED)
+ error = EINTR;
+ else
+ error = EIO;
+ break;
+ }
+ }
+
+ return (error);
+}
+
+int
+uscannerwrite(dev, uio, flag)
+ dev_t dev;
+ struct uio *uio;
+ int flag;
+{
+ struct uscanner_softc *sc;
+ int error;
+
+ USB_GET_SC(uscanner, USCANNERUNIT(dev), sc);
+
+ sc->sc_refcnt++;
+ error = uscanner_do_write(sc, uio, flag);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+ return (error);
+}
+
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+int
+uscanner_activate(self, act)
+ device_ptr_t self;
+ enum devact act;
+{
+ struct uscanner_softc *sc = (struct uscanner_softc *)self;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return (EOPNOTSUPP);
+ break;
+
+ case DVACT_DEACTIVATE:
+ sc->sc_dying = 1;
+ break;
+ }
+ return (0);
+}
+#endif
+
+USB_DETACH(uscanner)
+{
+ USB_DETACH_START(uscanner, sc);
+ int s;
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ int maj, mn;
+#elif defined(__FreeBSD__)
+ dev_t dev;
+ struct vnode *vp;
+#endif
+
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ DPRINTF(("uscanner_detach: sc=%p flags=%d\n", sc, flags));
+#elif defined(__FreeBSD__)
+ DPRINTF(("uscanner_detach: sc=%p\n", sc));
+#endif
+
+ sc->sc_dying = 1;
+
+ /* Abort all pipes. Causes processes waiting for transfer to wake. */
+ if (sc->sc_bulkin_pipe)
+ usbd_abort_pipe(sc->sc_bulkin_pipe);
+ if (sc->sc_bulkout_pipe)
+ usbd_abort_pipe(sc->sc_bulkout_pipe);
+
+ s = splusb();
+ if (--sc->sc_refcnt >= 0) {
+ /* Wait for processes to go away. */
+ usb_detach_wait(USBDEV(sc->sc_dev));
+ }
+ splx(s);
+
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ /* locate the major number */
+ for (maj = 0; maj < nchrdev; maj++)
+ if (cdevsw[maj].d_open == uscanneropen)
+ break;
+
+ /* Nuke the vnodes for any open instances (calls close). */
+ mn = self->dv_unit * USB_MAX_ENDPOINTS;
+ vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR);
+#elif defined(__FreeBSD__)
+ /* destroy the device for the control endpoint */
+ dev = makedev(USCANNER_CDEV_MAJOR, USBDEVUNIT(sc->sc_dev));
+ vp = SLIST_FIRST(&dev->si_hlist);
+ if (vp)
+ VOP_REVOKE(vp, REVOKEALL);
+ destroy_dev(dev);
+#endif
+
+ return (0);
+}
+
+int
+uscannerpoll(dev, events, p)
+ dev_t dev;
+ int events;
+ struct proc *p;
+{
+ struct uscanner_softc *sc;
+ int revents = 0;
+
+ USB_GET_SC(uscanner, USCANNERUNIT(dev), sc);
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ /*
+ * We have no easy way of determining if a read will
+ * yield any data or a write will happen.
+ * Pretend they will.
+ */
+ revents |= events &
+ (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM);
+
+ return (revents);
+}
+
+#if defined(__FreeBSD__)
+DRIVER_MODULE(uscanner, uhub, uscanner_driver, uscanner_devclass, usbd_driver_load, 0);
+#endif
diff --git a/sys/i4b/layer1/i4b_l1lib.c b/sys/i4b/layer1/i4b_l1lib.c
new file mode 100644
index 000000000000..d2e69e48bf94
--- /dev/null
+++ b/sys/i4b/layer1/i4b_l1lib.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2000 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_l1lib.c - general useful L1 procedures
+ * ------------------------------------------
+ *
+ * $Id: i4b_l1lib.c,v 1.3 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 15:24:21 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#define TEL_IDLE_MIN (BCH_MAX_DATALEN/2)
+
+/*---------------------------------------------------------------------------*
+ * telephony silence detection
+ *---------------------------------------------------------------------------*/
+int
+i4b_l1_bchan_tel_silence(unsigned char *data, int len)
+{
+ register int i = 0;
+ register int j = 0;
+
+ /* count idle bytes */
+
+ for(;i < len; i++)
+ {
+ if((*data >= 0xaa) && (*data <= 0xac))
+ j++;
+ data++;
+ }
+
+#ifdef NOTDEF
+ printf("i4b_l1_bchan_tel_silence: got %d silence bytes in frame\n", j);
+#endif
+
+ if(j < (TEL_IDLE_MIN))
+ return(0);
+ else
+ return(1);
+
+}
diff --git a/sys/i4b/layer1/ifpi/i4b_ifpi_isac.c b/sys/i4b/layer1/ifpi/i4b_ifpi_isac.c
new file mode 100644
index 000000000000..168506daba10
--- /dev/null
+++ b/sys/i4b/layer1/ifpi/i4b_ifpi_isac.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 1997, 2000 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_ifpi_isac.c - i4b Fritz PCI ISAC handler
+ * --------------------------------------------
+ *
+ * $Id: i4b_ifpi_isac.c,v 1.3 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 15:22:52 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "ifpi.h"
+#include "pci.h"
+
+#if (NIFPI > 0) && (NPCI > 0)
+
+#include "opt_i4b.h"
+
+#include <sys/param.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_trace.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/layer1/ifpi/i4b_ifpi_ext.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+
+static u_char ifpi_isac_exir_hdlr(register struct l1_softc *sc, u_char exir);
+static void ifpi_isac_ind_hdlr(register struct l1_softc *sc, int ind);
+
+/*---------------------------------------------------------------------------*
+ * ISAC interrupt service routine
+ *---------------------------------------------------------------------------*/
+void
+ifpi_isac_irq(struct l1_softc *sc, int ista)
+{
+ register u_char c = 0;
+ NDBGL1(L1_F_MSG, "unit %d: ista = 0x%02x", sc->sc_unit, ista);
+
+ if(ista & ISAC_ISTA_EXI) /* extended interrupt */
+ {
+ c |= ifpi_isac_exir_hdlr(sc, ISAC_READ(I_EXIR));
+ }
+
+ if(ista & ISAC_ISTA_RME) /* receive message end */
+ {
+ register int rest;
+ u_char rsta;
+
+ /* get rx status register */
+
+ rsta = ISAC_READ(I_RSTA);
+
+ if((rsta & ISAC_RSTA_MASK) != 0x20)
+ {
+ int error = 0;
+
+ if(!(rsta & ISAC_RSTA_CRC)) /* CRC error */
+ {
+ error++;
+ NDBGL1(L1_I_ERR, "unit %d: CRC error", sc->sc_unit);
+ }
+
+ if(rsta & ISAC_RSTA_RDO) /* ReceiveDataOverflow */
+ {
+ error++;
+ NDBGL1(L1_I_ERR, "unit %d: Data Overrun error", sc->sc_unit);
+ }
+
+ if(rsta & ISAC_RSTA_RAB) /* ReceiveABorted */
+ {
+ error++;
+ NDBGL1(L1_I_ERR, "unit %d: Receive Aborted error", sc->sc_unit);
+ }
+
+ if(error == 0)
+ NDBGL1(L1_I_ERR, "unit %d: RME unknown error, RSTA = 0x%02x!", sc->sc_unit, rsta);
+
+ i4b_Dfreembuf(sc->sc_ibuf);
+
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES);
+ ISACCMDRWRDELAY();
+
+ return;
+ }
+
+ rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1));
+
+ if(rest == 0)
+ rest = ISAC_FIFO_LEN;
+
+ if(sc->sc_ibuf == NULL)
+ {
+ if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL)
+ sc->sc_ib = sc->sc_ibuf->m_data;
+ else
+ panic("ifpi_isac_irq: RME, i4b_Dgetmbuf returns NULL!\n");
+ sc->sc_ilen = 0;
+ }
+
+ if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest))
+ {
+ ISAC_RDFIFO(sc->sc_ib, rest);
+ sc->sc_ilen += rest;
+
+ sc->sc_ibuf->m_pkthdr.len =
+ sc->sc_ibuf->m_len = sc->sc_ilen;
+
+ if(sc->sc_trace & TRACE_D_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = L0IFPIUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data);
+ }
+
+ c |= ISAC_CMDR_RMC;
+
+ if(sc->sc_enabled &&
+ (ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S))
+ {
+ i4b_l1_ph_data_ind(L0IFPIUNIT(sc->sc_unit), sc->sc_ibuf);
+ }
+ else
+ {
+ i4b_Dfreembuf(sc->sc_ibuf);
+ }
+ }
+ else
+ {
+ NDBGL1(L1_I_ERR, "RME, input buffer overflow!");
+ i4b_Dfreembuf(sc->sc_ibuf);
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+ }
+
+ if(ista & ISAC_ISTA_RPF) /* receive fifo full */
+ {
+ if(sc->sc_ibuf == NULL)
+ {
+ if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL)
+ sc->sc_ib= sc->sc_ibuf->m_data;
+ else
+ panic("ifpi_isac_irq: RPF, i4b_Dgetmbuf returns NULL!\n");
+ sc->sc_ilen = 0;
+ }
+
+ if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN))
+ {
+ ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN);
+ sc->sc_ilen += ISAC_FIFO_LEN;
+ sc->sc_ib += ISAC_FIFO_LEN;
+ c |= ISAC_CMDR_RMC;
+ }
+ else
+ {
+ NDBGL1(L1_I_ERR, "RPF, input buffer overflow!");
+ i4b_Dfreembuf(sc->sc_ibuf);
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+ }
+
+ if(ista & ISAC_ISTA_XPR) /* transmit fifo empty (XPR bit set) */
+ {
+ if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL))
+ {
+ sc->sc_freeflag = sc->sc_freeflag2;
+ sc->sc_obuf = sc->sc_obuf2;
+ sc->sc_op = sc->sc_obuf->m_data;
+ sc->sc_ol = sc->sc_obuf->m_len;
+ sc->sc_obuf2 = NULL;
+#ifdef NOTDEF
+ printf("ob2=%x, op=%x, ol=%d, f=%d #",
+ sc->sc_obuf,
+ sc->sc_op,
+ sc->sc_ol,
+ sc->sc_state);
+#endif
+ }
+ else
+ {
+#ifdef NOTDEF
+ printf("ob=%x, op=%x, ol=%d, f=%d #",
+ sc->sc_obuf,
+ sc->sc_op,
+ sc->sc_ol,
+ sc->sc_state);
+#endif
+ }
+
+ if(sc->sc_obuf)
+ {
+ ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN));
+
+ if(sc->sc_ol > ISAC_FIFO_LEN) /* length > 32 ? */
+ {
+ sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */
+ sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */
+ c |= ISAC_CMDR_XTF; /* set XTF bit */
+ }
+ else
+ {
+ if(sc->sc_freeflag)
+ {
+ i4b_Dfreembuf(sc->sc_obuf);
+ sc->sc_freeflag = 0;
+ }
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+
+ c |= ISAC_CMDR_XTF | ISAC_CMDR_XME;
+ }
+ }
+ else
+ {
+ sc->sc_state &= ~ISAC_TX_ACTIVE;
+ }
+ }
+
+ if(ista & ISAC_ISTA_CISQ) /* channel status change CISQ */
+ {
+ register u_char ci;
+
+ /* get command/indication rx register*/
+
+ ci = ISAC_READ(I_CIRR);
+
+ /* if S/Q IRQ, read SQC reg to clr SQC IRQ */
+
+ if(ci & ISAC_CIRR_SQC)
+ (void) ISAC_READ(I_SQRR);
+
+ /* C/I code change IRQ (flag already cleared by CIRR read) */
+
+ if(ci & ISAC_CIRR_CIC0)
+ ifpi_isac_ind_hdlr(sc, (ci >> 2) & 0xf);
+ }
+
+ if(c)
+ {
+ ISAC_WRITE(I_CMDR, c);
+ ISACCMDRWRDELAY();
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ISAC L1 Extended IRQ handler
+ *---------------------------------------------------------------------------*/
+static u_char
+ifpi_isac_exir_hdlr(register struct l1_softc *sc, u_char exir)
+{
+ u_char c = 0;
+
+ if(exir & ISAC_EXIR_XMR)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Tx Message Repeat");
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_XDU)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Tx Data Underrun");
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_PCE)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Protocol Error");
+ }
+
+ if(exir & ISAC_EXIR_RFO)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Rx Frame Overflow");
+
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+
+ if(exir & ISAC_EXIR_SOV)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Sync Xfer Overflow");
+ }
+
+ if(exir & ISAC_EXIR_MOS)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Monitor Status");
+ }
+
+ if(exir & ISAC_EXIR_SAW)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ NDBGL1(L1_I_ERR, "EXIRQ Subscriber Awake");
+ }
+
+ if(exir & ISAC_EXIR_WOV)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ NDBGL1(L1_I_ERR, "EXIRQ Watchdog Timer Overflow");
+ }
+
+ return(c);
+}
+
+/*---------------------------------------------------------------------------*
+ * ISAC L1 Indication handler
+ *---------------------------------------------------------------------------*/
+static void
+ifpi_isac_ind_hdlr(register struct l1_softc *sc, int ind)
+{
+ register int event;
+
+ switch(ind)
+ {
+ case ISAC_CIRR_IAI8:
+ NDBGL1(L1_I_CICO, "rx AI8 in state %s", ifpi_printstate(sc));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ ifpi_isac_l1_cmd(sc, CMD_AR8);
+ event = EV_INFO48;
+ i4b_l1_mph_status_ind(L0IFPIUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL);
+ break;
+
+ case ISAC_CIRR_IAI10:
+ NDBGL1(L1_I_CICO, "rx AI10 in state %s", ifpi_printstate(sc));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ ifpi_isac_l1_cmd(sc, CMD_AR10);
+ event = EV_INFO410;
+ i4b_l1_mph_status_ind(L0IFPIUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL);
+ break;
+
+ case ISAC_CIRR_IRSY:
+ NDBGL1(L1_I_CICO, "rx RSY in state %s", ifpi_printstate(sc));
+ event = EV_RSY;
+ break;
+
+ case ISAC_CIRR_IPU:
+ NDBGL1(L1_I_CICO, "rx PU in state %s", ifpi_printstate(sc));
+ event = EV_PU;
+ break;
+
+ case ISAC_CIRR_IDR:
+ NDBGL1(L1_I_CICO, "rx DR in state %s", ifpi_printstate(sc));
+ ifpi_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_DR;
+ break;
+
+ case ISAC_CIRR_IDID:
+ NDBGL1(L1_I_CICO, "rx DID in state %s", ifpi_printstate(sc));
+ event = EV_INFO0;
+ i4b_l1_mph_status_ind(L0IFPIUNIT(sc->sc_unit), STI_L1STAT, LAYER_IDLE, NULL);
+ break;
+
+ case ISAC_CIRR_IDIS:
+ NDBGL1(L1_I_CICO, "rx DIS in state %s", ifpi_printstate(sc));
+ event = EV_DIS;
+ break;
+
+ case ISAC_CIRR_IEI:
+ NDBGL1(L1_I_CICO, "rx EI in state %s", ifpi_printstate(sc));
+ ifpi_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_EI;
+ break;
+
+ case ISAC_CIRR_IARD:
+ NDBGL1(L1_I_CICO, "rx ARD in state %s", ifpi_printstate(sc));
+ event = EV_INFO2;
+ break;
+
+ case ISAC_CIRR_ITI:
+ NDBGL1(L1_I_CICO, "rx TI in state %s", ifpi_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_IATI:
+ NDBGL1(L1_I_CICO, "rx ATI in state %s", ifpi_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_ISD:
+ NDBGL1(L1_I_CICO, "rx SD in state %s", ifpi_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ default:
+ NDBGL1(L1_I_ERR, "UNKNOWN Indication 0x%x in state %s", ind, ifpi_printstate(sc));
+ event = EV_INFO0;
+ break;
+ }
+ ifpi_next_state(sc, event);
+}
+
+/*---------------------------------------------------------------------------*
+ * execute a layer 1 command
+ *---------------------------------------------------------------------------*/
+void
+ifpi_isac_l1_cmd(struct l1_softc *sc, int command)
+{
+ u_char cmd;
+
+#ifdef I4B_SMP_WORKAROUND
+
+ /* XXXXXXXXXXXXXXXXXXX */
+
+ /*
+ * patch from Wolfgang Helbig:
+ *
+ * Here is a patch that makes i4b work on an SMP:
+ * The card (TELES 16.3) didn't interrupt on an SMP machine.
+ * This is a gross workaround, but anyway it works *and* provides
+ * some information as how to finally fix this problem.
+ */
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+ ISAC_WRITE(I_MASK, 0xff);
+ DELAY(100);
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ /* XXXXXXXXXXXXXXXXXXX */
+
+#endif /* I4B_SMP_WORKAROUND */
+
+ if(command < 0 || command > CMD_ILL)
+ {
+ NDBGL1(L1_I_ERR, "illegal cmd 0x%x in state %s", command, ifpi_printstate(sc));
+ return;
+ }
+
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ cmd = ISAC_CIX0_LOW;
+ else
+ cmd = 0;
+
+ switch(command)
+ {
+ case CMD_TIM:
+ NDBGL1(L1_I_CICO, "tx TIM in state %s", ifpi_printstate(sc));
+ cmd |= (ISAC_CIXR_CTIM << 2);
+ break;
+
+ case CMD_RS:
+ NDBGL1(L1_I_CICO, "tx RS in state %s", ifpi_printstate(sc));
+ cmd |= (ISAC_CIXR_CRS << 2);
+ break;
+
+ case CMD_AR8:
+ NDBGL1(L1_I_CICO, "tx AR8 in state %s", ifpi_printstate(sc));
+ cmd |= (ISAC_CIXR_CAR8 << 2);
+ break;
+
+ case CMD_AR10:
+ NDBGL1(L1_I_CICO, "tx AR10 in state %s", ifpi_printstate(sc));
+ cmd |= (ISAC_CIXR_CAR10 << 2);
+ break;
+
+ case CMD_DIU:
+ NDBGL1(L1_I_CICO, "tx DIU in state %s", ifpi_printstate(sc));
+ cmd |= (ISAC_CIXR_CDIU << 2);
+ break;
+ }
+ ISAC_WRITE(I_CIXR, cmd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L1 ISAC initialization
+ *---------------------------------------------------------------------------*/
+int
+ifpi_isac_init(struct l1_softc *sc)
+{
+ ISAC_IMASK = 0xff; /* disable all irqs */
+
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ if(sc->sc_bustyp != BUS_TYPE_IOM2)
+ {
+ NDBGL1(L1_I_SETUP, "configuring for IOM-1 mode");
+
+ /* ADF2: Select mode IOM-1 */
+ ISAC_WRITE(I_ADF2, 0x00);
+
+ /* SPCR: serial port control register:
+ * SPU - software power up = 0
+ * SAC - SIP port high Z
+ * SPM - timing mode 0
+ * TLP - test loop = 0
+ * C1C, C2C - B1 and B2 switched to/from SPa
+ */
+ ISAC_WRITE(I_SPCR, ISAC_SPCR_C1C1|ISAC_SPCR_C2C1);
+
+ /* SQXR: S/Q channel xmit register:
+ * SQIE - S/Q IRQ enable = 0
+ * SQX1-4 - Fa bits = 1
+ */
+ ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);
+
+ /* ADF1: additional feature reg 1:
+ * WTC - watchdog = 0
+ * TEM - test mode = 0
+ * PFS - pre-filter = 0
+ * CFS - IOM clock/frame always active
+ * FSC1/2 - polarity of 8kHz strobe
+ * ITF - interframe fill = idle
+ */
+ ISAC_WRITE(I_ADF1, ISAC_ADF1_FC2); /* ADF1 */
+
+ /* STCR: sync transfer control reg:
+ * TSF - terminal secific functions = 0
+ * TBA - TIC bus address = 7
+ * STx/SCx = 0
+ */
+ ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
+
+ /* MODE: Mode Register:
+ * MDSx - transparent mode 2
+ * TMD - timer mode = external
+ * RAC - Receiver enabled
+ * DIMx - digital i/f mode
+ */
+ ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);
+ }
+ else
+ {
+ NDBGL1(L1_I_SETUP, "configuring for IOM-2 mode");
+
+ /* ADF2: Select mode IOM-2 */
+ ISAC_WRITE(I_ADF2, ISAC_ADF2_IMS);
+
+ /* SPCR: serial port control register:
+ * SPU - software power up = 0
+ * SPM - timing mode 0
+ * TLP - test loop = 0
+ * C1C, C2C - B1 + C1 and B2 + IC2 monitoring
+ */
+ ISAC_WRITE(I_SPCR, 0x00);
+
+ /* SQXR: S/Q channel xmit register:
+ * IDC - IOM direction = 0 (master)
+ * CFS - Config Select = 0 (clock always active)
+ * CI1E - C/I channel 1 IRQ enable = 0
+ * SQIE - S/Q IRQ enable = 0
+ * SQX1-4 - Fa bits = 1
+ */
+ ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);
+
+ /* ADF1: additional feature reg 1:
+ * WTC - watchdog = 0
+ * TEM - test mode = 0
+ * PFS - pre-filter = 0
+ * IOF - IOM i/f off = 0
+ * ITF - interframe fill = idle
+ */
+ ISAC_WRITE(I_ADF1, 0x00);
+
+ /* STCR: sync transfer control reg:
+ * TSF - terminal secific functions = 0
+ * TBA - TIC bus address = 7
+ * STx/SCx = 0
+ */
+ ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
+
+ /* MODE: Mode Register:
+ * MDSx - transparent mode 2
+ * TMD - timer mode = external
+ * RAC - Receiver enabled
+ * DIMx - digital i/f mode
+ */
+ ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);
+ }
+
+#ifdef NOTDEF
+ /*
+ * XXX a transmitter reset causes an ISAC tx IRQ which will not
+ * be serviced at attach time under some circumstances leaving
+ * the associated IRQ line on the ISA bus active. This prevents
+ * any further interrupts to be serviced because no low -> high
+ * transition can take place anymore. (-hm)
+ */
+
+ /* command register:
+ * RRES - HDLC receiver reset
+ * XRES - transmitter reset
+ */
+ ISAC_WRITE(I_CMDR, ISAC_CMDR_RRES|ISAC_CMDR_XRES);
+ ISACCMDRWRDELAY();
+#endif
+
+ /* enabled interrupts:
+ * ===================
+ * RME - receive message end
+ * RPF - receive pool full
+ * XPR - transmit pool ready
+ * CISQ - CI or S/Q channel change
+ * EXI - extended interrupt
+ */
+
+ ISAC_IMASK = ISAC_MASK_RSC | /* auto mode only */
+ ISAC_MASK_TIN | /* timer irq */
+ ISAC_MASK_SIN; /* sync xfer irq */
+
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ return(0);
+}
+
+#endif /* NIFPI > 0 */
diff --git a/sys/i4b/layer1/ifpi/i4b_ifpi_l1.c b/sys/i4b/layer1/ifpi/i4b_ifpi_l1.c
new file mode 100644
index 000000000000..3d417a35fb95
--- /dev/null
+++ b/sys/i4b/layer1/ifpi/i4b_ifpi_l1.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 1997, 2000 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_ifpi_l1.c - AVM Fritz PCI layer 1 handler
+ * ---------------------------------------------
+ *
+ * $Id: i4b_ifpi_l1.c,v 1.4 2000/06/02 16:14:36 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Fri Jun 2 14:54:30 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "ifpi.h"
+#include "pci.h"
+
+#if (NIFPI > 0) && (NPCI > 0)
+
+#include <sys/param.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_trace.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+
+#include <i4b/layer1/ifpi/i4b_ifpi_ext.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+/*---------------------------------------------------------------------------*
+ *
+ * L2 -> L1: PH-DATA-REQUEST
+ * =========================
+ *
+ * parms:
+ * unit physical interface unit number
+ * m mbuf containing L2 frame to be sent out
+ * freeflag MBUF_FREE: free mbuf here after having sent
+ * it out
+ * MBUF_DONTFREE: mbuf is freed by Layer 2
+ * returns:
+ * ==0 fail, nothing sent out
+ * !=0 ok, frame sent out
+ *
+ *---------------------------------------------------------------------------*/
+int
+ifpi_ph_data_req(int unit, struct mbuf *m, int freeflag)
+{
+ u_char cmd;
+ int s;
+ struct l1_softc *sc = ifpi_scp[unit];
+
+#ifdef NOTDEF
+ NDBGL1(L1_PRIM, "PH-DATA-REQ, unit %d, freeflag=%d", unit, freeflag);
+#endif
+
+ if(m == NULL) /* failsafe */
+ return (0);
+
+ s = SPLI4B();
+
+ if(sc->sc_I430state == ST_F3) /* layer 1 not running ? */
+ {
+ NDBGL1(L1_I_ERR, "still in state F3!");
+ ifpi_ph_activate_req(unit);
+ }
+
+ if(sc->sc_state & ISAC_TX_ACTIVE)
+ {
+ if(sc->sc_obuf2 == NULL)
+ {
+ sc->sc_obuf2 = m; /* save mbuf ptr */
+
+ if(freeflag)
+ sc->sc_freeflag2 = 1; /* IRQ must mfree */
+ else
+ sc->sc_freeflag2 = 0; /* IRQ must not mfree */
+
+ NDBGL1(L1_I_MSG, "using 2nd ISAC TX buffer, state = %s", ifpi_printstate(sc));
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = L0IFPIUNIT(unit);
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
+ }
+ splx(s);
+ return(1);
+ }
+
+ NDBGL1(L1_I_ERR, "No Space in TX FIFO, state = %s", ifpi_printstate(sc));
+
+ if(freeflag == MBUF_FREE)
+ i4b_Dfreembuf(m);
+
+ splx(s);
+ return (0);
+ }
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = L0IFPIUNIT(unit);
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
+ }
+
+ sc->sc_state |= ISAC_TX_ACTIVE; /* set transmitter busy flag */
+
+ NDBGL1(L1_I_MSG, "ISAC_TX_ACTIVE set");
+
+ sc->sc_freeflag = 0; /* IRQ must NOT mfree */
+
+ ISAC_WRFIFO(m->m_data, min(m->m_len, ISAC_FIFO_LEN)); /* output to TX fifo */
+
+ if(m->m_len > ISAC_FIFO_LEN) /* message > 32 bytes ? */
+ {
+ sc->sc_obuf = m; /* save mbuf ptr */
+ sc->sc_op = m->m_data + ISAC_FIFO_LEN; /* ptr for irq hdl */
+ sc->sc_ol = m->m_len - ISAC_FIFO_LEN; /* length for irq hdl */
+
+ if(freeflag)
+ sc->sc_freeflag = 1; /* IRQ must mfree */
+
+ cmd = ISAC_CMDR_XTF;
+ }
+ else
+ {
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+
+ if(freeflag)
+ i4b_Dfreembuf(m);
+
+ cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME;
+ }
+
+ ISAC_WRITE(I_CMDR, cmd);
+ ISACCMDRWRDELAY();
+
+ splx(s);
+
+ return(1);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ * L2 -> L1: PH-ACTIVATE-REQUEST
+ * =============================
+ *
+ * parms:
+ * unit physical interface unit number
+ *
+ * returns:
+ * ==0
+ * !=0
+ *
+ *---------------------------------------------------------------------------*/
+int
+ifpi_ph_activate_req(int unit)
+{
+ struct l1_softc *sc = ifpi_scp[unit];
+ NDBGL1(L1_PRIM, "PH-ACTIVATE-REQ, unit %d", unit);
+ ifpi_next_state(sc, EV_PHAR);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * command from the upper layers
+ *---------------------------------------------------------------------------*/
+int
+ifpi_mph_command_req(int unit, int command, void *parm)
+{
+ struct l1_softc *sc = ifpi_scp[unit];
+
+ switch(command)
+ {
+ case CMR_DOPEN: /* daemon running */
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_DOPEN", unit);
+ sc->sc_enabled = 1;
+ break;
+
+ case CMR_DCLOSE: /* daemon not running */
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_DCLOSE", unit);
+ sc->sc_enabled = 0;
+ break;
+
+ case CMR_SETTRACE:
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_SETTRACE, parm = %d", unit, (unsigned int)parm);
+ sc->sc_trace = (unsigned int)parm;
+ break;
+
+ default:
+ NDBGL1(L1_ERROR, "ERROR, unknown command = %d, unit = %d, parm = %d", command, unit, (unsigned int)parm);
+ break;
+ }
+
+ return(0);
+}
+
+#endif /* NIFPI > 0 */
diff --git a/sys/i4b/layer1/ifpi/i4b_ifpi_l1fsm.c b/sys/i4b/layer1/ifpi/i4b_ifpi_l1fsm.c
new file mode 100644
index 000000000000..274ab9896906
--- /dev/null
+++ b/sys/i4b/layer1/ifpi/i4b_ifpi_l1fsm.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 1997, 2000 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_ifpi_l1fsm.c - AVM Fritz PCI layer 1 I.430 state machine
+ * ------------------------------------------------------------
+ *
+ * $Id: i4b_ifpi_l1fsm.c,v 1.4 2000/05/29 15:41:41 hm Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 15:23:15 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "ifpi.h"
+#include "pci.h"
+
+#if (NIFPI > 0) && (NPCI > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/ifpi/i4b_ifpi_ext.h>
+
+#if DO_I4B_DEBUG
+static char *state_text[N_STATES] = {
+ "F3 Deactivated",
+ "F4 Awaiting Signal",
+ "F5 Identifying Input",
+ "F6 Synchronized",
+ "F7 Activated",
+ "F8 Lost Framing",
+ "Illegal State"
+};
+
+static char *event_text[N_EVENTS] = {
+ "EV_PHAR PH_ACT_REQ",
+ "EV_T3 Timer 3 expired",
+ "EV_INFO0 INFO0 received",
+ "EV_RSY Level Detected",
+ "EV_INFO2 INFO2 received",
+ "EV_INFO48 INFO4 received",
+ "EV_INFO410 INFO4 received",
+ "EV_DR Deactivate Req",
+ "EV_PU Power UP",
+ "EV_DIS Disconnected",
+ "EV_EI Error Ind",
+ "Illegal Event"
+};
+#endif
+
+/* Function prototypes */
+
+static void timer3_expired (struct l1_softc *sc);
+static void T3_start (struct l1_softc *sc);
+static void T3_stop (struct l1_softc *sc);
+static void F_T3ex (struct l1_softc *sc);
+static void timer4_expired (struct l1_softc *sc);
+static void T4_start (struct l1_softc *sc);
+static void T4_stop (struct l1_softc *sc);
+static void F_AI8 (struct l1_softc *sc);
+static void F_AI10 (struct l1_softc *sc);
+static void F_I01 (struct l1_softc *sc);
+static void F_I02 (struct l1_softc *sc);
+static void F_I03 (struct l1_softc *sc);
+static void F_I2 (struct l1_softc *sc);
+static void F_ill (struct l1_softc *sc);
+static void F_NULL (struct l1_softc *sc);
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer3_expired(struct l1_softc *sc)
+{
+ if(sc->sc_I430T3)
+ {
+ NDBGL1(L1_T_ERR, "state = %s", ifpi_printstate(sc));
+ sc->sc_I430T3 = 0;
+
+ /* XXX try some recovery here XXX */
+
+ ifpi_recover(sc);
+
+ sc->sc_init_tries++; /* increment retry count */
+
+/*XXX*/ if(sc->sc_init_tries > 4)
+ {
+ int s = SPLI4B();
+
+ sc->sc_init_tries = 0;
+
+ if(sc->sc_obuf2 != NULL)
+ {
+ i4b_Dfreembuf(sc->sc_obuf2);
+ sc->sc_obuf2 = NULL;
+ }
+ if(sc->sc_obuf != NULL)
+ {
+ i4b_Dfreembuf(sc->sc_obuf);
+ sc->sc_obuf = NULL;
+ sc->sc_freeflag = 0;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ }
+
+ splx(s);
+
+ i4b_l1_mph_status_ind(L0IFPIUNIT(sc->sc_unit), STI_NOL1ACC, 0, NULL);
+ }
+
+ ifpi_next_state(sc, EV_T3);
+ }
+ else
+ {
+ NDBGL1(L1_T_ERR, "expired without starting it ....");
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 start
+ *---------------------------------------------------------------------------*/
+static void
+T3_start(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", ifpi_printstate(sc));
+ sc->sc_I430T3 = 1;
+ sc->sc_T3_callout = timeout((TIMEOUT_FUNC_T)timer3_expired,(struct l1_softc *)sc, 2*hz);
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 stop
+ *---------------------------------------------------------------------------*/
+static void
+T3_stop(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", ifpi_printstate(sc));
+
+ sc->sc_init_tries = 0; /* init connect retry count */
+
+ if(sc->sc_I430T3)
+ {
+ sc->sc_I430T3 = 0;
+ untimeout((TIMEOUT_FUNC_T)timer3_expired,(struct l1_softc *)sc, sc->sc_T3_callout);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expiry
+ *---------------------------------------------------------------------------*/
+static void
+F_T3ex(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_T3ex executing");
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_deactivate_ind(L0IFPIUNIT(sc->sc_unit));
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer4_expired(struct l1_softc *sc)
+{
+ if(sc->sc_I430T4)
+ {
+ NDBGL1(L1_T_MSG, "state = %s", ifpi_printstate(sc));
+ sc->sc_I430T4 = 0;
+ i4b_l1_mph_status_ind(L0IFPIUNIT(sc->sc_unit), STI_PDEACT, 0, NULL);
+ }
+ else
+ {
+ NDBGL1(L1_T_ERR, "expired without starting it ....");
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 start
+ *---------------------------------------------------------------------------*/
+static void
+T4_start(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", ifpi_printstate(sc));
+ sc->sc_I430T4 = 1;
+ sc->sc_T4_callout = timeout((TIMEOUT_FUNC_T)timer4_expired,(struct l1_softc *)sc, hz);
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 stop
+ *---------------------------------------------------------------------------*/
+static void
+T4_stop(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", ifpi_printstate(sc));
+
+ if(sc->sc_I430T4)
+ {
+ sc->sc_I430T4 = 0;
+ untimeout((TIMEOUT_FUNC_T)timer4_expired,(struct l1_softc *)sc, sc->sc_T4_callout);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI8
+ *---------------------------------------------------------------------------*/
+static void
+F_AI8(struct l1_softc *sc)
+{
+ T4_stop(sc);
+
+ NDBGL1(L1_F_MSG, "FSM function F_AI8 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_activate_ind(L0IFPIUNIT(sc->sc_unit));
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_8;
+
+ hdr.unit = L0IFPIUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI10
+ *---------------------------------------------------------------------------*/
+static void
+F_AI10(struct l1_softc *sc)
+{
+ T4_stop(sc);
+
+ NDBGL1(L1_F_MSG, "FSM function F_AI10 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_activate_ind(L0IFPIUNIT(sc->sc_unit));
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_10;
+
+ hdr.unit = L0IFPIUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in states F3 .. F5
+ *---------------------------------------------------------------------------*/
+static void
+F_I01(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I01 executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = L0IFPIUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F6
+ *---------------------------------------------------------------------------*/
+static void
+F_I02(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I02 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_deactivate_ind(L0IFPIUNIT(sc->sc_unit));
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = L0IFPIUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F7 or F8
+ *---------------------------------------------------------------------------*/
+static void
+F_I03(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I03 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_deactivate_ind(L0IFPIUNIT(sc->sc_unit));
+
+ T4_start(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = L0IFPIUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: activate request
+ *---------------------------------------------------------------------------*/
+static void
+F_AR(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_AR executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO1_8;
+
+ hdr.unit = L0IFPIUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_TE;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+
+ ifpi_isac_l1_cmd(sc, CMD_AR8);
+
+ T3_start(sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO2
+ *---------------------------------------------------------------------------*/
+static void
+F_I2(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I2 executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO2;
+
+ hdr.unit = L0IFPIUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+
+}
+
+/*---------------------------------------------------------------------------*
+ * illegal state default action
+ *---------------------------------------------------------------------------*/
+static void
+F_ill(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_ERR, "FSM function F_ill executing");
+}
+
+/*---------------------------------------------------------------------------*
+ * No action
+ *---------------------------------------------------------------------------*/
+static void
+F_NULL(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_NULL executing");
+}
+
+
+/*---------------------------------------------------------------------------*
+ * layer 1 state transition table
+ *---------------------------------------------------------------------------*/
+struct ifpi_state_tab {
+ void (*func) (struct l1_softc *sc); /* function to execute */
+ int newstate; /* next state */
+} ifpi_state_tab[N_EVENTS][N_STATES] = {
+
+/* STATE: F3 F4 F5 F6 F7 F8 ILLEGAL STATE */
+/* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/* EV_PHAR x*/ {{F_AR, ST_F4}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_ill, ST_ILL}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_T3 x*/ {{F_NULL, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_INFO0 */ {{F_I01, ST_F3}, {F_I01, ST_F4}, {F_I01, ST_F5}, {F_I02, ST_F3}, {F_I03, ST_F3}, {F_I03, ST_F3}, {F_ill, ST_ILL}},
+/* EV_RSY x*/ {{F_NULL, ST_F3}, {F_NULL, ST_F5}, {F_NULL, ST_F5}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_INFO2 */ {{F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_ill, ST_ILL}},
+/* EV_INFO48*/ {{F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_NULL, ST_F7}, {F_AI8, ST_F7}, {F_ill, ST_ILL}},
+/* EV_INFO41*/ {{F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_NULL, ST_F7}, {F_AI10, ST_F7}, {F_ill, ST_ILL}},
+/* EV_DR */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_PU */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_DIS */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}},
+/* EV_EI */ {{F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_ill, ST_ILL}},
+/* EV_ILL */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}
+};
+
+/*---------------------------------------------------------------------------*
+ * event handler
+ *---------------------------------------------------------------------------*/
+void
+ifpi_next_state(struct l1_softc *sc, int event)
+{
+ int currstate, newstate;
+
+ if(event >= N_EVENTS)
+ panic("i4b_l1fsm.c: event >= N_EVENTS\n");
+
+ currstate = sc->sc_I430state;
+
+ if(currstate >= N_STATES)
+ panic("i4b_l1fsm.c: currstate >= N_STATES\n");
+
+ newstate = ifpi_state_tab[event][currstate].newstate;
+
+ if(newstate >= N_STATES)
+ panic("i4b_l1fsm.c: newstate >= N_STATES\n");
+
+ NDBGL1(L1_F_MSG, "FSM event [%s]: [%s => %s]", event_text[event],
+ state_text[currstate],
+ state_text[newstate]);
+
+ (*ifpi_state_tab[event][currstate].func)(sc);
+
+ if(newstate == ST_ILL)
+ {
+ newstate = ST_F3;
+ NDBGL1(L1_F_ERR, "FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!",
+ state_text[currstate],
+ state_text[newstate],
+ event_text[event]);
+ }
+
+ sc->sc_I430state = newstate;
+}
+
+#if DO_I4B_DEBUG
+/*---------------------------------------------------------------------------*
+ * return pointer to current state description
+ *---------------------------------------------------------------------------*/
+char *
+ifpi_printstate(struct l1_softc *sc)
+{
+ return((char *) state_text[sc->sc_I430state]);
+}
+#endif
+
+#endif /* NIFPI > 0 */
diff --git a/sys/i4b/layer1/ifpnp/i4b_ifpnp_isac.c b/sys/i4b/layer1/ifpnp/i4b_ifpnp_isac.c
new file mode 100644
index 000000000000..83fe1bf7ef58
--- /dev/null
+++ b/sys/i4b/layer1/ifpnp/i4b_ifpnp_isac.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 1997, 2000 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_ifpnp_isac.c - i4b Fritz PnP ISAC handler
+ * ---------------------------------------------
+ *
+ * $Id: i4b_ifpnp_isac.c,v 1.3 2000/05/29 15:41:41 hm Exp $
+ * $Ust: src/i4b/layer1-nb/ifpnp/i4b_ifpnp_isac.c,v 1.4 2000/04/18 08:03:05 ust Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 15:24:49 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "ifpnp.h"
+
+#if (NIFPNP > 0)
+
+#include "opt_i4b.h"
+
+#include <sys/param.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_trace.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+#include <i4b/layer1/isic/i4b_hscx.h>
+
+#include <i4b/layer1/ifpnp/i4b_ifpnp_ext.h>
+
+#include <i4b/include/i4b_global.h>
+#include <i4b/include/i4b_mbuf.h>
+
+static u_char ifpnp_isac_exir_hdlr(register struct l1_softc *sc, u_char exir);
+static void ifpnp_isac_ind_hdlr(register struct l1_softc *sc, int ind);
+
+/*---------------------------------------------------------------------------*
+ * ISAC interrupt service routine
+ *---------------------------------------------------------------------------*/
+void
+ifpnp_isac_irq(struct l1_softc *sc, int ista)
+{
+ register u_char c = 0;
+ NDBGL1(L1_F_MSG, "unit %d: ista = 0x%02x", sc->sc_unit, ista);
+
+ if(ista & ISAC_ISTA_EXI) /* extended interrupt */
+ {
+ c |= ifpnp_isac_exir_hdlr(sc, ISAC_READ(I_EXIR));
+ }
+
+ if(ista & ISAC_ISTA_RME) /* receive message end */
+ {
+ register int rest;
+ u_char rsta;
+
+ /* get rx status register */
+
+ rsta = ISAC_READ(I_RSTA);
+
+ if((rsta & ISAC_RSTA_MASK) != 0x20)
+ {
+ int error = 0;
+
+ if(!(rsta & ISAC_RSTA_CRC)) /* CRC error */
+ {
+ error++;
+ NDBGL1(L1_I_ERR, "unit %d: CRC error", sc->sc_unit);
+ }
+
+ if(rsta & ISAC_RSTA_RDO) /* ReceiveDataOverflow */
+ {
+ error++;
+ NDBGL1(L1_I_ERR, "unit %d: Data Overrun error", sc->sc_unit);
+ }
+
+ if(rsta & ISAC_RSTA_RAB) /* ReceiveABorted */
+ {
+ error++;
+ NDBGL1(L1_I_ERR, "unit %d: Receive Aborted error", sc->sc_unit);
+ }
+
+ if(error == 0)
+ NDBGL1(L1_I_ERR, "unit %d: RME unknown error, RSTA = 0x%02x!", sc->sc_unit, rsta);
+
+ i4b_Dfreembuf(sc->sc_ibuf);
+
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+
+ ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES);
+ ISACCMDRWRDELAY();
+
+ return;
+ }
+
+ rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1));
+
+ if(rest == 0)
+ rest = ISAC_FIFO_LEN;
+
+ if(sc->sc_ibuf == NULL)
+ {
+ if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL)
+ sc->sc_ib = sc->sc_ibuf->m_data;
+ else
+ panic("ifpnp_isac_irq: RME, i4b_Dgetmbuf returns NULL!\n");
+ sc->sc_ilen = 0;
+ }
+
+ if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest))
+ {
+ ISAC_RDFIFO(sc->sc_ib, rest);
+ sc->sc_ilen += rest;
+
+ sc->sc_ibuf->m_pkthdr.len =
+ sc->sc_ibuf->m_len = sc->sc_ilen;
+
+ if(sc->sc_trace & TRACE_D_RX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = L0IFPNPUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_NT;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data);
+ }
+
+ c |= ISAC_CMDR_RMC;
+
+ if(sc->sc_enabled &&
+ (ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S))
+ {
+ i4b_l1_ph_data_ind(L0IFPNPUNIT(sc->sc_unit), sc->sc_ibuf);
+ }
+ else
+ {
+ i4b_Dfreembuf(sc->sc_ibuf);
+ }
+ }
+ else
+ {
+ NDBGL1(L1_I_ERR, "RME, input buffer overflow!");
+ i4b_Dfreembuf(sc->sc_ibuf);
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+ }
+
+ if(ista & ISAC_ISTA_RPF) /* receive fifo full */
+ {
+ if(sc->sc_ibuf == NULL)
+ {
+ if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL)
+ sc->sc_ib= sc->sc_ibuf->m_data;
+ else
+ panic("ifpnp_isac_irq: RPF, i4b_Dgetmbuf returns NULL!\n");
+ sc->sc_ilen = 0;
+ }
+
+ if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN))
+ {
+ ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN);
+ sc->sc_ilen += ISAC_FIFO_LEN;
+ sc->sc_ib += ISAC_FIFO_LEN;
+ c |= ISAC_CMDR_RMC;
+ }
+ else
+ {
+ NDBGL1(L1_I_ERR, "RPF, input buffer overflow!");
+ i4b_Dfreembuf(sc->sc_ibuf);
+ sc->sc_ibuf = NULL;
+ sc->sc_ib = NULL;
+ sc->sc_ilen = 0;
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+ }
+
+ if(ista & ISAC_ISTA_XPR) /* transmit fifo empty (XPR bit set) */
+ {
+ if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL))
+ {
+ sc->sc_freeflag = sc->sc_freeflag2;
+ sc->sc_obuf = sc->sc_obuf2;
+ sc->sc_op = sc->sc_obuf->m_data;
+ sc->sc_ol = sc->sc_obuf->m_len;
+ sc->sc_obuf2 = NULL;
+#ifdef NOTDEF
+ printf("ob2=%x, op=%x, ol=%d, f=%d #",
+ sc->sc_obuf,
+ sc->sc_op,
+ sc->sc_ol,
+ sc->sc_state);
+#endif
+ }
+ else
+ {
+#ifdef NOTDEF
+ printf("ob=%x, op=%x, ol=%d, f=%d #",
+ sc->sc_obuf,
+ sc->sc_op,
+ sc->sc_ol,
+ sc->sc_state);
+#endif
+ }
+
+ if(sc->sc_obuf)
+ {
+ ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN));
+
+ if(sc->sc_ol > ISAC_FIFO_LEN) /* length > 32 ? */
+ {
+ sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */
+ sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */
+ c |= ISAC_CMDR_XTF; /* set XTF bit */
+ }
+ else
+ {
+ if(sc->sc_freeflag)
+ {
+ i4b_Dfreembuf(sc->sc_obuf);
+ sc->sc_freeflag = 0;
+ }
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+
+ c |= ISAC_CMDR_XTF | ISAC_CMDR_XME;
+ }
+ }
+ else
+ {
+ sc->sc_state &= ~ISAC_TX_ACTIVE;
+ }
+ }
+
+ if(ista & ISAC_ISTA_CISQ) /* channel status change CISQ */
+ {
+ register u_char ci;
+
+ /* get command/indication rx register*/
+
+ ci = ISAC_READ(I_CIRR);
+
+ /* if S/Q IRQ, read SQC reg to clr SQC IRQ */
+
+ if(ci & ISAC_CIRR_SQC)
+ (void) ISAC_READ(I_SQRR);
+
+ /* C/I code change IRQ (flag already cleared by CIRR read) */
+
+ if(ci & ISAC_CIRR_CIC0)
+ ifpnp_isac_ind_hdlr(sc, (ci >> 2) & 0xf);
+ }
+
+ if(c)
+ {
+ ISAC_WRITE(I_CMDR, c);
+ ISACCMDRWRDELAY();
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * ISAC L1 Extended IRQ handler
+ *---------------------------------------------------------------------------*/
+static u_char
+ifpnp_isac_exir_hdlr(register struct l1_softc *sc, u_char exir)
+{
+ u_char c = 0;
+
+ if(exir & ISAC_EXIR_XMR)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Tx Message Repeat");
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_XDU)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Tx Data Underrun");
+
+ c |= ISAC_CMDR_XRES;
+ }
+
+ if(exir & ISAC_EXIR_PCE)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Protocol Error");
+ }
+
+ if(exir & ISAC_EXIR_RFO)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Rx Frame Overflow");
+
+ c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
+ }
+
+ if(exir & ISAC_EXIR_SOV)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Sync Xfer Overflow");
+ }
+
+ if(exir & ISAC_EXIR_MOS)
+ {
+ NDBGL1(L1_I_ERR, "EXIRQ Monitor Status");
+ }
+
+ if(exir & ISAC_EXIR_SAW)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ NDBGL1(L1_I_ERR, "EXIRQ Subscriber Awake");
+ }
+
+ if(exir & ISAC_EXIR_WOV)
+ {
+ /* cannot happen, STCR:TSF is set to 0 */
+
+ NDBGL1(L1_I_ERR, "EXIRQ Watchdog Timer Overflow");
+ }
+
+ return(c);
+}
+
+/*---------------------------------------------------------------------------*
+ * ISAC L1 Indication handler
+ *---------------------------------------------------------------------------*/
+static void
+ifpnp_isac_ind_hdlr(register struct l1_softc *sc, int ind)
+{
+ register int event;
+
+ switch(ind)
+ {
+ case ISAC_CIRR_IAI8:
+ NDBGL1(L1_I_CICO, "rx AI8 in state %s", ifpnp_printstate(sc));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ ifpnp_isac_l1_cmd(sc, CMD_AR8);
+ event = EV_INFO48;
+ i4b_l1_mph_status_ind(L0IFPNPUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL);
+ break;
+
+ case ISAC_CIRR_IAI10:
+ NDBGL1(L1_I_CICO, "rx AI10 in state %s", ifpnp_printstate(sc));
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ ifpnp_isac_l1_cmd(sc, CMD_AR10);
+ event = EV_INFO410;
+ i4b_l1_mph_status_ind(L0IFPNPUNIT(sc->sc_unit), STI_L1STAT, LAYER_ACTIVE, NULL);
+ break;
+
+ case ISAC_CIRR_IRSY:
+ NDBGL1(L1_I_CICO, "rx RSY in state %s", ifpnp_printstate(sc));
+ event = EV_RSY;
+ break;
+
+ case ISAC_CIRR_IPU:
+ NDBGL1(L1_I_CICO, "rx PU in state %s", ifpnp_printstate(sc));
+ event = EV_PU;
+ break;
+
+ case ISAC_CIRR_IDR:
+ NDBGL1(L1_I_CICO, "rx DR in state %s", ifpnp_printstate(sc));
+ ifpnp_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_DR;
+ break;
+
+ case ISAC_CIRR_IDID:
+ NDBGL1(L1_I_CICO, "rx DID in state %s", ifpnp_printstate(sc));
+ event = EV_INFO0;
+ i4b_l1_mph_status_ind(L0IFPNPUNIT(sc->sc_unit), STI_L1STAT, LAYER_IDLE, NULL);
+ break;
+
+ case ISAC_CIRR_IDIS:
+ NDBGL1(L1_I_CICO, "rx DIS in state %s", ifpnp_printstate(sc));
+ event = EV_DIS;
+ break;
+
+ case ISAC_CIRR_IEI:
+ NDBGL1(L1_I_CICO, "rx EI in state %s", ifpnp_printstate(sc));
+ ifpnp_isac_l1_cmd(sc, CMD_DIU);
+ event = EV_EI;
+ break;
+
+ case ISAC_CIRR_IARD:
+ NDBGL1(L1_I_CICO, "rx ARD in state %s", ifpnp_printstate(sc));
+ event = EV_INFO2;
+ break;
+
+ case ISAC_CIRR_ITI:
+ NDBGL1(L1_I_CICO, "rx TI in state %s", ifpnp_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_IATI:
+ NDBGL1(L1_I_CICO, "rx ATI in state %s", ifpnp_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ case ISAC_CIRR_ISD:
+ NDBGL1(L1_I_CICO, "rx SD in state %s", ifpnp_printstate(sc));
+ event = EV_INFO0;
+ break;
+
+ default:
+ NDBGL1(L1_I_ERR, "UNKNOWN Indication 0x%x in state %s", ind, ifpnp_printstate(sc));
+ event = EV_INFO0;
+ break;
+ }
+ ifpnp_next_state(sc, event);
+}
+
+/*---------------------------------------------------------------------------*
+ * execute a layer 1 command
+ *---------------------------------------------------------------------------*/
+void
+ifpnp_isac_l1_cmd(struct l1_softc *sc, int command)
+{
+ u_char cmd;
+
+#ifdef I4B_SMP_WORKAROUND
+
+ /* XXXXXXXXXXXXXXXXXXX */
+
+ /*
+ * patch from Wolfgang Helbig:
+ *
+ * Here is a patch that makes i4b work on an SMP:
+ * The card (TELES 16.3) didn't interrupt on an SMP machine.
+ * This is a gross workaround, but anyway it works *and* provides
+ * some information as how to finally fix this problem.
+ */
+
+ HSCX_WRITE(0, H_MASK, 0xff);
+ HSCX_WRITE(1, H_MASK, 0xff);
+ ISAC_WRITE(I_MASK, 0xff);
+ DELAY(100);
+ HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
+ HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ /* XXXXXXXXXXXXXXXXXXX */
+
+#endif /* I4B_SMP_WORKAROUND */
+
+ if(command < 0 || command > CMD_ILL)
+ {
+ NDBGL1(L1_I_ERR, "illegal cmd 0x%x in state %s", command, ifpnp_printstate(sc));
+ return;
+ }
+
+ if(sc->sc_bustyp == BUS_TYPE_IOM2)
+ cmd = ISAC_CIX0_LOW;
+ else
+ cmd = 0;
+
+ switch(command)
+ {
+ case CMD_TIM:
+ NDBGL1(L1_I_CICO, "tx TIM in state %s", ifpnp_printstate(sc));
+ cmd |= (ISAC_CIXR_CTIM << 2);
+ break;
+
+ case CMD_RS:
+ NDBGL1(L1_I_CICO, "tx RS in state %s", ifpnp_printstate(sc));
+ cmd |= (ISAC_CIXR_CRS << 2);
+ break;
+
+ case CMD_AR8:
+ NDBGL1(L1_I_CICO, "tx AR8 in state %s", ifpnp_printstate(sc));
+ cmd |= (ISAC_CIXR_CAR8 << 2);
+ break;
+
+ case CMD_AR10:
+ NDBGL1(L1_I_CICO, "tx AR10 in state %s", ifpnp_printstate(sc));
+ cmd |= (ISAC_CIXR_CAR10 << 2);
+ break;
+
+ case CMD_DIU:
+ NDBGL1(L1_I_CICO, "tx DIU in state %s", ifpnp_printstate(sc));
+ cmd |= (ISAC_CIXR_CDIU << 2);
+ break;
+ }
+ ISAC_WRITE(I_CIXR, cmd);
+}
+
+/*---------------------------------------------------------------------------*
+ * L1 ISAC initialization
+ *---------------------------------------------------------------------------*/
+int
+ifpnp_isac_init(struct l1_softc *sc)
+{
+ ISAC_IMASK = 0xff; /* disable all irqs */
+
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ if(sc->sc_bustyp != BUS_TYPE_IOM2)
+ {
+ NDBGL1(L1_I_SETUP, "configuring for IOM-1 mode");
+
+ /* ADF2: Select mode IOM-1 */
+ ISAC_WRITE(I_ADF2, 0x00);
+
+ /* SPCR: serial port control register:
+ * SPU - software power up = 0
+ * SAC - SIP port high Z
+ * SPM - timing mode 0
+ * TLP - test loop = 0
+ * C1C, C2C - B1 and B2 switched to/from SPa
+ */
+ ISAC_WRITE(I_SPCR, ISAC_SPCR_C1C1|ISAC_SPCR_C2C1);
+
+ /* SQXR: S/Q channel xmit register:
+ * SQIE - S/Q IRQ enable = 0
+ * SQX1-4 - Fa bits = 1
+ */
+ ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);
+
+ /* ADF1: additional feature reg 1:
+ * WTC - watchdog = 0
+ * TEM - test mode = 0
+ * PFS - pre-filter = 0
+ * CFS - IOM clock/frame always active
+ * FSC1/2 - polarity of 8kHz strobe
+ * ITF - interframe fill = idle
+ */
+ ISAC_WRITE(I_ADF1, ISAC_ADF1_FC2); /* ADF1 */
+
+ /* STCR: sync transfer control reg:
+ * TSF - terminal secific functions = 0
+ * TBA - TIC bus address = 7
+ * STx/SCx = 0
+ */
+ ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
+
+ /* MODE: Mode Register:
+ * MDSx - transparent mode 2
+ * TMD - timer mode = external
+ * RAC - Receiver enabled
+ * DIMx - digital i/f mode
+ */
+ ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);
+ }
+ else
+ {
+ NDBGL1(L1_I_SETUP, "configuring for IOM-2 mode");
+
+ /* ADF2: Select mode IOM-2 */
+ ISAC_WRITE(I_ADF2, ISAC_ADF2_IMS);
+
+ /* SPCR: serial port control register:
+ * SPU - software power up = 0
+ * SPM - timing mode 0
+ * TLP - test loop = 0
+ * C1C, C2C - B1 + C1 and B2 + IC2 monitoring
+ */
+ ISAC_WRITE(I_SPCR, 0x00);
+
+ /* SQXR: S/Q channel xmit register:
+ * IDC - IOM direction = 0 (master)
+ * CFS - Config Select = 0 (clock always active)
+ * CI1E - C/I channel 1 IRQ enable = 0
+ * SQIE - S/Q IRQ enable = 0
+ * SQX1-4 - Fa bits = 1
+ */
+ ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);
+
+ /* ADF1: additional feature reg 1:
+ * WTC - watchdog = 0
+ * TEM - test mode = 0
+ * PFS - pre-filter = 0
+ * IOF - IOM i/f off = 0
+ * ITF - interframe fill = idle
+ */
+ ISAC_WRITE(I_ADF1, 0x00);
+
+ /* STCR: sync transfer control reg:
+ * TSF - terminal secific functions = 0
+ * TBA - TIC bus address = 7
+ * STx/SCx = 0
+ */
+ ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
+
+ /* MODE: Mode Register:
+ * MDSx - transparent mode 2
+ * TMD - timer mode = external
+ * RAC - Receiver enabled
+ * DIMx - digital i/f mode
+ */
+ ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);
+ }
+
+#ifdef NOTDEF
+ /*
+ * XXX a transmitter reset causes an ISAC tx IRQ which will not
+ * be serviced at attach time under some circumstances leaving
+ * the associated IRQ line on the ISA bus active. This prevents
+ * any further interrupts to be serviced because no low -> high
+ * transition can take place anymore. (-hm)
+ */
+
+ /* command register:
+ * RRES - HDLC receiver reset
+ * XRES - transmitter reset
+ */
+ ISAC_WRITE(I_CMDR, ISAC_CMDR_RRES|ISAC_CMDR_XRES);
+ ISACCMDRWRDELAY();
+#endif
+
+ /* enabled interrupts:
+ * ===================
+ * RME - receive message end
+ * RPF - receive pool full
+ * XPR - transmit pool ready
+ * CISQ - CI or S/Q channel change
+ * EXI - extended interrupt
+ */
+
+ ISAC_IMASK = ISAC_MASK_RSC | /* auto mode only */
+ ISAC_MASK_TIN | /* timer irq */
+ ISAC_MASK_SIN; /* sync xfer irq */
+
+ ISAC_WRITE(I_MASK, ISAC_IMASK);
+
+ return(0);
+}
+
+#endif /* NIFPNP > 0 */
diff --git a/sys/i4b/layer1/ifpnp/i4b_ifpnp_l1.c b/sys/i4b/layer1/ifpnp/i4b_ifpnp_l1.c
new file mode 100644
index 000000000000..f2b4ad228397
--- /dev/null
+++ b/sys/i4b/layer1/ifpnp/i4b_ifpnp_l1.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 1997, 2000 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_ifpnp_l1.c - AVM Fritz PnP layer 1 handler
+ * ----------------------------------------------
+ *
+ * $Id: i4b_ifpnp_l1.c,v 1.4 2000/06/02 16:14:36 hm Exp $
+ * $Ust: src/i4b/layer1-nb/ifpnp/i4b_ifpnp_l1.c,v 1.4 2000/04/18 08:03:05 ust Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Fri Jun 2 14:55:49 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "ifpnp.h"
+
+#if (NIFPNP > 0)
+
+#include <sys/param.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_trace.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+#include <i4b/layer1/isic/i4b_isac.h>
+
+#include <i4b/layer1/ifpnp/i4b_ifpnp_ext.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/include/i4b_mbuf.h>
+#include <i4b/include/i4b_global.h>
+
+/*---------------------------------------------------------------------------*
+ *
+ * L2 -> L1: PH-DATA-REQUEST
+ * =========================
+ *
+ * parms:
+ * unit physical interface unit number
+ * m mbuf containing L2 frame to be sent out
+ * freeflag MBUF_FREE: free mbuf here after having sent
+ * it out
+ * MBUF_DONTFREE: mbuf is freed by Layer 2
+ * returns:
+ * ==0 fail, nothing sent out
+ * !=0 ok, frame sent out
+ *
+ *---------------------------------------------------------------------------*/
+int
+ifpnp_ph_data_req(int unit, struct mbuf *m, int freeflag)
+{
+ u_char cmd;
+ int s;
+ struct l1_softc *sc = ifpnp_scp[unit];
+
+#ifdef NOTDEF
+ NDBGL1(L1_PRIM, "PH-DATA-REQ, unit %d, freeflag=%d", unit, freeflag);
+#endif
+
+ if(m == NULL) /* failsafe */
+ return (0);
+
+ s = SPLI4B();
+
+ if(sc->sc_I430state == ST_F3) /* layer 1 not running ? */
+ {
+ NDBGL1(L1_I_ERR, "still in state F3!");
+ ifpnp_ph_activate_req(unit);
+ }
+
+ if(sc->sc_state & ISAC_TX_ACTIVE)
+ {
+ if(sc->sc_obuf2 == NULL)
+ {
+ sc->sc_obuf2 = m; /* save mbuf ptr */
+
+ if(freeflag)
+ sc->sc_freeflag2 = 1; /* IRQ must mfree */
+ else
+ sc->sc_freeflag2 = 0; /* IRQ must not mfree */
+
+ NDBGL1(L1_I_MSG, "using 2nd ISAC TX buffer, state = %s", ifpnp_printstate(sc));
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = L0IFPNPUNIT(unit);
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
+ }
+ splx(s);
+ return(1);
+ }
+
+ NDBGL1(L1_I_ERR, "No Space in TX FIFO, state = %s", ifpnp_printstate(sc));
+
+ if(freeflag == MBUF_FREE)
+ i4b_Dfreembuf(m);
+
+ splx(s);
+ return (0);
+ }
+
+ if(sc->sc_trace & TRACE_D_TX)
+ {
+ i4b_trace_hdr_t hdr;
+ hdr.unit = L0IFPNPUNIT(unit);
+ hdr.type = TRC_CH_D;
+ hdr.dir = FROM_TE;
+ hdr.count = ++sc->sc_trace_dcount;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
+ }
+
+ sc->sc_state |= ISAC_TX_ACTIVE; /* set transmitter busy flag */
+
+ NDBGL1(L1_I_MSG, "ISAC_TX_ACTIVE set");
+
+ sc->sc_freeflag = 0; /* IRQ must NOT mfree */
+
+ ISAC_WRFIFO(m->m_data, min(m->m_len, ISAC_FIFO_LEN)); /* output to TX fifo */
+
+ if(m->m_len > ISAC_FIFO_LEN) /* message > 32 bytes ? */
+ {
+ sc->sc_obuf = m; /* save mbuf ptr */
+ sc->sc_op = m->m_data + ISAC_FIFO_LEN; /* ptr for irq hdl */
+ sc->sc_ol = m->m_len - ISAC_FIFO_LEN; /* length for irq hdl */
+
+ if(freeflag)
+ sc->sc_freeflag = 1; /* IRQ must mfree */
+
+ cmd = ISAC_CMDR_XTF;
+ }
+ else
+ {
+ sc->sc_obuf = NULL;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+
+ if(freeflag)
+ i4b_Dfreembuf(m);
+
+ cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME;
+ }
+
+ ISAC_WRITE(I_CMDR, cmd);
+ ISACCMDRWRDELAY();
+
+ splx(s);
+
+ return(1);
+}
+
+/*---------------------------------------------------------------------------*
+ *
+ * L2 -> L1: PH-ACTIVATE-REQUEST
+ * =============================
+ *
+ * parms:
+ * unit physical interface unit number
+ *
+ * returns:
+ * ==0
+ * !=0
+ *
+ *---------------------------------------------------------------------------*/
+int
+ifpnp_ph_activate_req(int unit)
+{
+ struct l1_softc *sc = ifpnp_scp[unit];
+ NDBGL1(L1_PRIM, "PH-ACTIVATE-REQ, unit %d\n", unit);
+ ifpnp_next_state(sc, EV_PHAR);
+ return(0);
+}
+
+/*---------------------------------------------------------------------------*
+ * command from the upper layers
+ *---------------------------------------------------------------------------*/
+int
+ifpnp_mph_command_req(int unit, int command, void *parm)
+{
+ struct l1_softc *sc = ifpnp_scp[unit];
+
+ switch(command)
+ {
+ case CMR_DOPEN: /* daemon running */
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_DOPEN", unit);
+ sc->sc_enabled = 1;
+ break;
+
+ case CMR_DCLOSE: /* daemon not running */
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_DCLOSE", unit);
+ sc->sc_enabled = 0;
+ break;
+
+ case CMR_SETTRACE:
+ NDBGL1(L1_PRIM, "unit %d, command = CMR_SETTRACE, parm = %d", unit, (unsigned int)parm);
+ sc->sc_trace = (unsigned int)parm;
+ break;
+
+ default:
+ NDBGL1(L1_ERROR, "ERROR, unknown command = %d, unit = %d, parm = %d", command, unit, (unsigned int)parm);
+ break;
+ }
+
+ return(0);
+}
+
+#endif /* NIFPNP > 0 */
diff --git a/sys/i4b/layer1/ifpnp/i4b_ifpnp_l1fsm.c b/sys/i4b/layer1/ifpnp/i4b_ifpnp_l1fsm.c
new file mode 100644
index 000000000000..26b154031b5e
--- /dev/null
+++ b/sys/i4b/layer1/ifpnp/i4b_ifpnp_l1fsm.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 1997, 2000 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.
+ *
+ *---------------------------------------------------------------------------
+ *
+ * i4b_ifpnp_l1fsm.c - AVM Fritz PnP layer 1 I.430 state machine
+ * -------------------------------------------------------------
+ *
+ * $Id: i4b_ifpnp_l1fsm.c,v 1.4 2000/05/29 15:41:41 hm Exp $
+ * $Ust: src/i4b/layer1-nb/ifpnp/i4b_ifpnp_l1fsm.c,v 1.4 2000/04/18 08:03:05 ust Exp $
+ *
+ * $FreeBSD$
+ *
+ * last edit-date: [Mon May 29 15:25:04 2000]
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "ifpnp.h"
+
+#if (NIFPNP > 0)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+
+
+#include <net/if.h>
+
+#include <machine/i4b_debug.h>
+#include <machine/i4b_ioctl.h>
+#include <machine/i4b_trace.h>
+
+#include <i4b/layer1/isic/i4b_isic.h>
+
+#include <i4b/layer1/i4b_l1.h>
+
+#include <i4b/include/i4b_global.h>
+
+#include <i4b/include/i4b_mbuf.h>
+
+#include <i4b/layer1/ifpnp/i4b_ifpnp_ext.h>
+
+#if DO_I4B_DEBUG
+static char *state_text[N_STATES] = {
+ "F3 Deactivated",
+ "F4 Awaiting Signal",
+ "F5 Identifying Input",
+ "F6 Synchronized",
+ "F7 Activated",
+ "F8 Lost Framing",
+ "Illegal State"
+};
+
+static char *event_text[N_EVENTS] = {
+ "EV_PHAR PH_ACT_REQ",
+ "EV_T3 Timer 3 expired",
+ "EV_INFO0 INFO0 received",
+ "EV_RSY Level Detected",
+ "EV_INFO2 INFO2 received",
+ "EV_INFO48 INFO4 received",
+ "EV_INFO410 INFO4 received",
+ "EV_DR Deactivate Req",
+ "EV_PU Power UP",
+ "EV_DIS Disconnected",
+ "EV_EI Error Ind",
+ "Illegal Event"
+};
+#endif
+
+/* Function prototypes */
+
+static void timer3_expired (struct l1_softc *sc);
+static void T3_start (struct l1_softc *sc);
+static void T3_stop (struct l1_softc *sc);
+static void F_T3ex (struct l1_softc *sc);
+static void timer4_expired (struct l1_softc *sc);
+static void T4_start (struct l1_softc *sc);
+static void T4_stop (struct l1_softc *sc);
+static void F_AI8 (struct l1_softc *sc);
+static void F_AI10 (struct l1_softc *sc);
+static void F_I01 (struct l1_softc *sc);
+static void F_I02 (struct l1_softc *sc);
+static void F_I03 (struct l1_softc *sc);
+static void F_I2 (struct l1_softc *sc);
+static void F_ill (struct l1_softc *sc);
+static void F_NULL (struct l1_softc *sc);
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer3_expired(struct l1_softc *sc)
+{
+ if(sc->sc_I430T3)
+ {
+ NDBGL1(L1_T_ERR, "state = %s", ifpnp_printstate(sc));
+ sc->sc_I430T3 = 0;
+
+ /* XXX try some recovery here XXX */
+
+ ifpnp_recover(sc);
+
+ sc->sc_init_tries++; /* increment retry count */
+
+/*XXX*/ if(sc->sc_init_tries > 4)
+ {
+ int s = SPLI4B();
+
+ sc->sc_init_tries = 0;
+
+ if(sc->sc_obuf2 != NULL)
+ {
+ i4b_Dfreembuf(sc->sc_obuf2);
+ sc->sc_obuf2 = NULL;
+ }
+ if(sc->sc_obuf != NULL)
+ {
+ i4b_Dfreembuf(sc->sc_obuf);
+ sc->sc_obuf = NULL;
+ sc->sc_freeflag = 0;
+ sc->sc_op = NULL;
+ sc->sc_ol = 0;
+ }
+
+ splx(s);
+
+ i4b_l1_mph_status_ind(L0IFPNPUNIT(sc->sc_unit), STI_NOL1ACC, 0, NULL);
+ }
+
+ ifpnp_next_state(sc, EV_T3);
+ }
+ else
+ {
+ NDBGL1(L1_T_ERR, "expired without starting it ....");
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 start
+ *---------------------------------------------------------------------------*/
+static void
+T3_start(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", ifpnp_printstate(sc));
+ sc->sc_I430T3 = 1;
+ sc->sc_T3_callout = timeout((TIMEOUT_FUNC_T)timer3_expired,(struct l1_softc *)sc, 2*hz);
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 stop
+ *---------------------------------------------------------------------------*/
+static void
+T3_stop(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", ifpnp_printstate(sc));
+
+ sc->sc_init_tries = 0; /* init connect retry count */
+
+ if(sc->sc_I430T3)
+ {
+ sc->sc_I430T3 = 0;
+ untimeout((TIMEOUT_FUNC_T)timer3_expired,(struct l1_softc *)sc, sc->sc_T3_callout);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * I.430 Timer T3 expiry
+ *---------------------------------------------------------------------------*/
+static void
+F_T3ex(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_T3ex executing");
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_deactivate_ind(L0IFPNPUNIT(sc->sc_unit));
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 expire function
+ *---------------------------------------------------------------------------*/
+static void
+timer4_expired(struct l1_softc *sc)
+{
+ if(sc->sc_I430T4)
+ {
+ NDBGL1(L1_T_MSG, "state = %s", ifpnp_printstate(sc));
+ sc->sc_I430T4 = 0;
+ i4b_l1_mph_status_ind(L0IFPNPUNIT(sc->sc_unit), STI_PDEACT, 0, NULL);
+ }
+ else
+ {
+ NDBGL1(L1_T_ERR, "expired without starting it ....");
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 start
+ *---------------------------------------------------------------------------*/
+static void
+T4_start(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", ifpnp_printstate(sc));
+ sc->sc_I430T4 = 1;
+ sc->sc_T4_callout = timeout((TIMEOUT_FUNC_T)timer4_expired,(struct l1_softc *)sc, hz);
+}
+
+/*---------------------------------------------------------------------------*
+ * Timer T4 stop
+ *---------------------------------------------------------------------------*/
+static void
+T4_stop(struct l1_softc *sc)
+{
+ NDBGL1(L1_T_MSG, "state = %s", ifpnp_printstate(sc));
+
+ if(sc->sc_I430T4)
+ {
+ sc->sc_I430T4 = 0;
+ untimeout((TIMEOUT_FUNC_T)timer4_expired,(struct l1_softc *)sc, sc->sc_T4_callout);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI8
+ *---------------------------------------------------------------------------*/
+static void
+F_AI8(struct l1_softc *sc)
+{
+ T4_stop(sc);
+
+ NDBGL1(L1_F_MSG, "FSM function F_AI8 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_activate_ind(L0IFPNPUNIT(sc->sc_unit));
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_8;
+
+ hdr.unit = L0IFPNPUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received AI10
+ *---------------------------------------------------------------------------*/
+static void
+F_AI10(struct l1_softc *sc)
+{
+ T4_stop(sc);
+
+ NDBGL1(L1_F_MSG, "FSM function F_AI10 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_activate_ind(L0IFPNPUNIT(sc->sc_unit));
+
+ T3_stop(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO4_10;
+
+ hdr.unit = L0IFPNPUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in states F3 .. F5
+ *---------------------------------------------------------------------------*/
+static void
+F_I01(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I01 executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = L0IFPNPUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F6
+ *---------------------------------------------------------------------------*/
+static void
+F_I02(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I02 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_deactivate_ind(L0IFPNPUNIT(sc->sc_unit));
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = L0IFPNPUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO 0 in state F7 or F8
+ *---------------------------------------------------------------------------*/
+static void
+F_I03(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I03 executing");
+
+ if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
+ i4b_l1_ph_deactivate_ind(L0IFPNPUNIT(sc->sc_unit));
+
+ T4_start(sc);
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO0;
+
+ hdr.unit = L0IFPNPUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: activate request
+ *---------------------------------------------------------------------------*/
+static void
+F_AR(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_AR executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO1_8;
+
+ hdr.unit = L0IFPNPUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_TE;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+
+ ifpnp_isac_l1_cmd(sc, CMD_AR8);
+
+ T3_start(sc);
+}
+
+/*---------------------------------------------------------------------------*
+ * FSM function: received INFO2
+ *---------------------------------------------------------------------------*/
+static void
+F_I2(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_I2 executing");
+
+ if(sc->sc_trace & TRACE_I)
+ {
+ i4b_trace_hdr_t hdr;
+ char info = INFO2;
+
+ hdr.unit = L0IFPNPUNIT(sc->sc_unit);
+ hdr.type = TRC_CH_I;
+ hdr.dir = FROM_NT;
+ hdr.count = 0;
+ MICROTIME(hdr.time);
+ i4b_l1_trace_ind(&hdr, 1, &info);
+ }
+
+}
+
+/*---------------------------------------------------------------------------*
+ * illegal state default action
+ *---------------------------------------------------------------------------*/
+static void
+F_ill(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_ERR, "FSM function F_ill executing");
+}
+
+/*---------------------------------------------------------------------------*
+ * No action
+ *---------------------------------------------------------------------------*/
+static void
+F_NULL(struct l1_softc *sc)
+{
+ NDBGL1(L1_F_MSG, "FSM function F_NULL executing");
+}
+
+
+/*---------------------------------------------------------------------------*
+ * layer 1 state transition table
+ *---------------------------------------------------------------------------*/
+struct ifpnp_state_tab {
+ void (*func) (struct l1_softc *sc); /* function to execute */
+ int newstate; /* next state */
+} ifpnp_state_tab[N_EVENTS][N_STATES] = {
+
+/* STATE: F3 F4 F5 F6 F7 F8 ILLEGAL STATE */
+/* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/* EV_PHAR x*/ {{F_AR, ST_F4}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_ill, ST_ILL}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_T3 x*/ {{F_NULL, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_INFO0 */ {{F_I01, ST_F3}, {F_I01, ST_F4}, {F_I01, ST_F5}, {F_I02, ST_F3}, {F_I03, ST_F3}, {F_I03, ST_F3}, {F_ill, ST_ILL}},
+/* EV_RSY x*/ {{F_NULL, ST_F3}, {F_NULL, ST_F5}, {F_NULL, ST_F5}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_INFO2 */ {{F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_ill, ST_ILL}},
+/* EV_INFO48*/ {{F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_NULL, ST_F7}, {F_AI8, ST_F7}, {F_ill, ST_ILL}},
+/* EV_INFO41*/ {{F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_NULL, ST_F7}, {F_AI10, ST_F7}, {F_ill, ST_ILL}},
+/* EV_DR */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_PU */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}},
+/* EV_DIS */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}},
+/* EV_EI */ {{F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_ill, ST_ILL}},
+/* EV_ILL */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}
+};
+
+/*---------------------------------------------------------------------------*
+ * event handler
+ *---------------------------------------------------------------------------*/
+void
+ifpnp_next_state(struct l1_softc *sc, int event)
+{
+ int currstate, newstate;
+
+ if(event >= N_EVENTS)
+ panic("i4b_l1fsm.c: event >= N_EVENTS\n");
+
+ currstate = sc->sc_I430state;
+
+ if(currstate >= N_STATES)
+ panic("i4b_l1fsm.c: currstate >= N_STATES\n");
+
+ newstate = ifpnp_state_tab[event][currstate].newstate;
+
+ if(newstate >= N_STATES)
+ panic("i4b_l1fsm.c: newstate >= N_STATES\n");
+
+ NDBGL1(L1_F_MSG, "FSM event [%s]: [%s => %s]", event_text[event],
+ state_text[currstate],
+ state_text[newstate]);
+
+ (*ifpnp_state_tab[event][currstate].func)(sc);
+
+ if(newstate == ST_ILL)
+ {
+ newstate = ST_F3;
+ NDBGL1(L1_F_ERR, "FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!",
+ state_text[currstate],
+ state_text[newstate],
+ event_text[event]);
+ }
+
+ sc->sc_I430state = newstate;
+}
+
+#if DO_I4B_DEBUG
+/*---------------------------------------------------------------------------*
+ * return pointer to current state description
+ *---------------------------------------------------------------------------*/
+char *
+ifpnp_printstate(struct l1_softc *sc)
+{
+ return((char *) state_text[sc->sc_I430state]);
+}
+#endif
+
+#endif /* NIFPNP > 0 */
diff --git a/sys/net/if_ieee80211.h b/sys/net/if_ieee80211.h
new file mode 100644
index 000000000000..d4364c77d2c8
--- /dev/null
+++ b/sys/net/if_ieee80211.h
@@ -0,0 +1,171 @@
+/* $NetBSD: if_ieee80211.h,v 1.5 2000/07/21 04:47:40 onoe Exp $ */
+/* $FreeBSD$ */
+
+#ifndef _NET_IF_IEEE80211_H_
+#define _NET_IF_IEEE80211_H_
+
+/*
+ * generic definitions for IEEE 802.11 frames
+ */
+struct ieee80211_frame {
+ u_int8_t i_fc[2];
+ u_int8_t i_dur[2];
+ u_int8_t i_addr1[ETHER_ADDR_LEN];
+ u_int8_t i_addr2[ETHER_ADDR_LEN];
+ u_int8_t i_addr3[ETHER_ADDR_LEN];
+ u_int8_t i_seq[2];
+ /* possibly followed by addr4[ETHER_ADDR_LEN]; */
+};
+
+#define IEEE80211_FC0_VERSION_MASK 0x03
+#define IEEE80211_FC0_VERSION_0 0x00
+#define IEEE80211_FC0_TYPE_MASK 0x0c
+#define IEEE80211_FC0_TYPE_MGT 0x00
+#define IEEE80211_FC0_TYPE_CTL 0x04
+#define IEEE80211_FC0_TYPE_DATA 0x08
+
+#define IEEE80211_FC0_SUBTYPE_MASK 0xf0
+/* for TYPE_MGT */
+#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00
+#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10
+#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20
+#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30
+#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40
+#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50
+#define IEEE80211_FC0_SUBTYPE_BEACON 0x80
+#define IEEE80211_FC0_SUBTYPE_ATIM 0x90
+#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0
+#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0
+#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0
+/* for TYPE_CTL */
+#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0
+#define IEEE80211_FC0_SUBTYPE_RTS 0xb0
+#define IEEE80211_FC0_SUBTYPE_CTS 0xc0
+#define IEEE80211_FC0_SUBTYPE_ACK 0xd0
+#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0
+#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0
+/* for TYPE_DATA (bit combination) */
+#define IEEE80211_FC0_SUBTYPE_DATA 0x00
+#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10
+#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20
+#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30
+#define IEEE80211_FC0_SUBTYPE_NODATA 0x40
+#define IEEE80211_FC0_SUBTYPE_CFACK 0x50
+#define IEEE80211_FC0_SUBTYPE_CFPOLL 0x60
+#define IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK 0x70
+
+#define IEEE80211_FC1_DIR_MASK 0x03
+#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */
+#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */
+#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */
+#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */
+
+#define IEEE80211_FC1_MORE_FRAG 0x04
+#define IEEE80211_FC1_RETRY 0x08
+#define IEEE80211_FC1_PWR_MGT 0x10
+#define IEEE80211_FC1_MORE_DATA 0x20
+#define IEEE80211_FC1_WEP 0x40
+#define IEEE80211_FC1_ORDER 0x80
+
+/*
+ * Management Frames
+ */
+
+#define IEEE80211_ELEMID_SSID 0
+#define IEEE80211_ELEMID_RATES 1
+#define IEEE80211_ELEMID_FHPARMS 2
+#define IEEE80211_ELEMID_DSPARMS 3
+#define IEEE80211_ELEMID_CFPARMS 4
+#define IEEE80211_ELEMID_TIM 5
+#define IEEE80211_ELEMID_IBSSPARMS 6
+#define IEEE80211_ELEMID_CHALLENGE 16
+
+/*
+ * AUTH management packets
+ *
+ * octect algo[2]
+ * octect seq[2]
+ * octect status[2]
+ * octect chal.id
+ * octect chal.length
+ * octect chal.text[253]
+ */
+typedef u_int8_t * ieee80211_mgt_auth_t;
+
+#define IEEE80211_AUTH_ALGORITHM(auth) \
+ (auth[0] + (auth[1] << 8))
+#define IEEE80211_AUTH_TRANSACTION(auth) \
+ (auth[2] + (auth[3] << 8))
+#define IEEE80211_AUTH_STATUS(auth) \
+ (auth[4] + (auth[5] << 8))
+
+#define IEEE80211_AUTH_ALG_OPEN 0x0000
+#define IEEE80211_AUTH_ALG_SHARED 0x0001
+
+#define IEEE80211_CAPINFO_ESS 0x01
+#define IEEE80211_CAPINFO_IBSS 0x02
+#define IEEE80211_CAPINFO_CF_POLLABLE 0x04
+#define IEEE80211_CAPINFO_CF_POLLREQ 0x08
+#define IEEE80211_CAPINFO_PRIVACY 0x10
+
+/*
+ * Reason codes
+ *
+ * Unlisted codes are reserved
+ */
+#define IEEE80211_REASON_UNSPECIFIED 1
+#define IEEE80211_REASON_AUTH_EXPIRE 2
+#define IEEE80211_REASON_AUTH_LEAVE 3
+#define IEEE80211_REASON_ASSOC_EXPIRE 4
+#define IEEE80211_REASON_ASSOC_TOOMANY 5
+#define IEEE80211_REASON_NOT_AUTHED 6
+#define IEEE80211_REASON_NOT_ASSOCED 7
+#define IEEE80211_REASON_ASSOC_LEAVE 8
+#define IEEE80211_REASON_ASSOC_NOT_AUTHED 9
+
+/*
+ * Status code
+ *
+ * Unlisted codes are reserved
+ */
+#define IEEE80211_STATUS_SUCCESS 0x0000
+#define IEEE80211_STATUS_UNSPECIFIED 1
+#define IEEE80211_STATUS_CAPINFO 10
+#define IEEE80211_STATUS_NOT_ASSOCED 11
+#define IEEE80211_STATUS_OTHER 12
+#define IEEE80211_STATUS_ALG 13
+#define IEEE80211_STATUS_SEQUENCE 14
+#define IEEE80211_STATUS_CHALLENGE 15
+#define IEEE80211_STATUS_TIMEOUT 16
+
+#define IEEE80211_WEP_KEYLEN 5 /* 40bit */
+#define IEEE80211_WEP_IVLEN 3 /* 24bit */
+#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */
+#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */
+#define IEEE80211_WEP_NKID 4 /* number of key ids */
+
+#define IEEE80211_NWID_LEN 32
+
+/* nwid is pointed at by ifr.ifr_data */
+struct ieee80211_nwid {
+ u_int8_t i_len;
+ u_int8_t i_nwid[IEEE80211_NWID_LEN];
+};
+
+#define SIOCS80211NWID _IOWR('i', 230, struct ifreq)
+#define SIOCG80211NWID _IOWR('i', 231, struct ifreq)
+
+/* the first member must be matched with struct ifreq */
+struct ieee80211_nwkey {
+ char i_name[IFNAMSIZ]; /* if_name, e.g. "wi0" */
+ int i_wepon; /* wep enabled flag */
+ int i_defkid; /* default encrypt key id */
+ struct {
+ int i_keylen;
+ u_int8_t *i_keydat;
+ } i_key[IEEE80211_WEP_NKID];
+};
+#define SIOCS80211NWKEY _IOW('i', 232, struct ieee80211_nwkey)
+#define SIOCG80211NWKEY _IOWR('i', 233, struct ieee80211_nwkey)
+
+#endif /* !_NET_IF_IEEE80211_H_ */