Remove the NATM framework including the en(4), fatm(4), hatm(4), and

patm(4) devices.

Maintaining an address family and framework has real costs when we make
infrastructure improvements.  In the case of NATM we support no devices
manufactured in the last 20 years and some will not even work in modern
motherboards (some newer devices that patm(4) could be updated to
support apparently exist, but we do not currently have support).

With this change, support remains for some netgraph modules that don't
require NATM support code. It is unclear if all these should remain,
though ng_atmllc certainly stands alone.

Note well: FreeBSD 11 supports NATM and will continue to do so until at
least September 30, 2021.  Improvements to the code in FreeBSD 11 are
certainly welcome.

Reviewed by:	philip
Approved by:	harti
This commit is contained in:
Brooks Davis 2017-04-24 21:21:49 +00:00
parent 858f6fe327
commit a7dc31283a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=317383
102 changed files with 56 additions and 46876 deletions

View File

@ -38,6 +38,44 @@
# xargs -n1 | sort | uniq -d;
# done
# 20170424: NATM support removed
OLD_FILES+=rescue/atmconfig
OLD_FILES+=sbin/atmconfig
OLD_FILES+=usr/include/bsnmp/snmp_atm.h
OLD_FILES+=usr/include/dev/utopia/idtphy.h
OLD_FILES+=usr/include/dev/utopia/suni.h
OLD_FILES+=usr/include/dev/utopia/utopia.h
OLD_FILES+=usr/include/dev/utopia/utopia_priv.h
OLD_DIRS+=usr/include/dev/utopia
OLD_FILES+=usr/include/net/if_atm.h
OLD_FILES+=usr/include/netgraph/atm/ng_atm.h
OLD_FILES+=usr/include/netinet/if_atm.h
OLD_FILES+=usr/include/netnatm/natm.h
OLD_FILES+=usr/lib/debug/sbin/atmconfig.debug
OLD_FILES+=usr/lib/debug/usr/lib/snmp_atm.so.6.debug
OLD_FILES+=usr/lib/snmp_atm.so
OLD_FILES+=usr/lib/snmp_atm.so.6
OLD_FILES+=usr/share/doc/atm/atmconfig.help
OLD_FILES+=usr/share/doc/atm/atmconfig_device.help
OLD_DIRS+=usr/share/doc/atm
OLD_FILES+=usr/share/man/man3/snmp_atm.3.gz
OLD_FILES+=usr/share/man/man4/en.4.gz
OLD_FILES+=usr/share/man/man4/fatm.4.gz
OLD_FILES+=usr/share/man/man4/hatm.4.gz
OLD_FILES+=usr/share/man/man4/if_en.4.gz
OLD_FILES+=usr/share/man/man4/if_fatm.4.gz
OLD_FILES+=usr/share/man/man4/if_hatm.4.gz
OLD_FILES+=usr/share/man/man4/if_patm.4.gz
OLD_FILES+=usr/share/man/man4/natm.4.gz
OLD_FILES+=usr/share/man/man4/natmip.4.gz
OLD_FILES+=usr/share/man/man4/ng_atm.4.gz
OLD_FILES+=usr/share/man/man4/patm.4.gz
OLD_FILES+=usr/share/man/man4/utopia.4.gz
OLD_FILES+=usr/share/man/man8/atmconfig.8.gz
OLD_FILES+=usr/share/snmp/defs/atm_freebsd.def
OLD_FILES+=usr/share/snmp/defs/atm_tree.def
OLD_FILES+=usr/share/snmp/mibs/BEGEMOT-ATM-FREEBSD-MIB.txt
OLD_FILES+=usr/share/snmp/mibs/BEGEMOT-ATM.txt
# 20170420: remove GNU diff
OLD_FILES+=usr/share/man/man7/diff.7.gz
# 20170322: rename <x> to <x>_test to match the FreeBSD test suite name scheme

View File

@ -189,8 +189,6 @@
..
atf
..
atm
..
legal
..
llvm

View File

@ -40,14 +40,14 @@ LHDRS= aio.h errno.h fcntl.h linker_set.h poll.h stdatomic.h stdint.h \
syslog.h ucontext.h
LDIRS= bsm cam geom net net80211 netgraph netinet netinet6 \
netipsec netnatm netsmb nfs nfsclient nfsserver sys vm
netipsec netsmb nfs nfsclient nfsserver sys vm
LSUBDIRS= cam/ata cam/nvme cam/scsi \
dev/acpica dev/agp dev/an dev/bktr dev/ciss dev/filemon dev/firewire \
dev/hwpmc dev/hyperv \
dev/ic dev/iicbus dev/io dev/lmc dev/mfi dev/mmc dev/nvme \
dev/ofw dev/pbio dev/pci ${_dev_powermac_nvram} dev/ppbus dev/smbus \
dev/speaker dev/utopia dev/vkbd dev/wi \
dev/speaker dev/vkbd dev/wi \
fs/devfs fs/fdescfs fs/msdosfs fs/nandfs fs/nfs fs/nullfs \
fs/procfs fs/smbfs fs/udf fs/unionfs \
geom/cache geom/concat geom/eli geom/gate geom/journal geom/label \

View File

@ -455,7 +455,6 @@ getnameinfo_link(const struct afd *afd,
host, hostlen);
/*
* The following have zero-length addresses.
* IFT_ATM (net/if_atmsubr.c)
* IFT_GIF (net/if_gif.c)
* IFT_LOOP (net/if_loop.c)
* IFT_PPP (net/if_ppp.c, net/if_spppsubr.c)

View File

@ -101,10 +101,6 @@ CRUNCH_PROGS_sbin= badsect \
restore rcorder route savecore \
shutdown spppcontrol swapon sysctl tunefs umount
.if ${MK_ATM} != "no"
CRUNCH_PROGS_sbin+= atmconfig
.endif
.if ${MK_CCD} != "no"
CRUNCH_PROGS_sbin+= ccdconfig
.endif

View File

@ -70,7 +70,6 @@ SUBDIR=adjkerntz \
tunefs \
umount
SUBDIR.${MK_ATM}+= atm
SUBDIR.${MK_CCD}+= ccdconfig
SUBDIR.${MK_CXX}+= devd
SUBDIR.${MK_HAST}+= hastctl

View File

@ -1,28 +0,0 @@
# ===================================
# HARP | Host ATM Research Platform
# ===================================
#
# This Host ATM Research Platform ("HARP") file (the "Software") is
# made available by Network Computing Services, Inc. ("NetworkCS")
# "AS IS". NetworkCS does not provide maintenance, improvements or
# support of any kind.
#
# NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
# INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
# SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
# In no event shall NetworkCS be responsible for any damages, including
# but not limited to consequential damages, arising from or relating to
# any use of the Software or related support.
#
# Copyright 1994-1998 Network Computing Services, Inc.
#
# Copies of this Software may be made, however, the above copyright
# notice must be reproduced on all copies.
#
# @(#) $Id: Makefile,v 1.5 1998/07/10 16:01:58 jpt Exp $
# $FreeBSD$
SUBDIR= atmconfig
.include <bsd.subdir.mk>

View File

@ -1,26 +0,0 @@
# ===================================
# HARP | Host ATM Research Platform
# ===================================
#
# This Host ATM Research Platform ("HARP") file (the "Software") is
# made available by Network Computing Services, Inc. ("NetworkCS")
# "AS IS". NetworkCS does not provide maintenance, improvements or
# support of any kind.
#
# NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
# INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
# SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
# In no event shall NetworkCS be responsible for any damages, including
# but not limited to consequential damages, arising from or relating to
# any use of the Software or related support.
#
# Copyright 1994-1998 Network Computing Services, Inc.
#
# Copies of this Software may be made, however, the above copyright
# notice must be reproduced on all copies.
#
# @(#) $Id: Makefile.inc,v 1.5 1998/07/10 16:01:58 jpt Exp $
# $FreeBSD$
.include "../Makefile.inc"

View File

@ -1,44 +0,0 @@
# Copyright (c) 2001-2003
# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
# All rights reserved.
# Author: Harti Brandt <brandt@fokus.gmd.de>
#
# $FreeBSD$
.include <src.opts.mk>
PACKAGE=atm
PROG= atmconfig
SRCS= main.c diag.c natm.c
MAN= atmconfig.8
# CFLAGS+= -DPATH_HELP='".:${SHAREDIR}/doc/atm:/usr/local/share/doc/atm"'
CFLAGS+= -I${.OBJDIR}
.if !defined(RESCUE) && ${MK_BSNMP} != "no"
CFLAGS+= -DWITH_BSNMP
SRCS+= oid.h atmconfig_device.c
LIBADD+= bsnmp
. if ${MK_DYNAMICROOT} == "no" && ${MK_OPENSSL} != "no"
LIBADD+= crypto
. endif
.endif
CLEANFILES+= oid.h
# XXX - this is verboten
.if ${MACHINE_CPUARCH} == "arm"
WARNS?= 3
.endif
FILES= atmconfig.help atmconfig_device.help
FILESDIR= ${SHAREDIR}/doc/atm
SNMP_ATM_DEF= ${SRCTOP}/contrib/ngatm/snmp_atm/atm_tree.def \
${SRCTOP}/usr.sbin/bsnmpd/modules/snmp_atm/atm_freebsd.def
oid.h: atm_oid.list ${SNMP_ATM_DEF}
cat ${SNMP_ATM_DEF} | gensnmptree -e `tail -n +2 ${.CURDIR}/atm_oid.list` \
> ${.TARGET}
.include <bsd.prog.mk>

View File

@ -1,22 +0,0 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libbsnmp/libbsnmp \
lib/libc \
lib/libcompiler_rt \
lib/libnetgraph \
secure/lib/libcrypto \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -1,20 +0,0 @@
# $FreeBSD$
begemotAtmIfTable
begemotAtmIfName
begemotAtmIfNodeId
begemotAtmIfPcr
begemotAtmIfMedia
begemotAtmIfVpiBits
begemotAtmIfVciBits
begemotAtmIfMaxVpcs
begemotAtmIfMaxVccs
begemotAtmIfEsi
begemotAtmIfCarrierStatus
begemotAtmIfMode
begemotAtmIfTableLastChange
begemotAtmHWTable
begemotAtmHWVendor
begemotAtmHWDevice
begemotAtmHWSerial
begemotAtmHWVersion
begemotAtmHWSoftVersion

View File

@ -1,323 +0,0 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" 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.
.\"
.\" Author: Hartmut Brandt <harti@FreeBSD.org>
.\"
.\" $FreeBSD$
.\"
.Dd October 5, 2016
.Dt ATMCONFIG 8
.Os
.Sh NAME
.Nm atmconfig
.Nd "ATM configuration tool"
.Sh SYNOPSIS
.Nm
.Op Fl htv
.Op Ar command Op Ar sub-command Op ...
.Op Ar options
.Op Ar arg ...
.Sh DESCRIPTION
The
.Nm
tool is used to configure the Netgraph ATM network sub-system.
.Pp
The command line of
.Nm
generally consists of common options followed by a command string, optionally
followed by sub-command strings, optional command specific options and
command specific arguments.
Commands and sub-commands as well as command
specific options may be abbreviated as
long as there is only one match possible.
.Ss Common Options
The following common options change the overall behaviour of
.Nm :
.Bl -tag -width indent
.It Fl h
Print a very short usage info and exit.
.It Fl t
Several show-type commands output a header and then several lines
of information.
If this option is given, the header is omitted, simplifying the parsing
of the output.
.It Fl v
Be more verbose.
.El
.Ss Obtaining Help
The
.Ic help
command has a number of useful sub-commands.
.Pp
To get general help use:
.D1 Nm Ic help
.Pp
To get a list of available commands use:
.D1 Nm Ic help Cm commands
.Pp
To get a list of available sub-commands use:
.D1 Nm Ic help Ar command
.Pp
or (if there are deeper levels of sub-commands):
.D1 Nm Ic help Ar command sub-command ...
.Pp
To get a list of options and arguments for a command use:
.D1 Nm Ic help Ar command sub-command ...
(given that there are no further sub-command levels).
.Pp
To get a list of common options use:
.D1 Nm Ic help Cm options
.Ss The Ic diag Command
The
.Ic diag
command allows the inspection of the ATM interfaces on the local host
and the modification of device parameters.
Sub-commands are:
.Cm list
(print a list of interfaces),
.Cm config
(print hardware configuration),
.Cm phy
(access PHY chip),
.Cm stats
(print statistics) and
.Cm vcc
(print list of VCCs).
.Bl -tag -width indent
.\"----------------------------------------
.It Nm Ic diag Cm list
This sub-command lists all ATM interfaces in the system.
It takes no options or arguments.
.\"----------------------------------------
.It Xo
.Nm Ic diag Cm config
.Op Fl atm
.Op Fl hardware
.Op Ar device ...
.Xc
This command prints the configuration of ATM interfaces.
If no
.Ar device
is given, all devices are listed, otherwise only the specified devices.
The option
.Fl atm
instructs the command to print ATM layer configuration parameters like
the number of VCI and VPI bits, whereas the
.Fl hardware
option requests card specific information like the vendor or the serial
number.
If none of the options is given, the defaults is to assume
.Fl atm .
.\"----------------------------------------
.It Xo
.Nm Ic diag Cm phy print
.Op Fl numeric
.Ar device
.Xc
This command prints the PHY registers in a (potential)
human comprehensible format.
If
.Fl numeric
is given, the format is hex bytes.
Otherwise, textual representation will be printed.
.\"----------------------------------------
.It Nm Ic diag Cm phy show Op Ar device ...
This sub-command prints static information about the PHY device used
in the ATM card like the type of the PHY and the media.
.\"----------------------------------------
.It Xo
.Nm Ic diag Cm phy set
.Ar device
.Ar reg
.Ar mask
.Ar val
.Xc
This sub-command allows one to change bits in PHY registers.
This should be used with great care.
The bits of the given PHY chip register for which the corresponding bit in
.Ar mask
is one are set to the values of the corresponding bits in
.Ar val .
All register bits that have a zero in
.Ar mask
are written back with their original value.
.\"----------------------------------------
.It Xo
.Nm Ic diag Cm phy stats
.Op Fl clear
.Ar device
.Xc
Print the PHY statistics for the given
.Ar device .
When the optional
.Fl clear
is given, the statistics are cleared atomically.
.\"----------------------------------------
.It Xo
.Nm Ic diag Cm vcc
.Op Fl abr
.Op Fl channel
.Op Fl traffic
.Op Ar device
.Xc
Retrieve the list of currently active channels on either all
or the specified interfaces.
For each channel, the following information is printed depending
on the options (default is
.Fl channel ) .
.Bl -tag -width ".Fl traffic"
.It Fl abr
Print ABR specific traffic parameters: ICR, TBE, NRM, TRM, ADTF, RIF, RDF,
CDF.
.It Fl channel
Print basic information: VPI, VCI, AAL, traffic type, MTU and flags.
.It Fl traffic
Print traffic parameters: PCR, SCR, MBS, MCR.
.El
.\"----------------------------------------
.It Nm Ic diag Cm stats Ar device
Print driver specific statistics.
.El
.Ss The Ic natm Command
The
.Ic natm
command is used to change
.Xr natmip 4
routes on the local host.
The sub-commands for the routing table are:
.Cm add
(to add a new route),
.Cm delete
(to delete an existing route) and
.Cm show
(to print the currently installed NATM routes).
.Pp
.Bl -tag -width indent -compact
.\"----------------------------------------
.It Xo
.Nm Ic natm Cm add
.Ar dest
.Ar device
.Ar vpi
.Ar vci
.Ar encaps
.Xc
.It Xo
.Nm Ic natm Cm add
.Ar dest
.Ar device
.Ar vpi
.Ar vci
.Ar encaps
.Cm ubr Op Ar pcr
.Xc
.It Xo
.Nm Ic natm Cm add
.Ar dest
.Ar device
.Ar vpi
.Ar vci
.Ar encaps
.Cm cbr Ar pcr
.Xc
.It Xo
.Nm Ic natm Cm add
.Ar dest
.Ar device
.Ar vpi
.Ar vci
.Ar encaps
.Cm vbr Ar pcr scr mbs
.Xc
.It Xo
.Nm Ic natm Cm add
.Ar dest
.Ar device
.Ar vpi
.Ar vci
.Ar encaps
.Cm abr Ar pcr mcr icr tbe nrm trm adtf rif rdf cdf
.Xc
Add a new route to the routing table.
The destination address (the address
on the other end of the link) is given in
.Ar dest .
The
.Ar device ,
.Ar vpi
and
.Ar vci
arguments
are the name of the ATM device and the VPI and VCI values for the link.
The
.Ar encaps
argument
may be either
.Cm AAL5
or
.Cm LLC/SNAP
both of which specify AAL5 encapsulation, the first one without additional
encapsulation, the second one with LLC/SNAP headers.
The first two forms of the command add an UBR (unspecified bit rate) channel,
where the second form allows the optional specification of a peak cell
rate (PCR).
The third form adds a CBR (constant bit rate) channel where a PCR
must be given.
The fourth form adds a VBR (variable bit rate) channel.
The arguments are the peak cell rate, the sustainable cell rate and the
maximum bursts size.
The last form of the command adds an ABR (available bit rate) channel.
.\"----------------------------------------
.Pp
.It Nm Ic natm Cm delete Ar dest
.It Xo
.Nm Ic natm Cm delete
.Ar device
.Ar vpi
.Ar vci
.Xc
This commands deletes an NATM route.
The route may be specified either by the destination address or
by the
.Ar device , vpi
and
.Ar vci
triple.
.\"----------------------------------------
.Pp
.It Nm Ic natm Cm show
List all NATM routes.
.El
.Sh SEE ALSO
.Xr natm 4 ,
.Xr natmip 4
.Sh HISTORY
An
.Nm
command appeared in
.Fx 3.0 .
.Sh AUTHORS
.An Hartmut Brandt Aq Mt harti@FreeBSD.org

View File

@ -1,102 +0,0 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*/
#ifndef _ATMCONFIG_H
#define _ATMCONFIG_H
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <netgraph/ng_message.h>
#define DEFAULT_INTERFACE "hatm0"
struct cmdtab {
const char *string;
const struct cmdtab *sub;
void (*func)(int, char *[]);
};
/*
* client configuration info
*/
struct amodule {
const struct cmdtab *cmd;
};
#define DEF_MODULE(CMDTAB) \
struct amodule amodule_1 = { CMDTAB }
/* for compiled-in modules */
void register_module(const struct amodule *);
/* print a message if we are verbose */
void verb(const char *, ...) __printflike(1, 2);
/* print heading */
void heading(const char *, ...) __printflike(1, 2);
/* before starting output */
void heading_init(void);
/* stringify an enumerated value */
struct penum {
int32_t value;
const char *str;
};
const char *penum(int32_t value, const struct penum *strtab, char *buf);
int pparse(int32_t *, const struct penum *, const char *);
enum {
OPT_NONE,
OPT_UINT,
OPT_INT,
OPT_UINT32,
OPT_INT32,
OPT_UINT64,
OPT_INT64,
OPT_FLAG,
OPT_VCI,
OPT_STRING,
OPT_SIMPLE,
};
struct option {
const char *optstr;
int opttype;
void *optarg;
};
int parse_options(int *_pargc, char ***_pargv,
const struct option *_opts);
/* XXX while this is compiled in */
void device_register(void);
#endif /* _ATMCONFIG_H */

View File

@ -1,223 +0,0 @@
#
# Copyright (c) 2001-2003
# Fraunhofer Institute for Open Communication Systems (FhG Fokus).
# All rights reserved.
# Copyright (c) 2004
# Hartmut Brandt.
# All rights reserved.
#
# Author: Hartmut Brandt <harti@freebsd.org>
#
# 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.
#
# Help file for the atmconfig utility
#
# $FreeBSD$
#
^0 intro
ATM configuration utility.
usage:
atmconfig [common-options] command [subcommand] [options]
Use 'atmconfig help' for general help or 'atmconfig help <command>' for
help on 'command' or 'atmconfig help commands' for a list of commands.
^0 help
^^ help show help information
Use one of the following commands to get help on atmconfig:
atmconfig help options
gives you help on common command line options
atmconfig help commands
prints a list of available commands (and help items)
atmconfig help <command>
prints help on the given command (including a list of subcommands)
atmconfig help <command> <subcommand>
gives help on the given subcommand
^0 options
^^ help options list common options
Common command line options can be specified for all commands. They
are written immediately before the command. The following options are
available:
-h print short help
-t don't print headings for 'show'-type commands
-v be verbose about all actions.
^0 commands
^^ help commands show available commands
The following commands are available:
$MAIN
^0 diag
^^ diag show/modify ATM hardware interfaces
This command shows information about the ATM hardware interfaces in the
system. A list of ATM devices is obtained by:
atmconfig [common-options] diag list
Information about the hardware configuration of the ATM interfaces is
reported by:
atmconfig [common-options] diag config [options] [<device> ...]
The phy chip can be access with:
atmconfig [common-options] diag phy print [options] <device>
atmconfig [common-options] diag phy show <device>
atmconfig [common-options] diag phy set <device> <reg> <msk> <val>
atmconfig [common-options] diag phy set stats [options] <device>
A list of open VCCs can be obtained with:
atmconfig [common-options] diag vcc [<device> ...]
Driver internal statistics are printed with
atmconfig [common-options] diag stats <device>
^1 list
usage: atmconfig [common-options] diag list
List all known ATM devices in the system.
^1 config
usage: atmconfig [common-options] diag config [-hardware] [-atm] [device ...]
options:
-hardware print hardware related information
-atm print ATM related information
If now device is given as argument information about all devices is shown.
The default is to print only ATM related information.
^1 phy
To show the type of the PHY and its state:
atmconfig [common-options] diag phy show <device>
Change a PHY register (use with care):
atmconfig [common-options] diag phy set <device> <reg> <msk> <val>
Print the PHY registers in a human readable form:
atmconfig [common-options] diag phy print [-numeric] <device>
The PHY statistics can be printed with:
atmconfig [common-options] diag phy stats [-clear] <device>
^2 show
usage: atmconfig [common-options] diag phy show <device>
Show configuration and state information about the PHY chip on the given
ATM interface.
^2 set
usage: atmconfig [common-options] diag phy set <device> <reg> <msk> <val>
Set the bits of given PHY chip register for which the corresponding bit in
<msk> is one to the value of the corresponding bit in <val>. All register
bits that have a zero in <msk> are written back with there original value.
^2 print
usage: atmconfig [common-options] diag phy print [-numeric] <device>
options:
-numeric print registers in hex
Print the registers of the PHY chip in a human readable format.
^2 stats
usage: atmconfig [common-options] diag phy stats [-clear] <device>
options:
-clear clear the statistics atomically after reading them
Prints the PHY layer statistics of the PHY chip and optionally clears them.
^1 vcc
usage: atmconfig [common-options] diag vcc [-abr] [-channel] [-traffic]
[<device> ...]
options:
-abr print ABR specific traffic parameters
-channel print VPI, VCI, AAL, traffic type and flags (default)
-traffic print traffic parameters
Prints a list of all open vccs. The default output is -channel.
^1 stats
usage: atmconfig [common-options] diag stats <device>
Prints the driver-internal statistics.
^0 natm
^^ natm simple IP over ATM management (see natmip(4))
The group of CLIP commands is used to manage classical IP over ATM
networking via NATM (see natm(4) and natmip(4)). A new PVC is added
to a CLIP via:
atmconfig [common-options] natm add <dest> <device> <vpi> <vci>
<encaps> [<traffic> [<params> ...]]
The PVC can be deleted with:
atmconfig [common-options] natm del <device> <vpi> <vci>
The list of PVC that are currently active is retrieved with:
atmconfig [common-options] natm show
^1 add
usage: atmconfig [common-options] natm add [-printonly] <dest> <device>
<vpi> <vci> <encaps> [<traffic> [<params> ...]]
options:
-printonly don't execute, print the route(8) command
This subcommand adds a new CLIP PVC on the ATM interface <device>. The
host on the other end of the PVC has IP address <addr>. <encaps> is one
of llc/snap (LLC/SNAP encapsulated frames in AAL5) or aal5 (AAL5 frames
without LLC/SNAP). <traffic> specifies the traffic type of the PVC
and is one of UBR, CBR, VBR or ABR. If not given UBR is assumed. Depending
on the traffic type none or more parameters can follow:
ubr [<pcr>]
cbr <pcr>
vbr <pcr> <scr> <mbs>
abr <pcr> <mcr> <icr> <tbe> <nrm> <trm> <adtf> <rif> <rdf> <cdf>
^1 delete
usage: atmconfig [common-options] natm delete [-printonly] <dest>
or: atmconfig [common-options] natm delete [-printonly] <device> <vpi> <vci>
options:
-printonly don't execute, print the route(8) command
This subcommand deletes and existing CLIP PVC that can bei either identified
by the destination address or by the <device><vpi><vci> triple.
^1 show
usage: atmconfig [common-options] natm show [-abr] [-numeric]
options:
-abr show ABR parameters for ABR connections
-numeric print IP addresses numerically
This subcommand prints all ATM routes.

View File

@ -1,444 +0,0 @@
/*
* Copyright (c) 2001-2002
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
* Copyright (c) 2003-2004
* Hartmut Brandt.
* All rights reserved.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "atmconfig.h"
#include "atmconfig_device.h"
#include "private.h"
#include "oid.h"
#include <bsnmp/asn1.h>
#include <bsnmp/snmp.h>
#include <bsnmp/snmpclient.h>
/*
* Description of the begemotAtmIfTable
*/
static const struct snmp_table atmif_table = {
OIDX_begemotAtmIfTable,
OIDX_begemotAtmIfTableLastChange, 2,
sizeof(struct atmif),
1, 0x7ffULL,
{
{ 0,
SNMP_SYNTAX_INTEGER, offsetof(struct atmif, index) },
{ OID_begemotAtmIfName,
SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmif, ifname) },
{ OID_begemotAtmIfPcr,
SNMP_SYNTAX_GAUGE, offsetof(struct atmif, pcr) },
{ OID_begemotAtmIfMedia,
SNMP_SYNTAX_INTEGER, offsetof(struct atmif, media) },
{ OID_begemotAtmIfVpiBits,
SNMP_SYNTAX_GAUGE, offsetof(struct atmif, vpi_bits) },
{ OID_begemotAtmIfVciBits,
SNMP_SYNTAX_GAUGE, offsetof(struct atmif, vci_bits) },
{ OID_begemotAtmIfMaxVpcs,
SNMP_SYNTAX_GAUGE, offsetof(struct atmif, max_vpcs) },
{ OID_begemotAtmIfMaxVccs,
SNMP_SYNTAX_GAUGE, offsetof(struct atmif, max_vccs) },
{ OID_begemotAtmIfEsi,
SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmif, esi) },
{ OID_begemotAtmIfCarrierStatus,
SNMP_SYNTAX_INTEGER, offsetof(struct atmif, carrier) },
{ OID_begemotAtmIfMode,
SNMP_SYNTAX_INTEGER, offsetof(struct atmif, mode) },
{ 0, SNMP_SYNTAX_NULL, 0 }
}
};
/* List of all ATM interfaces */
struct atmif_list atmif_list = TAILQ_HEAD_INITIALIZER(atmif_list);
/*
* ATM hardware table
*/
struct atmhw {
TAILQ_ENTRY(atmhw) link;
uint64_t found;
int32_t index;
u_char *vendor;
size_t vendorlen;
u_char *device;
size_t devicelen;
uint32_t serial;
uint32_t version;
uint32_t soft_version;
};
TAILQ_HEAD(atmhw_list, atmhw);
/* list of ATM hardware */
static struct atmhw_list atmhw_list;
/*
* Read ATM hardware table
*/
static const struct snmp_table atmhw_table = {
OIDX_begemotAtmHWTable,
OIDX_begemotAtmIfTableLastChange, 2,
sizeof(struct atmhw),
1, 0x3fULL,
{
{ 0,
SNMP_SYNTAX_INTEGER, offsetof(struct atmhw, index) },
{ OID_begemotAtmHWVendor,
SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmhw, vendor) },
{ OID_begemotAtmHWDevice,
SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmhw, device) },
{ OID_begemotAtmHWSerial,
SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, serial) },
{ OID_begemotAtmHWVersion,
SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, version) },
{ OID_begemotAtmHWSoftVersion,
SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, soft_version) },
{ 0, SNMP_SYNTAX_NULL, 0 }
}
};
static void device_status(int, char *[]);
static void device_hardware(int, char *[]);
static void device_modify(int, char *[]);
static const struct cmdtab device_tab[] = {
{ "hardware", NULL, device_hardware },
{ "status", NULL, device_status },
{ "modify", NULL, device_modify },
{ NULL, NULL, NULL }
};
static const struct cmdtab entry =
{ "device", device_tab, NULL };
static DEF_MODULE(&entry);
/*
* Carrier state to string
*/
static const struct penum strcarrier[] = {
{ 1, "on" },
{ 2, "off" },
{ 3, "unknown" },
{ 4, "none" },
{ 0, NULL }
};
/*
* SUNI mode to string
*/
static const struct penum strsunimode[] = {
{ 1, "sonet" },
{ 2, "sdh" },
{ 3, "unknown" },
{ 0, NULL }
};
/*
* OIDs
*/
static const struct asn_oid
oid_begemotAtmIfMode = OIDX_begemotAtmIfMode;
/*
* Print 1st status line
*/
static void
dev_status1(const struct atmif *aif)
{
char buf[100];
printf("%-5u %-8s %-6u %-4u %-5u %-4u %-5u "
"%02x:%02x:%02x:%02x:%02x:%02x %s\n", aif->index,
aif->ifname, aif->pcr,
(1 << aif->vpi_bits) - 1, (1 << aif->vci_bits) - 1,
aif->max_vpcs, aif->max_vccs, aif->esi[0],
aif->esi[1], aif->esi[2], aif->esi[3], aif->esi[4], aif->esi[5],
penum(aif->carrier, strcarrier, buf));
}
/*
* Print 2nd status line
*/
static void
dev_status2(const struct atmif *aif)
{
char buf[100];
printf("%-5u %-8s %s\n", aif->index, aif->ifname,
penum(aif->mode, strsunimode, buf));
}
/*
* Implement the 'device status' command
*/
static void
device_status(int argc, char *argv[])
{
int opt, i;
struct atmif *aif;
static const struct option opts[] = {
{ NULL, 0, NULL }
};
const char dev1[] =
"Interface Max Max\n"
"Index Name PCR VPI VCI VPCs VCCs ESI Carrier\n";
const char dev2[] =
"Interface\n"
"Index Name Mode\n";
while ((opt = parse_options(&argc, &argv, opts)) != -1)
switch (opt) {
}
snmp_open(NULL, NULL, NULL, NULL);
atexit(snmp_close);
atmif_fetchtable();
if (TAILQ_EMPTY(&atmif_list))
errx(1, "no ATM interfaces found");
if (argc > 0) {
heading_init();
for (i = 0; i < argc; i++) {
if ((aif = atmif_find_name(argv[i])) == NULL) {
warnx("%s: no such ATM interface", argv[i]);
continue;
}
heading(dev1);
dev_status1(aif);
}
heading_init();
for (i = 0; i < argc; i++) {
if ((aif = atmif_find_name(argv[i])) == NULL)
continue;
heading(dev2);
dev_status2(aif);
}
} else {
heading_init();
TAILQ_FOREACH(aif, &atmif_list, link) {
heading(dev1);
dev_status1(aif);
}
heading_init();
TAILQ_FOREACH(aif, &atmif_list, link) {
heading(dev2);
dev_status2(aif);
}
}
}
/*
* Print hardware info line
*/
static void
dev_hardware(const struct atmif *aif)
{
const struct atmhw *hw;
TAILQ_FOREACH(hw, &atmhw_list, link)
if (aif->index == hw->index)
break;
if (hw == NULL) {
warnx("hardware info not found for '%s'", aif->ifname);
return;
}
printf("%-5u %-8s %-16s%-10s %-10u %-10u %u\n", aif->index,
aif->ifname, hw->vendor, hw->device, hw->serial,
hw->version, hw->soft_version);
}
/*
* Show hardware configuration
*/
static void
device_hardware(int argc, char *argv[])
{
int opt, i;
struct atmif *aif;
static const struct option opts[] = {
{ NULL, 0, NULL }
};
static const char headline[] =
"Interface \n"
"Index Name Vendor Card Serial HW SW\n";
while ((opt = parse_options(&argc, &argv, opts)) != -1)
switch (opt) {
}
snmp_open(NULL, NULL, NULL, NULL);
atexit(snmp_close);
atmif_fetchtable();
if (snmp_table_fetch(&atmhw_table, &atmhw_list) != 0)
errx(1, "AtmHW table: %s", snmp_client.error);
if (argc > 0) {
heading_init();
for (i = 0; i < argc; i++) {
if ((aif = atmif_find_name(argv[i])) == NULL) {
warnx("interface not found '%s'", argv[i]);
continue;
}
heading(headline);
dev_hardware(aif);
}
} else {
heading_init();
TAILQ_FOREACH(aif, &atmif_list, link) {
heading(headline);
dev_hardware(aif);
}
}
}
/*
* Change device parameters
*/
static void
device_modify(int argc, char *argv[])
{
int opt;
struct atmif *aif;
int mode = 0;
int n;
struct snmp_pdu pdu, resp;
static const struct option opts[] = {
#define MODIFY_MODE 0
{ "mode", OPT_STRING, NULL },
{ NULL, 0, NULL }
};
while ((opt = parse_options(&argc, &argv, opts)) != -1)
switch (opt) {
case MODIFY_MODE:
if (pparse(&mode, strsunimode, optarg) == -1 ||
mode == 3)
errx(1, "illegal mode for -m '%s'", optarg);
break;
}
if (argc != 1)
errx(1, "device modify needs one argument");
snmp_open(NULL, NULL, NULL, NULL);
atexit(snmp_close);
atmif_fetchtable();
if ((aif = atmif_find_name(argv[0])) == NULL)
errx(1, "%s: no such ATM interface", argv[0]);
snmp_pdu_create(&pdu, SNMP_PDU_SET);
if (mode != 0) {
n = snmp_add_binding(&pdu,
&oid_begemotAtmIfMode, SNMP_SYNTAX_INTEGER,
NULL);
snmp_oid_append(&pdu.bindings[n + 0].var, "i",
(asn_subid_t)aif->index);
pdu.bindings[n + 0].v.integer = mode;
}
if (pdu.nbindings == 0)
errx(1, "must specify something to modify");
if (snmp_dialog(&pdu, &resp))
errx(1, "No response from '%s': %s", snmp_client.chost,
snmp_client.error);
if (snmp_pdu_check(&pdu, &resp) <= 0)
errx(1, "Error modifying device");
snmp_pdu_free(&resp);
snmp_pdu_free(&pdu);
}
/* XXX while this is compiled in */
void
device_register(void)
{
register_module(&amodule_1);
}
/*
* Fetch the ATM interface table
*/
void
atmif_fetchtable(void)
{
struct atmif *aif;
while ((aif = TAILQ_FIRST(&atmif_list)) != NULL) {
free(aif->ifname);
free(aif->esi);
TAILQ_REMOVE(&atmif_list, aif, link);
free(aif);
}
if (snmp_table_fetch(&atmif_table, &atmif_list) != 0)
errx(1, "AtmIf table: %s", snmp_client.error);
}
/*
* Find a named ATM interface
*/
struct atmif *
atmif_find_name(const char *ifname)
{
struct atmif *atmif;
TAILQ_FOREACH(atmif, &atmif_list, link)
if (strcmp(atmif->ifname, ifname) == 0)
return (atmif);
return (NULL);
}
/*
* find an ATM interface by index
*/
struct atmif *
atmif_find(u_int idx)
{
struct atmif *atmif;
TAILQ_FOREACH(atmif, &atmif_list, link)
if (atmif->index == (int32_t)idx)
return (atmif);
return (NULL);
}

View File

@ -1,75 +0,0 @@
/*
* Copyright (c) 2001-2002
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
* Copyright (c) 2003-2004
* Hartmut Brandt.
* All rights reserved.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef ATMCONFIG_DEVICE_H_
#define ATMCONFIG_DEVICE_H_
#include <sys/types.h>
#include <sys/queue.h>
#include <stdint.h>
/*
* ATM interface table
*/
struct atmif {
TAILQ_ENTRY(atmif) link;
uint64_t found;
int32_t index;
char *ifname;
size_t ifnamelen;
uint32_t pcr;
int32_t media;
uint32_t vpi_bits;
uint32_t vci_bits;
uint32_t max_vpcs;
uint32_t max_vccs;
u_char *esi;
size_t esilen;
int32_t carrier;
int32_t mode;
};
TAILQ_HEAD(atmif_list, atmif);
/* list of all ATM interfaces */
extern struct atmif_list atmif_list;
/* fetch this table */
void atmif_fetchtable(void);
/* find an ATM interface by name */
struct atmif *atmif_find_name(const char *);
/* find an ATM interface by index */
struct atmif *atmif_find(u_int);
#endif

View File

@ -1,62 +0,0 @@
# Copyright (c) 2003-2004
# Hartmut Brandt.
# All rights reserved.
#
# Author: Hartmut Brandt <harti@freebsd.org>
#
# 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.
#
# Help file for the atmconfig utility
#
# $FreeBSD$
#
^0 device
^^ device show information about ATM hardware interfaces
This command shows information about the ATM hardware interfaces on the
system. Status information can be obtained by:
atmconfig [common-options] device status [options] [device ...]
Information about the hardware of the ATM interfaces is reported by:
atmconfig [common-options] device hardware [options] [device ...]
The parameters of the a device can be changed by:
atmconfig [common-options] device modify [options] <device>
^1 status
usage: atmconfig [common-options] device status [device ...]
If no device is given as argument information about all devices is shown.
^1 hardware
usage: atmconfig [common-options] device hardware [device ...]
If now device is given as argument information about all devices is shown.
^1 modify
usage: atmconfig [common-options] device modify [-mode mode] <device>
options:
-mode switch the SUNI mode to either 'sonet' or 'sdh'.

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +0,0 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*/
struct diagif {
TAILQ_ENTRY(diagif) link;
char ifname[IFNAMSIZ];
u_int index;
struct ifatm_mib mib;
int phy_present : 1;
u_int phy_type;
u_int phy_loopback;
char phy_name[100];
u_int phy_state;
u_int phy_carrier;
struct atmio_vcctable *vtab;
};
TAILQ_HEAD(diagif_list, diagif);
extern struct diagif_list diagif_list;
void diagif_fetch(void);
void diagif_fetch_vcc(struct diagif *aif, int fd);

View File

@ -1,880 +0,0 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/sysctl.h>
#include <netdb.h>
#include <stdarg.h>
#include <ctype.h>
#include <limits.h>
#include <stdint.h>
#include <fnmatch.h>
#include <dirent.h>
#ifdef WITH_BSNMP
#include <bsnmp/asn1.h>
#include <bsnmp/snmp.h>
#include <bsnmp/snmpclient.h>
#endif
#include "atmconfig.h"
#include "private.h"
/* verbosity level */
static int verbose;
/* notitle option */
static int notitle;
/* need to put heading before next output */
static int need_heading;
/*
* TOP LEVEL commands
*/
static void help_func(int argc, char *argv[]) __dead2;
static const struct cmdtab static_main_tab[] = {
{ "help", NULL, help_func },
{ "options", NULL, NULL },
{ "commands", NULL, NULL },
{ "diag", diag_tab, NULL },
{ "natm", natm_tab, NULL },
{ NULL, NULL, NULL }
};
static struct cmdtab *main_tab = NULL;
static size_t main_tab_size = sizeof(static_main_tab) /
sizeof(static_main_tab[0]);
static int
substr(const char *s1, const char *s2)
{
return (strlen(s1) <= strlen(s2) && strncmp(s1, s2, strlen(s1)) == 0);
}
/*
* Current help file state
*/
struct help_file {
int file_state; /* 0:looking for main file, 1:found, 2:other */
const char *p_start; /* current path pointer */
const char *p_end; /* end of current path in path */
char *dirname; /* directory name */
DIR *dir; /* open directory */
char *fname; /* current filename */
FILE *fp; /* open file */
char line[LINE_MAX]; /* current line */
u_int fcnt; /* count of files found */
};
struct help_pos {
off_t pos; /* file position */
u_int fcnt; /* number of file */
char *fname; /* name of file */
const char *p_start; /* current path pointer */
const char *p_end; /* end of current path in path */
};
static int
help_next_file(struct help_file *hp)
{
const char *fpat;
struct dirent *ent;
if (hp->file_state == 3)
return (-1);
if (hp->file_state == 0)
fpat = FILE_HELP;
else
fpat = FILE_HELP_OTHERS;
if (hp->file_state == 0 || hp->file_state == 1) {
/* start from beginning */
hp->p_start = PATH_HELP;
hp->file_state++;
}
try_file:
if (hp->dir != NULL) {
/* directory open (must be state 2) */
while ((ent = readdir(hp->dir)) != NULL) {
if (fnmatch(fpat, ent->d_name, FNM_NOESCAPE) != 0)
continue;
if (asprintf(&hp->fname, "%s/%s", hp->dirname,
ent->d_name) == -1)
err(1, NULL);
if ((hp->fp = fopen(hp->fname, "r")) != NULL) {
hp->fcnt++;
return (0);
}
free(hp->fname);
}
/* end of directory */
closedir(hp->dir);
hp->dir = NULL;
free(hp->dirname);
goto next_path;
}
/* nothing open - advanc to new path element */
try_path:
for (hp->p_end = hp->p_start; *hp->p_end != '\0' &&
*hp->p_end != ':'; hp->p_end++)
;
if (asprintf(&hp->dirname, "%.*s", (int)(hp->p_end - hp->p_start),
hp->p_start) == -1)
err(1, NULL);
if (hp->file_state == 1) {
/* just try to open */
if (asprintf(&hp->fname, "%s/%s", hp->dirname, fpat) == -1)
err(1, NULL);
if ((hp->fp = fopen(hp->fname, "r")) != NULL) {
hp->fcnt++;
return (0);
}
free(hp->fname);
goto next_path;
}
/* open directory */
if ((hp->dir = opendir(hp->dirname)) != NULL)
goto try_file;
free(hp->dirname);
next_path:
hp->p_start = hp->p_end;
if (*hp->p_start == '\0') {
/* end of path */
if (hp->file_state == 1)
errx(1, "help file not found");
return (-1);
}
hp->p_start++;
goto try_path;
}
/*
* Save current file position
*/
static void
help_file_tell(struct help_file *hp, struct help_pos *pos)
{
if (pos->fname != NULL)
free(pos->fname);
if ((pos->fname = strdup(hp->fname)) == NULL)
err(1, NULL);
pos->fcnt = hp->fcnt;
pos->p_start = hp->p_start;
pos->p_end = hp->p_end;
if ((pos->pos = ftello(hp->fp)) == -1)
err(1, "%s", pos->fname);
}
/*
* Go to that position
*
* We can go either to the original help file or back in the current file.
*/
static void
help_file_seek(struct help_file *hp, struct help_pos *pos)
{
hp->p_start = pos->p_start;
hp->p_end = pos->p_end;
hp->fcnt = pos->fcnt;
if (hp->dir != NULL) {
free(hp->dirname);
closedir(hp->dir);
hp->dir = NULL;
}
if (hp->fp != NULL &&strcmp(hp->fname, pos->fname) != 0) {
free(hp->fname);
fclose(hp->fp);
hp->fp = NULL;
}
if (hp->fp == NULL) {
if ((hp->fname = strdup(pos->fname)) == NULL)
err(1, NULL);
if ((hp->fp = fopen(hp->fname, "r")) == NULL)
err(1, "reopen %s", hp->fname);
}
if (fseeko(hp->fp, pos->pos, SEEK_SET) == -1)
err(1, "seek %s", hp->fname);
if (pos->fcnt == 1)
/* go back to state 1 */
hp->file_state = 1;
else
/* lock */
hp->file_state = 3;
}
/*
* Rewind to position 0
*/
static void
help_file_rewind(struct help_file *hp)
{
if (hp->file_state == 1) {
if (fseeko(hp->fp, (off_t)0, SEEK_SET) == -1)
err(1, "rewind help file");
return;
}
if (hp->dir != NULL) {
free(hp->dirname);
closedir(hp->dir);
hp->dir = NULL;
}
if (hp->fp != NULL) {
free(hp->fname);
fclose(hp->fp);
hp->fp = NULL;
}
memset(hp, 0, sizeof(*hp));
}
/*
* Get next line from a help file
*/
static const char *
help_next_line(struct help_file *hp)
{
for (;;) {
if (hp->fp != NULL) {
if (fgets(hp->line, sizeof(hp->line), hp->fp) != NULL)
return (hp->line);
if (ferror(hp->fp))
err(1, "%s", hp->fname);
free(hp->fname);
fclose(hp->fp);
hp->fp = NULL;
}
if (help_next_file(hp) == -1)
return (NULL);
}
}
/*
* This function prints the available 0-level help topics from all
* other help files by scanning the files. It assumes, that this is called
* only from the main help file.
*/
static void
help_get_0topics(struct help_file *hp)
{
struct help_pos save;
const char *line;
memset(&save, 0, sizeof(save));
help_file_tell(hp, &save);
help_file_rewind(hp);
while ((line = help_next_line(hp)) != NULL) {
if (line[0] == '^' && line[1] == '^')
printf("%s", line + 2);
}
help_file_seek(hp, &save);
}
/*
* Function to print help. The help argument is in argv[0] here.
*/
static void
help_func(int argc, char *argv[])
{
struct help_file hfile;
struct help_pos match, last_match;
const char *line;
char key[100];
int level;
int i, has_sub_topics;
memset(&hfile, 0, sizeof(hfile));
memset(&match, 0, sizeof(match));
memset(&last_match, 0, sizeof(last_match));
if (argc == 0) {
/* only 'help' - show intro */
if ((argv[0] = strdup("intro")) == NULL)
err(1, NULL);
argc = 1;
}
optind = 0;
match.pos = -1;
last_match.pos = -1;
for (;;) {
/* read next line */
if ((line = help_next_line(&hfile)) == NULL) {
/* EOF */
level = 999;
goto stop;
}
if (line[0] != '^' || line[1] == '^')
continue;
if (sscanf(line + 1, "%d%99s", &level, key) != 2)
errx(1, "error in help file '%s'", line);
if (level < optind) {
stop:
/* next higher level entry - stop this level */
if (match.pos == -1) {
/* not found */
goto not_found;
}
/* go back to the match */
help_file_seek(&hfile, &match);
last_match = match;
memset(&match, 0, sizeof(match));
match.pos = -1;
/* go to next key */
if (++optind >= argc)
break;
}
if (level == optind) {
if (substr(argv[optind], key)) {
if (match.pos != -1) {
printf("Ambiguous topic.");
goto list_topics;
}
help_file_tell(&hfile, &match);
}
}
}
/* before breaking above we have seeked back to the matching point */
for (;;) {
if ((line = help_next_line(&hfile)) == NULL)
break;
if (line[0] == '#')
continue;
if (line[0] == '^') {
if (line[1] == '^')
continue;
break;
}
if (strncmp(line, "$MAIN", 5) == 0) {
help_get_0topics(&hfile);
continue;
}
printf("%s", line);
}
exit(0);
not_found:
printf("Topic not found.");
list_topics:
printf(" Use one of:\natmconfig help");
for (i = 0; i < optind; i++)
printf(" %s", argv[i]);
printf(" [");
/* list all the keys at this level */
if (last_match.pos == -1)
/* go back to start of help */
help_file_rewind(&hfile);
else
help_file_seek(&hfile, &last_match);
has_sub_topics = 0;
while ((line = help_next_line(&hfile)) != NULL) {
if (line[0] == '#' || line[0] != '^' || line[1] == '^')
continue;
if (sscanf(line + 1, "%d%99s", &level, key) != 2)
errx(1, "error in help file '%s'", line);
if (level < optind)
break;
if (level == optind) {
has_sub_topics = 1;
printf(" %s", key);
}
}
printf(" ].");
if (!has_sub_topics)
printf(" No sub-topics found.");
printf("\n");
exit(1);
}
#ifdef WITH_BSNMP
/*
* Parse a server specification
*
* syntax is [trans::][community@][server][:port]
*/
static void
parse_server(char *name)
{
char *p, *s = name;
/* look for a double colon */
for (p = s; *p != '\0'; p++) {
if (*p == '\\' && p[1] != '\0') {
p++;
continue;
}
if (*p == ':' && p[1] == ':')
break;
}
if (*p != '\0') {
if (p > s) {
if (p - s == 3 && strncmp(s, "udp", 3) == 0)
snmp_client.trans = SNMP_TRANS_UDP;
else if (p - s == 6 && strncmp(s, "stream", 6) == 0)
snmp_client.trans = SNMP_TRANS_LOC_STREAM;
else if (p - s == 5 && strncmp(s, "dgram", 5) == 0)
snmp_client.trans = SNMP_TRANS_LOC_DGRAM;
else
errx(1, "unknown SNMP transport '%.*s'",
(int)(p - s), s);
}
s = p + 2;
}
/* look for a @ */
for (p = s; *p != '\0'; p++) {
if (*p == '\\' && p[1] != '\0') {
p++;
continue;
}
if (*p == '@')
break;
}
if (*p != '\0') {
if (p - s > SNMP_COMMUNITY_MAXLEN)
err(1, "community string too long");
strncpy(snmp_client.read_community, s, p - s);
snmp_client.read_community[p - s] = '\0';
strncpy(snmp_client.write_community, s, p - s);
snmp_client.write_community[p - s] = '\0';
s = p + 1;
}
/* look for a colon */
for (p = s; *p != '\0'; p++) {
if (*p == '\\' && p[1] != '\0') {
p++;
continue;
}
if (*p == ':')
break;
}
if (*p == ':') {
if (p > s) {
*p = '\0';
snmp_client_set_host(&snmp_client, s);
*p = ':';
}
snmp_client_set_port(&snmp_client, p + 1);
} else if (p > s)
snmp_client_set_host(&snmp_client, s);
}
#endif
int
main(int argc, char *argv[])
{
int opt, i;
const struct cmdtab *match, *cc, *tab;
#ifdef WITH_BSNMP
snmp_client_init(&snmp_client);
snmp_client.trans = SNMP_TRANS_LOC_STREAM;
snmp_client_set_host(&snmp_client, PATH_ILMI_SOCK);
#endif
#ifdef WITH_BSNMP
#define OPTSTR "htvs:"
#else
#define OPTSTR "htv"
#endif
while ((opt = getopt(argc, argv, OPTSTR)) != -1)
switch (opt) {
case 'h':
help_func(0, argv);
#ifdef WITH_BSNMP
case 's':
parse_server(optarg);
break;
#endif
case 'v':
verbose++;
break;
case 't':
notitle = 1;
break;
}
if (argv[optind] == NULL)
help_func(0, argv);
argc -= optind;
argv += optind;
if ((main_tab = malloc(sizeof(static_main_tab))) == NULL)
err(1, NULL);
memcpy(main_tab, static_main_tab, sizeof(static_main_tab));
#ifdef WITH_BSNMP
/* XXX while this is compiled in */
device_register();
#endif
cc = main_tab;
i = 0;
for (;;) {
/*
* Scan the table for a match
*/
tab = cc;
match = NULL;
while (cc->string != NULL) {
if (substr(argv[i], cc->string)) {
if (match != NULL) {
printf("Ambiguous option '%s'",
argv[i]);
cc = tab;
goto subopts;
}
match = cc;
}
cc++;
}
if ((cc = match) == NULL) {
printf("Unknown option '%s'", argv[i]);
cc = tab;
goto subopts;
}
/*
* Have a match. If there is no subtable, there must
* be either a handler or the command is only a help entry.
*/
if (cc->sub == NULL) {
if (cc->func != NULL)
break;
printf("Unknown option '%s'", argv[i]);
cc = tab;
goto subopts;
}
/*
* Look at the next argument. If it doesn't exist or it
* looks like a switch, terminate the scan here.
*/
if (argv[i + 1] == NULL || argv[i + 1][0] == '-') {
if (cc->func != NULL)
break;
printf("Need sub-option for '%s'", argv[i]);
cc = cc->sub;
goto subopts;
}
cc = cc->sub;
i++;
}
argc -= i + 1;
argv += i + 1;
(*cc->func)(argc, argv);
return (0);
subopts:
printf(". Select one of:\n");
while (cc->string != NULL) {
if (cc->func != NULL || cc->sub != NULL)
printf("%s ", cc->string);
cc++;
}
printf("\n");
return (1);
}
void
verb(const char *fmt, ...)
{
va_list ap;
if (verbose) {
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
}
void
heading(const char *fmt, ...)
{
va_list ap;
if (need_heading) {
need_heading = 0;
if (!notitle) {
va_start(ap, fmt);
fprintf(stdout, fmt, ap);
va_end(ap);
}
}
}
void
heading_init(void)
{
need_heading = 1;
}
/*
* stringify an enumerated value
*/
const char *
penum(int32_t value, const struct penum *strtab, char *buf)
{
while (strtab->str != NULL) {
if (strtab->value == value) {
strcpy(buf, strtab->str);
return (buf);
}
strtab++;
}
warnx("illegal value for enumerated variable '%d'", value);
strcpy(buf, "?");
return (buf);
}
/*
* And the other way 'round
*/
int
pparse(int32_t *val, const struct penum *tab, const char *str)
{
while (tab->str != NULL) {
if (strcmp(tab->str, str) == 0) {
*val = tab->value;
return (0);
}
tab++;
}
return (-1);
}
/*
* Parse command line options
*/
int
parse_options(int *pargc, char ***pargv, const struct option *opts)
{
const struct option *o, *m;
char *arg;
u_long ularg, ularg1;
long larg;
char *end;
if (*pargc == 0)
return (-1);
arg = (*pargv)[0];
if (arg[0] != '-' || arg[1] == '\0')
return (-1);
if (arg[1] == '-' && arg[2] == '\0') {
(*pargv)++;
(*pargc)--;
return (-1);
}
m = NULL;
for (o = opts; o->optstr != NULL; o++) {
if (strlen(arg + 1) <= strlen(o->optstr) &&
strncmp(arg + 1, o->optstr, strlen(arg + 1)) == 0) {
if (m != NULL)
errx(1, "ambiguous option '%s'", arg);
m = o;
}
}
if (m == NULL)
errx(1, "unknown option '%s'", arg);
(*pargv)++;
(*pargc)--;
if (m->opttype == OPT_NONE)
return (m - opts);
if (m->opttype == OPT_SIMPLE) {
*(int *)m->optarg = 1;
return (m - opts);
}
if (*pargc == 0)
errx(1, "option requires argument '%s'", arg);
optarg = *(*pargv)++;
(*pargc)--;
switch (m->opttype) {
case OPT_UINT:
ularg = strtoul(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad unsigned integer argument for '%s'", arg);
if (ularg > UINT_MAX)
errx(1, "argument to large for option '%s'", arg);
*(u_int *)m->optarg = (u_int)ularg;
break;
case OPT_INT:
larg = strtol(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad integer argument for '%s'", arg);
if (larg > INT_MAX || larg < INT_MIN)
errx(1, "argument out of range for option '%s'", arg);
*(int *)m->optarg = (int)larg;
break;
case OPT_UINT32:
ularg = strtoul(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad unsigned integer argument for '%s'", arg);
if (ularg > UINT32_MAX)
errx(1, "argument to large for option '%s'", arg);
*(uint32_t *)m->optarg = (uint32_t)ularg;
break;
case OPT_INT32:
larg = strtol(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad integer argument for '%s'", arg);
if (larg > INT32_MAX || larg < INT32_MIN)
errx(1, "argument out of range for option '%s'", arg);
*(int32_t *)m->optarg = (int32_t)larg;
break;
case OPT_UINT64:
*(uint64_t *)m->optarg = strtoull(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad unsigned integer argument for '%s'", arg);
break;
case OPT_INT64:
*(int64_t *)m->optarg = strtoll(optarg, &end, 0);
if (*end != '\0')
errx(1, "bad integer argument for '%s'", arg);
break;
case OPT_FLAG:
if (strcasecmp(optarg, "enable") == 0 ||
strcasecmp(optarg, "yes") == 0 ||
strcasecmp(optarg, "true") == 0 ||
strcasecmp(optarg, "on") == 0 ||
strcmp(optarg, "1") == 0)
*(int *)m->optarg = 1;
else if (strcasecmp(optarg, "disable") == 0 ||
strcasecmp(optarg, "no") == 0 ||
strcasecmp(optarg, "false") == 0 ||
strcasecmp(optarg, "off") == 0 ||
strcmp(optarg, "0") == 0)
*(int *)m->optarg = 0;
else
errx(1, "bad boolean argument to '%s'", arg);
break;
case OPT_VCI:
ularg = strtoul(optarg, &end, 0);
if (*end == '.') {
ularg1 = strtoul(end + 1, &end, 0);
} else {
ularg1 = ularg;
ularg = 0;
}
if (*end != '\0')
errx(1, "bad VCI value for option '%s'", arg);
if (ularg > 0xff)
errx(1, "VPI value too large for option '%s'", arg);
if (ularg1 > 0xffff)
errx(1, "VCI value too large for option '%s'", arg);
((u_int *)m->optarg)[0] = ularg;
((u_int *)m->optarg)[1] = ularg1;
break;
case OPT_STRING:
if (m->optarg != NULL)
*(const char **)m->optarg = optarg;
break;
default:
errx(1, "(internal) bad option type %u for '%s'",
m->opttype, arg);
}
return (m - opts);
}
/*
* for compiled-in modules
*/
void
register_module(const struct amodule *mod)
{
main_tab_size++;
if ((main_tab = realloc(main_tab, main_tab_size * sizeof(main_tab[0])))
== NULL)
err(1, NULL);
main_tab[main_tab_size - 2] = *mod->cmd;
memset(&main_tab[main_tab_size - 1], 0, sizeof(main_tab[0]));
}

View File

@ -1,680 +0,0 @@
/*
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if_atm.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "atmconfig.h"
#include "private.h"
#include "diag.h"
static void natm_add(int, char *[]);
static void natm_delete(int, char *[]);
static void natm_show(int, char *[]);
const struct cmdtab natm_tab[] = {
{ "add", NULL, natm_add },
{ "delete", NULL, natm_delete },
{ "show", NULL, natm_show },
{ NULL, NULL, NULL }
};
/*
* Structure to hold a route
*/
struct natm_route {
TAILQ_ENTRY(natm_route) link;
struct in_addr host;
struct diagif *aif;
u_int flags;
int llcsnap;
u_int vpi, vci;
u_int traffic;
u_int pcr, scr, mbs, icr, mcr;
u_int tbe, nrm, trm, adtf, rif, rdf, cdf;
};
static TAILQ_HEAD(, natm_route) natm_route_list =
TAILQ_HEAD_INITIALIZER(natm_route_list);
static void
store_route(struct rt_msghdr *rtm)
{
u_int i;
struct natm_route *r;
char *cp;
struct sockaddr *sa;
struct sockaddr_in *sain;
struct sockaddr_dl *sdl;
struct diagif *aif;
u_int n;
r = malloc(sizeof(*r));
if (r == NULL)
err(1, "allocate route");
r->flags = rtm->rtm_flags;
cp = (char *)(rtm + 1);
for (i = 1; i != 0; i <<= 1) {
if (rtm->rtm_addrs & i) {
sa = (struct sockaddr *)cp;
cp += roundup(sa->sa_len, sizeof(long));
switch (i) {
case RTA_DST:
if (sa->sa_family != AF_INET) {
warnx("RTA_DST not AF_INET %u", sa->sa_family);
goto fail;
}
sain = (struct sockaddr_in *)(void *)sa;
if (sain->sin_len < 4)
r->host.s_addr = INADDR_ANY;
else
r->host = sain->sin_addr;
break;
case RTA_GATEWAY:
if (sa->sa_family != AF_LINK) {
warnx("RTA_GATEWAY not AF_LINK");
goto fail;
}
sdl = (struct sockaddr_dl *)(void *)sa;
TAILQ_FOREACH(aif, &diagif_list, link)
if (strlen(aif->ifname) ==
sdl->sdl_nlen &&
strncmp(aif->ifname, sdl->sdl_data,
sdl->sdl_nlen) == 0)
break;
if (aif == NULL) {
warnx("interface '%.*s' not found",
sdl->sdl_nlen, sdl->sdl_data);
goto fail;
}
r->aif = aif;
/* parse ATM stuff */
#define GET3() (((sdl->sdl_data[n] & 0xff) << 16) | \
((sdl->sdl_data[n + 1] & 0xff) << 8) | \
((sdl->sdl_data[n + 2] & 0xff) << 0))
#define GET2() (((sdl->sdl_data[n] & 0xff) << 8) | \
((sdl->sdl_data[n + 1] & 0xff) << 0))
#define GET1() (((sdl->sdl_data[n] & 0xff) << 0))
n = sdl->sdl_nlen;
if (sdl->sdl_alen < 4) {
warnx("RTA_GATEWAY alen too short");
goto fail;
}
r->llcsnap = GET1() & ATM_PH_LLCSNAP;
n++;
r->vpi = GET1();
n++;
r->vci = GET2();
n += 2;
if (sdl->sdl_alen == 4) {
/* old address */
r->traffic = ATMIO_TRAFFIC_UBR;
r->pcr = 0;
break;
}
/* new address */
r->traffic = GET1();
n++;
switch (r->traffic) {
case ATMIO_TRAFFIC_UBR:
if (sdl->sdl_alen >= 5 + 3) {
r->pcr = GET3();
n += 3;
} else
r->pcr = 0;
break;
case ATMIO_TRAFFIC_CBR:
if (sdl->sdl_alen < 5 + 3) {
warnx("CBR address too short");
goto fail;
}
r->pcr = GET3();
n += 3;
break;
case ATMIO_TRAFFIC_VBR:
if (sdl->sdl_alen < 5 + 3 * 3) {
warnx("VBR address too short");
goto fail;
}
r->pcr = GET3();
n += 3;
r->scr = GET3();
n += 3;
r->mbs = GET3();
n += 3;
break;
case ATMIO_TRAFFIC_ABR:
if (sdl->sdl_alen < 5 + 4 * 3 + 2 +
1 * 2 + 3) {
warnx("ABR address too short");
goto fail;
}
r->pcr = GET3();
n += 3;
r->mcr = GET3();
n += 3;
r->icr = GET3();
n += 3;
r->tbe = GET3();
n += 3;
r->nrm = GET1();
n++;
r->trm = GET1();
n++;
r->adtf = GET2();
n += 2;
r->rif = GET1();
n++;
r->rdf = GET1();
n++;
r->cdf = GET1();
n++;
break;
default:
goto fail;
}
break;
}
}
}
TAILQ_INSERT_TAIL(&natm_route_list, r, link);
return;
fail:
free(r);
}
/*
* Fetch the INET routes that a ours
*/
static void
natm_route_fetch(void)
{
int name[6];
size_t needed;
u_char *buf, *next;
struct rt_msghdr *rtm;
name[0] = CTL_NET;
name[1] = PF_ROUTE;
name[2] = 0;
name[3] = AF_INET;
name[4] = NET_RT_DUMP;
name[5] = 0;
if (sysctl(name, 6, NULL, &needed, NULL, 0) == -1)
err(1, "rtable estimate");
needed *= 2;
if ((buf = malloc(needed)) == NULL)
err(1, "rtable buffer (%zu)", needed);
if (sysctl(name, 6, buf, &needed, NULL, 0) == -1)
err(1, "rtable get");
next = buf;
while (next < buf + needed) {
rtm = (struct rt_msghdr *)(void *)next;
next += rtm->rtm_msglen;
if (rtm->rtm_type == RTM_GET) {
if ((rtm->rtm_flags & (RTF_UP | RTF_HOST |
RTF_STATIC)) == (RTF_UP | RTF_HOST | RTF_STATIC) &&
(rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY |
RTA_IFP)) == (RTA_DST | RTA_GATEWAY | RTA_IFP))
store_route(rtm);
}
}
}
static u_long
parse_num(const char *arg, const char *name, u_long limit)
{
u_long res;
char *end;
errno = 0;
res = strtoul(arg, &end, 10);
if (*end != '\0' || end == arg || errno != 0)
errx(1, "cannot parse %s '%s'", name, arg);
if (res > limit)
errx(1, "%s out of range (0...%lu)", name, limit);
return (res);
}
static void
do_route(u_int type, u_int flags, const struct sockaddr_in *sain,
const struct sockaddr_dl *sdl)
{
struct {
struct rt_msghdr h;
char space[512];
} msg;
char *ptr;
int s;
ssize_t rlen;
/* create routing message */
bzero(&msg, sizeof(msg));
msg.h.rtm_msglen = sizeof(msg.h);
msg.h.rtm_version = RTM_VERSION;
msg.h.rtm_type = type;
msg.h.rtm_index = 0;
msg.h.rtm_flags = flags;
msg.h.rtm_addrs = RTA_DST | (sdl != NULL ? RTA_GATEWAY : 0);
msg.h.rtm_pid = getpid();
ptr = (char *)&msg + sizeof(msg.h);
memcpy(ptr, sain, sain->sin_len);
ptr += roundup(sain->sin_len, sizeof(long));
msg.h.rtm_msglen += roundup(sain->sin_len, sizeof(long));
if (sdl != NULL) {
memcpy(ptr, sdl, sdl->sdl_len);
ptr += roundup(sdl->sdl_len, sizeof(long));
msg.h.rtm_msglen += roundup(sdl->sdl_len, sizeof(long));
}
/* open socket */
s = socket(PF_ROUTE, SOCK_RAW, AF_INET);
if (s == -1)
err(1, "cannot open routing socket");
rlen = write(s, &msg, msg.h.rtm_msglen);
if (rlen == -1)
err(1, "writing to routing socket");
if ((size_t)rlen != msg.h.rtm_msglen)
errx(1, "short write to routing socket: %zu %u",
(size_t)rlen, msg.h.rtm_msglen);
close(s);
}
/*
* Add a new NATM route
*/
static void
natm_add(int argc, char *argv[])
{
int opt;
struct hostent *hp;
struct sockaddr_in sain;
struct sockaddr_dl sdl;
struct diagif *aif;
u_long num, num1;
u_int idx;
static int printonly;
static const struct option opts[] = {
{ "printonly", OPT_SIMPLE, &printonly },
{ NULL, 0, NULL }
};
while ((opt = parse_options(&argc, &argv, opts)) != -1)
switch (opt) {
}
if (argc < 5)
errx(1, "missing arguments for 'natm add'");
memset(&sdl, 0, sizeof(sdl));
sdl.sdl_len = sizeof(sdl);
sdl.sdl_family = AF_LINK;
/* get the IP address for <dest> */
memset(&sain, 0, sizeof(sain));
hp = gethostbyname(argv[0]);
if (hp == NULL)
errx(1, "bad hostname %s: %s", argv[0], hstrerror(h_errno));
if (hp->h_addrtype != AF_INET)
errx(1, "bad address type for %s", argv[0]);
sain.sin_len = sizeof(sain);
sain.sin_family = AF_INET;
memcpy(&sain.sin_addr, hp->h_addr, sizeof(sain.sin_addr));
/* find interface */
diagif_fetch();
TAILQ_FOREACH(aif, &diagif_list, link)
if (strcmp(aif->ifname, argv[1]) == 0)
break;
if (aif == NULL)
errx(1, "unknown ATM interface '%s'", argv[1]);
sdl.sdl_index = aif->index;
strcpy(sdl.sdl_data, aif->ifname);
idx = sdl.sdl_nlen = strlen(aif->ifname);
idx++;
/* verify VPI/VCI */
num = parse_num(argv[2], "VPI", (1U << aif->mib.vpi_bits));
sdl.sdl_data[idx++] = num & 0xff;
num = parse_num(argv[3], "VCI", (1U << aif->mib.vci_bits));
if (num == 0)
errx(1, "VCI may not be 0");
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = num & 0xff;
/* encapsulation */
if (strcasecmp(argv[4], "llc/snap") == 0) {
sdl.sdl_data[sdl.sdl_nlen] = ATM_PH_LLCSNAP;
} else if (strcasecmp(argv[4], "aal5") == 0) {
sdl.sdl_data[sdl.sdl_nlen] = 0;
} else
errx(1, "bad encapsulation type '%s'", argv[4]);
/* look at the traffic */
argc -= 5;
argv += 5;
if (argc != 0) {
if (strcasecmp(argv[0], "ubr") == 0) {
sdl.sdl_data[idx++] = ATMIO_TRAFFIC_UBR;
if (argc == 1)
/* ok */;
else if (argc == 2) {
num = parse_num(argv[1], "PCR", aif->mib.pcr);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
} else
errx(1, "too many parameters for UBR");
} else if (strcasecmp(argv[0], "cbr") == 0) {
sdl.sdl_data[idx++] = ATMIO_TRAFFIC_CBR;
if (argc == 1)
errx(1, "missing PCR for CBR");
if (argc > 2)
errx(1, "too many parameters for CBR");
num = parse_num(argv[1], "PCR", aif->mib.pcr);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
} else if (strcasecmp(argv[0], "vbr") == 0) {
sdl.sdl_data[idx++] = ATMIO_TRAFFIC_VBR;
if (argc < 4)
errx(1, "missing arg(s) for VBR");
if (argc > 4)
errx(1, "too many parameters for VBR");
num = parse_num(argv[1], "PCR", aif->mib.pcr);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[2], "SCR", num);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[3], "MBS", 0xffffffLU);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
} else if (strcasecmp(argv[0], "abr") == 0) {
sdl.sdl_data[idx++] = ATMIO_TRAFFIC_ABR;
if (argc < 11)
errx(1, "missing arg(s) for ABR");
if (argc > 11)
errx(1, "too many parameters for ABR");
num = parse_num(argv[1], "PCR", aif->mib.pcr);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num1 = parse_num(argv[2], "MCR", num);
sdl.sdl_data[idx++] = (num1 >> 16) & 0xff;
sdl.sdl_data[idx++] = (num1 >> 8) & 0xff;
sdl.sdl_data[idx++] = (num1 >> 0) & 0xff;
num = parse_num(argv[3], "ICR", num);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
if (num < num1)
errx(1, "ICR must be >= MCR");
num = parse_num(argv[4], "TBE", 0xffffffUL);
sdl.sdl_data[idx++] = (num >> 16) & 0xff;
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[5], "NRM", 0x7UL);
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[6], "TRM", 0x7UL);
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[7], "ADTF", 0x3ffUL);
sdl.sdl_data[idx++] = (num >> 8) & 0xff;
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[8], "RIF", 0xfUL);
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[9], "RDF", 0xfUL);
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
num = parse_num(argv[10], "CDF", 0x7UL);
sdl.sdl_data[idx++] = (num >> 0) & 0xff;
} else
errx(1, "bad traffic type '%s'", argv[0]);
} else
sdl.sdl_data[idx++] = ATMIO_TRAFFIC_UBR;
sdl.sdl_alen = idx - sdl.sdl_nlen;
sdl.sdl_len += sdl.sdl_nlen + sdl.sdl_alen;
if (printonly) {
printf("route add -iface %s -link %.*s",
inet_ntoa(sain.sin_addr), sdl.sdl_nlen, sdl.sdl_data);
for (idx = 0; idx < sdl.sdl_alen; idx++)
printf("%c%x", ".:"[idx == 0],
(u_int)sdl.sdl_data[sdl.sdl_nlen + idx] & 0xffU);
printf("\n");
exit(0);
}
do_route(RTM_ADD, RTF_HOST | RTF_STATIC | RTF_UP, &sain, &sdl);
}
/*
* Delete an NATM route
*/
static void
natm_delete(int argc, char *argv[])
{
int opt;
struct hostent *hp;
struct sockaddr_in sain;
u_int vpi, vci;
struct diagif *aif;
struct natm_route *r;
static int printonly;
static const struct option opts[] = {
{ "printonly", OPT_SIMPLE, &printonly },
{ NULL, 0, NULL }
};
while ((opt = parse_options(&argc, &argv, opts)) != -1)
switch (opt) {
}
diagif_fetch();
natm_route_fetch();
memset(&sain, 0, sizeof(sain));
sain.sin_len = sizeof(sain);
sain.sin_family = AF_INET;
if (argc == 1) {
/* get the IP address for <dest> */
hp = gethostbyname(argv[0]);
if (hp == NULL)
errx(1, "bad hostname %s: %s", argv[0],
hstrerror(h_errno));
if (hp->h_addrtype != AF_INET)
errx(1, "bad address type for %s", argv[0]);
memcpy(&sain.sin_addr, hp->h_addr, sizeof(sain.sin_addr));
TAILQ_FOREACH(r, &natm_route_list, link)
if (r->host.s_addr == sain.sin_addr.s_addr)
break;
if (r == NULL)
errx(1, "no NATM route to host '%s' (%s)", argv[0],
inet_ntoa(sain.sin_addr));
} else if (argc == 3) {
TAILQ_FOREACH(aif, &diagif_list, link)
if (strcmp(aif->ifname, argv[0]) == 0)
break;
if (aif == NULL)
errx(1, "no such interface '%s'", argv[0]);
vpi = parse_num(argv[1], "VPI", 0xff);
vci = parse_num(argv[2], "VCI", 0xffff);
TAILQ_FOREACH(r, &natm_route_list, link)
if (r->aif == aif && r->vpi == vpi && r->vci == vci)
break;
if (r == NULL)
errx(1, "no such NATM route %s %u %u", argv[0],
vpi, vci);
sain.sin_addr = r->host;
} else
errx(1, "bad number of arguments for 'natm delete'");
if (printonly) {
printf("route delete %s\n", inet_ntoa(r->host));
exit(0);
}
do_route(RTM_DELETE, r->flags, &sain, NULL);
}
/*
* Show NATM routes
*/
static void
natm_show(int argc, char *argv[])
{
int opt;
struct natm_route *r;
struct hostent *hp;
static const char *const traffics[] = {
[ATMIO_TRAFFIC_UBR] = "UBR",
[ATMIO_TRAFFIC_CBR] = "CBR",
[ATMIO_TRAFFIC_VBR] = "VBR",
[ATMIO_TRAFFIC_ABR] = "ABR"
};
static int numeric, abr;
static const struct option opts[] = {
{ "abr", OPT_SIMPLE, &abr },
{ "numeric", OPT_SIMPLE, &numeric },
{ NULL, 0, NULL }
};
static const char head[] =
"Destination Iface VPI VCI Encaps Trf PCR "
"SCR/MCR MBS/ICR\n";
static const char head_abr[] =
"Destination Iface VPI VCI Encaps Trf PCR "
"SCR/MCR MBS/ICR TBE NRM TRM ADTF RIF RDF CDF\n";
while ((opt = parse_options(&argc, &argv, opts)) != -1)
switch (opt) {
}
diagif_fetch();
natm_route_fetch();
heading_init();
TAILQ_FOREACH(r, &natm_route_list, link) {
heading(abr ? head_abr : head);
if (numeric)
printf("%-20s", inet_ntoa(r->host));
else if (r->host.s_addr == INADDR_ANY)
printf("%-20s", "default");
else {
hp = gethostbyaddr((char *)&r->host, sizeof(r->host),
AF_INET);
if (hp != NULL)
printf("%-20s", hp->h_name);
else
printf("%-20s", inet_ntoa(r->host));
}
printf("%-12s%-4u%-6u%-9s%-4s", r->aif->ifname, r->vpi, r->vci,
r->llcsnap ? "LLC/SNAP" : "AAL5", traffics[r->traffic]);
switch (r->traffic) {
case ATMIO_TRAFFIC_UBR:
case ATMIO_TRAFFIC_CBR:
printf("%-8u", r->pcr);
break;
case ATMIO_TRAFFIC_VBR:
printf("%-8u%-8u%-8u", r->pcr, r->scr, r->mbs);
break;
case ATMIO_TRAFFIC_ABR:
printf("%-8u%-8u%-8u", r->pcr, r->mcr, r->icr);
if (abr)
printf("%-8u%-4u%-4u%-5u%-4u%-4u%-4u",
r->tbe, r->nrm, r->trm, r->adtf,
r->rif, r->rdf, r->cdf);
break;
}
printf("\n");
}
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
#include <netgraph.h>
#include <net/if.h>
#include <netinet/in.h>
#ifndef PATH_HELP
#define PATH_HELP "/usr/share/doc/atm:/usr/local/share/doc/atm"
#endif
#ifndef FILE_HELP
#define FILE_HELP "atmconfig.help"
#endif
#ifndef FILE_HELP_OTHERS
#define FILE_HELP_OTHERS "atmconfig_*.help"
#endif
#ifndef PATH_ILMI_SOCK
#define PATH_ILMI_SOCK "/var/run/ilmid.sock"
#endif
/*
* Builtin commands
*/
extern const struct cmdtab diag_tab[];
extern const struct cmdtab natm_tab[];

View File

@ -144,7 +144,6 @@ MAN= aac.4 \
edsc.4 \
ehci.4 \
em.4 \
en.4 \
enc.4 \
epair.4 \
esp.4 \
@ -153,7 +152,6 @@ MAN= aac.4 \
etherswitch.4 \
eventtimers.4 \
exca.4 \
fatm.4 \
fd.4 \
fdc.4 \
fdt.4 \
@ -181,7 +179,6 @@ MAN= aac.4 \
gpioled.4 \
gre.4 \
h_ertt.4 \
hatm.4 \
hifn.4 \
hme.4 \
hpet.4 \
@ -307,8 +304,6 @@ MAN= aac.4 \
my.4 \
nand.4 \
nandsim.4 \
natm.4 \
natmip.4 \
ncr.4 \
ncv.4 \
${_ndis.4} \
@ -320,7 +315,6 @@ MAN= aac.4 \
${_nfe.4} \
${_nfsmb.4} \
ng_async.4 \
ng_atm.4 \
ngatmbase.4 \
ng_atmllc.4 \
ng_bpf.4 \
@ -397,7 +391,6 @@ MAN= aac.4 \
owc.4 \
${_padlock.4} \
pass.4 \
patm.4 \
pccard.4 \
pccbb.4 \
pcf.4 \
@ -627,11 +620,9 @@ MLINKS+=disc.4 if_disc.4
MLINKS+=ed.4 if_ed.4
MLINKS+=edsc.4 if_edsc.4
MLINKS+=em.4 if_em.4
MLINKS+=en.4 if_en.4
MLINKS+=enc.4 if_enc.4
MLINKS+=epair.4 if_epair.4
MLINKS+=et.4 if_et.4
MLINKS+=fatm.4 if_fatm.4
MLINKS+=fd.4 stderr.4 \
fd.4 stdin.4 \
fd.4 stdout.4
@ -645,7 +636,6 @@ MLINKS+=geom.4 GEOM.4
MLINKS+=gif.4 if_gif.4
MLINKS+=gpio.4 gpiobus.4
MLINKS+=gre.4 if_gre.4
MLINKS+=hatm.4 if_hatm.4
MLINKS+=hme.4 if_hme.4
MLINKS+=hpet.4 acpi_hpet.4
MLINKS+=${_hptrr.4} ${_rr232x.4}
@ -695,7 +685,6 @@ MLINKS+=nge.4 if_nge.4
MLINKS+=${_ntb_hw.4} ${_ntb.4}
MLINKS+=${_nxge.4} ${_if_nxge.4}
MLINKS+=ow.4 onewire.4
MLINKS+=patm.4 if_patm.4
MLINKS+=pccbb.4 cbb.4
MLINKS+=pcm.4 snd.4 \
pcm.4 sound.4
@ -966,7 +955,6 @@ MAN+= \
usb_template.4 \
usfs.4 \
uslcom.4 \
utopia.4 \
uvisor.4 \
uvscom.4 \
zyd.4

View File

@ -1,78 +0,0 @@
.\" $FreeBSD$
.\"
.Dd July 16, 2005
.Dt EN 4
.Os
.Sh NAME
.Nm en
.Nd "device driver for Midway-based ATM interfaces"
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device en"
.Cd "device atm"
.Cd "device utopia"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
if_en_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
device driver supports Midway-based ATM interfaces including the
Efficient Networks, Inc.\& ENI-155 and Adaptec ANA-59x0.
Midway is an AAL5 SAR (Segmentation and Reassembly) chip.
.Pp
For configuring the card for IP see
.Xr natmip 4 .
.Pp
The following sysctls are recognized by the driver additionally to those
handled by
.Xr utopia 4 :
.Bl -tag -width indent
.It Va hw.atm.enX.istats
Contains an array of
.Vt uint32_t
with internal driver statistics.
.It Va hw.atm.enX.debug
This is a bit map of debugging options.
This variable is only available when the driver is compiled with debugging
support.
.El
.Pp
The driver supports the media options
.Cm sdh ,
.Cm noscramb
and
.Cm unassigned
(see
.Xr utopia 4 ) .
.Sh DIAGNOSTICS
.Bd -literal
en0 <Efficient Networks ENI-155p> rev 0 int a irq 5 on pci0:16
en0: ATM midway v0, board IDs 6.0, Utopia (pipelined), 512KB on-board RAM
en0: maximum DMA burst length = 64 bytes
en0: 7 32KB receive buffers, 8 32KB transmit buffers allocated
.Ed
.Sh SEE ALSO
.Xr natm 4 ,
.Xr natmip 4 ,
.Xr utopia 4 ,
.Xr ifconfig 8 ,
.Xr route 8
.Sh AUTHORS
.An Chuck Cranor
of Washington University implemented
.Nm
driver in 1996 for
.Nx .
.Sh CAVEATS
The driver extensively uses DMA on PCI.
The first
generation PCI chipsets do not work or exhibit poor performance.

View File

@ -1,115 +0,0 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" 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.
.\"
.\" Author: Hartmut Brandt <harti@FreeBSD.org>
.\"
.\" $FreeBSD$
.\"
.\" fatm(4) man page
.\"
.Dd May 15, 2003
.Dt FATM 4
.Os
.Sh NAME
.Nm fatm
.Nd "device driver for Fore PCA200E ATM interfaces"
.Sh SYNOPSIS
.Cd device fatm
.Cd device utopia
.Cd device atm
.Pp
.Cd options NATM
.Sh DESCRIPTION
The
.Nm
device driver supports the FORE (now Marconi) PCA200E ATM interface cards.
The driver interfaces with the
.Xr natm 4
framework,
.Xr netgraph 4
and HARP.
It provides only PVC services.
Signalling, ATMARP, ILMI and other
higher layer protocols are implemented using
.Xr netgraph 4
or HARP.
.Pp
For configuring the card for IP see
.Xr natmip 4 .
The following sysctls are recognized by the driver additionally to those
handled by
.Xr utopia 4 :
.Bl -tag -width indent
.It Va hw.atm.fatm Ns Ar N Ns Va .stats
Returns a device specific statistic list of
.Vt uint32_t
statistic counters.
.It Va hw.atm.fatm Ns Ar N Ns Va .istats
Returns a list of
.Vt uint32_t
with internal driver statistics.
.It Va hw.atm.fatm Ns Ar N Ns Va .retry_tx
If this is set packets are stuffed back into the interface's send queue when
the cards transmit queue is found to be full.
They are transmitted later.
If this is not set the packets are dropped.
It may be useful to set this
if only UBR traffic is sent.
.It Va hw.atm.fatm Ns Ar N Ns Va .debug
.Bf Em
(Only if debugging enabled.)
.Ef
These are debugging flags.
See
.Pa src/sys/dev/fatm/if_fatmvar.h
for the possible flags.
.El
.Pp
The driver supports the media options
.Cm sdh , noscramb
and
.Cm unassigned
(see
.Xr utopia 4 ) .
.Sh DIAGNOSTICS
.Bd -literal
fatm0: <FORE PCA200E> mem 0xd5800000-0xd59fffff irq 9 at device 9.0 on pci0
.Ed
.Sh SEE ALSO
.Xr natm 4 ,
.Xr natmip 4 ,
.Xr utopia 4
.Sh AUTHORS
.An Harti Brandt Aq Mt harti@FreeBSD.org
.Sh BUGS
These cards can CBR shape a single VCC only.
It is currently possible to
request more than one CBR connection.
In this case all the timing will be
wrong.
See
.Xr hatm 4
for a better card.

View File

@ -1,282 +0,0 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" 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.
.\"
.\" Author: Hartmut Brandt <harti@FreeBSD.org>
.\"
.\" $FreeBSD$
.\"
.\" hatm(4) man page
.\"
.Dd May 15, 2003
.Dt HATM 4
.Os
.Sh NAME
.Nm hatm
.Nd "device driver for Fore/Marconi HE155 and HE622 ATM interfaces"
.Sh SYNOPSIS
.Cd device hatm
.Cd device utopia
.Cd device atm
.Pp
.Cd options NATM
.Sh DESCRIPTION
The
.Nm
device driver supports the FORE (now Marconi) HE155 and HE622 ATM interface
cards.
The driver interfaces with the
.Xr natm 4
framework,
.Xr netgraph 4
and the HARP ATM stack.
It provides only PVC services.
Signalling, ATMARP, ILMI and other
higher layer protocols are implemented using
.Xr netgraph 4
or HARP.
.Pp
For configuring the card for IP see
.Xr natmip 4 .
.Pp
The following sysctls are recognized by the driver additionally to those
handled by
.Xr utopia 4 :
.Bl -tag -width indent
.It Va hw.atm.hatm.natm_traffic
This is the traffic type to be used for NATM pvc connections.
The type of
this variable is integer and it must have one of the values 0 (UBR) or 1 (CBR).
.It Va hw.atm.hatm.natm_pcr
This is the peak cell rate to be used for NATM CBR connections.
.It Va hw.atm.hatm Ns Ar N Ns Va .stats
Contains an array of
.Vt uint32_t
with device specific statistics.
.It Va hw.atm.hatm Ns Ar N Ns Va .istats
Contains an array of
.Vt uint32_t
with internal driver statistics.
.It Va hw.atm.hatm Ns Ar N Ns Va .debug
.Bf Em
(Only if debugging enabled.)
.Ef
These are the debugging flags.
See
.Pa src/sys/dev/hatm/if_hatmvar.h
for the possible flags.
.It Va hw.atm.hatm Ns Ar N Ns Va .tsr
.Bf Em
(Only if debugging enabled.)
.Ef
This is an array containing all transmission status registers.
For each of the
4096 possible VCCs there are 15 32-bit registers.
.It Va hw.atm.hatm Ns Ar N Ns Va .tpd
.Bf Em
(Only if debugging enabled.)
.Ef
This is an array containing all on card current transmission packet descriptors.
For each of the 4096 possible VCCs there are 16 32-bit registers.
.It Va hw.atm.hatm Ns Ar N Ns Va .mbox
.Bf Em
(Only if debugging enabled.)
.Ef
This is an array containing the mbox registers.
.It Va hw.atm.hatm Ns Ar N Ns Va .cm
.Bf Em
(Only if debugging enabled.)
.Ef
This is an array containing all connection memory registers.
The first 32-bit integer of this array is the ABR base address.
.It Va hw.atm.hatm Ns Ar N Ns Va .heregs
.Bf Em
(Only if debugging enabled.)
.Ef
This is an array containing all card registers including SUNI and the FLASH ROM.
.It Va hw.atm.hatm Ns Ar N Ns Va .lbmem
.Bf Em
(Only if debugging enabled.)
.Ef
Returns the contents of the local memory.
.El
.Pp
The driver supports the media options
.Cm sdh , noscramb
and
.Cm unassigned
(see
.Xr utopia 4 ) .
.Sh ENVIRONMENT
When attaching to a device the driver checks the kernel environment
(see
.Xr kenv 1 )
to see if the default queues sizes should be overwritten or not.
The
following variables are checked and interpreted as unsigned integer
values (in either radix):
.Bl -tag -width indent
.It Va hw.hatm Ns Ar N Ns Va .rbps0_size
Size of the small receive buffer pool 0.
This pool is used for all
except raw AAL connections.
The pool size must be a power of two between
4 and 8192 inclusive.
When attaching the driver allocates this number
of mbufs.
.It Va hw.hatm Ns Ar N Ns Va .rbps0_thresh
Interrupt threshold for small receive buffer pool 0.
When the number of free
buffers in the pool falls below this threshold it generates an interrupt
so that the driver can refill the pool.
.It Va hw.hatm Ns Ar N Ns Va .rbpl0_thresh
Size of the large receive buffer pool 0.
This pool is used for all
except raw AAL connections.
The pool size must be a power of two between
4 and 8192 inclusive.
When attaching the driver allocates this number
of mbufs with clusters.
.It Va hw.hatm Ns Ar N Ns Va .rbpl0_thresh
Interrupt threshold for large receive buffer pool 0.
When the number of free
buffers in the pool falls below this threshold it generates an interrupt
so that the driver can refill the pool.
.It Va hw.hatm Ns Ar N Ns Va .rbrq0_size
Size of receive buffer return queue 0.
This queue is used to return buffers
filled with received frames to the driver.
The size must be a power of 2
between 1 and 16384 inclusive.
.It Va hw.hatm Ns Ar N Ns Va .rbrq0_thresh
Interrupt threshold for receive buffer return queue 0.
This threshold
should only be triggered in exceptional cases.
.It Va hw.hatm Ns Ar N Ns Va .rbrq0_tout
Interrupt timeout for receive buffer return queue 0.
An interrupt is generated
after this time if the queue is not empty.
The number is in internal card
ticks.
.It Va hw.hatm Ns Ar N Ns Va .rbrq0_pcnt
Packet count threshold for receive buffer return queue 0.
An interrupt
is generated if this number of packets is in the queue.
.It Va hw.hatm Ns Ar N Ns Va .rbps1_size
Size of the small receive buffer pool 1.
This pool is used for all
raw AAL connections.
The pool size must be a power of two between
4 and 8192 inclusive.
When attaching the driver allocates this number
of mbufs.
.It Va hw.hatm Ns Ar N Ns Va .rbps1_thresh
Interrupt threshold for small receive buffer pool 1.
When the number of free
buffers in the pool falls below this threshold it generates an interrupt
so that the driver can refill the pool.
.It Va hw.hatm Ns Ar N Ns Va .rbrq1_size
Size of receive buffer return queue 1.
This queue is used to return buffers
filled with received cells to the driver.
The size must be a power of 2
between 1 and 16384 inclusive.
.It Va hw.hatm Ns Ar N Ns Va .rbrq1_thresh
Interrupt threshold for receive buffer return queue 1.
This threshold
should only be triggered in exceptional cases.
.It Va hw.hatm Ns Ar N Ns Va .rbrq1_tout
Interrupt timeout for receive buffer return queue 1.
An interrupt is generated
after this time if the queue is not empty.
The number is in internal card
ticks.
.It Va hw.hatm Ns Ar N Ns Va .rbrq1_pcnt
Packet count threshold for receive buffer return queue 0.
An interrupt
is generated if this number of cells is in the queue.
.It Va hw.hatm Ns Ar N Ns Va .irq0_size
Size of interrupt queue 0.
This must be a number between 1 and 1023 inclusive.
.It Va hw.hatm Ns Ar N Ns Va .irq0_thresh
Interrupt retrigger threshold of interrupt queue 0.
A new interrupt is trigger
if the queue fill state reaches this threshold and the interrupt was no
served.
.It Va hw.hatm Ns Ar N Ns Va .tbrq0_size
Transmit buffer return queue 0 size.
This queue is used to feed back empty
buffers of transmitted frames back to the driver.
It must be a power of 2
between 1 and 4096 inclusive.
.It Va hw.hatm Ns Ar N Ns Va .tbrq0_thresh
Transmit buffer return queue 0 threshold.
An interrupt is generated if the
queue fill state reaches this point.
.It Va hw.hatm Ns Ar N Ns Va .tpdrq_size
Transmit descriptor ready queue size.
This queue is used by the driver
to feed transmit descriptors into the card.
The size must be a power of 2
between 1 and 16384 inclusive.
.It Va hw.hatm Ns Ar N Ns Va .tpdmax
Maximum number of active TPDs per connection.
This controls the maximum
number of outstanding packet chunks per connection and thus the maximum
delay packets can have because of queueing on the adapter.
If set to 0,
a connection can eat up all available TPDs.
.It Va hw.hatm Ns Ar N Ns Va .mbuf_max_pages
Maximum number of memory pages allocated to small external mbufs.
This must not be zero and not larger than 65536.
.El
.Sh DIAGNOSTICS
.Bd -literal
hatm0: <FORE HE> mem 0xd2600000-0xd26fffff irq 9 at device 15.0 on pci2
hatm0: ForeRunnerHE 622, Rev. D, S/N 2949834, MAC=00:20:48:2d:02:ca
.Ed
.Sh SEE ALSO
.Xr natm 4 ,
.Xr natmip 4 ,
.Xr utopia 4 ,
.Xr ifconfig 8 ,
.Xr route 8
.Sh AUTHORS
.An Harti Brandt Aq Mt harti@FreeBSD.org
.Sh CAVEATS
When putting a HE155 into a 64-bit 66MHz PCI slot the machine may hang.
This occurs very early in the POST so that even the display does not turn on.
The HE155 runs only in 33MHz slots (either 32 or 64-bit).
HE622 cards work just fine in 64-bit slots.
.Pp
The driver may not work with bounce buffer, because of
.Xr bus_dmamap_sync 9
missing the
.Fa offset
and
.Fa len
arguments the
.Nx
function has.

View File

@ -1,102 +0,0 @@
.\" $FreeBSD$
.\"
.Dd December 29, 1997
.Dt NATM 4
.Os
.Sh NAME
.Nm natm
.Nd Native Mode ATM protocol layer
.Sh DESCRIPTION
The
.Bx
ATM software comes with a
.Em native mode ATM protocol layer
which provides socket level access to AAL0 and AAL5 virtual circuits.
To enable this protocol layer, add
.Dl options NATM
.Dl device atm
to your kernel configuration file and re-make the kernel (do not forget
to do
.Dq make clean ) .
.Sh NATM API
The NATM layer uses a
.Vt struct sockaddr_natm
to specify a virtual circuit:
.Bd -literal -offset indent
struct sockaddr_natm {
uint8_t snatm_len; /* length */
uint8_t snatm_family; /* AF_NATM */
char snatm_if[IFNAMSIZ]; /* interface name */
uint16_t snatm_vci; /* vci */
uint8_t snatm_vpi; /* vpi */
};
.Ed
.Pp
To create an AAL5 connection to a virtual circuit with VPI 0, VCI 201
one would use the following:
.Bd -literal -offset indent
struct sockaddr_natm snatm;
int s, r;
s = socket(AF_NATM, SOCK_STREAM, PROTO_NATMAAL5);
/* note: PROTO_NATMAAL0 is AAL0 */
if (s < 0) { perror("socket"); exit(1); }
bzero(&snatm, sizeof(snatm));
snatm.snatm_len = sizeof(snatm);
snatm.snatm_family = AF_NATM;
sprintf(snatm.snatm_if, "en0");
snatm.snatm_vci = 201;
snatm.snatm_vpi = 0;
r = connect(s, (struct sockaddr *)&snatm, sizeof(snatm));
if (r < 0) { perror("connect"); exit(1); }
/* s now connected to ATM! */
.Ed
.Pp
The
.Fn socket
call simply creates an unconnected NATM socket.
The
.Fn connect
call associates an unconnected NATM socket with a
virtual circuit and tells the driver to enable that virtual circuit
for receiving data.
After the
.Fn connect
call one can
.Fn read
or
.Fn write
to the socket to perform ATM I/O.
.Sh Internal NATM operation
Internally, the NATM protocol layer keeps a list of all active virtual
circuits on the system in
.Dv natm_pcbs .
This includes circuits currently being used for IP to prevent NATM and
IP from clashing over virtual circuit usage.
.Pp
When a virtual circuit is enabled for receiving data, the NATM
protocol layer passes the address of the protocol control block down
to the driver as a receive
.Dq handle .
When inbound data arrives, the driver passes the data back with the
appropriate receive handle.
The NATM layer uses this to avoid the
overhead of a protocol control block lookup.
This allows us to take
advantage of the fact that ATM has already demultiplexed the data for
us.
.Sh SEE ALSO
.Xr en 4 ,
.Xr fatm 4 ,
.Xr hatm 4 ,
.Xr natmip 4 ,
.Xr patm 4
.Sh AUTHORS
.An Chuck Cranor
of Washington University implemented the NATM protocol layer
along with the EN ATM driver in 1996 for
.Nx .
.Sh CAVEATS
The NATM protocol support is subject to change as
the ATM protocols develop.
Users should not depend on details of the current implementation, but rather
the services exported.

View File

@ -1,248 +0,0 @@
.\"
.\" Copyright (c) 2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" All rights reserved.
.\"
.\" Author: Hartmut Brandt <harti@FreeBSD.org>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd August 11, 2003
.Dt NATMIP 4
.Os
.Sh NAME
.Nm natmip
.Nd IP over ATM PVCs
.Sh SYNOPSIS
.Cd "device atm"
.Cd "options NATM"
.Sh DESCRIPTION
The NATM protocol stack includes support for IP over ATM.
Without any
additional signalling stacks or other modules it is possible to build
a CLIP (classical IP over ATM) network based on PVCs.
.Pp
An ATM network card
.Li ( en0
in this example) is configured for IP by something
like:
.Pp
.Dl "ifconfig en0 128.252.200.1 netmask 0xffffff00 up"
.Pp
IP routing is done with special interface routes (routes with directly
reachable destinations) with a link layer gateway address.
The link layer address specifies the ATM interface through which the
destination can be reached, the virtual channel that connects to the
destination and the ATM characteristics of this channel.
The address part of the link layer address (see
.Xr link_addr 3 )
consists of a fixed part (the first 5 bytes) and a part that
depends on the kind of the PVC (UBR, CBR, VBR, ABR).
Multi-byte values
are big-endian encoded: the bytes with the lower numbers contain the
higher order bits.
.Bl -tag -width "bytes 12...12" -offset indent
.It byte 0
Is a flag byte.
Currently only flag 0x20 is used.
When set, all IP frames are LLC/SNAP encapsulated before putting them into
an AAL5 frame.
Setting this flag is recommended and allows interoperability with other
CLIP implementations.
Note that BPF works only with LLC/SNAP encapsulation.
.It byte 1
This is the VPI of the channel.
.It bytes 2...3
VCI of the channel.
Must not be zero.
.It byte 4
Traffic type.
One of 0 (UBR), 1 (CBR), 2 (ABR), 3 (VBR).
.El
.Pp
The variable part for UBR connections may be either empty or three bytes:
.Bl -tag -width "bytes 12...12" -offset indent
.It bytes 5...7
Specifies the peak cell rate for UBR.
.El
.Pp
The variable part for CBR connections must be three bytes:
.Bl -tag -width "bytes 12...12" -offset indent
.It bytes 5...7
Specifies the peak cell rate for CBR.
.El
.Pp
The variable part for VBR connections must be 9 bytes long and specifies three
values:
.Bl -tag -width "bytes 12...12" -offset indent
.It bytes 5...7
Specifies the peak cell rate for VBR.
.It bytes 8...10
This is the sustainable cell rate.
.It bytes 11...13
The maximum burst size.
.El
.Pp
The variable part for ABR connections must be 19 bytes long and specifies the
following values:
.Bl -tag -width "bytes 12...12" -offset indent
.It bytes 5...7
Specifies the peak cell rate for ABR.
.It bytes 8...10
The minimum cell rate.
.It bytes 11...13
The initial cell rate.
.It bytes 14...16
The transient buffer exposure.
.It byte 17
The NRM value.
.It byte 18
The TRM value.
.It bytes 19...20
The ADTF value.
.It byte 21
The rate increase factor (RIF).
.It byte 22
The rate decrease factor (RDF).
.It byte 23
The cutoff decrease factor (CDF).
.El
.Pp
To add a PVC the
.Xr route 8
utility can be used:
.Bd -ragged -offset indent
.Nm route Cm add
.Fl iface Aq Ar "remote\ IP\ address"
.Fl link Ao Ar iface Ac : Ns Aq Ar lladdr
.Ed
.Pp
The
.Ar iface
is the ATM interface through which
.Ar "remote\ IP\ address"
can be reached and
.Ar lladdr
is the link layer address as a string of dot-separated, hexadecimal bytes.
.Pp
NATM also supports the old, original format.
This consists of 4 byte
link layer addresses (and the channels are implicit UBR):
.Bl -tag -width "bytes 12...12" -offset indent
.It byte 0
Flags:
.Bl -tag -width "0x02" -offset indent -compact
.It 0x01
use AAL5.
.It 0x02
if using AAL5, use an LLC/SNAP header.
.El
.Pp
Thus, parameter 3 means AAL5 and LLC/SNAP encapsulation (this is the required
setting for interworking with other CLIP clients).
Note that BPF works only with LLC/SNAP encapsulation.
.It byte 1
VPI for the channel
.It bytes 2...3
VCI for the channel
.El
.Sh EXAMPLES
Suppose you have 3 hosts 128.252.200.1, 128.252.200.2 and
128.252.200.3 connected by ATM through PVCs:
.Pp
.Bl -item -offset indent -compact
.It
between 128.252.200.1 and 128.252.200.2: 0xc9 UBR
.It
between 128.252.200.1 and 128.252.200.3: 0xca VBR
.It
between 128.252.200.2 and 128.252.200.3: 0xcb CBR
.El
.Pp
The parameters for the VBR channel are: PCR 50000, SCR 10000, MBS 10.
The peak cell rate for the CBR channel is 100000.
.Pp
To enable the links use the following commands:
.Pp
on host 128.252.200.1:
.Bd -literal -offset indent -compact
ifconfig en0 128.252.200.1 netmask 0xffffff00 up
route add -iface 128.252.200.2 -link en0:3.0.0.c9.0
route add -iface 128.252.200.3 -link en0:3.0.0.ca.3.0.c3.50.0.27.10.0.0.a
.Ed
.Pp
on host 128.252.200.2:
.Bd -literal -offset indent -compact
ifconfig en0 128.252.200.2 netmask 0xffffff00 up
route add -iface 128.252.200.1 -link en0:3.0.0.c9.0
route add -iface 128.252.200.3 -link en0:3.0.0.cb.1.1.86.a0
.Ed
.Pp
on host 128.252.200.3:
.Bd -literal -offset indent -compact
ifconfig en0 128.252.200.3 netmask 0xffffff00 up
route add -iface 128.252.200.1 -link en0:3.0.0.ca.3.0.c3.50.0.27.10.0.0.a
route add -iface 128.252.200.2 -link en0:3.0.0.cb.1.1.86.a0
.Ed
.Pp
This can also be done in
.Xr rc.conf 5 :
.Pp
on host 128.252.200.1:
.Bd -literal -offset indent -compact
network_interfaces="lo0 en0"
ifconfig_en0="inet 128.252.200.1 netmask 255.255.255.0"
static_routes="host2 host3"
route_host2="-iface 128.252.200.2 -link en0:3.0.0.c9.0"
route_host3="-iface 128.252.200.3 -link en0:3.0.0.ca.3.0.c3.50.0.27.10.0.0.a"
.Ed
.Pp
on host 128.252.200.2:
.Bd -literal -offset indent -compact
network_interfaces="lo0 en0"
ifconfig_en0="inet 128.252.200.2 netmask 255.255.255.0"
static_routes="host1 host3"
route_host1="-iface 128.252.200.1 -link en0:3.0.0.c9.0"
route_host3="-iface 128.252.200.3 -link en0:3.0.0.cb.1.1.86.a0"
.Ed
.Pp
on host 128.252.200.3:
.Bd -literal -offset indent -compact
network_interfaces="lo0 en0"
ifconfig_en0="inet 128.252.200.3 netmask 255.255.255.0"
static_routes="host1 host2"
route_host1="-iface 128.252.200.1 -link en0:3.0.0.ca.3.0.c3.50.0.27.10.0.0.a"
route_host2="-iface 128.252.200.2 -link en0:3.0.0.cb.1.1.86.a0"
.Ed
.Sh SEE ALSO
.Xr en 4 ,
.Xr fatm 4 ,
.Xr hatm 4 ,
.Xr natm 4 ,
.Xr patm 4
.Sh AUTHORS
.An Chuck Cranor
of Washington University implemented the NATM protocol layer
along with the EN ATM driver in 1996 for
.Nx .

View File

@ -1,406 +0,0 @@
.\"
.\" Copyright (c) 2001-2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" 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.
.\"
.\" Author: Hartmut Brandt <harti@FreeBSD.org>
.\"
.\" $FreeBSD$
.\"
.\" ng_atm(4) man page
.\"
.Dd November 2, 2012
.Dt NG_ATM 4
.Os
.Sh NAME
.Nm ng_atm
.Nd netgraph ATM node type
.Sh SYNOPSIS
.In sys/types.h
.In net/if_atm.h
.In netgraph.h
.In netgraph/atm/ng_atm.h
.Sh DESCRIPTION
The
.Nm atm
netgraph node type allows
.Xr natm 4
ATM drivers to be connected to the
.Xr netgraph 4
networking subsystem.
When the
.Nm
module is loaded a node is automatically created for each
.Xr natm 4
ATM interface.
The nodes are named with the same name as the
interface.
Nodes are also created if a driver for an ATM
card is loaded after
.Nm
was loaded.
.Pp
The
.Nm atm
nodes are persistent.
They are removed when the interface is removed.
.Dv NGM_SHUTDOWN
messages are ignored by the node.
.Sh HOOKS
Four special hooks with fixed names and an unlimited number of hooks with user
defined names are supported.
Three of the fixed hooks are attached to
strategic points in the information flow in the
.Xr natm 4
system and support only reading.
The fourth fixed hook behaves like the other
user hooks, but a number of management messages are sent along the hook.
The other hooks can be attached to VCIs dynamically by means of
control messages to the
.Nm atm
node and can be written and read.
.Pp
The four fixed hooks are:
.Bl -tag -width ".Va orphans"
.It Va input
This is a connection to the raw input stream from the network.
If this hook is connected, all incoming packets are delivered out to
this hook.
Note that this redirects ALL input.
Neither
.Xr natm 4
nor the user hooks will see any input if
.Va input
is connected.
An
.Vt atm_pseudohdr
(see
.Xr natm 4 )
is prepended to the actual data.
.It Va output
This is a connection to the raw output stream to the network device.
If this hook is connected, all outgoing packets are handed over to
the netgraph system and delivered to the hook instead of being delivered
to the ATM driver.
An
.Vt atm_pseudohdr
(see
.Xr natm 4 )
is prepended to the actual data.
.It Va orphans
This hook receives all packets that are unrecognized, i.e., do not belong to
either a
.Xr natm 4
socket, a
.Nm
VCI or
.Xr natm 4
IP.
Because ATM is connection oriented and packets are received on a given VCI only
when someone initiates this VCI, packets should never be orphaned.
There is
however one exception: if you use
.Xr natm 4
IP with LLC/SNAP encapsulation packets with do not have the IP protocol
indicated in the packet header are delivered out of this hook.
An
.Vt atm_pseudohdr
(see
.Xr natm 4 )
is prepended to the actual data send out to the hook.
.It Va manage
This hook behaves exactly like a normal user hook (see below) except that
the node at the other hand will receive management messages.
.El
.Pp
Hooks for dynamically initiated VCIs can have whatever name is allowed by
.Xr netgraph 4
as long as the name does not collide with one of the three predefined names.
.Pp
To initiate packet sending and receiving on a dynamic hook, one has to issue
a
.Dv NGM_ATM_CPCS_INIT
control message.
To terminate sending and receiving one must send a
.Dv NGM_ATM_CPCS_TERM
message (see
.Sx CONTROL MESSAGES ) .
The data sent and received on these hooks has no additional
headers.
.Sh CONTROL MESSAGES
This node type supports the generic messages plus the following:
.Bl -tag -width 4n
.It Dv NGM_ATM_GET_IFNAME Pq Ic getifname
Return the name of the interface as a
.Dv NUL Ns
-terminated string.
This is normally the same name as that of the node.
.It Dv NGM_ATM_GET_CONFIG Pq Ic getconfig
Returns a structure defining the configuration of the interface:
.Bd -literal
struct ngm_atm_config {
uint32_t pcr; /* peak cell rate */
uint32_t vpi_bits; /* number of active VPI bits */
uint32_t vci_bits; /* number of active VCI bits */
uint32_t max_vpcs; /* maximum number of VPCs */
uint32_t max_vccs; /* maximum number of VCCs */
};
.Ed
.It Dv NGM_ATM_GET_VCCS Pq Ic getvccs
Returns the table of open VCCs from the driver.
This table consists of
a header and a variable sized array of entries, one for each open VCC:
.Bd -literal
struct atmio_vcctable {
uint32_t count; /* number of vccs */
struct atmio_vcc vccs[0]; /* array of VCCs */
};
struct atmio_vcc {
uint16_t flags; /* flags */
uint16_t vpi; /* VPI */
uint16_t vci; /* VCI */
uint16_t rmtu; /* Receive maximum CPCS size */
uint16_t tmtu; /* Transmit maximum CPCS size */
uint8_t aal; /* aal type */
uint8_t traffic; /* traffic type */
struct atmio_tparam tparam; /* traffic parameters */
};
struct atmio_tparam {
uint32_t pcr; /* 24bit: Peak Cell Rate */
uint32_t scr; /* 24bit: VBR Sustainable Cell Rate */
uint32_t mbs; /* 24bit: VBR Maximum burst size */
uint32_t mcr; /* 24bit: ABR/VBR/UBR+MCR MCR */
uint32_t icr; /* 24bit: ABR ICR */
uint32_t tbe; /* 24bit: ABR TBE (1...2^24-1) */
uint8_t nrm; /* 3bit: ABR Nrm */
uint8_t trm; /* 3bit: ABR Trm */
uint16_t adtf; /* 10bit: ABR ADTF */
uint8_t rif; /* 4bit: ABR RIF */
uint8_t rdf; /* 4bit: ABR RDF */
uint8_t cdf; /* 3bit: ABR CDF */
};
.Ed
.Pp
Note that this is the driver's table, so all VCCs opened via
.Xr natm 4
sockets and IP are also shown.
They can, however, be distinguished by
their flags.
The
.Va flags
field contains the following flags:
.Pp
.Bl -tag -width ".Dv ATM_PH_LLCSNAP" -offset indent -compact
.It Dv ATM_PH_AAL5
use AAL5 instead of AAL0
.It Dv ATM_PH_LLCSNAP
if AAL5 use LLC SNAP encapsulation
.It Dv ATM_FLAG_NG
this is a netgraph VCC
.It Dv ATM_FLAG_HARP
this is a HARP VCC
.It Dv ATM_FLAG_NORX
transmit only VCC
.It Dv ATM_FLAG_NOTX
receive only VCC
.It Dv ATMIO_FLAG_PVC
treat channel as a PVC
.El
.Pp
If the
.Dv ATM_FLAG_NG
flag is set, then
.Va traffic
and
.Va tparam
contain meaningful information.
.Pp
The
.Va aal
field
contains one of the following values:
.Pp
.Bl -tag -width ".Dv ATM_PH_LLCSNAP" -offset indent -compact
.It Dv ATMIO_AAL_0
AAL 0 (raw cells)
.It Dv ATMIO_AAL_34
AAL 3 or AAL 4
.It Dv ATMIO_AAL_5
AAL 5
.It Dv ATMIO_AAL_RAW
device specific raw cells
.El
.Pp
The
.Va traffic
field
can have one of the following values (not all drivers support
all traffic types however):
.Pp
.Bl -tag -width ".Dv ATM_PH_LLCSNAP" -offset indent -compact
.It Dv ATMIO_TRAFFIC_UBR
.It Dv ATMIO_TRAFFIC_CBR
.It Dv ATMIO_TRAFFIC_ABR
.It Dv ATMIO_TRAFFIC_VBR
.El
.It Dv NGM_ATM_CPCS_INIT Pq Ic cpcsinit
Initialize a VCC for sending and receiving.
The argument is a structure:
.Bd -literal
struct ngm_atm_cpcs_init {
char name[NG_HOOKSIZ];
uint32_t flags; /* flags. (if_atm.h) */
uint16_t vci; /* VCI to open */
uint16_t vpi; /* VPI to open */
uint16_t rmtu; /* receive maximum PDU */
uint16_t tmtu; /* transmit maximum PDU */
uint8_t aal; /* AAL type (if_atm.h) */
uint8_t traffic; /* traffic type (if_atm.h) */
uint32_t pcr; /* Peak cell rate */
uint32_t scr; /* VBR: Sustainable cell rate */
uint32_t mbs; /* VBR: Maximum burst rate */
uint32_t mcr; /* UBR+: Minimum cell rate */
uint32_t icr; /* ABR: Initial cell rate */
uint32_t tbe; /* ABR: Transmit buffer exposure */
uint8_t nrm; /* ABR: Nrm */
uint8_t trm; /* ABR: Trm */
uint16_t adtf; /* ABR: ADTF */
uint8_t rif; /* ABR: RIF */
uint8_t rdf; /* ABR: RDF */
uint8_t cdf; /* ABR: CDF */
};
.Ed
.Pp
The
.Va name
field
is the name of the hook for which sending and receiving should be enabled.
This hook must already be connected.
The
.Va vpi
and
.Va vci
fields
are the respective VPI and VCI values to use for the ATM cells.
They must be
within the range, given by the
.Va maxvpi
and
.Va maxvci
fields of the
.Vt ng_atm_config
structure.
The
.Va flags
field
contains the flags (see above) and the other fields describe the
type of traffic.
.It Dv NGM_ATM_CPCS_TERM Pq Ic cpcsterm
Stop sending and receiving on the indicated hook.
The argument is a
.Bd -literal
struct ngm_atm_cpcs_term {
char name[NG_HOOKSIZ];
};
.Ed
.It Dv NGM_ATM_GET_STATS Pq Ic getstats
This command returns a message, containing node statistics.
The structure of the message is:
.Bd -literal
struct ngm_atm_stats {
uint64_t in_packets;
uint64_t in_errors;
uint64_t out_packets;
uint64_t out_errors;
};
.Ed
.El
.Sh MANAGEMENT MESSAGES
If the
.Va manage
hook is connected, certain messages are sent along the hook.
They are
received by the peer node with a cookie of
.Dv NG_ATM_COOKIE .
.Bl -tag -width 4n
.It Dv NGM_ATM_VCC_CHANGE Pq Ic vcc_change
A permanent VCC has been added, deleted or changed.
This is used by
.Xr ilmid 8
to generate the appropriate ILMI traps.
The structure of the message is:
.Bd -literal
struct ngm_atm_vcc_change {
uint32_t node;
uint16_t vci;
uint8_t vpi;
uint8_t state;
};
.Ed
Where
.Va state
is 0 if the PVC was deleted, and 1 if it was added or modified.
.El
.Sh FLOW CONTROL
If the hardware driver supports it, the node can emit flow control messages
along a user hook.
The format of these messages is described in
.In netgraph/ng_message.h .
The
.Nm atm
node may generate
.Dv NGM_HIGH_WATER_PASSED
and
.Dv NGM_LOW_WATER_PASSED
messages.
The first one indicates that the hardware driver has stopped output
on the channel and drops new packets, the second one reports that
output was reenabled.
Currently, the structures are not filled with
information.
.Sh SHUTDOWN
The nodes are persistent as long as the corresponding interface exists.
Upon receipt of a
.Dv NGM_SHUTDOWN
messages, all hooks are disconnected and the node is reinitialized.
All
VCCs opened via
.Xr netgraph 4
are closed.
When the ATM interface is unloaded,
the node disappears.
If the node is compiled with
.Dv NGATM_DEBUG
there is a sysctl
.Va net.graph.atm.allow_shutdown
which, when set to a non-zero value, allows the nodes to shut down.
Note that this is intended for development only and may lead to kernel
panics if set.
.Sh SEE ALSO
.Xr natm 4 ,
.Xr netgraph 4 ,
.Xr ng_ether 4 ,
.Xr ngctl 8
.Sh AUTHORS
.An Harti Brandt Aq Mt harti@FreeBSD.org

View File

@ -1,192 +0,0 @@
.\"
.\" Copyright (c) 2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" 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.
.\"
.\" Author: Hartmut Brandt <harti@FreeBSD.org>
.\"
.\" $FreeBSD$
.\"
.\" patm(4) man page
.\"
.Dd July 15, 2003
.Dt PATM 4
.Os
.Sh NAME
.Nm patm
.Nd "device driver for IDT77252 based ATM interfaces (ProSum and IDT)"
.Sh SYNOPSIS
.Cd device patm
.Cd device utopia
.Cd device atm
.Pp
.Cd options NATM
.Cd options LIBMBPOOL
.Sh DESCRIPTION
The
.Nm
device driver supports ATM cards based on the IDT77252 chip.
It has been tested with ProSum's ProATM-155 cards and with IDT's evaluation
boards.
The driver interfaces with the
.Xr natm 4
framework,
.Xr netgraph 4
and HARP.
It provides only PVC services.
Signalling, ATMARP, ILMI and other
higher layer protocols are implemented using
.Xr netgraph 4
or HARP.
.Pp
For configuring the card for IP see
.Xr natmip 4 .
.Pp
The driver supports UBR, CBR, VBR and ABR traffic.
Supported AALs are:
AAL0 (cell payloads), AAL5 and raw AAL.
The driver supports opening of VCI/VPI 0/0 in RX, raw AAL-mode.
This VC will receive all incoming cells (even those with non-zero GFC
fields and VPI/VCI values outside the allowed range) that are not
claimed by other open connections.
This may be used for monitoring purposes.
.Pp
The following sysctls are recognized by the driver additionally to those
handled by
.Xr utopia 4 :
.Bl -tag -width indent
.It Va hw.atm.patm Ns Ar N Ns Va .istats
Returns a list of
.Vt uint32_t
statistic counters with internal driver statistics.
.It Va hw.atm.patm Ns Ar N Ns Va .eeprom
This is a read-only variable containing the contents of the on-board EEPROM
device.
.It Va hw.atm.patm Ns Ar N Ns Va .lbuf_max
This puts an upper limit on the number of large receive buffers the
driver will allocate.
This is a read-only variable that can be set via a
.Xr loader 8
tunable.
.It Va hw.atm.patm Ns Ar N Ns Va .tx_maxmaps
This is the upper limit of transmission DMA maps the driver will allocate.
This is read-only but may be set via a
.Xr loader 8
tunable.
.It Va hw.atm.patm Ns Ar N Ns Va .debug
.Bf Em
(Only if debugging enabled.)
.Ef
These are debugging flags.
See
.Pa src/sys/dev/patm/if_patmvar.h
for the possible flags.
This may be initialized via a
.Xr loader 8
tunable.
.It Va hw.atm.patm Ns Ar N Ns Va .regs
.Bf Em
(Only if debugging enabled.)
.Ef
Returns the current values of the card's registers.
.It Va hw.atm.patm Ns Ar N Ns Va .tsq
Returns the transmit status queue.
.El
.Pp
When loaded, the driver initializes several variables from
.Xr loader 8
tunables:
.Bl -tag -width indent
.It Va hw.patm Ns Ar N Ns Va .lbuf_max
This initializes the corresponding
.Xr sysctl 8
variable and defines an upper
limit on the number of large receive buffers (mbuf clusters).
.It Va hw.patm Ns Ar N Ns Va .tx_maxmaps
This initializes the corresponding
.Xr sysctl 8
variable and is the maximum
number of DMA maps for transmission that the driver will allocated.
.It Va hw.patm Ns Ar N Ns Va .debug
.Bf Em
(Only if debugging enabled.)
.Ef
Initializes the debugging flags.
.El
.Pp
The driver supports the media options
.Cm sdh , noscramb
and
.Cm unassigned
(see
.Xr utopia 4 )
when the card is a 155MBit card.
Both PMC-Sierra S/UNI and IDT77155 PHY chips are supported for these cards.
For 25MBit cards the IDT77105 is supported.
.Sh DIAGNOSTICS
.Bd -literal
patm1: <NICStAR (77222/77252) ATM adapter> port 0xc000-0xc0ff mem 0xf8000000-0xf83fffff,0xf4000000-0xf4000fff irq 11 at device 8.0 on pci2
patm1: IDT77252 155MBit interface; idt77252 Rev. G; IDT77155 PHY
patm1: 128K x 32 SRAM; 4096 connections
.Ed
.Sh SEE ALSO
.Xr natm 4 ,
.Xr natmip 4 ,
.Xr utopia 4
.Sh ACKNOWLEDGEMENTS
Thanks to Christian Bucari from ProSum for lending two of these cards to enable
the development of this driver.
Thanks also for answering my questions.
.Sh AUTHORS
.An Harti Brandt Aq Mt harti@FreeBSD.org
.Sh CAVEATS
The card fails to generate an interrupt if a cell is received in AAL0 mode
that has the MSB of the PTI field cleared.
Therefore cells will be delivered on the next receive interrupt which can happen
either when the receive status queue is full, or a cell with the last bit of
the PTI set is received.
.Pp
Although the card supports AAL3/4 the driver does not.
.Pp
The rate tables used by this driver are not the tables recommended by IDT
(they are wrong anyway).
The driver's tables are slightly more aggressive than IDT's.
That means, that the actual cell rate can be slightly higher than the
specified.
This is in contrast to the IDT tables where cell rates 5% less than the
allowed one have been observed.
This can be changed by changing the program that generates these tables,
found in
.Pa /usr/src/sys/dev/patm/genrtab ,
and regenerating them.
.Pp
The reported media for the 155MBit cards will always be OC3/MM, because
there is no (known to me) way to figure out the actual medium.
The medium should really be coded in the EEPROM by the manufacturer.
.Pp
The Tx cell counter in the utopia statistics is wrong, because the chip
uses idle cells for spacing and the PHY counts these cells.
While there is a configuration option for the chip to switch of these cells
and, according to the documentation, this should not influence cell spacing,
it does, so the driver lets the chip generate idle cells.

View File

@ -1,196 +0,0 @@
.\" Copyright (c) 2003
.\" Fraunhofer Institute for Open Communication Systems (FhG Fokus).
.\" 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.
.\"
.\" Author: Hartmut Brandt <harti@FreeBSD.org>
.\"
.\" $FreeBSD$
.\"
.Dd November 22, 2006
.Dt UTOPIA 4
.Os
.Sh NAME
.Nm utopia
.Nd "driver module for ATM PHY chips"
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following line in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device utopia"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
utopia_load="YES"
.Ed
.Sh DESCRIPTION
This module is used by all ATM drivers for cards that use
PMC-Sierra S/Uni and IDT77105/IDT77155
chips to provide uniform functionality.
The module implements status monitoring
in either interrupt or polling mode, media option handling and application
access to chip registers.
.Pp
The driver implements several sysctls that are accessible under the
.Va hw.atm. Ns Ao Ar iface Ac Ns Va .\&
tree, where
.Ar iface
is the name of the ATM interface:
.Bl -tag -width indent
.It Va phy_regs
When reading this sysctl an array of 8-bit unsigned integers is returned
containing all accessible chip registers starting at register 0.
A register can be written by writing three 8-bit unsigned integers to the
sysctl: the register number, the new value and a bit mask.
This changes all bits in the register for which the corresponding bit in the
mask is one to the bit values from value.
Note that not all registers may
be writeable.
.It Va phy_loopback
allows to put the interface in one of several loopback modes.
Not all modes and all combinations of modes are supported on all chips.
The possible modes are:
.Bl -tag -width indent
.It Dv UTP_LOOP_NONE Pq No 0x00
No loopback, normal operation.
.It Dv UTP_LOOP_TIME Pq No 0x01
Timing source loopback.
When this is set the transmitter's clock is
derived from the receiver's clock.
.It Dv UTP_LOOP_DIAG Pq No 0x02
Diagnostic loopback.
In this mode the receiver's input is connected to the
transmitter's output.
The receiver gets back everything that is sent.
The
transmitter operates normally.
.It Dv UTP_LOOP_LINE Pq No 0x04
Serial line loopback.
This connects the line receiver to the line transmitter.
The chip transmits all cells back that it receives.
The receiver operates
normally.
.It Dv UTP_LOOP_PARAL Pq No 0x08
Parallel diagnostic loopback.
This feeds back all transmitted cells into the
receiver between the parallel/serial converters.
The transmitter
operates normally.
.It Dv UTP_LOOP_TWIST Pq No 0x10
Twisted pair diagnostic loopback.
Connects the high speed receive data to the
high speed transmit data.
All received data is sent back.
The receiver
operates normally.
.It Dv UTP_LOOP_PATH Pq No 0x20
Diagnostic path loopback.
This connects the receiver input to the transmitter
output just between the path overhead processor and the byte mux.
The
transmitter operates normally.
.El
.It Va phy_type
This is the detected type of the phy chip.
Currently the following chips are
supported:
.Bl -tag -width indent
.It Dv UTP_TYPE_UNKNOWN Pq No 0
The module could not determine the type of the PHY chip.
.It Dv UTP_TYPE_SUNI_LITE Pq No 1
PMC-5346 (S/Uni-Lite)
.It Dv UTP_TYPE_SUNI_ULTRA Pq No 2
PMC-5350 (S/Uni-Ultra)
.It Dv UTP_TYPE_SUNI_622 Pq No 3
PMC-5355 (S/Uni-622)
.It Dv UTP_TYPE_IDT77105 Pq No 4
IDT77105 (25.6MBit UTP interface)
.It Dv UTP_TYPE_IDT77155 Pq No 5
IDT77155 (155MBit interface)
.El
.It Va phy_name
This is a string describing the type of the PHY chip.
.It Va phy_stats
Physical and some ATM layer statistics.
These are the statistics usually
provided by the chip.
The data is a returned in the following structure:
.Bd -literal
struct utopia_stats1 {
uint32_t version; /* version of this struct */
uint32_t fill;
uint64_t rx_sbip; /* rx section BIP errors */
uint64_t rx_lbip; /* rx line BIP errors */
uint64_t rx_lfebe; /* rx line far end block errors */
uint64_t rx_pbip; /* rx path BIP errors */
uint64_t rx_pfebe; /* rx path far end block errors */
uint64_t rx_cells; /* received cells */
uint64_t rx_corr; /* correctable cell errors */
uint64_t rx_uncorr; /* uncorrectable cell errors */
uint64_t rx_symerr; /* symbol errors */
uint64_t tx_cells; /* transmitted cells */
};
.Ed
.Pp
The current version is 1.
The statistics are updated from the chip once
a second.
On overflow the counters wrap to zero.
Note that not all counters
are meaningful for all PHY chips.
The statistics are cleared by writing an
arbitrary new value (the value is ignored).
.El
.Pp
The
.Nm
module also interfaces with the ifmedia system.
The module reports the current state of the carrier and will issue a
warning message when the carrier state changes.
While the physical media itself cannot be changed, several media options can:
.Bl -tag -width indent
.It Cm SDH
If the PHY is a Sonet/SDH chip this flag switches the interface into SDH mode.
If this option is not set (the default) the interface is in Sonet mode.
.It Cm noscramb
If the PHY is a Sonet/SDH chip disable scrambling.
This may be useful for debugging purposes.
.It Cm unassigned
Normally the interface emits idle cells when there are no other cells to
transmit.
This changes the default cell type to unassigned cells.
This
may be needed for interworking with public networks.
.El
.Sh SEE ALSO
.Xr en 4 ,
.Xr fatm 4 ,
.Xr hatm 4 ,
.Xr patm 4 ,
.Xr utopia 9
.Sh AUTHORS
.An Harti Brandt Aq Mt harti@FreeBSD.org

View File

@ -327,16 +327,13 @@ if_de_load="NO" # DEC DC21x4x Ethernet
if_ed_load="NO" # National Semiconductor DS8390/WD83C690
# Ethernet
if_em_load="NO" # Intel(R) PRO/1000 Gigabit Ethernet
if_en_load="NO" # Midway-based ATM interfaces
if_ep_load="NO" # 3Com Etherlink III (3c5x9)
if_et_load="NO" # Agere ET1310 10/100/Gigabit Ethernet
if_ex_load="NO" # Intel EtherExpress Pro/10 Ethernet
if_fatm_load="NO" # Fore PCA200E ATM
if_fe_load="NO" # Fujitsu MB86960A/MB86965A based Ethernet
# adapters
if_fxp_load="NO" # Intel EtherExpress PRO/100B (82557, 82558)
if_gem_load="NO" # Sun GEM/Sun ERI/Apple GMAC
if_hatm_load="NO" # Fore/Marconi HE155 and HE622
if_hme_load="NO" # Sun Microelectronics STP2002-STQ Ethernet
if_ie_load="NO" # Intel 82586
if_ipw_load="NO" # Intel PRO/Wireless 2100 wireless
@ -360,7 +357,6 @@ if_my_load="NO" # Myson PCI Fast Ethernet
if_nfe_load="NO" # NVIDIA nForce MCP Networking Adapter
if_nge_load="NO" # National Semiconductor PCI Gigabit Ethernet
if_nxge_load="NO" # Neterion Xframe 10Gb Ethernet
if_patm_load="NO" # IDT77252 ATM
if_pcn_load="NO" # AMD PCnet PCI
if_ral_load="NO" # Ralink Technology wireless
if_re_load="NO" # RealTek 8139C+/8169/8169S/8110S
@ -395,7 +391,6 @@ if_wpi_load="NO" # Intel 3945ABG Wireless LAN IEEE 802.11
if_xe_load="NO" # Xircom CreditCard PCMCIA
if_xl_load="NO" # 3Com Etherlink XL (3c900, 3c905, 3c905B)
sfxge_load="NO" # Solarflare 10Gb Ethernet adapter driver
utopia_load="NO" # ATM PHY driver
##############################################################

View File

@ -2212,42 +2212,7 @@ device rtwnfw
options MCLSHIFT=12 # mbuf cluster shift in bits, 12 == 4KB
options MSIZE=512 # mbuf size in bytes
#
# ATM related options (Cranor version)
# (note: this driver cannot be used with the HARP ATM stack)
#
# The `en' device provides support for Efficient Networks (ENI)
# ENI-155 PCI midway cards, and the Adaptec 155Mbps PCI ATM cards (ANA-59x0).
#
# The `hatm' device provides support for Fore/Marconi HE155 and HE622
# ATM PCI cards.
#
# The `fatm' device provides support for Fore PCA200E ATM PCI cards.
#
# The `patm' device provides support for IDT77252 based cards like
# ProSum's ProATM-155 and ProATM-25 and IDT's evaluation boards.
#
# atm device provides generic atm functions and is required for
# atm devices.
# NATM enables the netnatm protocol family that can be used to
# bypass TCP/IP.
#
# utopia provides the access to the ATM PHY chips and is required for en,
# hatm and fatm.
#
# the current driver supports only PVC operations (no atm-arp, no multicast).
# for more details, please read the original documents at
# http://www.ccrc.wustl.edu/pub/chuck/tech/bsdatm/bsdatm.html
#
device atm
device en
device fatm #Fore PCA200E
device hatm #Fore/Marconi HE155/622
device patm #IDT77252 cards (ProATM and IDT)
device utopia #ATM PHY driver
options NATM #native ATM
options LIBMBPOOL #needed by patm, iatm
options LIBMBPOOL
#
# Sound drivers

View File

@ -25,8 +25,6 @@ opt_ratelimit.h:
.endif
opt_mrouting.h:
echo "#define MROUTING 1" > ${.TARGET}
opt_natm.h:
echo "#define NATM 1" > ${.TARGET}
opt_printf.h:
echo "#define PRINTF_BUFR_SIZE 128" > ${.TARGET}
opt_scsi.h:
@ -38,7 +36,7 @@ opt_wlan.h:
KERN_OPTS.i386=NEW_PCIB DEV_PCI
KERN_OPTS.amd64=NEW_PCIB DEV_PCI
KERN_OPTS.powerpc=NEW_PCIB DEV_PCI
KERN_OPTS=MROUTING NATM IEEE80211_DEBUG \
KERN_OPTS=MROUTING IEEE80211_DEBUG \
IEEE80211_AMPDU_AGE IEEE80211_SUPPORT_MESH DEV_BPF \
${KERN_OPTS.${MACHINE}} ${KERN_OPTS_EXTRA}
.if ${MK_INET_SUPPORT} != "no"

View File

@ -1579,8 +1579,6 @@ dev/e1000/e1000_mbx.c optional em \
dev/e1000/e1000_osdep.c optional em \
compile-with "${NORMAL_C} -I$S/dev/e1000"
dev/et/if_et.c optional et
dev/en/if_en_pci.c optional en pci
dev/en/midway.c optional en
dev/ep/if_ep.c optional ep
dev/ep/if_ep_isa.c optional ep isa
dev/ep/if_ep_pccard.c optional ep pccard
@ -1636,7 +1634,6 @@ dev/extres/regulator/regnode_if.m optional ext_resources regulator fdt
dev/extres/regulator/regulator.c optional ext_resources regulator fdt
dev/extres/regulator/regulator_bus.c optional ext_resources regulator fdt
dev/extres/regulator/regulator_fixed.c optional ext_resources regulator fdt
dev/fatm/if_fatm.c optional fatm pci
dev/fb/fbd.c optional fbd | vt
dev/fb/fb_if.m standard
dev/fb/splash.c optional sc splash
@ -1688,11 +1685,6 @@ dev/gpio/gpio_if.m optional gpio
dev/gpio/gpiobus_if.m optional gpio
dev/gpio/gpiopps.c optional gpiopps
dev/gpio/ofw_gpiobus.c optional fdt gpio
dev/hatm/if_hatm.c optional hatm pci
dev/hatm/if_hatm_intr.c optional hatm pci
dev/hatm/if_hatm_ioctl.c optional hatm pci
dev/hatm/if_hatm_rx.c optional hatm pci
dev/hatm/if_hatm_tx.c optional hatm pci
dev/hifn/hifn7751.c optional hifn
dev/hme/if_hme.c optional hme
dev/hme/if_hme_pci.c optional hme pci
@ -2374,13 +2366,6 @@ dev/ow/owll_if.m optional ow
dev/ow/own_if.m optional ow
dev/ow/ow_temp.c optional ow_temp
dev/ow/owc_gpiobus.c optional owc gpio
dev/patm/if_patm.c optional patm pci
dev/patm/if_patm_attach.c optional patm pci
dev/patm/if_patm_intr.c optional patm pci
dev/patm/if_patm_ioctl.c optional patm pci
dev/patm/if_patm_rtables.c optional patm pci
dev/patm/if_patm_rx.c optional patm pci
dev/patm/if_patm_tx.c optional patm pci
dev/pbio/pbio.c optional pbio isa
dev/pccard/card_if.m standard
dev/pccard/pccard.c optional pccard
@ -3202,9 +3187,6 @@ dev/videomode/videomode.c optional videomode
dev/videomode/edid.c optional videomode
dev/videomode/pickmode.c optional videomode
dev/videomode/vesagtf.c optional videomode
dev/utopia/idtphy.c optional utopia
dev/utopia/suni.c optional utopia
dev/utopia/utopia.c optional utopia
dev/vge/if_vge.c optional vge
dev/viapm/viapm.c optional viapm pci
dev/virtio/virtio.c optional virtio
@ -3884,7 +3866,6 @@ net/flowtable.c optional flowtable inet | flowtable inet6
net/ieee8023ad_lacp.c optional lagg
net/if.c standard
net/if_arcsubr.c optional arcnet
net/if_atmsubr.c optional atm
net/if_bridge.c optional bridge inet | if_bridge inet
net/if_clone.c standard
net/if_dead.c standard
@ -3981,7 +3962,6 @@ net80211/ieee80211_xauth.c optional wlan wlan_xauth
net80211/ieee80211_alq.c optional wlan ieee80211_alq
netgraph/atm/ccatm/ng_ccatm.c optional ngatm_ccatm \
compile-with "${NORMAL_C} -I$S/contrib/ngatm"
netgraph/atm/ng_atm.c optional ngatm_atm
netgraph/atm/ngatmbase.c optional ngatm_atmbase \
compile-with "${NORMAL_C} -I$S/contrib/ngatm"
netgraph/atm/sscfu/ng_sscfu.c optional ngatm_sscfu \
@ -4063,7 +4043,6 @@ netgraph/ng_vlan.c optional netgraph_vlan
netinet/accf_data.c optional accept_filter_data inet
netinet/accf_dns.c optional accept_filter_dns inet
netinet/accf_http.c optional accept_filter_http inet
netinet/if_atm.c optional atm
netinet/if_ether.c optional inet ether
netinet/igmp.c optional inet
netinet/in.c optional inet
@ -4188,9 +4167,6 @@ netipsec/xform_ipcomp.c optional ipsec inet | ipsec inet6
netipsec/xform_tcp.c optional ipsec inet tcp_signature | \
ipsec inet6 tcp_signature | ipsec_support inet tcp_signature | \
ipsec_support inet6 tcp_signature
netnatm/natm.c optional natm
netnatm/natm_pcb.c optional natm
netnatm/natm_proto.c optional natm
netpfil/ipfw/dn_aqm_codel.c optional inet dummynet
netpfil/ipfw/dn_aqm_pie.c optional inet dummynet
netpfil/ipfw/dn_heap.c optional inet dummynet

View File

@ -553,10 +553,6 @@ DRM_DEBUG opt_drm.h
TI_SF_BUF_JUMBO opt_ti.h
TI_JUMBO_HDRSPLIT opt_ti.h
# XXX Conflict: # of devices vs network protocol (Native ATM).
# This makes "atm.h" unusable.
NATM
# DPT driver debug flags
DPT_MEASURE_PERFORMANCE opt_dpt.h
DPT_RESET_HBA opt_dpt.h

View File

@ -1,496 +0,0 @@
/* $NetBSD: if_en_pci.c,v 1.1 1996/06/22 02:00:31 chuck Exp $ */
/*-
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED 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.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* i f _ e n _ p c i . c
*
* author: Chuck Cranor <chuck@ccrc.wustl.edu>
* started: spring, 1996.
*
* FreeBSD PCI glue for the eni155p card.
* thanks to Matt Thomas for figuring out FreeBSD vs NetBSD vs etc.. diffs.
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/condvar.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <vm/uma.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_atm.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/utopia/utopia.h>
#include <dev/en/midwayreg.h>
#include <dev/en/midwayvar.h>
MODULE_DEPEND(en, pci, 1, 1, 1);
MODULE_DEPEND(en, atm, 1, 1, 1);
MODULE_DEPEND(en, utopia, 1, 1, 1);
/*
* local structures
*/
struct en_pci_softc {
/* bus independent stuff */
struct en_softc esc; /* includes "device" structure */
/* freebsd newbus glue */
struct resource *res; /* resource descriptor for registers */
struct resource *irq; /* resource descriptor for interrupt */
void *ih; /* interrupt handle */
};
static void eni_get_macaddr(device_t, struct en_pci_softc *);
static void adp_get_macaddr(struct en_pci_softc *);
/*
* address of config base memory address register in PCI config space
* (this is card specific)
*/
#define PCI_CBMA PCIR_BAR(0)
/*
* tonga (pci bridge). ENI cards only!
*/
#define EN_TONGA 0x60 /* PCI config addr of tonga reg */
#define TONGA_SWAP_DMA 0x80 /* endian swap control */
#define TONGA_SWAP_BYTE 0x40
#define TONGA_SWAP_WORD 0x20
#define TONGA_READ_MULT 0x00
#define TONGA_READ_MEM 0x04
#define TONGA_READ_IVAN 0x08
#define TONGA_READ_KEN 0x0C
/*
* adaptec pci bridge. ADP cards only!
*/
#define ADP_PCIREG 0x050040 /* PCI control register */
#define ADP_PCIREG_RESET 0x1 /* reset card */
#define ADP_PCIREG_IENABLE 0x2 /* interrupt enable */
#define ADP_PCIREG_SWAP_WORD 0x4 /* swap byte on slave access */
#define ADP_PCIREG_SWAP_DMA 0x8 /* swap byte on DMA */
#define PCI_VENDOR_EFFICIENTNETS 0x111a /* Efficent Networks */
#define PCI_PRODUCT_EFFICIENTNETS_ENI155PF 0x0000 /* ENI-155P ATM */
#define PCI_PRODUCT_EFFICIENTNETS_ENI155PA 0x0002 /* ENI-155P ATM */
#define PCI_VENDOR_ADP 0x9004 /* adaptec */
#define PCI_PRODUCT_ADP_AIC5900 0x5900
#define PCI_PRODUCT_ADP_AIC5905 0x5905
#define PCI_VENDOR(x) ((x) & 0xFFFF)
#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF)
/*
* bus specific reset function [ADP only!]
*/
static void
adp_busreset(void *v)
{
struct en_softc *sc = (struct en_softc *)v;
uint32_t dummy;
bus_space_write_4(sc->en_memt, sc->en_base, ADP_PCIREG,
ADP_PCIREG_RESET);
DELAY(1000); /* let it reset */
dummy = bus_space_read_4(sc->en_memt, sc->en_base, ADP_PCIREG);
bus_space_write_4(sc->en_memt, sc->en_base, ADP_PCIREG,
(ADP_PCIREG_SWAP_DMA | ADP_PCIREG_IENABLE));
dummy = bus_space_read_4(sc->en_memt, sc->en_base, ADP_PCIREG);
if ((dummy & (ADP_PCIREG_SWAP_WORD | ADP_PCIREG_SWAP_DMA)) !=
ADP_PCIREG_SWAP_DMA)
device_printf(sc->dev, "%s: Adaptec ATM did NOT reset!\n",
__func__);
}
/***********************************************************************/
/*
* autoconfig stuff
*/
static int
en_pci_probe(device_t dev)
{
switch (pci_get_vendor(dev)) {
case PCI_VENDOR_EFFICIENTNETS:
switch (pci_get_device(dev)) {
case PCI_PRODUCT_EFFICIENTNETS_ENI155PF:
case PCI_PRODUCT_EFFICIENTNETS_ENI155PA:
device_set_desc(dev, "Efficient Networks ENI-155p");
return (BUS_PROBE_DEFAULT);
}
break;
case PCI_VENDOR_ADP:
switch (pci_get_device(dev)) {
case PCI_PRODUCT_ADP_AIC5900:
case PCI_PRODUCT_ADP_AIC5905:
device_set_desc(dev, "Adaptec 155 ATM");
return (BUS_PROBE_DEFAULT);
}
break;
}
return (ENXIO);
}
static int
en_pci_attach(device_t dev)
{
struct en_softc *sc;
struct en_pci_softc *scp;
int rid, error = 0;
sc = device_get_softc(dev);
scp = (struct en_pci_softc *)sc;
sc->dev = dev;
sc->ifp = if_alloc(IFT_ATM);
if (sc->ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
error = ENOSPC;
goto fail;
}
if_initname(sc->ifp, device_get_name(dev),
device_get_unit(dev));
/*
* Enable bus mastering.
*/
pci_enable_busmaster(dev);
/*
* Map control/status registers.
*/
rid = PCI_CBMA;
scp->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (scp->res == NULL) {
device_printf(dev, "could not map memory\n");
if_free(sc->ifp);
error = ENXIO;
goto fail;
}
sc->en_memt = rman_get_bustag(scp->res);
sc->en_base = rman_get_bushandle(scp->res);
/*
* Allocate our interrupt.
*/
rid = 0;
scp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE);
if (scp->irq == NULL) {
device_printf(dev, "could not map interrupt\n");
bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
if_free(sc->ifp);
error = ENXIO;
goto fail;
}
sc->ipl = 1; /* XXX (required to enable interrupt on midway) */
/* figure out if we are an adaptec card or not */
sc->is_adaptec = (pci_get_vendor(dev) == PCI_VENDOR_ADP) ? 1 : 0;
/*
* set up pci bridge
*/
if (sc->is_adaptec) {
adp_get_macaddr(scp);
sc->en_busreset = adp_busreset;
adp_busreset(sc);
} else {
eni_get_macaddr(dev, scp);
sc->en_busreset = NULL;
pci_write_config(dev, EN_TONGA, TONGA_SWAP_DMA | TONGA_READ_IVAN, 4);
}
/*
* Common attach stuff
*/
if ((error = en_attach(sc)) != 0) {
device_printf(dev, "attach failed\n");
bus_teardown_intr(dev, scp->irq, scp->ih);
bus_release_resource(dev, SYS_RES_IRQ, 0, scp->irq);
bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
if_free(sc->ifp);
goto fail;
}
/*
* Do the interrupt SETUP last just before returning
*/
error = bus_setup_intr(dev, scp->irq, INTR_TYPE_NET,
NULL, en_intr, sc, &scp->ih);
if (error) {
en_reset(sc);
atm_ifdetach(sc->ifp);
device_printf(dev, "could not setup irq\n");
bus_release_resource(dev, SYS_RES_IRQ, 0, scp->irq);
bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
en_destroy(sc);
if_free(sc->ifp);
goto fail;
}
return (0);
fail:
return (error);
}
/*
* Detach the adapter
*/
static int
en_pci_detach(device_t dev)
{
struct en_softc *sc = device_get_softc(dev);
struct en_pci_softc *scp = (struct en_pci_softc *)sc;
/*
* Stop DMA and drop transmit queue.
*/
if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
device_printf(sc->dev, "still running\n");
sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
}
/*
* Close down routes etc.
*/
en_reset(sc);
atm_ifdetach(sc->ifp);
/*
* Deallocate resources.
*/
bus_teardown_intr(dev, scp->irq, scp->ih);
bus_release_resource(dev, SYS_RES_IRQ, 0, scp->irq);
bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
/*
* Free all the driver internal resources
*/
en_destroy(sc);
if_free(sc->ifp);
return (0);
}
static int
en_pci_shutdown(device_t dev)
{
struct en_pci_softc *psc = device_get_softc(dev);
en_reset(&psc->esc);
DELAY(10); /* is this necessary? */
return (0);
}
/*
* Get the MAC address from an Adaptec board. No idea how to get
* serial number or other stuff, because I have no documentation for that
* card.
*/
static void
adp_get_macaddr(struct en_pci_softc *scp)
{
struct en_softc * sc = (struct en_softc *)scp;
int lcv;
for (lcv = 0; lcv < sizeof(IFP2IFATM(sc->ifp)->mib.esi); lcv++)
IFP2IFATM(sc->ifp)->mib.esi[lcv] = bus_space_read_1(sc->en_memt,
sc->en_base, MID_ADPMACOFF + lcv);
}
/*
* Read station (MAC) address from serial EEPROM.
* derived from linux drivers/atm/eni.c by Werner Almesberger, EPFL LRC.
*/
#define EN_PROM_MAGIC 0x0c
#define EN_PROM_DATA 0x02
#define EN_PROM_CLK 0x01
#define EN_ESI 64
#define EN_SERIAL 112
/*
* Read a byte from the given address in the EEPROM
*/
static uint8_t
eni_get_byte(device_t dev, uint32_t *data, u_int address)
{
int j;
uint8_t tmp;
address = (address << 1) + 1;
/* start operation */
*data |= EN_PROM_DATA ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data |= EN_PROM_CLK ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data &= ~EN_PROM_DATA ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data &= ~EN_PROM_CLK ;
pci_write_config(dev, EN_TONGA, *data, 4);
/* send address with serial line */
for ( j = 7 ; j >= 0 ; j --) {
*data = ((address >> j) & 1) ? (*data | EN_PROM_DATA) :
(*data & ~EN_PROM_DATA);
pci_write_config(dev, EN_TONGA, *data, 4);
*data |= EN_PROM_CLK ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data &= ~EN_PROM_CLK ;
pci_write_config(dev, EN_TONGA, *data, 4);
}
/* get ack */
*data |= EN_PROM_DATA ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data |= EN_PROM_CLK ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data = pci_read_config(dev, EN_TONGA, 4);
*data &= ~EN_PROM_CLK ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data |= EN_PROM_DATA ;
pci_write_config(dev, EN_TONGA, *data, 4);
tmp = 0;
for ( j = 7 ; j >= 0 ; j --) {
tmp <<= 1;
*data |= EN_PROM_DATA ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data |= EN_PROM_CLK ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data = pci_read_config(dev, EN_TONGA, 4);
if(*data & EN_PROM_DATA) tmp |= 1;
*data &= ~EN_PROM_CLK ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data |= EN_PROM_DATA ;
pci_write_config(dev, EN_TONGA, *data, 4);
}
/* get ack */
*data |= EN_PROM_DATA ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data |= EN_PROM_CLK ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data = pci_read_config(dev, EN_TONGA, 4);
*data &= ~EN_PROM_CLK ;
pci_write_config(dev, EN_TONGA, *data, 4);
*data |= EN_PROM_DATA ;
pci_write_config(dev, EN_TONGA, *data, 4);
return (tmp);
}
/*
* Get MAC address and other stuff from the EEPROM
*/
static void
eni_get_macaddr(device_t dev, struct en_pci_softc *scp)
{
struct en_softc * sc = (struct en_softc *)scp;
int i;
uint32_t data, t_data;
t_data = pci_read_config(dev, EN_TONGA, 4) & 0xffffff00;
data = EN_PROM_MAGIC | EN_PROM_DATA | EN_PROM_CLK;
pci_write_config(dev, EN_TONGA, data, 4);
for (i = 0; i < sizeof(IFP2IFATM(sc->ifp)->mib.esi); i ++)
IFP2IFATM(sc->ifp)->mib.esi[i] = eni_get_byte(dev, &data, i + EN_ESI);
IFP2IFATM(sc->ifp)->mib.serial = 0;
for (i = 0; i < 4; i++) {
IFP2IFATM(sc->ifp)->mib.serial <<= 8;
IFP2IFATM(sc->ifp)->mib.serial |= eni_get_byte(dev, &data, i + EN_SERIAL);
}
/* stop operation */
data &= ~EN_PROM_DATA;
pci_write_config(dev, EN_TONGA, data, 4);
data |= EN_PROM_CLK;
pci_write_config(dev, EN_TONGA, data, 4);
data |= EN_PROM_DATA;
pci_write_config(dev, EN_TONGA, data, 4);
pci_write_config(dev, EN_TONGA, t_data, 4);
}
/*
* Driver infrastructure
*/
static device_method_t en_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, en_pci_probe),
DEVMETHOD(device_attach, en_pci_attach),
DEVMETHOD(device_detach, en_pci_detach),
DEVMETHOD(device_shutdown, en_pci_shutdown),
{ 0, 0 }
};
static driver_t en_driver = {
"en",
en_methods,
sizeof(struct en_pci_softc),
};
static devclass_t en_devclass;
DRIVER_MODULE(en, pci, en_driver, en_devclass, en_modevent, 0);

File diff suppressed because it is too large Load Diff

View File

@ -1,282 +0,0 @@
/* $NetBSD: midwayreg.h,v 1.6 1997/03/20 21:34:47 chuck Exp $ */
/*
* m i d w a y r e g . h
*
* this file contains the description of the ENI ATM midway chip
* data structures. see midway.c for more details.
*
* $FreeBSD$
*/
#define MID_SZTOB(X) ((X) * 256 * 4) /* size to bytes */
#define MID_BTOSZ(X) ((X) / 256 / 4) /* bytes to "size" */
#define MID_N_VC 1024 /* # of VCs we can use */
#define MID_VCI_BITS 10 /* number of bits */
#define MID_NTX_CH 8 /* 8 transmit channels (shared) */
#define MID_ATMDATASZ 48 /* need data in 48 byte blocks */
/*
* card data structures, top down
*
* in order to have a portable driver, the netbsd guys will not let us
* use structs. we have a bus_space_handle_t which is the en_base address.
* everything else is an offset from that base. all card data must be
* accessed with bus_space_read_4()/bus_space_write_4():
*
* rv = bus_space_read_4(sc->en_memt, sc->en_base, BYTE_OFFSET);
* bus_space_write_4(sc->en_memt, sc->en_base, BYTE_OFFSET, VALUE);
*
* en_card: the whole card (prom + phy + midway + obmem)
* obmem contains: vci tab + dma queues (rx & tx) + service list + bufs
*/
/* byte offsets from en_base of various items */
#define MID_SUNIOFF 0x020000 /* SUNI offset */
#define MID_PHYOFF 0x030000 /* PHY offset */
#define MID_MIDOFF 0x040000 /* midway regs offset */
#define MID_RAMOFF 0x200000 /* RAM offset */
#define MID_DRQOFF 0x204000 /* DRQ offset */
#define MID_DRQEND MID_DTQOFF /* DRQ end */
#define MID_DTQOFF 0x205000 /* DTQ offset */
#define MID_DTQEND MID_SLOFF /* DTQ end */
#define MID_SLOFF 0x206000 /* service list */
#define MID_SLEND MID_BUFOFF /* service list end */
#define MID_BUFOFF 0x207000 /* buffer area */
#define MID_PROBEOFF 0x21fffc /* start probe here */
#define MID_PROBSIZE 0x020000 /* 128 KB */
#define MID_MAXOFF 0x3ffffc /* max offset */
/*
* prom & phy: not defined here
*/
#define MID_ADPMACOFF 0xffc0 /* mac address offset (adaptec only) */
#define MID_NSUNI 256 /* suni registers */
/*
* midway regs (byte offsets from en_base)
*/
#define MID_RESID 0x40000 /* write=reset reg, read=ID reg */
#define MID_VER(X) (((X) & 0xf0000000) >> 28) /* midway version # */
#define MID_MID(X) (((X) & 0x700) >> 8) /* motherboard ID */
#define MID_IS_SABRE(X) ((X) & 0x80) /* sabre controller? */
#define MID_IS_SUNI(X) ((X) & 0x40) /* SUNI? vs utopia */
#define MID_IS_UPIPE(X) ((X) & 0x20) /* utopia pipeline? */
#define MID_DID(X) ((X) & 0x1f) /* daughterboard ID */
#define MID_INTACK 0x40004 /* interrupt ACK */
#define MID_INTSTAT 0x40008 /* interrupt status */
#define MID_INTENA 0x4000c /* interrupt enable */
#define MID_TXCHAN(N) (1 << ((N) + 9)) /* ack/status/enable xmit channel bit*/
#define MID_INT_TX 0x1fe00 /* mask for any xmit interrupt */
#define MID_INT_DMA_OVR 0x00100 /* DMA overflow interrupt */
#define MID_INT_IDENT 0x00080 /* ident match error interrupt */
#define MID_INT_LERR 0x00040 /* LERR interrupt (sbus?) */
#define MID_INT_DMA_ERR 0x00020 /* DMA error interrupt */
#define MID_INT_DMA_RX 0x00010 /* DMA recv interrupt */
#define MID_INT_DMA_TX 0x00008 /* DMA xmit interrupt */
#define MID_INT_SERVICE 0x00004 /* service list interrupt */
#define MID_INT_SUNI 0x00002 /* SUNI interrupt */
#define MID_INT_STATS 0x00001 /* stats overflow interrupt */
#define MID_INT_ANY 0x1ffff /* any interrupt? */
#define MID_INTBITS "\20\21T7\20T6\17T5\16T4\15T3\14T2\13T1\12T0\11DMAOVR\10ID\7LERR\6DMAERR\5RXDMA\4TXDMA\3SERV\2SUNI\1STAT"
#define MID_MAST_CSR 0x40010 /* master CSR */
#define MID_IPL(X) (((X) & 0x1c0) >> 6) /* IPL */
#define MID_SETIPL(I) ((I) << 6)
#define MID_MCSR_TXLOCK 0x20 /* lock on xmit overflow mode */
/* NOTE: next 5 bits: write 1 means enable, write 0 means no change */
#define MID_MCSR_ENDMA 0x10 /* DMA enable */
#define MID_MCSR_ENTX 0x08 /* TX enable */
#define MID_MCSR_ENRX 0x04 /* RX enable */
#define MID_MCSR_W1MS 0x02 /* wait 1 msec */
#define MID_MCSR_W500US 0x01 /* wait 500 usec */
#define MID_MCSRBITS "\20\6LCK\5DMAON\4TXON\3RXON\2W1MS\1W500US"
#define MID_STAT 0x40014 /* stat register, clear on read */
#define MID_VTRASH(X) (((X) >> 16) & 0xffff)
/* # cells trashed due to VCI's mode */
#define MID_OTRASH(X) ((X) & 0xffff) /* # cells trashed due to overflow */
#define MID_SERV_WRITE 0x40018 /* 10 bit service write pointer (r/o) */
#define MID_DMA_ADDR 0x4001c /* VA of DMA (r/o) */
/* DMA queue pointers (bits 0 to 8) */
#define MID_DMA_WRRX 0x40020 /* write ptr. for DMA recv queue */
/* (for adaptor -> host xfers) */
#define MID_DMA_RDRX 0x40024 /* read ptr for DMA recv queue (r/o) */
/* (i.e. current adaptor->host xfer) */
#define MID_DMA_WRTX 0x40028 /* write ptr for DMA xmit queue */
/* (for host -> adaptor xfers) */
#define MID_DMA_RDTX 0x4002c /* read ptr for DMA xmit queue (r/o) */
/* (i.e. current host->adaptor xfer) */
/* xmit channel regs (1 per channel, MID_NTX_CH max channels) */
#define MIDX_PLACE(N) (0x40040+((N)*0x10)) /* xmit place */
#define MIDX_MKPLACE(SZ,LOC) ( ((SZ) << 11) | (LOC) )
#define MIDX_LOC(X) ((X) & 0x7ff) /* location in obmem */
#define MIDX_SZ(X) ((X) >> 11) /* (size of block / 256) in int32_t's*/
#define MIDX_BASE(X) \
(((MIDX_LOC(X) << MIDV_LOCTOPSHFT) * sizeof(uint32_t)) + MID_RAMOFF)
/* the following two regs are word offsets in the block */
/* xmit read pointer (r/o) */
#define MIDX_READPTR(N) (0x40044 + ((N) * 0x10))
/* seg currently in DMA (r/o) */
#define MIDX_DESCSTART(N) (0x40048 + ((N) * 0x10))
/*
* obmem items
*/
/*
* vci table in obmem (offset from MID_VCTOFF)
*/
#define MID_VC(N) (MID_RAMOFF + ((N) * 0x10))
#define MIDV_TRASH 0x00000000 /* ignore VC */
#define MIDV_AAL5 0x80000000 /* do AAL5 on it */
#define MIDV_NOAAL 0x40000000 /* do per-cell stuff on it */
#define MIDV_MASK 0xc0000000 /* mode mask */
#define MIDV_SETMODE(VC,M) (((VC) & ~(MIDV_MASK)) | (M)) /* new mode */
#define MIDV_PTI 0x20000000 /* save PTI cells? */
#define MIDV_LOCTOPSHFT 8 /* shift to get top 11 bits of 19 */
#define MIDV_LOCSHIFT 18
#define MIDV_LOCMASK 0x7ff
#define MIDV_LOC(X) (((X) >> MIDV_LOCSHIFT) & MIDV_LOCMASK)
/* 11 most sig bits of addr */
#define MIDV_SZSHIFT 15
#define MIDV_SZ(X) (((X) >> MIDV_SZSHIFT) & 7)
/* size encoded the usual way */
#define MIDV_INSERVICE 0x1 /* in service list */
#define MID_DST_RP(N) (MID_VC(N)|0x4)
#define MIDV_DSTART_SHIFT 16 /* shift */
#define MIDV_DSTART(X) (((X) >> MIDV_DSTART_SHIFT) & 0x7fff)
#define MIDV_READP_MASK 0x7fff /* valid bits, (shift = 0) */
#define MID_WP_ST_CNT(N) (MID_VC(N)|0x8) /* write pointer/state/count */
#define MIDV_WRITEP_MASK 0x7fff0000 /* mask for write ptr. */
#define MIDV_WRITEP_SHIFT 16
#define MIDV_ST_IDLE 0x0000
#define MIDV_ST_TRASH 0xc000
#define MIDV_ST_REASS 0x4000
#define MIDV_CCOUNT 0x7ff /* cell count */
#define MID_CRC(N) (MID_VC(N)|0xc) /* CRC */
/*
* dma recv q.
*/
#define MID_DMA_END (1 << 5) /* for both tx and rx */
#define MID_DMA_CNT(X) (((X) >> 16) & 0xffff)
#define MID_DMA_TXCHAN(X) (((X) >> 6) & 0x7)
#define MID_DMA_RXVCI(X) (((X) >> 6) & 0x3ff)
#define MID_DMA_TYPE(X) ((X) & 0xf)
#define MID_DRQ_N 512 /* # of descriptors */
/* convert byte offset to reg value */
#define MID_DRQ_A2REG(N) (((N) - MID_DRQOFF) >> 3)
/* and back */
#define MID_DRQ_REG2A(N) (((N) << 3) + MID_DRQOFF)
/* note: format of word 1 of RXQ is different beween ENI and ADP cards */
#define MID_MK_RXQ_ENI(CNT, VC, END, TYPE) \
(((CNT) << 16) | ((VC) << 6) | (END) | (TYPE))
#define MID_MK_RXQ_ADP(CNT, VC, END, JK) \
(((CNT) << 12) | ((VC) << 2) | ((END) >> 4) | (((JK) != 0) ? 1 : 0))
/*
* dma xmit q.
*/
#define MID_DTQ_N 512 /* # of descriptors */
/* convert byte offset to reg value */
#define MID_DTQ_A2REG(N) (((N) - MID_DTQOFF) >> 3)
/* and back */
#define MID_DTQ_REG2A(N) (((N) << 3) + MID_DTQOFF)
/* note: format of word 1 of TXQ is different beween ENI and ADP cards */
#define MID_MK_TXQ_ENI(CNT, CHN, END, TYPE) \
(((CNT) << 16) | ((CHN) << 6) | (END) | (TYPE))
#define MID_MK_TXQ_ADP(CNT, CHN, END, JK) \
(((CNT) << 12) | ((CHN) << 2) | ((END) >> 4) | (((JK) != 0) ? 1 : 0))
/*
* dma types
*/
#define MIDDMA_JK 0x3 /* just kidding */
#define MIDDMA_BYTE 0x1 /* byte */
#define MIDDMA_2BYTE 0x2 /* 2 bytes */
#define MIDDMA_WORD 0x0 /* word */
#define MIDDMA_2WORD 0x7 /* 2 words */
#define MIDDMA_4WORD 0x4 /* 4 words */
#define MIDDMA_8WORD 0x5 /* 8 words */
#define MIDDMA_16WORD 0x6 /* 16 words!!! */
#define MIDDMA_2WMAYBE 0xf /* 2 words, maybe */
#define MIDDMA_4WMAYBE 0xc /* 4 words, maybe */
#define MIDDMA_8WMAYBE 0xd /* 8 words, maybe */
#define MIDDMA_16WMAYBE 0xe /* 16 words, maybe */
#define MIDDMA_MAYBE 0xc /* mask to detect WMAYBE dma code */
#define MIDDMA_MAXBURST (16 * sizeof(uint32_t)) /* largest burst */
/*
* service list
*/
#define MID_SL_N 1024 /* max # entries on slist */
/* convert byte offset to reg value */
#define MID_SL_A2REG(N) (((N) - MID_SLOFF) >> 2)
/* and back */
#define MID_SL_REG2A(N) (((N) << 2) + MID_SLOFF)
/*
* data in the buffer area of obmem
*/
/*
* recv buffer desc. (1 uint32_t at start of buffer)
*/
#define MID_RBD_SIZE 4 /* RBD size */
#define MID_CHDR_SIZE 4 /* on aal0, cell header size */
#define MID_RBD_ID(X) ((X) & 0xfe000000) /* get ID */
#define MID_RBD_STDID 0x36000000 /* standard ID */
#define MID_RBD_CLP 0x01000000 /* CLP: cell loss priority */
#define MID_RBD_CE 0x00010000 /* CE: congestion experienced */
#define MID_RBD_T 0x00001000 /* T: trashed due to overflow */
#define MID_RBD_CRCERR 0x00000800 /* CRC error */
#define MID_RBD_CNT(X) ((X) & 0x7ff) /* cell count */
/*
* xmit buffer desc. (2 uint32_t's at start of buffer)
* (note we treat the PR & RATE as a single uint8_t)
*/
#define MID_TBD_SIZE 8
#define MID_TBD_MK1(AAL,PR_RATE,CNT) \
(MID_TBD_STDID | (AAL) | ((PR_RATE) << 19) | (CNT))
#define MID_TBD_STDID 0xb0000000 /* standard ID */
#define MID_TBD_AAL5 0x08000000 /* AAL 5 */
#define MID_TBD_NOAAL5 0x00000000 /* not AAL 5 */
#define MID_TBD_MK2(VCI,PTI,CLP) \
(((VCI) << 4) | ((PTI) << 1) | (CLP))
/*
* aal5 pdu tail, last 2 words of last cell of AAL5 frame
* (word 2 is CRC .. handled by hw)
*/
#define MID_PDU_SIZE 8
#define MID_PDU_MK1(UU, CPI, LEN) \
(((UU) << 24) | ((CPI) << 16) | (LEN))
#define MID_PDU_LEN(X) ((X) & 0xffff)

View File

@ -1,240 +0,0 @@
/* $NetBSD: midwayvar.h,v 1.10 1997/03/20 21:34:46 chuck Exp $ */
/*-
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED 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$
*/
/*
* m i d w a y v a r . h
*
* we define the en_softc here so that bus specific modules can allocate
* it as the first item in their softc.
*
* author: Chuck Cranor <chuck@ccrc.wustl.edu>
*/
/*
* params needed to determine softc size
*/
#ifndef EN_NTX
#define EN_NTX 8 /* number of tx bufs to use */
#endif
#ifndef EN_TXSZ
#define EN_TXSZ 32 /* trasmit buf size in KB */
#endif
#ifndef EN_RXSZ
#define EN_RXSZ 32 /* recv buf size in KB */
#endif
/* largest possible NRX (depends on RAM size) */
#define EN_MAXNRX ((2048 - (EN_NTX * EN_TXSZ)) / EN_RXSZ)
#ifndef EN_MAX_DMASEG
#define EN_MAX_DMASEG 32
#endif
/* number of bytes to use in the first receive buffer. This must not be larger
* than MHLEN, should be a multiple of 64 and must be a multiple of 4. */
#define EN_RX1BUF 128
/*
* Structure to hold DMA maps. These are handle via a typestable uma zone.
*/
struct en_map {
uintptr_t flags; /* map flags */
struct en_map *rsvd2; /* see uma_zalloc(9) */
struct en_softc *sc; /* back pointer */
bus_dmamap_t map; /* the map */
};
#define ENMAP_LOADED 0x02
#define ENMAP_ALLOC 0x01
#define EN_MAX_MAPS 400
/*
* Statistics
*/
struct en_stats {
uint32_t vtrash; /* sw copy of counter */
uint32_t otrash; /* sw copy of counter */
uint32_t ttrash; /* # of RBD's with T bit set */
uint32_t mfixaddr; /* # of times we had to mfix an address */
uint32_t mfixlen; /* # of times we had to mfix a lenght*/
uint32_t mfixfail; /* # of times mfix failed */
uint32_t txmbovr; /* # of times we dropped due to mbsize */
uint32_t dmaovr; /* tx dma overflow count */
uint32_t txoutspace; /* out of space in xmit buffer */
uint32_t txdtqout; /* out of DTQs */
uint32_t launch; /* total # of launches */
uint32_t hwpull; /* # of pulls off hardware service list */
uint32_t swadd; /* # of pushes on sw service list */
uint32_t rxqnotus; /* # of times we pull from rx q, but fail */
uint32_t rxqus; /* # of good pulls from rx q */
uint32_t rxdrqout; /* # of times out of DRQs */
uint32_t rxmbufout; /* # of time out of mbufs */
uint32_t txnomap; /* out of DMA maps in TX */
};
/*
* Each of these structures describes one of the eight transmit channels
*/
struct en_txslot {
uint32_t mbsize; /* # mbuf bytes in use (max=TXHIWAT) */
uint32_t bfree; /* # free bytes in buffer */
uint32_t start; /* start of buffer area (byte offset) */
uint32_t stop; /* ends of buffer area (byte offset) */
uint32_t cur; /* next free area (byte offset) */
uint32_t nref; /* # of VCs using this channel */
struct ifqueue q; /* mbufs waiting for DMA now */
struct ifqueue indma; /* mbufs waiting for DMA now */
};
/*
* Each of these structures is used for each of the receive buffers on the
* card.
*/
struct en_rxslot {
uint32_t mode; /* saved copy of mode info */
uint32_t start; /* begin of my buffer area */
uint32_t stop; /* end of my buffer area */
uint32_t cur; /* where I am at in the buffer */
struct en_vcc *vcc; /* backpointer to VCI */
struct ifqueue q; /* mbufs waiting for dma now */
struct ifqueue indma; /* mbufs being dma'd now */
};
struct en_vcc {
struct atmio_vcc vcc; /* required by common code */
void *rxhand;
u_int vflags;
uint32_t ipackets;
uint32_t opackets;
uint32_t ibytes;
uint32_t obytes;
uint8_t txspeed;
struct en_txslot *txslot; /* transmit slot */
struct en_rxslot *rxslot; /* receive slot */
};
#define VCC_DRAIN 0x0001 /* closed, but draining rx */
#define VCC_SWSL 0x0002 /* on rx software service list */
#define VCC_CLOSE_RX 0x0004 /* currently closing */
/*
* softc
*/
struct en_softc {
struct ifnet *ifp;
device_t dev;
/* bus glue */
bus_space_tag_t en_memt; /* for EN_READ/EN_WRITE */
bus_space_handle_t en_base; /* base of en card */
bus_size_t en_obmemsz; /* size of en card (bytes) */
void (*en_busreset)(void *); /* bus specific reset function */
bus_dma_tag_t txtag; /* TX DMA tag */
/* serv list */
uint32_t hwslistp; /* hw pointer to service list (byte offset) */
uint16_t swslist[MID_SL_N]; /* software svc list (see en_service()) */
uint16_t swsl_head; /* ends of swslist (index into swslist) */
uint16_t swsl_tail;
uint32_t swsl_size; /* # of items in swsl */
/* xmit dma */
uint32_t dtq[MID_DTQ_N];/* sw copy of dma q (see EN_DQ_MK macros) */
uint32_t dtq_free; /* # of dtq's free */
uint32_t dtq_us; /* software copy of our pointer (byte offset) */
uint32_t dtq_chip; /* chip's pointer (byte offset) */
uint32_t need_dtqs; /* true if we ran out of DTQs */
/* recv dma */
uint32_t drq[MID_DRQ_N];/* sw copy of dma q (see ENIDQ macros) */
uint32_t drq_free; /* # of drq's free */
uint32_t drq_us; /* software copy of our pointer (byte offset) */
uint32_t drq_chip; /* chip's pointer (byte offset) */
uint32_t need_drqs; /* true if we ran out of DRQs */
/* xmit buf ctrl. (per channel) */
struct en_txslot txslot[MID_NTX_CH];
/* recv buf ctrl. (per recv slot) */
struct en_rxslot rxslot[EN_MAXNRX];
int en_nrx; /* # of active rx slots */
/* vccs */
struct en_vcc **vccs;
u_int vccs_open;
struct cv cv_close; /* close CV */
/* stats */
struct en_stats stats;
/* random stuff */
uint32_t ipl; /* sbus interrupt lvl (1 on pci?) */
uint8_t bestburstcode; /* code of best burst we can use */
uint8_t bestburstlen; /* length of best burst (bytes) */
uint8_t bestburstshift; /* (x >> shift) == (x / bestburstlen) */
uint8_t bestburstmask; /* bits to check if not multiple of burst */
uint8_t alburst; /* align dma bursts? */
uint8_t noalbursts; /* don't use unaligned > 4 byte bursts */
uint8_t is_adaptec; /* adaptec version of midway? */
struct mbuf *padbuf; /* buffer of zeros for TX padding */
/* mutex to protect this structure and the associated hardware */
struct mtx en_mtx;
/* sysctl support */
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
/* memory zones */
uma_zone_t map_zone;
/* media and phy */
struct ifmedia media;
struct utopia utopia;
#ifdef EN_DEBUG
/* debugging */
u_int debug;
#endif
};
/*
* exported functions
*/
int en_attach(struct en_softc *);
void en_destroy(struct en_softc *);
void en_intr(void *);
void en_reset(struct en_softc *);
int en_modevent(module_t, int, void *arg);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,294 +0,0 @@
/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* Fore PCA200E driver for NATM
*
* This has been generated with:
*
* awk </dev/null 'BEGIN { period=255; linerate=353053; \
* printf "{ 0x00000000, %u },\n", linerate; \
* for(i=period-1; i>0; i--) printf "{ 0x%08x, %u },\n", \
* (i * 65536) + (period - i), i * linerate/period; }'
*
* $FreeBSD$
*/
{ 0x00000000, 353053 },
{ 0x00fe0001, 351668 },
{ 0x00fd0002, 350283 },
{ 0x00fc0003, 348899 },
{ 0x00fb0004, 347514 },
{ 0x00fa0005, 346130 },
{ 0x00f90006, 344745 },
{ 0x00f80007, 343361 },
{ 0x00f70008, 341976 },
{ 0x00f60009, 340592 },
{ 0x00f5000a, 339207 },
{ 0x00f4000b, 337823 },
{ 0x00f3000c, 336438 },
{ 0x00f2000d, 335054 },
{ 0x00f1000e, 333669 },
{ 0x00f0000f, 332285 },
{ 0x00ef0010, 330900 },
{ 0x00ee0011, 329516 },
{ 0x00ed0012, 328131 },
{ 0x00ec0013, 326747 },
{ 0x00eb0014, 325362 },
{ 0x00ea0015, 323978 },
{ 0x00e90016, 322593 },
{ 0x00e80017, 321209 },
{ 0x00e70018, 319824 },
{ 0x00e60019, 318439 },
{ 0x00e5001a, 317055 },
{ 0x00e4001b, 315670 },
{ 0x00e3001c, 314286 },
{ 0x00e2001d, 312901 },
{ 0x00e1001e, 311517 },
{ 0x00e0001f, 310132 },
{ 0x00df0020, 308748 },
{ 0x00de0021, 307363 },
{ 0x00dd0022, 305979 },
{ 0x00dc0023, 304594 },
{ 0x00db0024, 303210 },
{ 0x00da0025, 301825 },
{ 0x00d90026, 300441 },
{ 0x00d80027, 299056 },
{ 0x00d70028, 297672 },
{ 0x00d60029, 296287 },
{ 0x00d5002a, 294903 },
{ 0x00d4002b, 293518 },
{ 0x00d3002c, 292134 },
{ 0x00d2002d, 290749 },
{ 0x00d1002e, 289365 },
{ 0x00d0002f, 287980 },
{ 0x00cf0030, 286595 },
{ 0x00ce0031, 285211 },
{ 0x00cd0032, 283826 },
{ 0x00cc0033, 282442 },
{ 0x00cb0034, 281057 },
{ 0x00ca0035, 279673 },
{ 0x00c90036, 278288 },
{ 0x00c80037, 276904 },
{ 0x00c70038, 275519 },
{ 0x00c60039, 274135 },
{ 0x00c5003a, 272750 },
{ 0x00c4003b, 271366 },
{ 0x00c3003c, 269981 },
{ 0x00c2003d, 268597 },
{ 0x00c1003e, 267212 },
{ 0x00c0003f, 265828 },
{ 0x00bf0040, 264443 },
{ 0x00be0041, 263059 },
{ 0x00bd0042, 261674 },
{ 0x00bc0043, 260290 },
{ 0x00bb0044, 258905 },
{ 0x00ba0045, 257521 },
{ 0x00b90046, 256136 },
{ 0x00b80047, 254751 },
{ 0x00b70048, 253367 },
{ 0x00b60049, 251982 },
{ 0x00b5004a, 250598 },
{ 0x00b4004b, 249213 },
{ 0x00b3004c, 247829 },
{ 0x00b2004d, 246444 },
{ 0x00b1004e, 245060 },
{ 0x00b0004f, 243675 },
{ 0x00af0050, 242291 },
{ 0x00ae0051, 240906 },
{ 0x00ad0052, 239522 },
{ 0x00ac0053, 238137 },
{ 0x00ab0054, 236753 },
{ 0x00aa0055, 235368 },
{ 0x00a90056, 233984 },
{ 0x00a80057, 232599 },
{ 0x00a70058, 231215 },
{ 0x00a60059, 229830 },
{ 0x00a5005a, 228446 },
{ 0x00a4005b, 227061 },
{ 0x00a3005c, 225677 },
{ 0x00a2005d, 224292 },
{ 0x00a1005e, 222907 },
{ 0x00a0005f, 221523 },
{ 0x009f0060, 220138 },
{ 0x009e0061, 218754 },
{ 0x009d0062, 217369 },
{ 0x009c0063, 215985 },
{ 0x009b0064, 214600 },
{ 0x009a0065, 213216 },
{ 0x00990066, 211831 },
{ 0x00980067, 210447 },
{ 0x00970068, 209062 },
{ 0x00960069, 207678 },
{ 0x0095006a, 206293 },
{ 0x0094006b, 204909 },
{ 0x0093006c, 203524 },
{ 0x0092006d, 202140 },
{ 0x0091006e, 200755 },
{ 0x0090006f, 199371 },
{ 0x008f0070, 197986 },
{ 0x008e0071, 196602 },
{ 0x008d0072, 195217 },
{ 0x008c0073, 193833 },
{ 0x008b0074, 192448 },
{ 0x008a0075, 191063 },
{ 0x00890076, 189679 },
{ 0x00880077, 188294 },
{ 0x00870078, 186910 },
{ 0x00860079, 185525 },
{ 0x0085007a, 184141 },
{ 0x0084007b, 182756 },
{ 0x0083007c, 181372 },
{ 0x0082007d, 179987 },
{ 0x0081007e, 178603 },
{ 0x0080007f, 177218 },
{ 0x007f0080, 175834 },
{ 0x007e0081, 174449 },
{ 0x007d0082, 173065 },
{ 0x007c0083, 171680 },
{ 0x007b0084, 170296 },
{ 0x007a0085, 168911 },
{ 0x00790086, 167527 },
{ 0x00780087, 166142 },
{ 0x00770088, 164758 },
{ 0x00760089, 163373 },
{ 0x0075008a, 161989 },
{ 0x0074008b, 160604 },
{ 0x0073008c, 159219 },
{ 0x0072008d, 157835 },
{ 0x0071008e, 156450 },
{ 0x0070008f, 155066 },
{ 0x006f0090, 153681 },
{ 0x006e0091, 152297 },
{ 0x006d0092, 150912 },
{ 0x006c0093, 149528 },
{ 0x006b0094, 148143 },
{ 0x006a0095, 146759 },
{ 0x00690096, 145374 },
{ 0x00680097, 143990 },
{ 0x00670098, 142605 },
{ 0x00660099, 141221 },
{ 0x0065009a, 139836 },
{ 0x0064009b, 138452 },
{ 0x0063009c, 137067 },
{ 0x0062009d, 135683 },
{ 0x0061009e, 134298 },
{ 0x0060009f, 132914 },
{ 0x005f00a0, 131529 },
{ 0x005e00a1, 130145 },
{ 0x005d00a2, 128760 },
{ 0x005c00a3, 127375 },
{ 0x005b00a4, 125991 },
{ 0x005a00a5, 124606 },
{ 0x005900a6, 123222 },
{ 0x005800a7, 121837 },
{ 0x005700a8, 120453 },
{ 0x005600a9, 119068 },
{ 0x005500aa, 117684 },
{ 0x005400ab, 116299 },
{ 0x005300ac, 114915 },
{ 0x005200ad, 113530 },
{ 0x005100ae, 112146 },
{ 0x005000af, 110761 },
{ 0x004f00b0, 109377 },
{ 0x004e00b1, 107992 },
{ 0x004d00b2, 106608 },
{ 0x004c00b3, 105223 },
{ 0x004b00b4, 103839 },
{ 0x004a00b5, 102454 },
{ 0x004900b6, 101070 },
{ 0x004800b7, 99685 },
{ 0x004700b8, 98301 },
{ 0x004600b9, 96916 },
{ 0x004500ba, 95531 },
{ 0x004400bb, 94147 },
{ 0x004300bc, 92762 },
{ 0x004200bd, 91378 },
{ 0x004100be, 89993 },
{ 0x004000bf, 88609 },
{ 0x003f00c0, 87224 },
{ 0x003e00c1, 85840 },
{ 0x003d00c2, 84455 },
{ 0x003c00c3, 83071 },
{ 0x003b00c4, 81686 },
{ 0x003a00c5, 80302 },
{ 0x003900c6, 78917 },
{ 0x003800c7, 77533 },
{ 0x003700c8, 76148 },
{ 0x003600c9, 74764 },
{ 0x003500ca, 73379 },
{ 0x003400cb, 71995 },
{ 0x003300cc, 70610 },
{ 0x003200cd, 69226 },
{ 0x003100ce, 67841 },
{ 0x003000cf, 66457 },
{ 0x002f00d0, 65072 },
{ 0x002e00d1, 63687 },
{ 0x002d00d2, 62303 },
{ 0x002c00d3, 60918 },
{ 0x002b00d4, 59534 },
{ 0x002a00d5, 58149 },
{ 0x002900d6, 56765 },
{ 0x002800d7, 55380 },
{ 0x002700d8, 53996 },
{ 0x002600d9, 52611 },
{ 0x002500da, 51227 },
{ 0x002400db, 49842 },
{ 0x002300dc, 48458 },
{ 0x002200dd, 47073 },
{ 0x002100de, 45689 },
{ 0x002000df, 44304 },
{ 0x001f00e0, 42920 },
{ 0x001e00e1, 41535 },
{ 0x001d00e2, 40151 },
{ 0x001c00e3, 38766 },
{ 0x001b00e4, 37382 },
{ 0x001a00e5, 35997 },
{ 0x001900e6, 34613 },
{ 0x001800e7, 33228 },
{ 0x001700e8, 31843 },
{ 0x001600e9, 30459 },
{ 0x001500ea, 29074 },
{ 0x001400eb, 27690 },
{ 0x001300ec, 26305 },
{ 0x001200ed, 24921 },
{ 0x001100ee, 23536 },
{ 0x001000ef, 22152 },
{ 0x000f00f0, 20767 },
{ 0x000e00f1, 19383 },
{ 0x000d00f2, 17998 },
{ 0x000c00f3, 16614 },
{ 0x000b00f4, 15229 },
{ 0x000a00f5, 13845 },
{ 0x000900f6, 12460 },
{ 0x000800f7, 11076 },
{ 0x000700f8, 9691 },
{ 0x000600f9, 8307 },
{ 0x000500fa, 6922 },
{ 0x000400fb, 5538 },
{ 0x000300fc, 4153 },
{ 0x000200fd, 2769 },
{ 0x000100fe, 1384 },

View File

@ -1,499 +0,0 @@
/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*
* Fore PCA200E hardware definitions.
*/
/*
* Fore implements some additional PCI registers. One of them is the
* master control register. One of the bits allow to automatically byte
* swap accesses to the on-board RAM.
*/
#define FATM_PCIR_MCTL 0x41
#define FATM_PCIM_SWAB 0x100
/*
* Operations codes for commands.
*/
enum {
FATM_OP_INITIALIZE = 0x01, /* Initialize the card */
FATM_OP_ACTIVATE_VCIN = 0x02, /* Start reassembly on a channel */
FATM_OP_ACTIVATE_VCOUT = 0x03, /* (not used) */
FATM_OP_DEACTIVATE_VCIN = 0x04, /* Stop reassembly on a channel */
FATM_OP_DEACTIVATE_VCOUT= 0x05, /* (not used) */
FATM_OP_REQUEST_STATS = 0x06, /* Get statistics */
FATM_OP_OC3_SET_REG = 0x07, /* Set OC3 chip register */
FATM_OP_OC3_GET_REG = 0x08, /* Get OC3 chip registers */
FATM_OP_ZERO_STATS = 0x09, /* Zero out statistics */
FATM_OP_GET_PROM_DATA = 0x0a, /* Return expansion ROM data */
FATM_OP_SETVPI_BITS = 0x0b, /* (not used, not implemented) */
FATM_OP_INTERRUPT_SEL = 0x80, /* Request interrupt on completion */
};
/*
* Status word definitions. Before initiating an operation the host sets the
* status word to PENDING. The card sets it to COMPLETE upon completion of
* the transmit/receive or command. An unused queue entry contains FREE.
* The ERROR can be ored into the COMPLETE. Note, that there are circumstances
* when ERROR is set without COMPLETE being set (when you try to activate
* a bad VCI like, for example, VCI 0).
*/
enum {
FATM_STAT_PENDING = 0x01,
FATM_STAT_COMPLETE = 0x02,
FATM_STAT_FREE = 0x04,
FATM_STAT_ERROR = 0x08,
};
/*
* On board queue offsets. There are two fundamentally different queue types:
* the command queue and all other queues. The command queue has 32 byte
* entries on the card which contain the operation code, parameters and the
* DMA pointer to the status word. All other queues have 8 byte entries, which
* contain a DMA pointer to the i/o block, that contains the parameters, and
* a DMA pointer to the status word.
*/
#define FATMOC_OP 0 /* cmd queue: offset to op code */
#define FATMOC_PARAM 4 /* cmd queue: offset to parameters */
#define FATMOC_STATP 16 /* cmd queue: offset to status ptr */
#define FATMOC_END 32 /* cmd queue: element size */
#define FATMOC_ACTIN_VPVC (FATMOC_PARAM + 0)
#define FATMOC_ACTIN_MTU (FATMOC_PARAM + 4)
#define FATMOC_DEACTIN_VPVC (FATMOC_PARAM + 0)
#define FATMOC_GETOC3_BUF (FATMOC_PARAM + 0)
#define FATMOC_GSTAT_BUF (FATMOC_PARAM + 0)
#define FATMOC_GPROM_BUF (FATMOC_PARAM + 0)
#define FATMOS_IOBLK 0 /* other queues: offset to ioblk ptr */
#define FATMOS_STATP 4 /* other queues: offset to status ptr */
#define FATM_MAKE_SETOC3(REG,VAL,MASK) \
(FATM_OP_OC3_SET_REG | (((REG) & 0xff) << 8) | \
(((VAL) & 0xff) << 16) | (((MASK) & 0xff) << 24))
#define FATM_NREGS 128
/*
* On board memory layout.
*
* The card contains up to 2MByte memory that is mapped at virtual offset 0.
* It is followed by three registers. The memory contains two areas at
* fixed addresses: the mon960 area that is used for communication with
* the card's operating system and the common block that is used by the
* firmware to communicate with the driver.
*/
#define FATM_RAM_SIZE (256 * 1024) /* normal RAM size */
#define FATMO_RAM (0x0) /* virtual RAM start */
#define FATMO_MON960 (0x400) /* mon960 communication area */
#define FATMO_COMMON_ORIGIN (0x4d40) /* firmware comm. area */
#define FATMO_HCR (0x100000) /* host control registers */
#define FATMO_HIMR (0x100004) /* host interrupt mask */
#define FATMO_PSR (0x100008) /* PCI control register */
#define FATMO_END (0x200000) /* end of mapped area */
/*
* The mon960 area contains two cells that are used as a virtual serial
* interface, a status word, the base for loading the application (i.e.
* firmware) and a version number.
*/
#define FATMO_UART_TO_960 (FATMO_MON960 + 0)
#define FATMO_UART_TO_HOST (FATMO_MON960 + 4)
#define FATMO_BOOT_STATUS (FATMO_MON960 + 8)
#define FATMO_APP_BASE (FATMO_MON960 + 12)
#define FATMO_VERSION (FATMO_MON960 + 16)
/*
* The host control register allows to hold the i960 or send it interrupts.
* The bits have different meaning on read and write.
*/
#define FATM_HCR_RESET 0x01 /* (W) reset the card */
#define FATM_HCR_LOCK_HOLD 0x02 /* (W) hold the i960 */
#define FATM_HCR_I960FAIL 0x04 /* (R) internal self-test failed */
#define FATM_HCR_INTR2 0x04 /* (W) assert i960 interrupt 2 */
#define FATM_HCR_HOLDA 0x08 /* (R) hold ack from i960 */
#define FATM_HCR_INTR1 0x08 /* (W) assert i960 interrupt 1 */
#define FATM_HCR_OFIFO 0x10 /* (R) DMA request FIFO full */
#define FATM_HCR_CLRIRQ 0x10 /* (W) clear interrupt request */
#define FATM_HCR_ESP_HOLD 0x20 /* (R) SAR chip holds i960 */
#define FATM_HCR_IFIFO 0x40 /* (R) input FIFO full */
#define FATM_HCR_TESTMODE 0x80 /* (R) board is in test mode */
/*
* The mon960 area contains a virtual UART and a status word.
* The UART uses a simple protocol: a zero means, that there is no
* character available from the i960 or that one can write the next
* character to the i960. This character has to be ored with 0x1000000
* to signal to the i960 that there is a new character.
* The cold_start values must be written to the status word, the others
* denote certain stages of initializing.
*/
#define XMIT_READY 0
#define CHAR_AVAIL 0x1000000
#define COLD_START 0xc01dc01d
#define SELF_TEST_OK 0x02201958
#define SELF_TEST_FAIL 0xadbadbad
#define CP_RUNNING 0xce11feed
#define MON906_TOO_BIG 0x10aded00
/*
* The firmware communication area contains a big structure most of which
* is used only during initialisation.
*/
/*
* These are the offsets to the onboard queues that are valid after the
* initialisation command has completed.
*/
#define FATMO_COMMAND_QUEUE (FATMO_COMMON_ORIGIN + 0)
#define FATMO_TRANSMIT_QUEUE (FATMO_COMMON_ORIGIN + 4)
#define FATMO_RECEIVE_QUEUE (FATMO_COMMON_ORIGIN + 8)
#define FATMO_SMALL_B1_QUEUE (FATMO_COMMON_ORIGIN + 12)
#define FATMO_LARGE_B1_QUEUE (FATMO_COMMON_ORIGIN + 16)
#define FATMO_SMALL_B2_QUEUE (FATMO_COMMON_ORIGIN + 20)
#define FATMO_LARGE_B2_QUEUE (FATMO_COMMON_ORIGIN + 24)
/*
* If the interrupt mask is set to 1, interrupts to the host are queued, but
* inhbited. The istat variable is set, when this card has posted an interrupt.
*/
#define FATMO_IMASK (FATMO_COMMON_ORIGIN + 28)
#define FATMO_ISTAT (FATMO_COMMON_ORIGIN + 32)
/*
* This is the offset and the size of the queue area. Could be used to
* dynamically compute queue sizes.
*/
#define FATMO_HEAP_BASE (FATMO_COMMON_ORIGIN + 36)
#define FATMO_HEAP_SIZE (FATMO_COMMON_ORIGIN + 40)
#define FATMO_HLOGGER (FATMO_COMMON_ORIGIN + 44)
/*
* The heartbeat variable is incremented in each loop of the normal processing.
* If it is stuck this means, that the card had a fatal error. In this case
* it may set the word to a number of values of the form 0xdeadXXXX where
* XXXX is an error code.
*/
#define FATMO_HEARTBEAT (FATMO_COMMON_ORIGIN + 48)
#define FATMO_FIRMWARE_RELEASE (FATMO_COMMON_ORIGIN + 52)
#define FATMO_MON960_RELEASE (FATMO_COMMON_ORIGIN + 56)
#define FATMO_TQ_PLEN (FATMO_COMMON_ORIGIN + 60)
/*
* At this offset the init command block is located. The init command cannot
* use the normal queue mechanism because it is used to initialize the
* queues. For this reason it is located at this fixed offset.
*/
#define FATMO_INIT (FATMO_COMMON_ORIGIN + 64)
/*
* physical media type
*/
#define FATMO_MEDIA_TYPE (FATMO_COMMON_ORIGIN + 176)
#define FATMO_OC3_REVISION (FATMO_COMMON_ORIGIN + 180)
/*
* End of the common block
*/
#define FATMO_COMMON_END (FATMO_COMMON_ORIGIN + 184)
/*
* The INITIALIZE command block. This is embedded into the above common
* block. The offsets are from the beginning of the command block.
*/
#define FATMOI_OP 0 /* operation code */
#define FATMOI_STATUS 4 /* status word */
#define FATMOI_RECEIVE_TRESHOLD 8 /* when to start interrupting */
#define FATMOI_NUM_CONNECT 12 /* max number of VCIs */
#define FATMOI_CQUEUE_LEN 16 /* length of command queue */
#define FATMOI_TQUEUE_LEN 20 /* length of transmit queue */
#define FATMOI_RQUEUE_LEN 24 /* length of receive queue */
#define FATMOI_RPD_EXTENSION 28 /* additional 32 byte blocks */
#define FATMOI_TPD_EXTENSION 32 /* additional 32 byte blocks */
#define FATMOI_CONLESS_VPVC 36 /* (not used) */
#define FATMOI_SMALL_B1 48 /* small buffer 1 pool */
#define FATMOI_LARGE_B1 64 /* small buffer 2 pool */
#define FATMOI_SMALL_B2 80 /* large buffer 1 pool */
#define FATMOI_LARGE_B2 96 /* large buffer 2 pool */
#define FATMOI_END 112 /* size of init block */
/*
* Each of the four buffer schemes is initialized with a block that
* contains four words:
*/
#define FATMOB_QUEUE_LENGTH 0 /* supply queue length */
#define FATMOB_BUFFER_SIZE 4 /* size of each buffer */
#define FATMOB_POOL_SIZE 8 /* size of on-board pool */
#define FATMOB_SUPPLY_BLKSIZE 12 /* number of buffers/supply */
/*
* The fore firmware is a binary file, that starts with a header. The
* header contains the offset to where the file must be loaded and the
* entry for execution. The header must also be loaded onto the card!
*/
struct firmware {
uint32_t id; /* "FORE" */
uint32_t version; /* firmware version */
uint32_t offset; /* load offset */
uint32_t entry; /* entry point */
};
#define FATM_FWID 0x65726f66 /* "FORE" */
#define FATM_FWVERSION 0x100 /* supported version */
/*
* PDUs to be transmitted are described by Transmit PDU Descriptors.
* These descriptors are held in host memory, but referenced from the ioblk
* member of the queue structure on the card. The card DMAs the descriptor
* and than gather-DMAs the PDU transmitting it on-the-fly. Tpds are variable
* length in blocks of 32 byte (8 words). The minimum length is one block,
* maximum 15. The number of blocks beyond 1 is configured during the
* initialisation command (tpd_extension).
* Each gather-DMA segment is described by a segment descriptor. The buffer
* address and the length must be a multiple of four.
* Tpd must also be 4 byte aligned.
* Because of the minimum length of 32 byte, the first blocks contains already
* 2 segement descriptors. Each extension block holds four descriptors.
*/
#define TXD_FIXED 2
#define SEGS_PER_BLOCK 4 /* segment descriptors per extension block */
struct txseg {
uint32_t buffer; /* DMA buffer address */
uint32_t length; /* and length */
};
struct tpd {
uint32_t atm_header; /* header for the transmitted cells */
uint32_t spec; /* PDU description */
uint32_t stream; /* traffic shaping word */
uint32_t pad[1];
struct txseg segment[TXD_FIXED];
};
#define TDX_MKSPEC(INTR,AAL,NSEG,LEN) \
(((INTR) << 28) | ((AAL) << 24) | ((NSEG) << 16) | (LEN))
#define TDX_MKSTR(DATA,IDLE) \
(((DATA) << 16) | (IDLE))
#define TDX_MKHDR(VPI,VCI,PT,CLP) \
(((VPI) << 20) | ((VCI) << 4) | ((PT) << 1) | (CLP))
#define TDX_SEGS2BLKS(SEGS) \
(1 + ((SEGS)-TXD_FIXED+SEGS_PER_BLOCK-1)/SEGS_PER_BLOCK)
/*
* We want probably support scatter transmission, so we use the maximum
* transmit descriptor extension that is possible. Because the size of the
* Tpd is encoded in 32-byte blocks in a 4-bit field, the maximum extension
* is 14 such blocks. The value for the init command is the number of
* additional descriptor entries NOT the number of 32 byte blocks.
*/
#define TPD_EXTENSION_BLOCKS 14
#define TPD_EXTENSIONS (TPD_EXTENSION_BLOCKS * 4)
#define TPD_SIZE ((size_t)((TPD_EXTENSION_BLOCKS+1) * 32))
/*
* Received PDUs are handed from the card to the host by means of Receive
* PDU descriptors. Each segment describes on part of the PDU. The buffer
* handle is a 32 bit value that is supplied by the host and passed
* transparently back to the host by the card. It is used to locate the buffer.
* The length field is the number of actual bytes in that buffer.
*/
#define RXD_FIXED 3
struct rxseg {
uint32_t handle; /* buffer handle */
uint32_t length; /* number of bytes */
};
struct rpd {
uint32_t atm_header;
uint32_t nseg;
struct rxseg segment[RXD_FIXED];
};
/*
* PDUs received are stored in buffers supplied to the card. We use only
* buffer scheme 1: small buffers are normal mbuf's which can hold three
* cells in their default size (256 byte) and mbuf clusters which can
* hold 42 cells (2 kbyte).
* The number of receive segments can be computed from these sizes:
*/
#define FATM_MAXPDU 65535
#define MAXPDU_CELLS ((FATM_MAXPDU+47)/48)
#define SMALL_BUFFER_CELLS (MHLEN/48)
#define LARGE_BUFFER_CELLS (MCLBYTES/48)
#define SMALL_BUFFER_LEN (SMALL_BUFFER_CELLS * 48)
#define LARGE_BUFFER_LEN (LARGE_BUFFER_CELLS * 48)
/*
* The card first alloctes a small buffer and the switches to large
* buffers. So the number of large buffers needed to store the maximum
* PDU is:
*/
#define MAX_LARGE_BUFFERS ((MAXPDU_CELLS - SMALL_BUFFER_CELLS \
+ LARGE_BUFFER_CELLS - 1) \
/ LARGE_BUFFER_CELLS) \
/*
* From this we get the number of extension blocks for the Rpds as:
*/
#define RPD_EXTENSION_BLOCKS ((MAX_LARGE_BUFFERS + 1 - RXD_FIXED \
+ SEGS_PER_BLOCK - 1) \
/ SEGS_PER_BLOCK)
#define RPD_EXTENSIONS (RPD_EXTENSION_BLOCKS * 4)
#define RPD_SIZE ((size_t)((RPD_EXTENSION_BLOCKS+1) * 32))
/*
* Buffers are supplied to the card prior receiving by the supply queues.
* We use two queues: scheme 1 small buffers and scheme 1 large buffers.
* The queues and on-card pools are initialized by the initialize command.
* Buffers are supplied in chunks. Each chunk can contain from 4 to 124
* buffers in multiples of four. The chunk sizes are configured by the
* initialize command. Each buffer in a chunk is described by a Receive
* Buffer Descriptor that is held in host memory and given as the ioblk
* to the card.
*/
#define BSUP_BLK2SIZE(CHUNK) (8 * (CHUNK))
struct rbd {
uint32_t handle;
uint32_t buffer; /* DMA address for card */
};
/*
* The PCA200E has an expansion ROM that contains version information and
* the FORE-assigned MAC address. It can be read via the get_prom_data
* operation.
*/
struct prom {
uint32_t version;
uint32_t serial;
uint8_t mac[8];
};
/*
* The media type member of the firmware communication block contains a
* code that describes the physical medium and physical protocol.
*/
#define FORE_MT_TAXI_100 0x04
#define FORE_MT_TAXI_140 0x05
#define FORE_MT_UTP_SONET 0x06
#define FORE_MT_MM_OC3_ST 0x16
#define FORE_MT_MM_OC3_SC 0x26
#define FORE_MT_SM_OC3_ST 0x36
#define FORE_MT_SM_OC3_SC 0x46
/*
* Assorted constants
*/
#define FORE_MAX_VCC 1024 /* max. number of VCIs supported */
#define FORE_VCIBITS 10
#define FATM_STATE_TIMEOUT 500 /* msec */
/*
* Statistics as delivered by the FORE cards
*/
struct fatm_stats {
struct {
uint32_t crc_header_errors;
uint32_t framing_errors;
uint32_t pad[2];
} phy_4b5b;
struct {
uint32_t section_bip8_errors;
uint32_t path_bip8_errors;
uint32_t line_bip24_errors;
uint32_t line_febe_errors;
uint32_t path_febe_errors;
uint32_t corr_hcs_errors;
uint32_t ucorr_hcs_errors;
uint32_t pad[1];
} phy_oc3;
struct {
uint32_t cells_transmitted;
uint32_t cells_received;
uint32_t vpi_bad_range;
uint32_t vpi_no_conn;
uint32_t vci_bad_range;
uint32_t vci_no_conn;
uint32_t pad[2];
} atm;
struct {
uint32_t cells_transmitted;
uint32_t cells_received;
uint32_t cells_dropped;
uint32_t pad[1];
} aal0;
struct {
uint32_t cells_transmitted;
uint32_t cells_received;
uint32_t cells_crc_errors;
uint32_t cels_protocol_errors;
uint32_t cells_dropped;
uint32_t cspdus_transmitted;
uint32_t cspdus_received;
uint32_t cspdus_protocol_errors;
uint32_t cspdus_dropped;
uint32_t pad[3];
} aal4;
struct {
uint32_t cells_transmitted;
uint32_t cells_received;
uint32_t congestion_experienced;
uint32_t cells_dropped;
uint32_t cspdus_transmitted;
uint32_t cspdus_received;
uint32_t cspdus_crc_errors;
uint32_t cspdus_protocol_errors;
uint32_t cspdus_dropped;
uint32_t pad[3];
} aal5;
struct {
uint32_t small_b1_failed;
uint32_t large_b1_failed;
uint32_t small_b2_failed;
uint32_t large_b2_failed;
uint32_t rpd_alloc_failed;
uint32_t receive_carrier;
uint32_t pad[2];
} aux;
};
#define FATM_NSTATS 42

View File

@ -1,395 +0,0 @@
/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*
* Fore PCA200E driver definitions.
*/
/*
* Debug statistics of the PCA200 driver
*/
struct istats {
uint32_t cmd_queue_full;
uint32_t get_stat_errors;
uint32_t clr_stat_errors;
uint32_t get_prom_errors;
uint32_t suni_reg_errors;
uint32_t tx_queue_full;
uint32_t tx_queue_almost_full;
uint32_t tx_pdu2big;
uint32_t tx_too_many_segs;
uint32_t tx_retry;
uint32_t fix_empty;
uint32_t fix_addr_copy;
uint32_t fix_addr_noext;
uint32_t fix_addr_ext;
uint32_t fix_len_noext;
uint32_t fix_len_copy;
uint32_t fix_len;
uint32_t rx_badvc;
uint32_t rx_closed;
};
/*
* Addresses on the on-board RAM are expressed as offsets to the
* start of that RAM.
*/
typedef uint32_t cardoff_t;
/*
* The card uses a number of queues for communication with the host.
* Parts of the queue are located on the card (pointers to the status
* word and the ioblk and the command blocks), the rest in host memory.
* Each of these queues forms a ring, where the head and tail pointers are
* managed * either by the card or the host. For the receive queue the
* head is managed by the card (and not used altogether by the host) and the
* tail by the host - for all other queues its the other way around.
* The host resident parts of the queue entries contain pointers to
* the host resident status and the host resident ioblk (the latter not for
* the command queue) as well as DMA addresses for supply to the card.
*/
struct fqelem {
cardoff_t card; /* corresponding element on card */
bus_addr_t card_ioblk; /* ioblk address to supply to card */
volatile uint32_t *statp; /* host status pointer */
void *ioblk; /* host ioblk (not for commands) */
};
struct fqueue {
struct fqelem *chunk; /* pointer to the element array */
int head; /* queue head */
int tail; /* queue tail */
};
/*
* Queue manipulation macros
*/
#define NEXT_QUEUE_ENTRY(HEAD,LEN) ((HEAD) = ((HEAD) + 1) % LEN)
#define GET_QUEUE(Q,TYPE,IDX) (&((TYPE *)(Q).chunk)[(IDX)])
/*
* Now define structures for the different queues. Each of these structures
* must start with a struct fqelem.
*/
struct txqueue { /* transmit queue element */
struct fqelem q;
struct mbuf *m; /* the chain we are transmitting */
bus_dmamap_t map; /* map for the packet */
};
struct rxqueue { /* receive queue element */
struct fqelem q;
};
struct supqueue { /* supply queue element */
struct fqelem q;
};
struct cmdqueue;
struct fatm_softc;
typedef void (*completion_cb)(struct fatm_softc *, struct cmdqueue *);
struct cmdqueue { /* command queue element */
struct fqelem q;
completion_cb cb; /* call on command completion */
int error; /* set if error occurred */
};
/*
* Card-DMA-able memory is managed by means of the bus_dma* functions.
* To allocate a chunk of memory with a specific size and alignment one
* has to:
* 1. create a DMA tag
* 2. allocate the memory
* 3. load the memory into a map.
* This finally gives the physical address that can be given to the card.
* The card can DMA the entire 32-bit space without boundaries. We assume,
* that all the allocations can be mapped in one contiguous segment. This
* may be wrong in the future if we have more than 32 bit addresses.
* Allocation is done at attach time and managed by the following structure.
*
* This could be done easier with the NetBSD bus_dma* functions. They appear
* to be more useful and consistent.
*/
struct fatm_mem {
u_int size; /* size */
u_int align; /* alignment */
bus_dma_tag_t dmat; /* DMA tag */
void *mem; /* memory block */
bus_addr_t paddr; /* pysical address */
bus_dmamap_t map; /* map */
};
/*
* Each of these structures describes one receive buffer while the buffer
* is on the card or in the receive return queue. These structures are
* allocated at initialisation time together with the DMA maps. The handle that
* is given to the card is the index into the array of these structures.
*/
struct rbuf {
struct mbuf *m; /* the mbuf while we are on the card */
bus_dmamap_t map; /* the map */
LIST_ENTRY(rbuf) link; /* the free list link */
};
LIST_HEAD(rbuf_list, rbuf);
/*
* The driver maintains a list of all open VCCs. Because we
* use only VPI=0 and a maximum VCI of 1024, the list is rather an array
* than a list. We also store the atm pseudoheader flags here and the
* rxhand (aka. protocol block).
*/
struct card_vcc {
struct atmio_vcc param; /* traffic parameters */
void *rxhand;
u_int vflags;
uint32_t ipackets;
uint32_t opackets;
uint32_t ibytes;
uint32_t obytes;
};
#define FATM_VCC_OPEN 0x00010000 /* is open */
#define FATM_VCC_TRY_OPEN 0x00020000 /* is currently opening */
#define FATM_VCC_TRY_CLOSE 0x00040000 /* is currently closing */
#define FATM_VCC_BUSY 0x00070000 /* one of the above */
#define FATM_VCC_REOPEN 0x00080000 /* reopening during init */
/*
* Finally the softc structure
*/
struct fatm_softc {
struct ifnet *ifp; /* common part */
struct mtx mtx; /* lock this structure */
struct ifmedia media; /* media */
struct callout watchdog_timer;
int init_state; /* initialisation step */
int memid; /* resource id for card memory */
struct resource *memres; /* resource for card memory */
bus_space_handle_t memh; /* handle for card memory */
bus_space_tag_t memt; /* tag for card memory */
int irqid; /* resource id for interrupt */
struct resource *irqres; /* resource for interrupt */
void *ih; /* interrupt handler */
bus_dma_tag_t parent_dmat; /* parent DMA tag */
struct fatm_mem stat_mem; /* memory for status blocks */
struct fatm_mem txq_mem; /* TX descriptor queue */
struct fatm_mem rxq_mem; /* RX descriptor queue */
struct fatm_mem s1q_mem; /* Small buffer 1 queue */
struct fatm_mem l1q_mem; /* Large buffer 1 queue */
struct fatm_mem prom_mem; /* PROM memory */
struct fqueue txqueue; /* transmission queue */
struct fqueue rxqueue; /* receive queue */
struct fqueue s1queue; /* SMALL S1 queue */
struct fqueue l1queue; /* LARGE S1 queue */
struct fqueue cmdqueue; /* command queue */
/* fields for access to the SUNI registers */
struct fatm_mem reg_mem; /* DMAable memory for readregs */
struct cv cv_regs; /* to serialize access to reg_mem */
/* fields for access to statistics */
struct fatm_mem sadi_mem; /* sadistics memory */
struct cv cv_stat; /* to serialize access to sadi_mem */
u_int flags;
#define FATM_STAT_INUSE 0x0001
#define FATM_REGS_INUSE 0x0002
u_int txcnt; /* number of used transmit desc */
int retry_tx; /* keep mbufs in queue if full */
struct card_vcc **vccs; /* table of vccs */
int open_vccs; /* number of vccs in use */
int small_cnt; /* number of buffers owned by card */
int large_cnt; /* number of buffers owned by card */
uma_zone_t vcc_zone; /* allocator for VCCs */
/* receiving */
struct rbuf *rbufs; /* rbuf array */
struct rbuf_list rbuf_free; /* free rbufs list */
struct rbuf_list rbuf_used; /* used rbufs list */
u_int rbuf_total; /* total number of buffs */
bus_dma_tag_t rbuf_tag; /* tag for rbuf mapping */
/* transmission */
bus_dma_tag_t tx_tag; /* transmission tag */
uint32_t heartbeat; /* last heartbeat */
u_int stop_cnt; /* how many times checked */
struct istats istats; /* internal statistics */
/* SUNI state */
struct utopia utopia;
/* sysctl support */
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
#ifdef FATM_DEBUG
/* debugging */
u_int debug;
#endif
};
#ifndef FATM_DEBUG
#define FATM_LOCK(SC) mtx_lock(&(SC)->mtx)
#define FATM_UNLOCK(SC) mtx_unlock(&(SC)->mtx)
#else
#define FATM_LOCK(SC) do { \
DBG(SC, LOCK, ("locking in line %d", __LINE__)); \
mtx_lock(&(SC)->mtx); \
} while (0)
#define FATM_UNLOCK(SC) do { \
DBG(SC, LOCK, ("unlocking in line %d", __LINE__)); \
mtx_unlock(&(SC)->mtx); \
} while (0)
#endif
#define FATM_CHECKLOCK(SC) mtx_assert(&sc->mtx, MA_OWNED)
/*
* Macros to access host memory fields that are also access by the card.
* These fields need to little-endian always.
*/
#define H_GETSTAT(STATP) (le32toh(*(STATP)))
#define H_SETSTAT(STATP, S) do { *(STATP) = htole32(S); } while (0)
#define H_SETDESC(DESC, D) do { (DESC) = htole32(D); } while (0)
#ifdef notyet
#define H_SYNCSTAT_POSTREAD(SC, P) \
bus_dmamap_sync_size((SC)->stat_mem.dmat, \
(SC)->stat_mem.map, \
(volatile char *)(P) - (volatile char *)(SC)->stat_mem.mem, \
sizeof(volatile uint32_t), BUS_DMASYNC_POSTREAD)
#define H_SYNCSTAT_PREWRITE(SC, P) \
bus_dmamap_sync_size((SC)->stat_mem.dmat, \
(SC)->stat_mem.map, \
(volatile char *)(P) - (volatile char *)(SC)->stat_mem.mem, \
sizeof(volatile uint32_t), BUS_DMASYNC_PREWRITE)
#define H_SYNCQ_PREWRITE(M, P, SZ) \
bus_dmamap_sync_size((M)->dmat, (M)->map, \
(volatile char *)(P) - (volatile char *)(M)->mem, (SZ), \
BUS_DMASYNC_PREWRITE)
#define H_SYNCQ_POSTREAD(M, P, SZ) \
bus_dmamap_sync_size((M)->dmat, (M)->map, \
(volatile char *)(P) - (volatile char *)(M)->mem, (SZ), \
BUS_DMASYNC_POSTREAD)
#else
#define H_SYNCSTAT_POSTREAD(SC, P) do { } while (0)
#define H_SYNCSTAT_PREWRITE(SC, P) do { } while (0)
#define H_SYNCQ_PREWRITE(M, P, SZ) do { } while (0)
#define H_SYNCQ_POSTREAD(M, P, SZ) do { } while (0)
#endif
/*
* Macros to manipulate VPVCs
*/
#define MKVPVC(VPI,VCI) (((VPI) << 16) | (VCI))
#define GETVPI(VPVC) (((VPVC) >> 16) & 0xff)
#define GETVCI(VPVC) ((VPVC) & 0xffff)
/*
* These macros encapsulate the bus_space functions for better readabiliy.
*/
#define WRITE4(SC, OFF, VAL) bus_space_write_4(SC->memt, SC->memh, OFF, VAL)
#define WRITE1(SC, OFF, VAL) bus_space_write_1(SC->memt, SC->memh, OFF, VAL)
#define READ4(SC, OFF) bus_space_read_4(SC->memt, SC->memh, OFF)
#define READ1(SC, OFF) bus_space_read_1(SC->memt, SC->memh, OFF)
#define BARRIER_R(SC) \
bus_space_barrier(SC->memt, SC->memh, 0, FATMO_END, \
BUS_SPACE_BARRIER_READ)
#define BARRIER_W(SC) \
bus_space_barrier(SC->memt, SC->memh, 0, FATMO_END, \
BUS_SPACE_BARRIER_WRITE)
#define BARRIER_RW(SC) \
bus_space_barrier(SC->memt, SC->memh, 0, FATMO_END, \
BUS_SPACE_BARRIER_WRITE|BUS_SPACE_BARRIER_READ)
#ifdef FATM_DEBUG
#define DBG(SC, FL, PRINT) do { \
if ((SC)->debug & DBG_##FL) { \
if_printf(&(SC)->ifatm.ifnet, "%s: ", __func__); \
printf PRINT; \
printf("\n"); \
} \
} while (0)
#define DBGC(SC, FL, PRINT) do { \
if ((SC)->debug & DBG_##FL) \
printf PRINT; \
} while (0)
enum {
DBG_RCV = 0x0001,
DBG_XMIT = 0x0002,
DBG_VCC = 0x0004,
DBG_IOCTL = 0x0008,
DBG_ATTACH = 0x0010,
DBG_INIT = 0x0020,
DBG_DMA = 0x0040,
DBG_BEAT = 0x0080,
DBG_UART = 0x0100,
DBG_LOCK = 0x0200,
DBG_ALL = 0xffff
};
#else
#define DBG(SC, FL, PRINT)
#define DBGC(SC, FL, PRINT)
#endif
/*
* Configuration.
*
* This section contains tunable parameters and dependend defines.
*/
#define FATM_CMD_QLEN 16 /* command queue length */
#ifndef TEST_DMA_SYNC
#define FATM_TX_QLEN 128 /* transmit queue length */
#define FATM_RX_QLEN 64 /* receive queue length */
#else
#define FATM_TX_QLEN 8 /* transmit queue length */
#define FATM_RX_QLEN 8 /* receive queue length */
#endif
#define SMALL_SUPPLY_QLEN 16
#define SMALL_POOL_SIZE 256
#define SMALL_SUPPLY_BLKSIZE 8
#define LARGE_SUPPLY_QLEN 16
#define LARGE_POOL_SIZE 128
#define LARGE_SUPPLY_BLKSIZE 8

File diff suppressed because it is too large Load Diff

View File

@ -1,731 +0,0 @@
/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
* Author: Hartmut Brandt <harti@freebsd.org>
*
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* ForeHE driver.
*
* Interrupt handler.
*/
#include "opt_inet.h"
#include "opt_natm.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/queue.h>
#include <sys/syslog.h>
#include <sys/condvar.h>
#include <sys/sysctl.h>
#include <vm/uma.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_atm.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_atm.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/utopia/utopia.h>
#include <dev/hatm/if_hatmconf.h>
#include <dev/hatm/if_hatmreg.h>
#include <dev/hatm/if_hatmvar.h>
CTASSERT(sizeof(struct mbuf_page) == MBUF_ALLOC_SIZE);
CTASSERT(sizeof(struct mbuf0_chunk) == MBUF0_CHUNK);
CTASSERT(sizeof(struct mbuf1_chunk) == MBUF1_CHUNK);
CTASSERT(sizeof(((struct mbuf0_chunk *)NULL)->storage) >= MBUF0_SIZE);
CTASSERT(sizeof(((struct mbuf1_chunk *)NULL)->storage) >= MBUF1_SIZE);
CTASSERT(sizeof(struct tpd) <= HE_TPD_SIZE);
CTASSERT(MBUF0_PER_PAGE <= 256);
CTASSERT(MBUF1_PER_PAGE <= 256);
static void hatm_mbuf_page_alloc(struct hatm_softc *sc, u_int group);
/*
* Free an external mbuf to a list. We use atomic functions so that
* we don't need a mutex for the list.
*
* Note that in general this algorithm is not safe when multiple readers
* and writers are present. To cite from a mail from David Schultz
* <das@freebsd.org>:
*
* It looks like this is subject to the ABA problem. For instance,
* suppose X, Y, and Z are the top things on the freelist and a
* thread attempts to make an allocation. You set buf to X and load
* buf->link (Y) into a register. Then the thread get preempted, and
* another thread allocates both X and Y, then frees X. When the
* original thread gets the CPU again, X is still on top of the
* freelist, so the atomic operation succeeds. However, the atomic
* op places Y on top of the freelist, even though Y is no longer
* free.
*
* We are, however sure that we have only one thread that ever allocates
* buffers because the only place we're call from is the interrupt handler.
* Under these circumstances the code looks safe.
*/
void
hatm_ext_free(struct mbufx_free **list, struct mbufx_free *buf)
{
for (;;) {
buf->link = *list;
if (atomic_cmpset_ptr((uintptr_t *)list, (uintptr_t)buf->link,
(uintptr_t)buf))
break;
}
}
static __inline struct mbufx_free *
hatm_ext_alloc(struct hatm_softc *sc, u_int g)
{
struct mbufx_free *buf;
for (;;) {
if ((buf = sc->mbuf_list[g]) == NULL)
break;
if (atomic_cmpset_ptr((uintptr_t *)&sc->mbuf_list[g],
(uintptr_t)buf, (uintptr_t)buf->link))
break;
}
if (buf == NULL) {
hatm_mbuf_page_alloc(sc, g);
for (;;) {
if ((buf = sc->mbuf_list[g]) == NULL)
break;
if (atomic_cmpset_ptr((uintptr_t *)&sc->mbuf_list[g],
(uintptr_t)buf, (uintptr_t)buf->link))
break;
}
}
return (buf);
}
/*
* Either the queue treshold was crossed or a TPD with the INTR bit set
* was transmitted.
*/
static void
he_intr_tbrq(struct hatm_softc *sc, struct hetbrq *q, u_int group)
{
uint32_t *tailp = &sc->hsp->group[group].tbrq_tail;
u_int no;
while (q->head != (*tailp >> 2)) {
no = (q->tbrq[q->head].addr & HE_REGM_TBRQ_ADDR) >>
HE_REGS_TPD_ADDR;
hatm_tx_complete(sc, TPD_ADDR(sc, no),
(q->tbrq[q->head].addr & HE_REGM_TBRQ_FLAGS));
if (++q->head == q->size)
q->head = 0;
}
WRITE4(sc, HE_REGO_TBRQ_H(group), q->head << 2);
}
/*
* DMA loader function for external mbuf page.
*/
static void
hatm_extbuf_helper(void *arg, bus_dma_segment_t *segs, int nsegs,
int error)
{
if (error) {
printf("%s: mapping error %d\n", __func__, error);
return;
}
KASSERT(nsegs == 1,
("too many segments for DMA: %d", nsegs));
KASSERT(segs[0].ds_addr <= 0xffffffffLU,
("phys addr too large %lx", (u_long)segs[0].ds_addr));
*(uint32_t *)arg = segs[0].ds_addr;
}
/*
* Allocate a page of external mbuf storage for the small pools.
* Create a DMA map and load it. Put all the chunks onto the right
* free list.
*/
static void
hatm_mbuf_page_alloc(struct hatm_softc *sc, u_int group)
{
struct mbuf_page *pg;
int err;
u_int i;
if (sc->mbuf_npages == sc->mbuf_max_pages)
return;
if ((pg = malloc(MBUF_ALLOC_SIZE, M_DEVBUF, M_NOWAIT)) == NULL)
return;
err = bus_dmamap_create(sc->mbuf_tag, 0, &pg->hdr.map);
if (err != 0) {
if_printf(sc->ifp, "%s -- bus_dmamap_create: %d\n",
__func__, err);
free(pg, M_DEVBUF);
return;
}
err = bus_dmamap_load(sc->mbuf_tag, pg->hdr.map, pg, MBUF_ALLOC_SIZE,
hatm_extbuf_helper, &pg->hdr.phys, BUS_DMA_NOWAIT);
if (err != 0) {
if_printf(sc->ifp, "%s -- mbuf mapping failed %d\n",
__func__, err);
bus_dmamap_destroy(sc->mbuf_tag, pg->hdr.map);
free(pg, M_DEVBUF);
return;
}
sc->mbuf_pages[sc->mbuf_npages] = pg;
if (group == 0) {
struct mbuf0_chunk *c;
pg->hdr.pool = 0;
pg->hdr.nchunks = MBUF0_PER_PAGE;
pg->hdr.chunksize = MBUF0_CHUNK;
pg->hdr.hdroff = sizeof(c->storage);
c = (struct mbuf0_chunk *)pg;
for (i = 0; i < MBUF0_PER_PAGE; i++, c++) {
c->hdr.pageno = sc->mbuf_npages;
c->hdr.chunkno = i;
c->hdr.flags = 0;
hatm_ext_free(&sc->mbuf_list[0],
(struct mbufx_free *)c);
}
} else {
struct mbuf1_chunk *c;
pg->hdr.pool = 1;
pg->hdr.nchunks = MBUF1_PER_PAGE;
pg->hdr.chunksize = MBUF1_CHUNK;
pg->hdr.hdroff = sizeof(c->storage);
c = (struct mbuf1_chunk *)pg;
for (i = 0; i < MBUF1_PER_PAGE; i++, c++) {
c->hdr.pageno = sc->mbuf_npages;
c->hdr.chunkno = i;
c->hdr.flags = 0;
hatm_ext_free(&sc->mbuf_list[1],
(struct mbufx_free *)c);
}
}
sc->mbuf_npages++;
}
/*
* Free an mbuf and put it onto the free list.
*/
static void
hatm_mbuf0_free(struct mbuf *m, void *buf, void *args)
{
struct hatm_softc *sc = args;
struct mbuf0_chunk *c = buf;
KASSERT((c->hdr.flags & (MBUF_USED | MBUF_CARD)) == MBUF_USED,
("freeing unused mbuf %x", c->hdr.flags));
c->hdr.flags &= ~MBUF_USED;
hatm_ext_free(&sc->mbuf_list[0], (struct mbufx_free *)c);
}
static void
hatm_mbuf1_free(struct mbuf *m, void *buf, void *args)
{
struct hatm_softc *sc = args;
struct mbuf1_chunk *c = buf;
KASSERT((c->hdr.flags & (MBUF_USED | MBUF_CARD)) == MBUF_USED,
("freeing unused mbuf %x", c->hdr.flags));
c->hdr.flags &= ~MBUF_USED;
hatm_ext_free(&sc->mbuf_list[1], (struct mbufx_free *)c);
}
static void
hatm_mbuf_helper(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
uint32_t *ptr = (uint32_t *)arg;
if (nsegs == 0) {
printf("%s: error=%d\n", __func__, error);
return;
}
KASSERT(nsegs == 1, ("too many segments for mbuf: %d", nsegs));
KASSERT(segs[0].ds_addr <= 0xffffffffLU,
("phys addr too large %lx", (u_long)segs[0].ds_addr));
*ptr = segs[0].ds_addr;
}
/*
* Receive buffer pool interrupt. This means the number of entries in the
* queue has dropped below the threshold. Try to supply new buffers.
*/
static void
he_intr_rbp(struct hatm_softc *sc, struct herbp *rbp, u_int large,
u_int group)
{
u_int ntail;
struct mbuf *m;
int error;
struct mbufx_free *cf;
struct mbuf_page *pg;
struct mbuf0_chunk *buf0;
struct mbuf1_chunk *buf1;
DBG(sc, INTR, ("%s buffer supply threshold crossed for group %u",
large ? "large" : "small", group));
rbp->head = (READ4(sc, HE_REGO_RBP_S(large, group)) >> HE_REGS_RBP_HEAD)
& (rbp->size - 1);
for (;;) {
if ((ntail = rbp->tail + 1) == rbp->size)
ntail = 0;
if (ntail == rbp->head)
break;
m = NULL;
if (large) {
/* allocate the MBUF */
if ((m = m_getcl(M_NOWAIT, MT_DATA,
M_PKTHDR)) == NULL) {
if_printf(sc->ifp,
"no mbuf clusters\n");
break;
}
m->m_data += MBUFL_OFFSET;
if (sc->lbufs[sc->lbufs_next] != NULL)
panic("hatm: lbufs full %u", sc->lbufs_next);
sc->lbufs[sc->lbufs_next] = m;
if ((error = bus_dmamap_load(sc->mbuf_tag,
sc->rmaps[sc->lbufs_next],
m->m_data, rbp->bsize, hatm_mbuf_helper,
&rbp->rbp[rbp->tail].phys, BUS_DMA_NOWAIT)) != 0)
panic("hatm: mbuf mapping failed %d", error);
bus_dmamap_sync(sc->mbuf_tag,
sc->rmaps[sc->lbufs_next],
BUS_DMASYNC_PREREAD);
rbp->rbp[rbp->tail].handle =
MBUF_MAKE_LHANDLE(sc->lbufs_next);
if (++sc->lbufs_next == sc->lbufs_size)
sc->lbufs_next = 0;
} else if (group == 0) {
/*
* Allocate small buffer in group 0
*/
if ((cf = hatm_ext_alloc(sc, 0)) == NULL)
break;
buf0 = (struct mbuf0_chunk *)cf;
pg = sc->mbuf_pages[buf0->hdr.pageno];
buf0->hdr.flags |= MBUF_CARD;
rbp->rbp[rbp->tail].phys = pg->hdr.phys +
buf0->hdr.chunkno * MBUF0_CHUNK + MBUF0_OFFSET;
rbp->rbp[rbp->tail].handle =
MBUF_MAKE_HANDLE(buf0->hdr.pageno,
buf0->hdr.chunkno);
bus_dmamap_sync(sc->mbuf_tag, pg->hdr.map,
BUS_DMASYNC_PREREAD);
} else if (group == 1) {
/*
* Allocate small buffer in group 1
*/
if ((cf = hatm_ext_alloc(sc, 1)) == NULL)
break;
buf1 = (struct mbuf1_chunk *)cf;
pg = sc->mbuf_pages[buf1->hdr.pageno];
buf1->hdr.flags |= MBUF_CARD;
rbp->rbp[rbp->tail].phys = pg->hdr.phys +
buf1->hdr.chunkno * MBUF1_CHUNK + MBUF1_OFFSET;
rbp->rbp[rbp->tail].handle =
MBUF_MAKE_HANDLE(buf1->hdr.pageno,
buf1->hdr.chunkno);
bus_dmamap_sync(sc->mbuf_tag, pg->hdr.map,
BUS_DMASYNC_PREREAD);
} else
/* ups */
break;
DBG(sc, DMA, ("MBUF loaded: handle=%x m=%p phys=%x",
rbp->rbp[rbp->tail].handle, m, rbp->rbp[rbp->tail].phys));
rbp->tail = ntail;
}
WRITE4(sc, HE_REGO_RBP_T(large, group),
(rbp->tail << HE_REGS_RBP_TAIL));
}
/*
* Extract the buffer and hand it to the receive routine
*/
static struct mbuf *
hatm_rx_buffer(struct hatm_softc *sc, u_int group, u_int handle)
{
u_int pageno;
u_int chunkno;
struct mbuf *m;
if (handle & MBUF_LARGE_FLAG) {
/* large buffer - sync and unload */
MBUF_PARSE_LHANDLE(handle, handle);
DBG(sc, RX, ("RX large handle=%x", handle));
bus_dmamap_sync(sc->mbuf_tag, sc->rmaps[handle],
BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->mbuf_tag, sc->rmaps[handle]);
m = sc->lbufs[handle];
sc->lbufs[handle] = NULL;
return (m);
}
MBUF_PARSE_HANDLE(handle, pageno, chunkno);
DBG(sc, RX, ("RX group=%u handle=%x page=%u chunk=%u", group, handle,
pageno, chunkno));
MGETHDR(m, M_NOWAIT, MT_DATA);
if (group == 0) {
struct mbuf0_chunk *c0;
c0 = (struct mbuf0_chunk *)sc->mbuf_pages[pageno] + chunkno;
KASSERT(c0->hdr.pageno == pageno, ("pageno = %u/%u",
c0->hdr.pageno, pageno));
KASSERT(c0->hdr.chunkno == chunkno, ("chunkno = %u/%u",
c0->hdr.chunkno, chunkno));
KASSERT(c0->hdr.flags & MBUF_CARD, ("mbuf not on card %u/%u",
pageno, chunkno));
KASSERT(!(c0->hdr.flags & MBUF_USED), ("used mbuf %u/%u",
pageno, chunkno));
c0->hdr.flags |= MBUF_USED;
c0->hdr.flags &= ~MBUF_CARD;
if (m != NULL) {
m->m_ext.ext_cnt = &c0->hdr.ref_cnt;
MEXTADD(m, (void *)c0, MBUF0_SIZE,
hatm_mbuf0_free, c0, sc, M_PKTHDR, EXT_EXTREF);
m->m_data += MBUF0_OFFSET;
} else
(void)hatm_mbuf0_free(NULL, c0, sc);
} else {
struct mbuf1_chunk *c1;
c1 = (struct mbuf1_chunk *)sc->mbuf_pages[pageno] + chunkno;
KASSERT(c1->hdr.pageno == pageno, ("pageno = %u/%u",
c1->hdr.pageno, pageno));
KASSERT(c1->hdr.chunkno == chunkno, ("chunkno = %u/%u",
c1->hdr.chunkno, chunkno));
KASSERT(c1->hdr.flags & MBUF_CARD, ("mbuf not on card %u/%u",
pageno, chunkno));
KASSERT(!(c1->hdr.flags & MBUF_USED), ("used mbuf %u/%u",
pageno, chunkno));
c1->hdr.flags |= MBUF_USED;
c1->hdr.flags &= ~MBUF_CARD;
if (m != NULL) {
m->m_ext.ext_cnt = &c1->hdr.ref_cnt;
MEXTADD(m, (void *)c1, MBUF1_SIZE,
hatm_mbuf1_free, c1, sc, M_PKTHDR, EXT_EXTREF);
m->m_data += MBUF1_OFFSET;
} else
(void)hatm_mbuf1_free(NULL, c1, sc);
}
return (m);
}
/*
* Interrupt because of receive buffer returned.
*/
static void
he_intr_rbrq(struct hatm_softc *sc, struct herbrq *rq, u_int group)
{
struct he_rbrqen *e;
uint32_t flags, tail;
u_int cid, len;
struct mbuf *m;
for (;;) {
tail = sc->hsp->group[group].rbrq_tail >> 3;
if (rq->head == tail)
break;
e = &rq->rbrq[rq->head];
flags = e->addr & HE_REGM_RBRQ_FLAGS;
if (!(flags & HE_REGM_RBRQ_HBUF_ERROR))
m = hatm_rx_buffer(sc, group, e->addr);
else
m = NULL;
cid = (e->len & HE_REGM_RBRQ_CID) >> HE_REGS_RBRQ_CID;
len = 4 * (e->len & HE_REGM_RBRQ_LEN);
hatm_rx(sc, cid, flags, m, len);
if (++rq->head == rq->size)
rq->head = 0;
}
WRITE4(sc, HE_REGO_RBRQ_H(group), rq->head << 3);
}
void
hatm_intr(void *p)
{
struct heirq *q = p;
struct hatm_softc *sc = q->sc;
u_int status;
u_int tail;
/* if we have a stray interrupt with a non-initialized card,
* we cannot even lock before looking at the flag */
if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING))
return;
mtx_lock(&sc->mtx);
(void)READ4(sc, HE_REGO_INT_FIFO);
tail = *q->tailp;
if (q->head == tail) {
/* workaround for tail pointer not updated bug (8.1.1) */
DBG(sc, INTR, ("hatm: intr tailq not updated bug triggered"));
/* read the tail pointer from the card */
tail = READ4(sc, HE_REGO_IRQ_BASE(q->group)) &
HE_REGM_IRQ_BASE_TAIL;
BARRIER_R(sc);
sc->istats.bug_no_irq_upd++;
}
/* clear the interrupt */
WRITE4(sc, HE_REGO_INT_FIFO, HE_REGM_INT_FIFO_CLRA);
BARRIER_W(sc);
while (q->head != tail) {
status = q->irq[q->head];
q->irq[q->head] = HE_REGM_ITYPE_INVALID;
if (++q->head == (q->size - 1))
q->head = 0;
switch (status & HE_REGM_ITYPE) {
case HE_REGM_ITYPE_TBRQ:
DBG(sc, INTR, ("TBRQ treshold %u", status & HE_REGM_IGROUP));
sc->istats.itype_tbrq++;
he_intr_tbrq(sc, &sc->tbrq, status & HE_REGM_IGROUP);
break;
case HE_REGM_ITYPE_TPD:
DBG(sc, INTR, ("TPD ready %u", status & HE_REGM_IGROUP));
sc->istats.itype_tpd++;
he_intr_tbrq(sc, &sc->tbrq, status & HE_REGM_IGROUP);
break;
case HE_REGM_ITYPE_RBPS:
sc->istats.itype_rbps++;
switch (status & HE_REGM_IGROUP) {
case 0:
he_intr_rbp(sc, &sc->rbp_s0, 0, 0);
break;
case 1:
he_intr_rbp(sc, &sc->rbp_s1, 0, 1);
break;
default:
if_printf(sc->ifp, "bad INTR RBPS%u\n",
status & HE_REGM_IGROUP);
break;
}
break;
case HE_REGM_ITYPE_RBPL:
sc->istats.itype_rbpl++;
switch (status & HE_REGM_IGROUP) {
case 0:
he_intr_rbp(sc, &sc->rbp_l0, 1, 0);
break;
default:
if_printf(sc->ifp, "bad INTR RBPL%u\n",
status & HE_REGM_IGROUP);
break;
}
break;
case HE_REGM_ITYPE_RBRQ:
DBG(sc, INTR, ("INTERRUPT RBRQ %u", status & HE_REGM_IGROUP));
sc->istats.itype_rbrq++;
switch (status & HE_REGM_IGROUP) {
case 0:
he_intr_rbrq(sc, &sc->rbrq_0, 0);
break;
case 1:
if (sc->rbrq_1.size > 0) {
he_intr_rbrq(sc, &sc->rbrq_1, 1);
break;
}
/* FALLTHRU */
default:
if_printf(sc->ifp, "bad INTR RBRQ%u\n",
status & HE_REGM_IGROUP);
break;
}
break;
case HE_REGM_ITYPE_RBRQT:
DBG(sc, INTR, ("INTERRUPT RBRQT %u", status & HE_REGM_IGROUP));
sc->istats.itype_rbrqt++;
switch (status & HE_REGM_IGROUP) {
case 0:
he_intr_rbrq(sc, &sc->rbrq_0, 0);
break;
case 1:
if (sc->rbrq_1.size > 0) {
he_intr_rbrq(sc, &sc->rbrq_1, 1);
break;
}
/* FALLTHRU */
default:
if_printf(sc->ifp, "bad INTR RBRQT%u\n",
status & HE_REGM_IGROUP);
break;
}
break;
case HE_REGM_ITYPE_PHYS:
sc->istats.itype_phys++;
utopia_intr(&sc->utopia);
break;
#if HE_REGM_ITYPE_UNKNOWN != HE_REGM_ITYPE_INVALID
case HE_REGM_ITYPE_UNKNOWN:
sc->istats.itype_unknown++;
if_printf(sc->ifp, "bad interrupt\n");
break;
#endif
case HE_REGM_ITYPE_ERR:
sc->istats.itype_err++;
switch (status) {
case HE_REGM_ITYPE_PERR:
if_printf(sc->ifp, "parity error\n");
break;
case HE_REGM_ITYPE_ABORT:
if_printf(sc->ifp, "abort interrupt "
"addr=0x%08x\n",
READ4(sc, HE_REGO_ABORT_ADDR));
break;
default:
if_printf(sc->ifp,
"bad interrupt type %08x\n", status);
break;
}
break;
case HE_REGM_ITYPE_INVALID:
/* this is the documented fix for the ISW bug 8.1.1
* Note, that the documented fix is partly wrong:
* the ISWs should be intialized to 0xf8 not 0xff */
sc->istats.bug_bad_isw++;
DBG(sc, INTR, ("hatm: invalid ISW bug triggered"));
he_intr_tbrq(sc, &sc->tbrq, 0);
he_intr_rbp(sc, &sc->rbp_s0, 0, 0);
he_intr_rbp(sc, &sc->rbp_l0, 1, 0);
he_intr_rbp(sc, &sc->rbp_s1, 0, 1);
he_intr_rbrq(sc, &sc->rbrq_0, 0);
he_intr_rbrq(sc, &sc->rbrq_1, 1);
utopia_intr(&sc->utopia);
break;
default:
if_printf(sc->ifp, "bad interrupt type %08x\n",
status);
break;
}
}
/* write back head to clear queue */
WRITE4(sc, HE_REGO_IRQ_HEAD(0),
((q->size - 1) << HE_REGS_IRQ_HEAD_SIZE) |
(q->thresh << HE_REGS_IRQ_HEAD_THRESH) |
(q->head << HE_REGS_IRQ_HEAD_HEAD));
BARRIER_W(sc);
/* workaround the back-to-back irq access problem (8.1.2) */
(void)READ4(sc, HE_REGO_INT_FIFO);
BARRIER_R(sc);
mtx_unlock(&sc->mtx);
}

View File

@ -1,385 +0,0 @@
/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* ForeHE driver.
*
* Ioctl handler.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_natm.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/queue.h>
#include <sys/syslog.h>
#include <sys/condvar.h>
#include <sys/sysctl.h>
#include <vm/uma.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_atm.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_atm.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/utopia/utopia.h>
#include <dev/hatm/if_hatmconf.h>
#include <dev/hatm/if_hatmreg.h>
#include <dev/hatm/if_hatmvar.h>
static u_int hatm_natm_traffic = ATMIO_TRAFFIC_UBR;
static u_int hatm_natm_pcr = 0;
static int hatm_sysctl_natm_traffic(SYSCTL_HANDLER_ARGS);
SYSCTL_DECL(_hw_atm);
SYSCTL_PROC(_hw_atm, OID_AUTO, natm_traffic, CTLTYPE_UINT | CTLFLAG_RW,
&hatm_natm_traffic, sizeof(hatm_natm_traffic), hatm_sysctl_natm_traffic,
"IU", "traffic type for NATM connections");
SYSCTL_UINT(_hw_atm, OID_AUTO, natm_pcr, CTLFLAG_RW,
&hatm_natm_pcr, 0, "PCR for NATM connections");
/*
* Try to open the given VCC.
*/
static int
hatm_open_vcc(struct hatm_softc *sc, struct atmio_openvcc *arg)
{
u_int cid;
struct hevcc *vcc;
int error = 0;
DBG(sc, VCC, ("Open VCC: %u.%u flags=%#x", arg->param.vpi,
arg->param.vci, arg->param.flags));
if ((arg->param.vpi & ~HE_VPI_MASK) ||
(arg->param.vci & ~HE_VCI_MASK) ||
(arg->param.vci == 0))
return (EINVAL);
cid = HE_CID(arg->param.vpi, arg->param.vci);
if ((arg->param.flags & ATMIO_FLAG_NOTX) &&
(arg->param.flags & ATMIO_FLAG_NORX))
return (EINVAL);
vcc = uma_zalloc(sc->vcc_zone, M_NOWAIT | M_ZERO);
if (vcc == NULL)
return (ENOMEM);
mtx_lock(&sc->mtx);
if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
error = EIO;
goto done;
}
if (sc->vccs[cid] != NULL) {
error = EBUSY;
goto done;
}
vcc->param = arg->param;
vcc->rxhand = arg->rxhand;
switch (vcc->param.aal) {
case ATMIO_AAL_0:
case ATMIO_AAL_5:
case ATMIO_AAL_RAW:
break;
default:
error = EINVAL;
goto done;
}
switch (vcc->param.traffic) {
case ATMIO_TRAFFIC_UBR:
case ATMIO_TRAFFIC_CBR:
case ATMIO_TRAFFIC_ABR:
break;
default:
error = EINVAL;
goto done;
}
vcc->ntpds = 0;
vcc->chain = vcc->last = NULL;
vcc->ibytes = vcc->ipackets = 0;
vcc->obytes = vcc->opackets = 0;
if (!(vcc->param.flags & ATMIO_FLAG_NOTX) &&
(error = hatm_tx_vcc_can_open(sc, cid, vcc)) != 0)
goto done;
/* ok - go ahead */
sc->vccs[cid] = vcc;
hatm_load_vc(sc, cid, 0);
/* don't free below */
vcc = NULL;
sc->open_vccs++;
done:
mtx_unlock(&sc->mtx);
if (vcc != NULL)
uma_zfree(sc->vcc_zone, vcc);
return (error);
}
void
hatm_load_vc(struct hatm_softc *sc, u_int cid, int reopen)
{
struct hevcc *vcc = sc->vccs[cid];
if (!(vcc->param.flags & ATMIO_FLAG_NOTX))
hatm_tx_vcc_open(sc, cid);
if (!(vcc->param.flags & ATMIO_FLAG_NORX))
hatm_rx_vcc_open(sc, cid);
if (reopen)
return;
/* inform management about non-NG and NG-PVCs */
if (!(vcc->param.flags & ATMIO_FLAG_NG) ||
(vcc->param.flags & ATMIO_FLAG_PVC))
ATMEV_SEND_VCC_CHANGED(IFP2IFATM(sc->ifp), vcc->param.vpi,
vcc->param.vci, 1);
}
/*
* VCC has been finally closed.
*/
void
hatm_vcc_closed(struct hatm_softc *sc, u_int cid)
{
struct hevcc *vcc = sc->vccs[cid];
/* inform management about non-NG and NG-PVCs */
if (!(vcc->param.flags & ATMIO_FLAG_NG) ||
(vcc->param.flags & ATMIO_FLAG_PVC))
ATMEV_SEND_VCC_CHANGED(IFP2IFATM(sc->ifp), HE_VPI(cid), HE_VCI(cid), 0);
sc->open_vccs--;
uma_zfree(sc->vcc_zone, vcc);
sc->vccs[cid] = NULL;
}
/*
* Try to close the given VCC
*/
static int
hatm_close_vcc(struct hatm_softc *sc, struct atmio_closevcc *arg)
{
u_int cid;
struct hevcc *vcc;
int error = 0;
DBG(sc, VCC, ("Close VCC: %u.%u", arg->vpi, arg->vci));
if((arg->vpi & ~HE_VPI_MASK) ||
(arg->vci & ~HE_VCI_MASK) ||
(arg->vci == 0))
return (EINVAL);
cid = HE_CID(arg->vpi, arg->vci);
mtx_lock(&sc->mtx);
vcc = sc->vccs[cid];
if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
error = EIO;
goto done;
}
if (vcc == NULL || !(vcc->vflags & HE_VCC_OPEN)) {
error = ENOENT;
goto done;
}
if (vcc->vflags & HE_VCC_TX_OPEN)
hatm_tx_vcc_close(sc, cid);
if (vcc->vflags & HE_VCC_RX_OPEN)
hatm_rx_vcc_close(sc, cid);
if (vcc->param.flags & ATMIO_FLAG_ASYNC)
goto done;
while ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING) &&
(vcc->vflags & (HE_VCC_TX_CLOSING | HE_VCC_RX_CLOSING)))
cv_wait(&sc->vcc_cv, &sc->mtx);
if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
error = EIO;
goto done;
}
if (!(vcc->vflags & ATMIO_FLAG_NOTX))
hatm_tx_vcc_closed(sc, cid);
hatm_vcc_closed(sc, cid);
done:
mtx_unlock(&sc->mtx);
return (error);
}
/*
* IOCTL handler
*/
int
hatm_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct ifreq *ifr = (struct ifreq *)data;
struct ifaddr *ifa = (struct ifaddr *)data;
struct hatm_softc *sc = ifp->if_softc;
struct atmio_vcctable *vtab;
int error = 0;
switch (cmd) {
case SIOCSIFADDR:
mtx_lock(&sc->mtx);
ifp->if_flags |= IFF_UP;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
hatm_initialize(sc);
switch (ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET:
case AF_INET6:
ifa->ifa_rtrequest = atm_rtrequest;
break;
#endif
default:
break;
}
mtx_unlock(&sc->mtx);
break;
case SIOCSIFFLAGS:
mtx_lock(&sc->mtx);
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
hatm_initialize(sc);
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
hatm_stop(sc);
}
}
mtx_unlock(&sc->mtx);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd);
break;
case SIOCSIFMTU:
/*
* Set the interface MTU.
*/
if (ifr->ifr_mtu > ATMMTU)
error = EINVAL;
else
ifp->if_mtu = ifr->ifr_mtu;
break;
case SIOCATMGVCCS:
/* return vcc table */
vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
HE_MAX_VCCS, sc->open_vccs, &sc->mtx, 1);
error = copyout(vtab, ifr->ifr_data, sizeof(*vtab) +
vtab->count * sizeof(vtab->vccs[0]));
free(vtab, M_DEVBUF);
break;
case SIOCATMGETVCCS: /* netgraph internal use */
vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
HE_MAX_VCCS, sc->open_vccs, &sc->mtx, 0);
if (vtab == NULL) {
error = ENOMEM;
break;
}
*(void **)data = vtab;
break;
case SIOCATMOPENVCC: /* kernel internal use */
error = hatm_open_vcc(sc, (struct atmio_openvcc *)data);
break;
case SIOCATMCLOSEVCC: /* kernel internal use */
error = hatm_close_vcc(sc, (struct atmio_closevcc *)data);
break;
default:
DBG(sc, IOCTL, ("cmd=%08lx arg=%p", cmd, data));
error = EINVAL;
break;
}
return (error);
}
static int
hatm_sysctl_natm_traffic(SYSCTL_HANDLER_ARGS)
{
int error;
int tmp;
tmp = hatm_natm_traffic;
error = sysctl_handle_int(oidp, &tmp, 0, req);
if (error != 0 || req->newptr == NULL)
return (error);
if (tmp != ATMIO_TRAFFIC_UBR && tmp != ATMIO_TRAFFIC_CBR)
return (EINVAL);
hatm_natm_traffic = tmp;
return (0);
}

View File

@ -1,331 +0,0 @@
/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* ForeHE driver.
*
* Receive.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_natm.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/queue.h>
#include <sys/syslog.h>
#include <sys/condvar.h>
#include <sys/sysctl.h>
#include <vm/uma.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_atm.h>
#include <net/route.h>
#ifdef ENABLE_BPF
#include <net/bpf.h>
#endif
#include <netinet/in.h>
#include <netinet/if_atm.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/utopia/utopia.h>
#include <dev/hatm/if_hatmconf.h>
#include <dev/hatm/if_hatmreg.h>
#include <dev/hatm/if_hatmvar.h>
void
hatm_rx(struct hatm_softc *sc, u_int cid, u_int flags, struct mbuf *m0,
u_int len)
{
struct hevcc *vcc;
struct atm_pseudohdr aph;
struct mbuf *m, *m1;
u_int vpi, vci;
u_char *ptr;
DBG(sc, RX, ("cid=%#x flags=%#x len=%u mbuf=%p", cid, flags, len, m0));
vcc = sc->vccs[cid];
if (vcc == NULL)
goto drop;
if (flags & HE_REGM_RBRQ_CON_CLOSED) {
if (vcc->vflags & HE_VCC_RX_CLOSING) {
vcc->vflags &= ~HE_VCC_RX_CLOSING;
if (vcc->param.flags & ATMIO_FLAG_ASYNC) {
if (!(vcc->vflags & HE_VCC_OPEN))
hatm_vcc_closed(sc, cid);
} else
cv_signal(&sc->vcc_cv);
}
goto drop;
}
if (!(vcc->vflags & HE_VCC_RX_OPEN))
goto drop;
if (flags & HE_REGM_RBRQ_HBUF_ERROR) {
sc->istats.hbuf_error++;
if (vcc->chain != NULL) {
m_freem(vcc->chain);
vcc->chain = vcc->last = NULL;
}
goto drop;
}
if (m0 == NULL) {
sc->istats.no_rcv_mbuf++;
return;
}
if ((m0->m_len = len) == 0) {
sc->istats.empty_hbuf++;
m_free(m0);
} else if (vcc->chain == NULL) {
sc->istats.rx_seg++;
vcc->chain = vcc->last = m0;
vcc->last->m_next = NULL;
vcc->chain->m_pkthdr.len = m0->m_len;
vcc->chain->m_pkthdr.rcvif = sc->ifp;
} else {
sc->istats.rx_seg++;
vcc->last->m_next = m0;
vcc->last = m0;
vcc->last->m_next = NULL;
vcc->chain->m_pkthdr.len += m0->m_len;
}
if (!(flags & HE_REGM_RBRQ_END_PDU))
return;
if (flags & HE_REGM_RBRQ_CRC_ERROR) {
if (vcc->chain)
m_freem(vcc->chain);
vcc->chain = vcc->last = NULL;
sc->istats.crc_error++;
if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1);
return;
}
if (flags & HE_REGM_RBRQ_LEN_ERROR) {
if (vcc->chain)
m_freem(vcc->chain);
vcc->chain = vcc->last = NULL;
sc->istats.len_error++;
if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1);
return;
}
#ifdef HATM_DEBUG
if (sc->debug & DBG_DUMP) {
struct mbuf *tmp;
for (tmp = vcc->chain; tmp != NULL; tmp = tmp->m_next) {
printf("mbuf %p: len=%u\n", tmp, tmp->m_len);
for (ptr = mtod(tmp, u_char *);
ptr < mtod(tmp, u_char *) + tmp->m_len; ptr++)
printf("%02x ", *ptr);
printf("\n");
}
}
#endif
if (vcc->param.aal == ATMIO_AAL_5) {
/*
* Need to remove padding and the trailer. The trailer
* may be split across buffers according to 2.10.1.2
* Assume that mbufs sizes are even (buffer sizes and cell
* payload sizes are) and that there are no empty mbufs.
*/
m = vcc->last;
if (m->m_len == 2) {
/* Ah, oh, only part of CRC */
if (m == vcc->chain) {
/* ups */
sc->istats.short_aal5++;
m_freem(vcc->chain);
vcc->chain = vcc->last = NULL;
return;
}
for (m1 = vcc->chain; m1->m_next != m; m1 = m1->m_next)
;
ptr = (u_char *)m1->m_data + m1->m_len - 4;
} else if (m->m_len == 4) {
/* Ah, oh, only CRC */
if (m == vcc->chain) {
/* ups */
sc->istats.short_aal5++;
m_freem(vcc->chain);
vcc->chain = vcc->last = NULL;
return;
}
for (m1 = vcc->chain; m1->m_next != m; m1 = m1->m_next)
;
ptr = (u_char *)m1->m_data + m1->m_len - 2;
} else if (m->m_len >= 6) {
ptr = (u_char *)m->m_data + m->m_len - 6;
} else
panic("hatm_rx: bad mbuf len %d", m->m_len);
len = (ptr[0] << 8) + ptr[1];
if (len > (u_int)vcc->chain->m_pkthdr.len - 4) {
sc->istats.badlen_aal5++;
m_freem(vcc->chain);
vcc->chain = vcc->last = NULL;
return;
}
m_adj(vcc->chain, -(vcc->chain->m_pkthdr.len - len));
}
m = vcc->chain;
vcc->chain = vcc->last = NULL;
#ifdef ENABLE_BPF
if (!(vcc->param.flags & ATMIO_FLAG_NG) &&
(vcc->param.aal == ATMIO_AAL_5) &&
(vcc->param.flags & ATM_PH_LLCSNAP))
BPF_MTAP(sc->ifp, m);
#endif
vpi = HE_VPI(cid);
vci = HE_VCI(cid);
ATM_PH_FLAGS(&aph) = vcc->param.flags & 0xff;
ATM_PH_VPI(&aph) = vpi;
ATM_PH_SETVCI(&aph, vci);
if_inc_counter(sc->ifp, IFCOUNTER_IPACKETS, 1);
/* this is in if_atmsubr.c */
/* if_inc_counter(sc->ifp, IFCOUNTER_IBYTES, len); */
vcc->ibytes += len;
vcc->ipackets++;
#if 0
{
struct mbuf *tmp;
for (tmp = m; tmp != NULL; tmp = tmp->m_next) {
printf("mbuf %p: len=%u\n", tmp, tmp->m_len);
for (ptr = mtod(tmp, u_char *);
ptr < mtod(tmp, u_char *) + tmp->m_len; ptr++)
printf("%02x ", *ptr);
printf("\n");
}
}
#endif
atm_input(sc->ifp, &aph, m, vcc->rxhand);
return;
drop:
if (m0 != NULL)
m_free(m0);
}
void
hatm_rx_vcc_open(struct hatm_softc *sc, u_int cid)
{
struct hevcc *vcc = sc->vccs[cid];
uint32_t rsr0, rsr1, rsr4;
rsr0 = rsr1 = rsr4 = 0;
if (vcc->param.traffic == ATMIO_TRAFFIC_ABR) {
rsr1 |= HE_REGM_RSR1_AQI;
rsr4 |= HE_REGM_RSR4_AQI;
}
if (vcc->param.aal == ATMIO_AAL_5) {
rsr0 |= HE_REGM_RSR0_STARTPDU | HE_REGM_RSR0_AAL_5;
} else if (vcc->param.aal == ATMIO_AAL_0) {
rsr0 |= HE_REGM_RSR0_AAL_0;
} else {
if (sc->rbp_s1.size != 0) {
rsr1 |= (1 << HE_REGS_RSR1_GROUP);
rsr4 |= (1 << HE_REGS_RSR4_GROUP);
}
rsr0 |= HE_REGM_RSR0_AAL_RAW | HE_REGM_RSR0_PTI7 |
HE_REGM_RSR0_RM | HE_REGM_RSR0_F5OAM;
}
rsr0 |= HE_REGM_RSR0_OPEN;
WRITE_RSR(sc, cid, 0, 0xf, rsr0);
WRITE_RSR(sc, cid, 1, 0xf, rsr1);
WRITE_RSR(sc, cid, 4, 0xf, rsr4);
vcc->vflags |= HE_VCC_RX_OPEN;
}
/*
* Close the RX side of a VCC.
*/
void
hatm_rx_vcc_close(struct hatm_softc *sc, u_int cid)
{
struct hevcc *vcc = sc->vccs[cid];
uint32_t v;
vcc->vflags |= HE_VCC_RX_CLOSING;
WRITE_RSR(sc, cid, 0, 0xf, 0);
v = READ4(sc, HE_REGO_RCCSTAT);
while ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING) &&
(READ4(sc, HE_REGO_RCCSTAT) & HE_REGM_RCCSTAT_PROG))
cv_timedwait(&sc->cv_rcclose, &sc->mtx, 1);
if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING))
return;
WRITE_MBOX4(sc, HE_REGO_RCON_CLOSE, cid);
vcc->vflags |= HE_VCC_RX_CLOSING;
vcc->vflags &= ~HE_VCC_RX_OPEN;
}

View File

@ -1,827 +0,0 @@
/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* ForeHE driver.
*
* Transmission.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_natm.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/bus.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/queue.h>
#include <sys/syslog.h>
#include <sys/condvar.h>
#include <sys/sysctl.h>
#include <vm/uma.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_atm.h>
#include <net/route.h>
#ifdef ENABLE_BPF
#include <net/bpf.h>
#endif
#include <netinet/in.h>
#include <netinet/if_atm.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/utopia/utopia.h>
#include <dev/hatm/if_hatmconf.h>
#include <dev/hatm/if_hatmreg.h>
#include <dev/hatm/if_hatmvar.h>
/*
* These macros are used to trace the flow of transmit mbufs and to
* detect transmit mbuf leaks in the driver.
*/
#ifdef HATM_DEBUG
#define hatm_free_txmbuf(SC) \
do { \
if (--sc->txmbuf < 0) \
DBG(sc, TX, ("txmbuf below 0!")); \
else if (sc->txmbuf == 0) \
DBG(sc, TX, ("txmbuf now 0")); \
} while (0)
#define hatm_get_txmbuf(SC) \
do { \
if (++sc->txmbuf > 20000) \
DBG(sc, TX, ("txmbuf %u", sc->txmbuf)); \
else if (sc->txmbuf == 1) \
DBG(sc, TX, ("txmbuf leaves 0")); \
} while (0)
#else
#define hatm_free_txmbuf(SC) do { } while (0)
#define hatm_get_txmbuf(SC) do { } while (0)
#endif
/*
* Allocate a new TPD, zero the TPD part. Cannot return NULL if
* flag is 0. The TPD is removed from the free list and its used
* bit is set.
*/
static struct tpd *
hatm_alloc_tpd(struct hatm_softc *sc, u_int flags)
{
struct tpd *t;
/* if we allocate a transmit TPD check for the reserve */
if (flags & M_NOWAIT) {
if (sc->tpd_nfree <= HE_CONFIG_TPD_RESERVE)
return (NULL);
} else {
if (sc->tpd_nfree == 0)
return (NULL);
}
/* make it being used */
t = SLIST_FIRST(&sc->tpd_free);
KASSERT(t != NULL, ("tpd botch"));
SLIST_REMOVE_HEAD(&sc->tpd_free, link);
TPD_SET_USED(sc, t->no);
sc->tpd_nfree--;
/* initialize */
t->mbuf = NULL;
t->cid = 0;
bzero(&t->tpd, sizeof(t->tpd));
t->tpd.addr = t->no << HE_REGS_TPD_ADDR;
return (t);
}
/*
* Free a TPD. If the mbuf pointer in that TPD is not zero, it is assumed, that
* the DMA map of this TPD was used to load this mbuf. The map is unloaded
* and the mbuf is freed. The TPD is put back onto the free list and
* its used bit is cleared.
*/
static void
hatm_free_tpd(struct hatm_softc *sc, struct tpd *tpd)
{
if (tpd->mbuf != NULL) {
bus_dmamap_unload(sc->tx_tag, tpd->map);
hatm_free_txmbuf(sc);
m_freem(tpd->mbuf);
tpd->mbuf = NULL;
}
/* insert TPD into free list */
SLIST_INSERT_HEAD(&sc->tpd_free, tpd, link);
TPD_CLR_USED(sc, tpd->no);
sc->tpd_nfree++;
}
/*
* Queue a number of TPD. If there is not enough space none of the TPDs
* is queued and an error code is returned.
*/
static int
hatm_queue_tpds(struct hatm_softc *sc, u_int count, struct tpd **list,
u_int cid)
{
u_int space;
u_int i;
if (count >= sc->tpdrq.size) {
sc->istats.tdprq_full++;
return (EBUSY);
}
if (sc->tpdrq.tail < sc->tpdrq.head)
space = sc->tpdrq.head - sc->tpdrq.tail;
else
space = sc->tpdrq.head - sc->tpdrq.tail + sc->tpdrq.size;
if (space <= count) {
sc->tpdrq.head =
(READ4(sc, HE_REGO_TPDRQ_H) >> HE_REGS_TPDRQ_H_H) &
(sc->tpdrq.size - 1);
if (sc->tpdrq.tail < sc->tpdrq.head)
space = sc->tpdrq.head - sc->tpdrq.tail;
else
space = sc->tpdrq.head - sc->tpdrq.tail +
sc->tpdrq.size;
if (space <= count) {
if_printf(sc->ifp, "TPDRQ full\n");
sc->istats.tdprq_full++;
return (EBUSY);
}
}
/* we are going to write to the TPD queue space */
bus_dmamap_sync(sc->tpdrq.mem.tag, sc->tpdrq.mem.map,
BUS_DMASYNC_PREWRITE);
/* put the entries into the TPD space */
for (i = 0; i < count; i++) {
/* we are going to 'write' the TPD to the device */
bus_dmamap_sync(sc->tpds.tag, sc->tpds.map,
BUS_DMASYNC_PREWRITE);
sc->tpdrq.tpdrq[sc->tpdrq.tail].tpd =
sc->tpds.paddr + HE_TPD_SIZE * list[i]->no;
sc->tpdrq.tpdrq[sc->tpdrq.tail].cid = cid;
if (++sc->tpdrq.tail == sc->tpdrq.size)
sc->tpdrq.tail = 0;
}
/* update tail pointer */
WRITE4(sc, HE_REGO_TPDRQ_T, (sc->tpdrq.tail << HE_REGS_TPDRQ_T_T));
return (0);
}
/*
* Helper struct for communication with the DMA load helper.
*/
struct load_txbuf_arg {
struct hatm_softc *sc;
struct tpd *first;
struct mbuf *mbuf;
struct hevcc *vcc;
int error;
u_int pti;
u_int vpi, vci;
};
/*
* Loader callback for the mbuf. This function allocates the TPDs and
* fills them. It puts the dmamap and and the mbuf pointer into the last
* TPD and then tries to queue all the TPDs. If anything fails, all TPDs
* allocated by this function are freed and the error flag is set in the
* argument structure. The first TPD must then be freed by the caller.
*/
static void
hatm_load_txbuf(void *uarg, bus_dma_segment_t *segs, int nseg,
bus_size_t mapsize, int error)
{
struct load_txbuf_arg *arg = uarg;
u_int tpds_needed, i, n, tpd_cnt;
int need_intr;
struct tpd *tpd;
struct tpd *tpd_list[HE_CONFIG_MAX_TPD_PER_PACKET];
if (error != 0) {
DBG(arg->sc, DMA, ("%s -- error=%d plen=%d\n",
__func__, error, arg->mbuf->m_pkthdr.len));
return;
}
/* ensure, we have enough TPDs (remember, we already have one) */
tpds_needed = (nseg + 2) / 3;
if (HE_CONFIG_TPD_RESERVE + tpds_needed - 1 > arg->sc->tpd_nfree) {
if_printf(arg->sc->ifp, "%s -- out of TPDs (need %d, "
"have %u)\n", __func__, tpds_needed - 1,
arg->sc->tpd_nfree + 1);
arg->error = 1;
return;
}
/*
* Check for the maximum number of TPDs on the connection.
*/
need_intr = 0;
if (arg->sc->max_tpd > 0) {
if (arg->vcc->ntpds + tpds_needed > arg->sc->max_tpd) {
arg->sc->istats.flow_closed++;
arg->vcc->vflags |= HE_VCC_FLOW_CTRL;
ATMEV_SEND_FLOW_CONTROL(IFP2IFATM(arg->sc->ifp),
arg->vpi, arg->vci, 1);
arg->error = 1;
return;
}
if (arg->vcc->ntpds + tpds_needed >
(9 * arg->sc->max_tpd) / 10)
need_intr = 1;
}
tpd = arg->first;
tpd_cnt = 0;
tpd_list[tpd_cnt++] = tpd;
for (i = n = 0; i < nseg; i++, n++) {
if (n == 3) {
if ((tpd = hatm_alloc_tpd(arg->sc, M_NOWAIT)) == NULL)
/* may not fail (see check above) */
panic("%s: out of TPDs", __func__);
tpd->cid = arg->first->cid;
tpd->tpd.addr |= arg->pti;
tpd_list[tpd_cnt++] = tpd;
n = 0;
}
KASSERT(segs[i].ds_addr <= 0xffffffffLU,
("phys addr too large %lx", (u_long)segs[i].ds_addr));
DBG(arg->sc, DMA, ("DMA loaded: %lx/%lu",
(u_long)segs[i].ds_addr, (u_long)segs[i].ds_len));
tpd->tpd.bufs[n].addr = segs[i].ds_addr;
tpd->tpd.bufs[n].len = segs[i].ds_len;
DBG(arg->sc, TX, ("seg[%u]=tpd[%u,%u]=%x/%u", i,
tpd_cnt, n, tpd->tpd.bufs[n].addr, tpd->tpd.bufs[n].len));
if (i == nseg - 1)
tpd->tpd.bufs[n].len |= HE_REGM_TPD_LST;
}
/*
* Swap the MAP in the first and the last TPD and set the mbuf
* pointer into the last TPD. We use the map in the last TPD, because
* the map must stay valid until the last TPD is processed by the card.
*/
if (tpd_cnt > 1) {
bus_dmamap_t tmp;
tmp = arg->first->map;
arg->first->map = tpd_list[tpd_cnt - 1]->map;
tpd_list[tpd_cnt - 1]->map = tmp;
}
tpd_list[tpd_cnt - 1]->mbuf = arg->mbuf;
if (need_intr)
tpd_list[tpd_cnt - 1]->tpd.addr |= HE_REGM_TPD_INTR;
/* queue the TPDs */
if (hatm_queue_tpds(arg->sc, tpd_cnt, tpd_list, arg->first->cid)) {
/* free all, except the first TPD */
for (i = 1; i < tpd_cnt; i++)
hatm_free_tpd(arg->sc, tpd_list[i]);
arg->error = 1;
return;
}
arg->vcc->ntpds += tpd_cnt;
}
/*
* Start output on the interface
*/
void
hatm_start(struct ifnet *ifp)
{
struct hatm_softc *sc = ifp->if_softc;
struct mbuf *m;
struct atm_pseudohdr *aph;
u_int cid;
struct tpd *tpd;
struct load_txbuf_arg arg;
u_int len;
int error;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
return;
mtx_lock(&sc->mtx);
arg.sc = sc;
while (1) {
IF_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
hatm_get_txmbuf(sc);
if (m->m_len < sizeof(*aph))
if ((m = m_pullup(m, sizeof(*aph))) == NULL) {
hatm_free_txmbuf(sc);
continue;
}
aph = mtod(m, struct atm_pseudohdr *);
arg.vci = ATM_PH_VCI(aph);
arg.vpi = ATM_PH_VPI(aph);
m_adj(m, sizeof(*aph));
if ((len = m->m_pkthdr.len) == 0) {
hatm_free_txmbuf(sc);
m_freem(m);
continue;
}
if ((arg.vpi & ~HE_VPI_MASK) || (arg.vci & ~HE_VCI_MASK) ||
(arg.vci == 0)) {
hatm_free_txmbuf(sc);
m_freem(m);
continue;
}
cid = HE_CID(arg.vpi, arg.vci);
arg.vcc = sc->vccs[cid];
if (arg.vcc == NULL || !(arg.vcc->vflags & HE_VCC_OPEN)) {
hatm_free_txmbuf(sc);
m_freem(m);
continue;
}
if (arg.vcc->vflags & HE_VCC_FLOW_CTRL) {
hatm_free_txmbuf(sc);
m_freem(m);
sc->istats.flow_drop++;
continue;
}
arg.pti = 0;
if (arg.vcc->param.aal == ATMIO_AAL_RAW) {
if (len < 52) {
/* too short */
hatm_free_txmbuf(sc);
m_freem(m);
continue;
}
/*
* Get the header and ignore except
* payload type and CLP.
*/
if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) {
hatm_free_txmbuf(sc);
continue;
}
arg.pti = mtod(m, u_char *)[3] & 0xf;
arg.pti = ((arg.pti & 0xe) << 2) | ((arg.pti & 1) << 1);
m_adj(m, 4);
len -= 4;
if (len % 48 != 0) {
m_adj(m, -((int)(len % 48)));
len -= len % 48;
}
}
#ifdef ENABLE_BPF
if (!(arg.vcc->param.flags & ATMIO_FLAG_NG) &&
(arg.vcc->param.aal == ATMIO_AAL_5) &&
(arg.vcc->param.flags & ATM_PH_LLCSNAP))
BPF_MTAP(ifp, m);
#endif
/* Now load a DMA map with the packet. Allocate the first
* TPD to get a map. Additional TPDs may be allocated by the
* callback. */
if ((tpd = hatm_alloc_tpd(sc, M_NOWAIT)) == NULL) {
hatm_free_txmbuf(sc);
m_freem(m);
if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
continue;
}
tpd->cid = cid;
tpd->tpd.addr |= arg.pti;
arg.first = tpd;
arg.error = 0;
arg.mbuf = m;
error = bus_dmamap_load_mbuf(sc->tx_tag, tpd->map, m,
hatm_load_txbuf, &arg, BUS_DMA_NOWAIT);
if (error == EFBIG) {
/* try to defragment the packet */
sc->istats.defrag++;
m = m_defrag(m, M_NOWAIT);
if (m == NULL) {
tpd->mbuf = NULL;
hatm_free_txmbuf(sc);
hatm_free_tpd(sc, tpd);
if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
continue;
}
arg.mbuf = m;
error = bus_dmamap_load_mbuf(sc->tx_tag, tpd->map, m,
hatm_load_txbuf, &arg, BUS_DMA_NOWAIT);
}
if (error != 0) {
if_printf(sc->ifp, "mbuf loaded error=%d\n",
error);
hatm_free_tpd(sc, tpd);
if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
continue;
}
if (arg.error) {
hatm_free_tpd(sc, tpd);
if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
continue;
}
arg.vcc->opackets++;
arg.vcc->obytes += len;
if_inc_counter(sc->ifp, IFCOUNTER_OPACKETS, 1);
}
mtx_unlock(&sc->mtx);
}
void
hatm_tx_complete(struct hatm_softc *sc, struct tpd *tpd, uint32_t flags)
{
struct hevcc *vcc = sc->vccs[tpd->cid];
DBG(sc, TX, ("tx_complete cid=%#x flags=%#x", tpd->cid, flags));
if (vcc == NULL)
return;
if ((flags & HE_REGM_TBRQ_EOS) && (vcc->vflags & HE_VCC_TX_CLOSING)) {
vcc->vflags &= ~HE_VCC_TX_CLOSING;
if (vcc->param.flags & ATMIO_FLAG_ASYNC) {
hatm_tx_vcc_closed(sc, tpd->cid);
if (!(vcc->vflags & HE_VCC_OPEN)) {
hatm_vcc_closed(sc, tpd->cid);
vcc = NULL;
}
} else
cv_signal(&sc->vcc_cv);
}
hatm_free_tpd(sc, tpd);
if (vcc == NULL)
return;
vcc->ntpds--;
if ((vcc->vflags & HE_VCC_FLOW_CTRL) &&
vcc->ntpds <= HE_CONFIG_TPD_FLOW_ENB) {
vcc->vflags &= ~HE_VCC_FLOW_CTRL;
ATMEV_SEND_FLOW_CONTROL(IFP2IFATM(sc->ifp),
HE_VPI(tpd->cid), HE_VCI(tpd->cid), 0);
}
}
/*
* Convert CPS to Rate for a rate group
*/
static u_int
cps_to_rate(struct hatm_softc *sc, uint32_t cps)
{
u_int clk = sc->he622 ? HE_622_CLOCK : HE_155_CLOCK;
u_int period, rate;
/* how many double ticks between two cells */
period = (clk + 2 * cps - 1) / (2 * cps);
rate = hatm_cps2atmf(period);
if (hatm_atmf2cps(rate) < period)
rate++;
return (rate);
}
/*
* Check whether the VCC is really closed on the hardware and available for
* open. Check that we have enough resources. If this function returns ok,
* a later actual open must succeed. Assume, that we are locked between this
* function and the next one, so that nothing does change. For CBR this
* assigns the rate group and set the rate group's parameter.
*/
int
hatm_tx_vcc_can_open(struct hatm_softc *sc, u_int cid, struct hevcc *vcc)
{
uint32_t v, line_rate;
u_int rc, idx, free_idx;
struct atmio_tparam *t = &vcc->param.tparam;
/* verify that connection is closed */
#if 0
v = READ_TSR(sc, cid, 4);
if(!(v & HE_REGM_TSR4_SESS_END)) {
if_printf(sc->ifp, "cid=%#x not closed (TSR4)\n", cid);
return (EBUSY);
}
#endif
v = READ_TSR(sc, cid, 0);
if((v & HE_REGM_TSR0_CONN_STATE) != 0) {
if_printf(sc->ifp, "cid=%#x not closed (TSR0=%#x)\n",
cid, v);
return (EBUSY);
}
/* check traffic parameters */
line_rate = sc->he622 ? ATM_RATE_622M : ATM_RATE_155M;
switch (vcc->param.traffic) {
case ATMIO_TRAFFIC_UBR:
if (t->pcr == 0 || t->pcr > line_rate)
t->pcr = line_rate;
if (t->mcr != 0 || t->icr != 0 || t->tbe != 0 || t->nrm != 0 ||
t->trm != 0 || t->adtf != 0 || t->rif != 0 || t->rdf != 0 ||
t->cdf != 0)
return (EINVAL);
break;
case ATMIO_TRAFFIC_CBR:
/*
* Compute rate group index
*/
if (t->pcr < 10)
t->pcr = 10;
if (sc->cbr_bw + t->pcr > line_rate)
return (EINVAL);
if (t->mcr != 0 || t->icr != 0 || t->tbe != 0 || t->nrm != 0 ||
t->trm != 0 || t->adtf != 0 || t->rif != 0 || t->rdf != 0 ||
t->cdf != 0)
return (EINVAL);
rc = cps_to_rate(sc, t->pcr);
free_idx = HE_REGN_CS_STPER;
for (idx = 0; idx < HE_REGN_CS_STPER; idx++) {
if (sc->rate_ctrl[idx].refcnt == 0) {
if (free_idx == HE_REGN_CS_STPER)
free_idx = idx;
} else {
if (sc->rate_ctrl[idx].rate == rc)
break;
}
}
if (idx == HE_REGN_CS_STPER) {
if ((idx = free_idx) == HE_REGN_CS_STPER)
return (EBUSY);
sc->rate_ctrl[idx].rate = rc;
}
vcc->rc = idx;
/* commit */
sc->rate_ctrl[idx].refcnt++;
sc->cbr_bw += t->pcr;
break;
case ATMIO_TRAFFIC_ABR:
if (t->pcr > line_rate)
t->pcr = line_rate;
if (t->mcr > line_rate)
t->mcr = line_rate;
if (t->icr > line_rate)
t->icr = line_rate;
if (t->tbe == 0 || t->tbe >= 1 << 24 || t->nrm > 7 ||
t->trm > 7 || t->adtf >= 1 << 10 || t->rif > 15 ||
t->rdf > 15 || t->cdf > 7)
return (EINVAL);
break;
default:
return (EINVAL);
}
return (0);
}
#define NRM_CODE2VAL(CODE) (2 * (1 << (CODE)))
/*
* Actually open the transmit VCC
*/
void
hatm_tx_vcc_open(struct hatm_softc *sc, u_int cid)
{
struct hevcc *vcc = sc->vccs[cid];
uint32_t tsr0, tsr4, atmf, crm;
const struct atmio_tparam *t = &vcc->param.tparam;
if (vcc->param.aal == ATMIO_AAL_5) {
tsr0 = HE_REGM_TSR0_AAL_5 << HE_REGS_TSR0_AAL;
tsr4 = HE_REGM_TSR4_AAL_5 << HE_REGS_TSR4_AAL;
} else {
tsr0 = HE_REGM_TSR0_AAL_0 << HE_REGS_TSR0_AAL;
tsr4 = HE_REGM_TSR4_AAL_0 << HE_REGS_TSR4_AAL;
}
tsr4 |= 1;
switch (vcc->param.traffic) {
case ATMIO_TRAFFIC_UBR:
atmf = hatm_cps2atmf(t->pcr);
tsr0 |= HE_REGM_TSR0_TRAFFIC_UBR << HE_REGS_TSR0_TRAFFIC;
tsr0 |= HE_REGM_TSR0_USE_WMIN | HE_REGM_TSR0_UPDATE_GER;
WRITE_TSR(sc, cid, 0, 0xf, tsr0);
WRITE_TSR(sc, cid, 4, 0xf, tsr4);
WRITE_TSR(sc, cid, 1, 0xf, (atmf << HE_REGS_TSR1_PCR));
WRITE_TSR(sc, cid, 2, 0xf, (atmf << HE_REGS_TSR2_ACR));
WRITE_TSR(sc, cid, 9, 0xf, HE_REGM_TSR9_INIT);
WRITE_TSR(sc, cid, 3, 0xf, 0);
WRITE_TSR(sc, cid, 5, 0xf, 0);
WRITE_TSR(sc, cid, 6, 0xf, 0);
WRITE_TSR(sc, cid, 7, 0xf, 0);
WRITE_TSR(sc, cid, 8, 0xf, 0);
WRITE_TSR(sc, cid, 10, 0xf, 0);
WRITE_TSR(sc, cid, 11, 0xf, 0);
WRITE_TSR(sc, cid, 12, 0xf, 0);
WRITE_TSR(sc, cid, 13, 0xf, 0);
WRITE_TSR(sc, cid, 14, 0xf, 0);
break;
case ATMIO_TRAFFIC_CBR:
atmf = hatm_cps2atmf(t->pcr);
if (sc->rate_ctrl[vcc->rc].refcnt == 1)
WRITE_MBOX4(sc, HE_REGO_CS_STPER(vcc->rc),
sc->rate_ctrl[vcc->rc].rate);
tsr0 |= HE_REGM_TSR0_TRAFFIC_CBR << HE_REGS_TSR0_TRAFFIC;
tsr0 |= vcc->rc;
WRITE_TSR(sc, cid, 1, 0xf, (atmf << HE_REGS_TSR1_PCR));
WRITE_TSR(sc, cid, 2, 0xf, (atmf << HE_REGS_TSR2_ACR));
WRITE_TSR(sc, cid, 3, 0xf, 0);
WRITE_TSR(sc, cid, 5, 0xf, 0);
WRITE_TSR(sc, cid, 6, 0xf, 0);
WRITE_TSR(sc, cid, 7, 0xf, 0);
WRITE_TSR(sc, cid, 8, 0xf, 0);
WRITE_TSR(sc, cid, 10, 0xf, 0);
WRITE_TSR(sc, cid, 11, 0xf, 0);
WRITE_TSR(sc, cid, 12, 0xf, 0);
WRITE_TSR(sc, cid, 13, 0xf, 0);
WRITE_TSR(sc, cid, 14, 0xf, 0);
WRITE_TSR(sc, cid, 4, 0xf, tsr4);
WRITE_TSR(sc, cid, 9, 0xf, HE_REGM_TSR9_INIT);
WRITE_TSR(sc, cid, 0, 0xf, tsr0);
break;
case ATMIO_TRAFFIC_ABR:
if ((crm = t->tbe / NRM_CODE2VAL(t->nrm)) > 0xffff)
crm = 0xffff;
tsr0 |= HE_REGM_TSR0_TRAFFIC_ABR << HE_REGS_TSR0_TRAFFIC;
tsr0 |= HE_REGM_TSR0_USE_WMIN | HE_REGM_TSR0_UPDATE_GER;
WRITE_TSR(sc, cid, 0, 0xf, tsr0);
WRITE_TSR(sc, cid, 4, 0xf, tsr4);
WRITE_TSR(sc, cid, 1, 0xf,
((hatm_cps2atmf(t->pcr) << HE_REGS_TSR1_PCR) |
(hatm_cps2atmf(t->mcr) << HE_REGS_TSR1_MCR)));
WRITE_TSR(sc, cid, 2, 0xf,
(hatm_cps2atmf(t->icr) << HE_REGS_TSR2_ACR));
WRITE_TSR(sc, cid, 3, 0xf,
((NRM_CODE2VAL(t->nrm) - 1) << HE_REGS_TSR3_NRM) |
(crm << HE_REGS_TSR3_CRM));
WRITE_TSR(sc, cid, 5, 0xf, 0);
WRITE_TSR(sc, cid, 6, 0xf, 0);
WRITE_TSR(sc, cid, 7, 0xf, 0);
WRITE_TSR(sc, cid, 8, 0xf, 0);
WRITE_TSR(sc, cid, 10, 0xf, 0);
WRITE_TSR(sc, cid, 12, 0xf, 0);
WRITE_TSR(sc, cid, 14, 0xf, 0);
WRITE_TSR(sc, cid, 9, 0xf, HE_REGM_TSR9_INIT);
WRITE_TSR(sc, cid, 11, 0xf,
(hatm_cps2atmf(t->icr) << HE_REGS_TSR11_ICR) |
(t->trm << HE_REGS_TSR11_TRM) |
(t->nrm << HE_REGS_TSR11_NRM) |
(t->adtf << HE_REGS_TSR11_ADTF));
WRITE_TSR(sc, cid, 13, 0xf,
(t->rdf << HE_REGS_TSR13_RDF) |
(t->rif << HE_REGS_TSR13_RIF) |
(t->cdf << HE_REGS_TSR13_CDF) |
(crm << HE_REGS_TSR13_CRM));
break;
default:
return;
}
vcc->vflags |= HE_VCC_TX_OPEN;
}
/*
* Close the TX side of a VCC. Set the CLOSING flag.
*/
void
hatm_tx_vcc_close(struct hatm_softc *sc, u_int cid)
{
struct hevcc *vcc = sc->vccs[cid];
struct tpd *tpd_list[1];
u_int i, pcr = 0;
WRITE_TSR(sc, cid, 4, 0x8, HE_REGM_TSR4_FLUSH);
switch (vcc->param.traffic) {
case ATMIO_TRAFFIC_CBR:
WRITE_TSR(sc, cid, 14, 0x8, HE_REGM_TSR14_CBR_DELETE);
break;
case ATMIO_TRAFFIC_ABR:
WRITE_TSR(sc, cid, 14, 0x4, HE_REGM_TSR14_ABR_CLOSE);
pcr = vcc->param.tparam.pcr;
/* FALL THROUGH */
case ATMIO_TRAFFIC_UBR:
WRITE_TSR(sc, cid, 1, 0xf,
hatm_cps2atmf(HE_CONFIG_FLUSH_RATE) << HE_REGS_TSR1_MCR |
hatm_cps2atmf(pcr) << HE_REGS_TSR1_PCR);
break;
}
tpd_list[0] = hatm_alloc_tpd(sc, 0);
tpd_list[0]->tpd.addr |= HE_REGM_TPD_EOS | HE_REGM_TPD_INTR;
tpd_list[0]->cid = cid;
vcc->vflags |= HE_VCC_TX_CLOSING;
vcc->vflags &= ~HE_VCC_TX_OPEN;
i = 0;
while (hatm_queue_tpds(sc, 1, tpd_list, cid) != 0) {
if (++i == 1000)
panic("TPDRQ permanently full");
DELAY(1000);
}
}
void
hatm_tx_vcc_closed(struct hatm_softc *sc, u_int cid)
{
if (sc->vccs[cid]->param.traffic == ATMIO_TRAFFIC_CBR) {
sc->cbr_bw -= sc->vccs[cid]->param.tparam.pcr;
sc->rate_ctrl[sc->vccs[cid]->rc].refcnt--;
}
}

View File

@ -1,104 +0,0 @@
/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*
* Default configuration
*/
/* configuration */
#define HE_CONFIG_VPI_BITS 2
#define HE_CONFIG_VCI_BITS 10
/* interrupt group 0 only */
/* the size must be 1 <= size <= 1023 */
#define HE_CONFIG_IRQ0_SIZE 256
#define HE_CONFIG_IRQ0_THRESH 224 /* retrigger interrupt */
#define HE_CONFIG_IRQ0_LINE HE_REGM_IRQ_A /* routing */
/* don't change these */
#define HE_CONFIG_TXMEM (128 * 1024) /* words */
#define HE_CONFIG_RXMEM (64 * 1024) /* words */
#define HE_CONFIG_LCMEM (512 * 1024) /* words */
/* group 0 - all AALs except AAL.raw */
/* receive group 0 buffer pools (mbufs and mbufs+cluster) */
/* the size must be a power of 2: 4 <= size <= 8192 */
#define HE_CONFIG_RBPS0_SIZE 2048 /* entries per queue */
#define HE_CONFIG_RBPS0_THRESH 256 /* interrupt threshold */
#define HE_CONFIG_RBPL0_SIZE 512 /* entries per queue */
#define HE_CONFIG_RBPL0_THRESH 32 /* interrupt threshold */
/* receive group 0 buffer return queue */
/* the size must be a power of 2: 1 <= size <= 16384 */
#define HE_CONFIG_RBRQ0_SIZE 512 /* entries in queue */
#define HE_CONFIG_RBRQ0_THRESH 256 /* interrupt threshold */
#define HE_CONFIG_RBRQ0_TOUT 10 /* interrupt timeout */
#define HE_CONFIG_RBRQ0_PCNT 5 /* packet count threshold */
/* group 1 - raw cells */
/* receive group 1 small buffer pool */
/* the size must be a power of 2: 4 <= size <= 8192 */
#define HE_CONFIG_RBPS1_SIZE 1024 /* entries in queue */
#define HE_CONFIG_RBPS1_THRESH 512 /* interrupt threshold */
/* receive group 1 buffer return queue */
/* the size must be a power of 2: 1 <= size <= 16384 */
#define HE_CONFIG_RBRQ1_SIZE 512 /* entries in queue */
#define HE_CONFIG_RBRQ1_THRESH 256 /* interrupt threshold */
#define HE_CONFIG_RBRQ1_TOUT 100 /* interrupt timeout */
#define HE_CONFIG_RBRQ1_PCNT 25 /* packet count threshold */
/* there is only one TPD queue */
/* the size must be a power of 2: 1 <= size <= 4096 */
#define HE_CONFIG_TPDRQ_SIZE 2048 /* entries in queue */
/* transmit group 0 */
/* the size must be a power of 2: 1 <= size <= 16384 */
#define HE_CONFIG_TBRQ_SIZE 512 /* entries in queue */
#define HE_CONFIG_TBRQ_THRESH 400 /* interrupt threshold */
/* Maximum number of TPDs to allocate to a single VCC. This
* number should depend on the cell rate and the maximum allowed cell delay */
#define HE_CONFIG_TPD_MAXCC 2048
/* Maximum number of external mbuf pages */
#define HE_CONFIG_MAX_MBUF_PAGES 256
/* Maximum number of TPDs used for one packet */
#define HE_CONFIG_MAX_TPD_PER_PACKET \
((((HE_MAX_PDU + MCLBYTES - 1) / MCLBYTES + 2) / 3) + 2)
/* Number of TPDs to reserve for close operations */
#define HE_CONFIG_TPD_RESERVE 32
/* Number of TPDs per VCC when to re-enable flow control */
#define HE_CONFIG_TPD_FLOW_ENB 80
/* MCR for flushing CBR and ABR connections at close */
#define HE_CONFIG_FLUSH_RATE 200000

View File

@ -1,641 +0,0 @@
/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*
* Fore HE driver for NATM
*/
/* check configuration */
#if HE_CONFIG_VPI_BITS + HE_CONFIG_VCI_BITS > 12
#error "hatm: too many bits configured for VPI/VCI"
#endif
#define HE_MAX_VCCS (1 << (HE_CONFIG_VPI_BITS + HE_CONFIG_VCI_BITS))
#define HE_VPI_MASK ((1 << (HE_CONFIG_VPI_BITS))-1)
#define HE_VCI_MASK ((1 << (HE_CONFIG_VCI_BITS))-1)
#define HE_VPI(CID) (((CID) >> HE_CONFIG_VCI_BITS) & HE_VPI_MASK)
#define HE_VCI(CID) ((CID) & HE_VCI_MASK)
#define HE_CID(VPI,VCI) ((((VPI) & HE_VPI_MASK) << HE_CONFIG_VCI_BITS) | \
((VCI) & HE_VCI_MASK))
/* GEN_CNTL_0 register */
#define HE_PCIR_GEN_CNTL_0 0x40
#define HE_PCIM_CTL0_64BIT (1 << 0)
#define HE_PCIM_CTL0_IGNORE_TIMEOUT (1 << 1)
#define HE_PCIM_CTL0_INIT_ENB (1 << 2)
#define HE_PCIM_CTL0_MRM (1 << 4)
#define HE_PCIM_CTL0_MRL (1 << 5)
#define HE_PCIM_CTL0_BIGENDIAN (1 << 16)
#define HE_PCIM_CTL0_INT_PROC_ENB (1 << 25)
/*
* Memory registers
*/
#define HE_REGO_FLASH 0x00000
#define HE_REGO_RESET_CNTL 0x80000
#define HE_REGM_RESET_STATE (1 << 6)
#define HE_REGO_HOST_CNTL 0x80004
#define HE_REGM_HOST_BUS64 (1 << 27)
#define HE_REGM_HOST_DESC_RD64 (1 << 26)
#define HE_REGM_HOST_DATA_RD64 (1 << 25)
#define HE_REGM_HOST_DATA_WR64 (1 << 24)
#define HE_REGM_HOST_PROM_SEL (1 << 12)
#define HE_REGM_HOST_PROM_WREN (1 << 11)
#define HE_REGM_HOST_PROM_DATA_OUT (1 << 10)
#define HE_REGS_HOST_PROM_DATA_OUT 10
#define HE_REGM_HOST_PROM_DATA_IN (1 << 9)
#define HE_REGS_HOST_PROM_DATA_IN 9
#define HE_REGM_HOST_PROM_CLOCK (1 << 8)
#define HE_REGM_HOST_PROM_BITS (0x00001f00)
#define HE_REGM_HOST_QUICK_RD (1 << 7)
#define HE_REGM_HOST_QUICK_WR (1 << 6)
#define HE_REGM_HOST_OUTFF_ENB (1 << 5)
#define HE_REGM_HOST_CMDFF_ENB (1 << 4)
#define HE_REGO_LB_SWAP 0x80008
#define HE_REGM_LBSWAP_RNUM (0xf << 27)
#define HE_REGS_LBSWAP_RNUM 27
#define HE_REGM_LBSWAP_DATA_WR_SWAP (1 << 20)
#define HE_REGM_LBSWAP_DESC_RD_SWAP (1 << 19)
#define HE_REGM_LBSWAP_DATA_RD_SWAP (1 << 18)
#define HE_REGM_LBSWAP_INTR_SWAP (1 << 17)
#define HE_REGM_LBSWAP_DESC_WR_SWAP (1 << 16)
#define HE_REGM_LBSWAP_BIG_ENDIAN (1 << 14)
#define HE_REGM_LBSWAP_XFER_SIZE (1 << 7)
#define HE_REGO_LB_MEM_ADDR 0x8000C
#define HE_REGO_LB_MEM_DATA 0x80010
#define HE_REGO_LB_MEM_ACCESS 0x80014
#define HE_REGM_LB_MEM_HNDSHK (1 << 30)
#define HE_REGM_LB_MEM_READ 0x3
#define HE_REGM_LB_MEM_WRITE 0x7
#define HE_REGO_SDRAM_CNTL 0x80018
#define HE_REGM_SDRAM_64BIT (1 << 3)
#define HE_REGO_INT_FIFO 0x8001C
#define HE_REGM_INT_FIFO_CLRA (1 << 8)
#define HE_REGM_INT_FIFO_CLRB (1 << 9)
#define HE_REGM_INT_FIFO_CLRC (1 << 10)
#define HE_REGM_INT_FIFO_CLRD (1 << 11)
#define HE_REGO_ABORT_ADDR 0x80020
#define HE_REGO_IRQ0_BASE 0x80080
#define HE_REGO_IRQ_BASE(Q) (HE_REGO_IRQ0_BASE + (Q) * 0x10 + 0x00)
#define HE_REGM_IRQ_BASE_TAIL 0x3ff
#define HE_REGO_IRQ_HEAD(Q) (HE_REGO_IRQ0_BASE + (Q) * 0x10 + 0x04)
#define HE_REGS_IRQ_HEAD_SIZE 22
#define HE_REGS_IRQ_HEAD_THRESH 12
#define HE_REGS_IRQ_HEAD_HEAD 2
#define HE_REGO_IRQ_CNTL(Q) (HE_REGO_IRQ0_BASE + (Q) * 0x10 + 0x08)
#define HE_REGM_IRQ_A (0 << 2)
#define HE_REGM_IRQ_B (1 << 2)
#define HE_REGM_IRQ_C (2 << 2)
#define HE_REGM_IRQ_D (3 << 2)
#define HE_REGO_IRQ_DATA(Q) (HE_REGO_IRQ0_BASE + (Q) * 0x10 + 0x0C)
#define HE_REGO_GRP_1_0_MAP 0x800C0
#define HE_REGO_GRP_3_2_MAP 0x800C4
#define HE_REGO_GRP_5_4_MAP 0x800C8
#define HE_REGO_GRP_7_6_MAP 0x800CC
/*
* Receive buffer pools
*/
#define HE_REGO_G0_RBPS_S 0x80400
#define HE_REGO_G0_RBPS_T 0x80404
#define HE_REGO_G0_RBPS_QI 0x80408
#define HE_REGO_G0_RBPS_BL 0x8040C
#define HE_REGO_RBP_S(K,G) (HE_REGO_G0_RBPS_S + (K) * 0x10 + (G) * 0x20)
#define HE_REGO_RBP_T(K,G) (HE_REGO_G0_RBPS_T + (K) * 0x10 + (G) * 0x20)
#define HE_REGO_RBP_QI(K,G) (HE_REGO_G0_RBPS_QI + (K) * 0x10 + (G) * 0x20)
#define HE_REGO_RBP_BL(K,G) (HE_REGO_G0_RBPS_BL + (K) * 0x10 + (G) * 0x20)
#define HE_REGS_RBP_HEAD 3
#define HE_REGS_RBP_TAIL 3
#define HE_REGS_RBP_SIZE 14
#define HE_REGM_RBP_INTR_ENB (1 << 13)
#define HE_REGS_RBP_THRESH 0
/*
* Receive buffer return queues
*/
#define HE_REGO_G0_RBRQ_ST 0x80500
#define HE_REGO_G0_RBRQ_H 0x80504
#define HE_REGO_G0_RBRQ_Q 0x80508
#define HE_REGO_G0_RBRQ_I 0x8050C
#define HE_REGO_RBRQ_ST(G) (HE_REGO_G0_RBRQ_ST + (G) * 0x10)
#define HE_REGO_RBRQ_H(G) (HE_REGO_G0_RBRQ_H + (G) * 0x10)
#define HE_REGO_RBRQ_Q(G) (HE_REGO_G0_RBRQ_Q + (G) * 0x10)
#define HE_REGO_RBRQ_I(G) (HE_REGO_G0_RBRQ_I + (G) * 0x10)
#define HE_REGS_RBRQ_HEAD 3
#define HE_REGS_RBRQ_THRESH 13
#define HE_REGS_RBRQ_SIZE 0
#define HE_REGS_RBRQ_TIME 8
#define HE_REGS_RBRQ_COUNT 0
/*
* Intermediate queues
*/
#define HE_REGO_G0_INMQ_S 0x80580
#define HE_REGO_G0_INMQ_L 0x80584
#define HE_REGO_INMQ_S(G) (HE_REGO_G0_INMQ_S + (G) * 8)
#define HE_REGO_INMQ_L(G) (HE_REGO_G0_INMQ_L + (G) * 8)
#define HE_REGO_RHCONFIG 0x805C0
#define HE_REGM_RHCONFIG_PHYENB (1 << 10)
#define HE_REGS_RHCONFIG_OAM_GID 7
#define HE_REGS_RHCONFIG_PTMR_PRE 0
/*
* Transmit buffer return queues
*/
#define HE_REGO_TBRQ0_B_T 0x80600
#define HE_REGO_TBRQ0_H 0x80604
#define HE_REGO_TBRQ0_S 0x80608
#define HE_REGO_TBRQ0_THRESH 0x8060C
#define HE_REGO_TBRQ_B_T(G) (HE_REGO_TBRQ0_B_T + (G) * 0x10)
#define HE_REGO_TBRQ_H(G) (HE_REGO_TBRQ0_H + (G) * 0x10)
#define HE_REGO_TBRQ_S(G) (HE_REGO_TBRQ0_S + (G) * 0x10)
#define HE_REGO_TBRQ_THRESH(G) (HE_REGO_TBRQ0_THRESH + (G) * 0x10)
#define HE_REGS_TBRQ_HEAD 2
/*
* Transmit packet descriptor ready queue
*/
#define HE_REGO_TPDRQ_H 0x80680
#define HE_REGS_TPDRQ_H_H 3
/* #define HE_REGM_TPDRQ_H_H ((HE_CONFIG_TPDRQ_SIZE - 1) << 3) */
#define HE_REGO_TPDRQ_T 0x80684
#define HE_REGS_TPDRQ_T_T 3
/* #define HE_REGM_TPDRQ_T_T ((HE_CONFIG_TPDRQ_SIZE - 1) << 3) */
#define HE_REGO_TPDRQ_S 0x80688
#define HE_REGO_UBUFF_BA 0x8068C
#define HE_REGO_RLBF0_H 0x806C0
#define HE_REGO_RLBF0_T 0x806C4
#define HE_REGO_RLBF1_H 0x806C8
#define HE_REGO_RLBF1_T 0x806CC
#define HE_REGO_RLBF_H(N) (HE_REGO_RLBF0_H + (N) * 8)
#define HE_REGO_RLBF_T(N) (HE_REGO_RLBF0_T + (N) * 8)
#define HE_REGO_RLBC_H 0x806D0
#define HE_REGO_RLBC_T 0x806D4
#define HE_REGO_RLBC_H2 0x806D8
#define HE_REGO_TLBF_H 0x806E0
#define HE_REGO_TLBF_T 0x806E4
#define HE_REGO_RLBF0_C 0x806E8
#define HE_REGO_RLBF1_C 0x806EC
#define HE_REGO_RLBF_C(N) (HE_REGO_RLBF0_C + (N) * 4)
#define HE_REGO_RXTHRSH 0x806F0
#define HE_REGO_LITHRSH 0x806F4
#define HE_REGO_LBARB 0x80700
#define HE_REGS_LBARB_SLICE 28
#define HE_REGS_LBARB_RNUM 23
#define HE_REGS_LBARB_THPRI 21
#define HE_REGS_LBARB_RHPRI 19
#define HE_REGS_LBARB_TLPRI 17
#define HE_REGS_LBARB_RLPRI 15
#define HE_REGS_LBARB_BUS_MULT 8
#define HE_REGS_LBARB_NET_PREF 0
#define HE_REGO_SDRAMCON 0x80704
#define HE_REGM_SDRAMCON_BANK (1 << 14)
#define HE_REGM_SDRAMCON_WIDE (1 << 13)
#define HE_REGM_SDRAMCON_TWRWAIT (1 << 12)
#define HE_REGM_SDRAMCON_TRPWAIT (1 << 11)
#define HE_REGM_SDRAMCON_TRASWAIT (1 << 10)
#define HE_REGS_SDRAMCON_REF 0
#define HE_REGO_RCCSTAT 0x8070C
#define HE_REGM_RCCSTAT_PROG (1 << 0)
#define HE_REGO_TCMCONFIG 0x80740
#define HE_REGS_TCMCONFIG_BANK_WAIT 6
#define HE_REGS_TCMCONFIG_RW_WAIT 2
#define HE_REGS_TCMCONFIG_TYPE 0
#define HE_REGO_TSRB_BA 0x80744
#define HE_REGO_TSRC_BA 0x80748
#define HE_REGO_TMABR_BA 0x8074C
#define HE_REGO_TPD_BA 0x80750
#define HE_REGO_TSRD_BA 0x80758
#define HE_REGO_TXCONFIG 0x80760
#define HE_REGS_TXCONFIG_THRESH 22
#define HE_REGM_TXCONFIG_UTMODE (1 << 21)
#define HE_REGS_TXCONFIG_VCI_MASK 17
#define HE_REGS_TXCONFIG_LBFREE 0
#define HE_REGO_TXAAL5_PROTO 0x80764
#define HE_REGO_RCMCONFIG 0x80780
#define HE_REGS_RCMCONFIG_BANK_WAIT 6
#define HE_REGS_RCMCONFIG_RW_WAIT 2
#define HE_REGS_RCMCONFIG_TYPE 0
#define HE_REGO_RCMRSRB_BA 0x80784
#define HE_REGO_RCMLBM_BA 0x80788
#define HE_REGO_RCMABR_BA 0x8078C
#define HE_REGO_RCCONFIG 0x807C0
#define HE_REGS_RCCONFIG_UTDELAY 11
#define HE_REGM_RCCONFIG_WRAP_MODE (1 << 10)
#define HE_REGM_RCCONFIG_UT_MODE (1 << 9)
#define HE_REGM_RCCONFIG_RXENB (1 << 8)
#define HE_REGS_RCCONFIG_VP 4
#define HE_REGS_RCCONFIG_VC 0
#define HE_REGO_MCC 0x807C4
#define HE_REGO_OEC 0x807C8
#define HE_REGO_DCC 0x807CC
#define HE_REGO_CEC 0x807D0
#define HE_REGO_HSP_BA 0x807F0
#define HE_REGO_LBCONFIG 0x807F4
#define HE_REGO_CON_DAT 0x807F8
#define HE_REGO_CON_CTL 0x807FC
#define HE_REGM_CON_MBOX (2U << 30)
#define HE_REGM_CON_TCM (1 << 30)
#define HE_REGM_CON_RCM (0 << 30)
#define HE_REGM_CON_WE (1 << 29)
#define HE_REGM_CON_STATUS (1 << 28)
#define HE_REGM_CON_DIS3 (1 << 22)
#define HE_REGM_CON_DIS2 (1 << 21)
#define HE_REGM_CON_DIS1 (1 << 20)
#define HE_REGM_CON_DIS0 (1 << 19)
#define HE_REGS_CON_DIS 19
#define HE_REGS_CON_ADDR 0
#define HE_REGO_SUNI 0x80800
#define HE_REGO_SUNI_END 0x80C00
#define HE_REGO_END 0x100000
/*
* MBOX registers
*/
#define HE_REGO_CS_STPER0 0x000
#define HE_REGO_CS_STPER(G) (HE_REGO_CS_STPER0 + (G))
#define HE_REGN_CS_STPER 32
#define HE_REGO_CS_STTIM0 0x020
#define HE_REGO_CS_STTIM(G) (HE_REGO_CS_STTIM0 + (G))
#define HE_REGO_CS_TGRLD0 0x040
#define HE_REGO_CS_TGRLD(G) (HE_REGO_CS_TGRLD0 + (G))
#define HE_REGO_CS_ERTHR0 0x50
#define HE_REGO_CS_ERTHR1 0x51
#define HE_REGO_CS_ERTHR2 0x52
#define HE_REGO_CS_ERTHR3 0x53
#define HE_REGO_CS_ERTHR4 0x54
#define HE_REGO_CS_ERCTL0 0x55
#define HE_REGO_CS_ERCTL1 0x56
#define HE_REGO_CS_ERCTL2 0x57
#define HE_REGO_CS_ERSTAT0 0x58
#define HE_REGO_CS_ERSTAT1 0x59
#define HE_REGO_CS_RTCCT 0x60
#define HE_REGO_CS_RTFWC 0x61
#define HE_REGO_CS_RTFWR 0x62
#define HE_REGO_CS_RTFTC 0x63
#define HE_REGO_CS_RTATR 0x64
#define HE_REGO_CS_TFBSET 0x70
#define HE_REGO_CS_TFBADD 0x71
#define HE_REGO_CS_TFBSUB 0x72
#define HE_REGO_CS_WCRMAX 0x73
#define HE_REGO_CS_WCRMIN 0x74
#define HE_REGO_CS_WCRINC 0x75
#define HE_REGO_CS_WCRDEC 0x76
#define HE_REGO_CS_WCRCEIL 0x77
#define HE_REGO_CS_BWDCNT 0x78
#define HE_REGO_CS_OTPPER 0x80
#define HE_REGO_CS_OTWPER 0x81
#define HE_REGO_CS_OTTLIM 0x82
#define HE_REGO_CS_OTTCNT 0x83
#define HE_REGO_CS_HGRRT0 0x90
#define HE_REGO_CS_HGRRT(G) (HE_REGO_CS_HGRRT0 + (G))
#define HE_REGO_CS_ORPTRS 0xA0
#define HE_REGO_RCON_CLOSE 0x100
#define HE_REGO_CS_END 0x101
#define HE_REGT_CS_ERTHR { \
{ /* 155 */ \
{ 0x000800ea, 0x000400ea, 0x000200ea }, /* ERTHR0 */ \
{ 0x000C3388, 0x00063388, 0x00033388 }, /* ERTHR1 */ \
{ 0x00101018, 0x00081018, 0x00041018 }, /* ERTHR2 */ \
{ 0x00181dac, 0x000c1dac, 0x00061dac }, /* ERTHR3 */ \
{ 0x0028051a, 0x0014051a, 0x000a051a }, /* ERTHR4 */ \
}, { /* 622 */ \
{ 0x000800fa, 0x000400fa, 0x000200fa }, /* ERTHR0 */ \
{ 0x000c33cb, 0x000633cb, 0x000333cb }, /* ERTHR1 */ \
{ 0x0010101b, 0x0008101b, 0x0004101b }, /* ERTHR2 */ \
{ 0x00181dac, 0x000c1dac, 0x00061dac }, /* ERTHR3 */ \
{ 0x00280600, 0x00140600, 0x000a0600 }, /* ERTHR4 */ \
} \
}
#define HE_REGT_CS_ERCTL { \
{ 0x0235e4b1, 0x4701, 0x64b1 }, /* 155 */ \
{ 0x023de8b3, 0x1801, 0x68b3 } /* 622 */ \
}
#define HE_REGT_CS_ERSTAT { \
{ 0x1280, 0x64b1 }, /* 155 */ \
{ 0x1280, 0x68b3 }, /* 622 */ \
}
#define HE_REGT_CS_RTFWR { \
0xf424, /* 155 */ \
0x14585 /* 622 */ \
}
#define HE_REGT_CS_RTATR { \
0x4680, /* 155 */ \
0x4680 /* 622 */ \
}
#define HE_REGT_CS_BWALLOC { \
{ 0x000563b7, 0x64b1, 0x5ab1, 0xe4b1, 0xdab1, 0x64b1 }, /* 155 */\
{ 0x00159ece, 0x68b3, 0x5eb3, 0xe8b3, 0xdeb3, 0x68b3 }, /* 622 */\
}
#define HE_REGT_CS_ORCF { \
{ 0x6, 0x1e }, /* 155 */ \
{ 0x5, 0x14 } /* 622 */ \
}
/*
* TSRs - NR is relative to the starting number of the block
*/
#define HE_REGO_TSRA(BASE,CID,NR) ((BASE) + ((CID) << 3) + (NR))
#define HE_REGO_TSRB(BASE,CID,NR) ((BASE) + ((CID) << 2) + (NR))
#define HE_REGO_TSRC(BASE,CID,NR) ((BASE) + ((CID) << 1) + (NR))
#define HE_REGO_TSRD(BASE,CID) ((BASE) + (CID))
#define HE_REGM_TSR0_CONN_STATE (7 << 28)
#define HE_REGS_TSR0_CONN_STATE 28
#define HE_REGM_TSR0_USE_WMIN (1 << 23)
#define HE_REGM_TSR0_GROUP (7 << 18)
#define HE_REGS_TSR0_GROUP 18
#define HE_REGM_TSR0_TRAFFIC (3 << 16)
#define HE_REGS_TSR0_TRAFFIC 16
#define HE_REGM_TSR0_TRAFFIC_CBR 0
#define HE_REGM_TSR0_TRAFFIC_UBR 1
#define HE_REGM_TSR0_TRAFFIC_ABR 2
#define HE_REGM_TSR0_PROT (1 << 15)
#define HE_REGM_TSR0_AAL (3 << 12)
#define HE_REGS_TSR0_AAL 12
#define HE_REGM_TSR0_AAL_5 0
#define HE_REGM_TSR0_AAL_0 1
#define HE_REGM_TSR0_AAL_0T 2
#define HE_REGM_TSR0_HALT_ER (1 << 11)
#define HE_REGM_TSR0_MARK_CI (1 << 10)
#define HE_REGM_TSR0_MARK_ER (1 << 9)
#define HE_REGM_TSR0_UPDATE_GER (1 << 8)
#define HE_REGM_TSR0_RC 0xff
#define HE_REGM_TSR1_PCR (0x7fff << 16)
#define HE_REGS_TSR1_PCR 16
#define HE_REGM_TSR1_MCR (0x7fff << 0)
#define HE_REGS_TSR1_MCR 0
#define HE_REGM_TSR2_ACR (0x7fff << 16)
#define HE_REGS_TSR2_ACR 16
#define HE_REGM_TSR3_NRM (0xff << 24)
#define HE_REGS_TSR3_NRM 24
#define HE_REGM_TSR3_CRM (0xff << 0)
#define HE_REGS_TSR3_CRM 0
#define HE_REGM_TSR4_FLUSH (1U << 31)
#define HE_REGM_TSR4_SESS_END (1 << 30)
#define HE_REGM_TSR4_OAM_CRC10 (1 << 28)
#define HE_REGM_TSR4_NULL_CRC10 (1 << 27)
#define HE_REGM_TSR4_PROT (1 << 26)
#define HE_REGM_TSR4_AAL (3 << 24)
#define HE_REGS_TSR4_AAL 24
#define HE_REGM_TSR4_AAL_5 0
#define HE_REGM_TSR4_AAL_0 1
#define HE_REGM_TSR4_AAL_0T 2
#define HE_REGM_TSR9_INIT 0x00100000
#define HE_REGM_TSR11_ICR (0x7fff << 16)
#define HE_REGS_TSR11_ICR 16
#define HE_REGM_TSR11_TRM (0x7 << 13)
#define HE_REGS_TSR11_TRM 13
#define HE_REGM_TSR11_NRM (0x7 << 10)
#define HE_REGS_TSR11_NRM 10
#define HE_REGM_TSR11_ADTF 0x3ff
#define HE_REGS_TSR11_ADTF 0
#define HE_REGM_TSR13_RDF (0xf << 23)
#define HE_REGS_TSR13_RDF 23
#define HE_REGM_TSR13_RIF (0xf << 19)
#define HE_REGS_TSR13_RIF 19
#define HE_REGM_TSR13_CDF (0x7 << 16)
#define HE_REGS_TSR13_CDF 16
#define HE_REGM_TSR13_CRM 0xffff
#define HE_REGS_TSR13_CRM 0
#define HE_REGM_TSR14_CBR_DELETE (1U << 31)
#define HE_REGM_TSR14_ABR_CLOSE (1 << 16)
/*
* RSRs
*/
#define HE_REGO_RSRA(BASE,CID,NR) ((BASE) + ((CID) << 3) + (NR))
#define HE_REGO_RSRB(BASE,CID,NR) ((BASE) + ((CID) << 1) + (NR))
#define HE_REGM_RSR0_PTI7 (1 << 15)
#define HE_REGM_RSR0_RM (1 << 14)
#define HE_REGM_RSR0_F5OAM (1 << 13)
#define HE_REGM_RSR0_STARTPDU (1 << 10)
#define HE_REGM_RSR0_OPEN (1 << 6)
#define HE_REGM_RSR0_PPD (1 << 5)
#define HE_REGM_RSR0_EPD (1 << 4)
#define HE_REGM_RSR0_TCPCS (1 << 3)
#define HE_REGM_RSR0_AAL 0x7
#define HE_REGM_RSR0_AAL_5 0x0
#define HE_REGM_RSR0_AAL_0 0x1
#define HE_REGM_RSR0_AAL_0T 0x2
#define HE_REGM_RSR0_AAL_RAW 0x3
#define HE_REGM_RSR0_AAL_RAWCRC10 0x4
#define HE_REGM_RSR1_AQI (1 << 20)
#define HE_REGM_RSR1_RBPL_ONLY (1 << 19)
#define HE_REGM_RSR1_GROUP (7 << 16)
#define HE_REGS_RSR1_GROUP 16
#define HE_REGM_RSR4_AQI (1 << 30)
#define HE_REGM_RSR4_GROUP (7 << 27)
#define HE_REGS_RSR4_GROUP 27
#define HE_REGM_RSR4_RBPL_ONLY (1 << 26)
/*
* Relative to RCMABR_BA
*/
#define HE_REGO_CM_GQTBL 0x000
#define HE_REGL_CM_GQTBL 0x100
#define HE_REGO_CM_RGTBL 0x100
#define HE_REGL_CM_RGTBL 0x100
#define HE_REGO_CM_TNRMTBL 0x200
#define HE_REGL_CM_TNRMTBL 0x100
#define HE_REGO_CM_ORCF 0x300
#define HE_REGL_CM_ORCF 0x100
#define HE_REGO_CM_RTGTBL 0x400
#define HE_REGL_CM_RTGTBL 0x200
#define HE_REGO_CM_IRCF 0x600
#define HE_REGL_CM_IRCF 0x200
/*
* Interrupt Status
*/
#define HE_REGM_ITYPE 0xf8
#define HE_REGM_IGROUP 0x07
#define HE_REGM_ITYPE_TBRQ (0x0 << 3)
#define HE_REGM_ITYPE_TPD (0x1 << 3)
#define HE_REGM_ITYPE_RBPS (0x2 << 3)
#define HE_REGM_ITYPE_RBPL (0x3 << 3)
#define HE_REGM_ITYPE_RBRQ (0x4 << 3)
#define HE_REGM_ITYPE_RBRQT (0x5 << 3)
#define HE_REGM_ITYPE_PHYS (0x6 << 3)
#define HE_REGM_ITYPE_UNKNOWN 0xf8
#define HE_REGM_ITYPE_ERR 0x80
#define HE_REGM_ITYPE_PERR 0x81
#define HE_REGM_ITYPE_ABORT 0x82
#define HE_REGM_ITYPE_INVALID 0xf8
/*
* Serial EEPROM
*/
#define HE_EEPROM_PROD_ID 0x08
#define HE_EEPROM_PROD_ID_LEN 30
#define HE_EEPROM_REV 0x26
#define HE_EEPROM_REV_LEN 4
#define HE_EEPROM_M_SN 0x3A
#define HE_EEPROM_MEDIA 0x3E
#define HE_EEPROM_MAC 0x42
#define HE_MEDIA_UTP155 0x06
#define HE_MEDIA_MMF155 0x26
#define HE_MEDIA_MMF622 0x27
#define HE_MEDIA_SMF155 0x46
#define HE_MEDIA_SMF622 0x47
#define HE_622_CLOCK 66667000
#define HE_155_CLOCK 50000000
/*
* Statistics
*/
struct fatm_statshe {
};
/*
* Queue entries
*/
/* Receive Buffer Pool Queue entry */
struct he_rbpen {
uint32_t phys; /* physical address */
uint32_t handle; /* handle or virtual address */
};
/* Receive Buffer Return Queue entry */
struct he_rbrqen {
uint32_t addr; /* handle and flags */
uint32_t len; /* length and CID */
};
#define HE_REGM_RBRQ_ADDR 0xFFFFFFC0
#define HE_REGS_RBRQ_ADDR 6
#define HE_REGM_RBRQ_FLAGS 0x0000003F
#define HE_REGM_RBRQ_HBUF_ERROR (1 << 0)
#define HE_REGM_RBRQ_CON_CLOSED (1 << 1)
#define HE_REGM_RBRQ_AAL5_PROT (1 << 2)
#define HE_REGM_RBRQ_END_PDU (1 << 3)
#define HE_REGM_RBRQ_LEN_ERROR (1 << 4)
#define HE_REGM_RBRQ_CRC_ERROR (1 << 5)
#define HE_REGM_RBRQ_CID (0x1fff << 16)
#define HE_REGS_RBRQ_CID 16
#define HE_REGM_RBRQ_LEN 0xffff
/* Transmit Packet Descriptor Ready Queue entry */
struct he_tpdrqen {
uint32_t tpd; /* physical address */
uint32_t cid; /* connection id */
};
/* Transmit buffer return queue */
struct he_tbrqen {
uint32_t addr; /* handle and flags */
};
#define HE_REGM_TBRQ_ADDR 0xffffffc0
#define HE_REGM_TBRQ_FLAGS 0x0000000a
#define HE_REGM_TBRQ_EOS 0x00000008
#define HE_REGM_TBRQ_MULT 0x00000002
struct he_tpd {
uint32_t addr; /* handle or virtual address and flags */
uint32_t res; /* reserved */
struct {
uint32_t addr; /* buffer address */
uint32_t len; /* buffer length and flags */
} bufs[3];
};
#define HE_REGM_TPD_ADDR 0xffffffC0
#define HE_REGS_TPD_ADDR 6
#define HE_REGM_TPD_INTR 0x0001
#define HE_REGM_TPD_CLP 0x0002
#define HE_REGM_TPD_EOS 0x0004
#define HE_REGM_TPD_PTI 0x0038
#define HE_REGS_TPD_PTI 3
#define HE_REGM_TPD_LST 0x80000000
/*
* The HOST STATUS PAGE
*/
struct he_hsp {
struct {
uint32_t tbrq_tail;
uint32_t res1[15];
uint32_t rbrq_tail;
uint32_t res2[15];
} group[8];
};
#define HE_MAX_PDU (65535)

View File

@ -1,640 +0,0 @@
/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*
* Fore HE driver for NATM
*/
/*
* Debug statistics of the HE driver
*/
struct istats {
uint32_t tdprq_full;
uint32_t hbuf_error;
uint32_t crc_error;
uint32_t len_error;
uint32_t flow_closed;
uint32_t flow_drop;
uint32_t tpd_no_mem;
uint32_t rx_seg;
uint32_t empty_hbuf;
uint32_t short_aal5;
uint32_t badlen_aal5;
uint32_t bug_bad_isw;
uint32_t bug_no_irq_upd;
uint32_t itype_tbrq;
uint32_t itype_tpd;
uint32_t itype_rbps;
uint32_t itype_rbpl;
uint32_t itype_rbrq;
uint32_t itype_rbrqt;
uint32_t itype_unknown;
uint32_t itype_phys;
uint32_t itype_err;
uint32_t defrag;
uint32_t mcc;
uint32_t oec;
uint32_t dcc;
uint32_t cec;
uint32_t no_rcv_mbuf;
};
/* Card memory layout parameters */
#define HE_CONFIG_MEM_LAYOUT { \
{ /* 155 */ \
20, /* cells_per_row */ \
1024, /* bytes_per_row */ \
512, /* r0_numrows */ \
1018, /* tx_numrows */ \
512, /* r1_numrows */ \
6, /* r0_startrow */ \
2 /* cells_per_lbuf */ \
}, { /* 622 */ \
40, /* cells_per_row */ \
2048, /* bytes_per_row */ \
256, /* r0_numrows */ \
512, /* tx_numrows */ \
256, /* r1_numrows */ \
0, /* r0_startrow */ \
4 /* cells_per_lbuf */ \
} \
}
/*********************************************************************/
struct hatm_softc;
/*
* A chunk of DMA-able memory
*/
struct dmamem {
u_int size; /* in bytes */
u_int align; /* alignement */
bus_dma_tag_t tag; /* DMA tag */
void *base; /* the memory */
bus_addr_t paddr; /* physical address */
bus_dmamap_t map; /* the MAP */
};
/*
* RBP (Receive Buffer Pool) queue entry and queue.
*/
struct herbp {
u_int size; /* RBP number of entries (power of two) */
u_int thresh; /* interrupt treshold */
uint32_t bsize; /* buffer size in bytes */
u_int offset; /* free space at start for small bufs */
uint32_t mask; /* mask for index */
struct dmamem mem; /* the queue area */
struct he_rbpen *rbp;
uint32_t head, tail; /* head and tail */
};
/*
* RBRQ (Receive Buffer Return Queue) entry and queue.
*/
struct herbrq {
u_int size; /* number of entries */
u_int thresh; /* interrupt threshold */
u_int tout; /* timeout value */
u_int pcnt; /* packet count threshold */
struct dmamem mem; /* memory */
struct he_rbrqen *rbrq;
uint32_t head; /* driver end */
};
/*
* TPDRQ (Transmit Packet Descriptor Ready Queue) entry and queue
*/
struct hetpdrq {
u_int size; /* number of entries */
struct dmamem mem; /* memory */
struct he_tpdrqen *tpdrq;
u_int head; /* head (copy of adapter) */
u_int tail; /* written back to adapter */
};
/*
* TBRQ (Transmit Buffer Return Queue) entry and queue
*/
struct hetbrq {
u_int size; /* number of entries */
u_int thresh; /* interrupt threshold */
struct dmamem mem; /* memory */
struct he_tbrqen *tbrq;
u_int head; /* adapter end */
};
/*==================================================================*/
/*
* TPDs are 32 byte and must be aligned on 64 byte boundaries. That means,
* that half of the space is free. We use this space to plug in a link for
* the list of free TPDs. Note, that the m_act member of the mbufs contain
* a pointer to the dmamap.
*
* The maximum number of TDPs is the size of the common transmit packet
* descriptor ready queue plus the sizes of the transmit buffer return queues
* (currently only queue 0). We allocate and map these TPD when initializing
* the card. We also allocate on DMA map for each TPD. Only the map in the
* last TPD of a packets is used when a packet is transmitted.
* This is signalled by having the mbuf member of this TPD non-zero and
* pointing to the mbuf.
*/
#define HE_TPD_SIZE 64
struct tpd {
struct he_tpd tpd; /* at beginning */
SLIST_ENTRY(tpd) link; /* free cid list link */
struct mbuf *mbuf; /* the buf chain */
bus_dmamap_t map; /* map */
uint32_t cid; /* CID */
uint16_t no; /* number of this tpd */
};
SLIST_HEAD(tpd_list, tpd);
#define TPD_SET_USED(SC, I) do { \
(SC)->tpd_used[(I) / 8] |= (1 << ((I) % 8)); \
} while (0)
#define TPD_CLR_USED(SC, I) do { \
(SC)->tpd_used[(I) / 8] &= ~(1 << ((I) % 8)); \
} while (0)
#define TPD_TST_USED(SC, I) ((SC)->tpd_used[(I) / 8] & (1 << ((I) % 8)))
#define TPD_ADDR(SC, I) ((struct tpd *)((char *)sc->tpds.base + \
(I) * HE_TPD_SIZE))
/*==================================================================*/
/*
* External MBUFs. The card needs a lot of mbufs in the pools for high
* performance. The problem with using mbufs directly is that we would need
* a dmamap for each of the mbufs. This can exhaust iommu space on the sparc
* and it eats also a lot of processing time. So we use external mbufs
* for the small buffers and clusters for the large buffers.
* For receive group 0 we use 5 ATM cells, for group 1 one (52 byte) ATM
* cell. The mbuf storage is allocated pagewise and one dmamap is used per
* page.
*
* The handle we give to the card for the small buffers is a word combined
* of the page number and the number of the chunk in the page. This restricts
* the number of chunks per page to 256 (8 bit) and the number of pages to
* 65536 (16 bits).
*
* A chunk may be in one of three states: free, on the card and floating around
* in the system. If it is free, it is on one of the two free lists and
* start with a struct mbufx_free. Each page has a bitmap that tracks where
* its chunks are.
*
* For large buffers we use mbuf clusters. Here we have two problems: we need
* to track the buffers on the card (in the case we want to stop it) and
* we need to map the 64bit mbuf address to a 26bit handle for 64-bit machines.
* The card uses the buffers in the order we give it to the card. Therefor
* we can use a private array holding pointers to the mbufs as a circular
* queue for both tasks. This is done with the lbufs member of softc. The
* handle for these buffer is the lbufs index ored with a flag.
*/
/* data space in each external mbuf */
#define MBUF0_SIZE (5 * 48) /* 240 */
#define MBUF1_SIZE (52) /* 1 raw cell */
/* size of the buffer. Must fit data, offset and header */
#define MBUF0_CHUNK 256 /* 16 free bytes */
#define MBUF1_CHUNK 96 /* 44 free bytes */
/* start of actual data in buffer */
#define MBUF0_OFFSET 0
#define MBUF1_OFFSET 16
#define MBUFL_OFFSET 16 /* two pointers for HARP */
#if PAGE_SIZE > 8192
#define MBUF_ALLOC_SIZE (8192)
#else
#define MBUF_ALLOC_SIZE (PAGE_SIZE)
#endif
/* each allocated page has one of these structures at its very end. */
struct mbuf_page_hdr {
uint16_t nchunks; /* chunks on this page */
bus_dmamap_t map; /* the DMA MAP */
uint32_t phys; /* physical base address */
uint32_t hdroff; /* chunk header offset */
uint32_t chunksize; /* chunk size */
u_int pool; /* pool number */
};
struct mbuf_page {
char storage[MBUF_ALLOC_SIZE - sizeof(struct mbuf_page_hdr)];
struct mbuf_page_hdr hdr;
};
/* numbers per page */
#define MBUF0_PER_PAGE ((MBUF_ALLOC_SIZE - sizeof(struct mbuf_page_hdr)) / \
MBUF0_CHUNK)
#define MBUF1_PER_PAGE ((MBUF_ALLOC_SIZE - sizeof(struct mbuf_page_hdr)) / \
MBUF1_CHUNK)
/*
* Convert to/from handles
*/
/* small buffers */
#define MBUF_MAKE_HANDLE(PAGENO, CHUNKNO) \
((((PAGENO) << 10) | (CHUNKNO)) << HE_REGS_RBRQ_ADDR)
#define MBUF_MAKE_LHANDLE(INDEX) \
(MBUF_LARGE_FLAG | ((INDEX) << HE_REGS_RBRQ_ADDR))
/* large buffers */
#define MBUF_PARSE_HANDLE(HANDLE, PAGENO, CHUNKNO) do { \
(CHUNKNO) = ((HANDLE) >> HE_REGS_RBRQ_ADDR) & 0x3ff; \
(PAGENO) = (((HANDLE) >> 10) >> HE_REGS_RBRQ_ADDR) & 0x3fff; \
} while (0)
#define MBUF_PARSE_LHANDLE(HANDLE, INDEX) do { \
(INDEX) = ((HANDLE) >> HE_REGS_RBRQ_ADDR) & 0xffffff; \
} while (0)
#define MBUF_LARGE_FLAG 0x80000000
/* chunks have the following structure at the end (8 byte) */
struct mbuf_chunk_hdr {
uint16_t pageno;
uint8_t chunkno;
uint8_t flags;
u_int ref_cnt;
};
#define MBUF_CARD 0x01 /* buffer is on card */
#define MBUF_USED 0x02 /* buffer is somewhere in the system */
#define MBUFX_STORAGE_SIZE(X) (MBUF##X##_CHUNK \
- sizeof(struct mbuf_chunk_hdr))
struct mbuf0_chunk {
char storage[MBUFX_STORAGE_SIZE(0)];
struct mbuf_chunk_hdr hdr;
};
struct mbuf1_chunk {
char storage[MBUFX_STORAGE_SIZE(1)];
struct mbuf_chunk_hdr hdr;
};
struct mbufx_free {
struct mbufx_free *link;
};
/*==================================================================*/
/*
* Interrupt queue
*/
struct heirq {
u_int size; /* number of entries */
u_int thresh; /* re-interrupt threshold */
u_int line; /* interrupt line to use */
struct dmamem mem; /* interrupt queues */
uint32_t * irq; /* interrupt queue */
uint32_t head; /* head index */
uint32_t * tailp; /* pointer to tail */
struct hatm_softc *sc; /* back pointer */
u_int group; /* interrupt group */
};
/*
* This structure describes all information for a VCC open on the card.
* The array of these structures is indexed by the compressed connection ID
* (CID). This structure must begin with the atmio_vcc.
*/
struct hevcc {
struct atmio_vcc param; /* traffic parameters */
void * rxhand; /* NATM protocol block */
u_int vflags; /* private flags */
uint32_t ipackets;
uint32_t opackets;
uint32_t ibytes;
uint32_t obytes;
u_int rc; /* rate control group for CBR */
struct mbuf * chain; /* partial received PDU */
struct mbuf * last; /* last mbuf in chain */
u_int ntpds; /* number of active TPDs */
};
#define HE_VCC_OPEN 0x000f0000
#define HE_VCC_RX_OPEN 0x00010000
#define HE_VCC_RX_CLOSING 0x00020000
#define HE_VCC_TX_OPEN 0x00040000
#define HE_VCC_TX_CLOSING 0x00080000
#define HE_VCC_FLOW_CTRL 0x00100000
/*
* CBR rate groups
*/
struct herg {
u_int refcnt; /* how many connections reference this group */
u_int rate; /* the value */
};
/*
* Softc
*/
struct hatm_softc {
struct ifnet *ifp;
struct mtx mtx; /* lock */
struct ifmedia media; /* media */
device_t dev; /* device */
int memid; /* resoure id for memory */
struct resource * memres; /* memory resource */
bus_space_handle_t memh; /* handle */
bus_space_tag_t memt; /* ... and tag */
bus_dma_tag_t parent_tag; /* global restriction */
struct cv vcc_cv; /* condition variable */
int irqid; /* resource id */
struct resource * irqres; /* resource */
void * ih; /* interrupt handle */
struct utopia utopia; /* utopia state */
/* rest has to be reset by stop */
int he622; /* this is a HE622 */
int pci64; /* 64bit bus */
char prod_id[HE_EEPROM_PROD_ID_LEN + 1];
char rev[HE_EEPROM_REV_LEN + 1];
struct heirq irq_0; /* interrupt queues 0 */
/* generic network controller state */
u_int cells_per_row;
u_int bytes_per_row;
u_int r0_numrows;
u_int tx_numrows;
u_int r1_numrows;
u_int r0_startrow;
u_int tx_startrow;
u_int r1_startrow;
u_int cells_per_lbuf;
u_int r0_numbuffs;
u_int r1_numbuffs;
u_int tx_numbuffs;
/* HSP */
struct he_hsp *hsp;
struct dmamem hsp_mem;
/*** TX ***/
struct hetbrq tbrq; /* TBRQ 0 */
struct hetpdrq tpdrq; /* TPDRQ */
struct tpd_list tpd_free; /* Free TPDs */
u_int tpd_nfree; /* number of free TPDs */
u_int tpd_total; /* total TPDs */
uint8_t *tpd_used; /* bitmap of used TPDs */
struct dmamem tpds; /* TPD memory */
bus_dma_tag_t tx_tag; /* DMA tag for all tx mbufs */
/*** RX ***/
/* receive/transmit groups */
struct herbp rbp_s0; /* RBPS0 */
struct herbp rbp_l0; /* RBPL0 */
struct herbp rbp_s1; /* RBPS1 */
struct herbrq rbrq_0; /* RBRQ0 */
struct herbrq rbrq_1; /* RBRQ1 */
/* list of external mbuf storage */
bus_dma_tag_t mbuf_tag;
struct mbuf_page **mbuf_pages;
u_int mbuf_npages;
u_int mbuf_max_pages;
struct mbufx_free *mbuf_list[2];
/* mbuf cluster tracking and mapping for group 0 */
struct mbuf **lbufs; /* mbufs */
bus_dmamap_t *rmaps; /* DMA maps */
u_int lbufs_size;
u_int lbufs_next;
/* VCCs */
struct hevcc *vccs[HE_MAX_VCCS];
u_int cbr_bw; /* BW allocated to CBR */
u_int max_tpd; /* per VCC */
u_int open_vccs;
uma_zone_t vcc_zone;
/* rate groups */
struct herg rate_ctrl[HE_REGN_CS_STPER];
/* memory offsets */
u_int tsrb, tsrc, tsrd;
u_int rsrb;
struct cv cv_rcclose; /* condition variable */
uint32_t rate_grid[16][16]; /* our copy */
/* sysctl support */
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
/* internal statistics */
struct istats istats;
u_int mpsafe;
#ifdef HATM_DEBUG
/* debugging */
u_int debug;
/* transmit mbuf count */
int txmbuf;
#endif
};
#define READ4(SC,OFF) bus_space_read_4(SC->memt, SC->memh, (OFF))
#define READ2(SC,OFF) bus_space_read_2(SC->memt, SC->memh, (OFF))
#define READ1(SC,OFF) bus_space_read_1(SC->memt, SC->memh, (OFF))
#define WRITE4(SC,OFF,VAL) bus_space_write_4(SC->memt, SC->memh, (OFF), (VAL))
#define WRITE2(SC,OFF,VAL) bus_space_write_2(SC->memt, SC->memh, (OFF), (VAL))
#define WRITE1(SC,OFF,VAL) bus_space_write_1(SC->memt, SC->memh, (OFF), (VAL))
#define BARRIER_R(SC) bus_space_barrier(SC->memt, SC->memh, 0, HE_REGO_END, \
BUS_SPACE_BARRIER_READ)
#define BARRIER_W(SC) bus_space_barrier(SC->memt, SC->memh, 0, HE_REGO_END, \
BUS_SPACE_BARRIER_WRITE)
#define BARRIER_RW(SC) bus_space_barrier(SC->memt, SC->memh, 0, HE_REGO_END, \
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
#define READ_SUNI(SC,OFF) READ4(SC, HE_REGO_SUNI + 4 * (OFF))
#define WRITE_SUNI(SC,OFF,VAL) WRITE4(SC, HE_REGO_SUNI + 4 * (OFF), (VAL))
#define READ_LB4(SC,OFF) \
({ \
WRITE4(SC, HE_REGO_LB_MEM_ADDR, (OFF)); \
WRITE4(SC, HE_REGO_LB_MEM_ACCESS, \
(HE_REGM_LB_MEM_HNDSHK | HE_REGM_LB_MEM_READ)); \
while((READ4(SC, HE_REGO_LB_MEM_ACCESS) & HE_REGM_LB_MEM_HNDSHK))\
; \
READ4(SC, HE_REGO_LB_MEM_DATA); \
})
#define WRITE_LB4(SC,OFF,VAL) \
do { \
WRITE4(SC, HE_REGO_LB_MEM_ADDR, (OFF)); \
WRITE4(SC, HE_REGO_LB_MEM_DATA, (VAL)); \
WRITE4(SC, HE_REGO_LB_MEM_ACCESS, \
(HE_REGM_LB_MEM_HNDSHK | HE_REGM_LB_MEM_WRITE)); \
while((READ4(SC, HE_REGO_LB_MEM_ACCESS) & HE_REGM_LB_MEM_HNDSHK))\
; \
} while(0)
#define WRITE_MEM4(SC,OFF,VAL,SPACE) \
do { \
WRITE4(SC, HE_REGO_CON_DAT, (VAL)); \
WRITE4(SC, HE_REGO_CON_CTL, \
(SPACE | HE_REGM_CON_WE | HE_REGM_CON_STATUS | (OFF))); \
while((READ4(SC, HE_REGO_CON_CTL) & HE_REGM_CON_STATUS) != 0) \
; \
} while(0)
#define READ_MEM4(SC,OFF,SPACE) \
({ \
WRITE4(SC, HE_REGO_CON_CTL, \
(SPACE | HE_REGM_CON_STATUS | (OFF))); \
while((READ4(SC, HE_REGO_CON_CTL) & HE_REGM_CON_STATUS) != 0) \
; \
READ4(SC, HE_REGO_CON_DAT); \
})
#define WRITE_TCM4(SC,OFF,VAL) WRITE_MEM4(SC,(OFF),(VAL),HE_REGM_CON_TCM)
#define WRITE_RCM4(SC,OFF,VAL) WRITE_MEM4(SC,(OFF),(VAL),HE_REGM_CON_RCM)
#define WRITE_MBOX4(SC,OFF,VAL) WRITE_MEM4(SC,(OFF),(VAL),HE_REGM_CON_MBOX)
#define READ_TCM4(SC,OFF) READ_MEM4(SC,(OFF),HE_REGM_CON_TCM)
#define READ_RCM4(SC,OFF) READ_MEM4(SC,(OFF),HE_REGM_CON_RCM)
#define READ_MBOX4(SC,OFF) READ_MEM4(SC,(OFF),HE_REGM_CON_MBOX)
#define WRITE_TCM(SC,OFF,BYTES,VAL) \
WRITE_MEM4(SC,(OFF) | ((~(BYTES) & 0xf) << HE_REGS_CON_DIS), \
(VAL), HE_REGM_CON_TCM)
#define WRITE_RCM(SC,OFF,BYTES,VAL) \
WRITE_MEM4(SC,(OFF) | ((~(BYTES) & 0xf) << HE_REGS_CON_DIS), \
(VAL), HE_REGM_CON_RCM)
#define READ_TSR(SC,CID,NR) \
({ \
uint32_t _v; \
if((NR) <= 7) { \
_v = READ_TCM4(SC, HE_REGO_TSRA(0,CID,NR)); \
} else if((NR) <= 11) { \
_v = READ_TCM4(SC, HE_REGO_TSRB((SC)->tsrb,CID,(NR-8)));\
} else if((NR) <= 13) { \
_v = READ_TCM4(SC, HE_REGO_TSRC((SC)->tsrc,CID,(NR-12)));\
} else { \
_v = READ_TCM4(SC, HE_REGO_TSRD((SC)->tsrd,CID)); \
} \
_v; \
})
#define WRITE_TSR(SC,CID,NR,BEN,VAL) \
do { \
if((NR) <= 7) { \
WRITE_TCM(SC, HE_REGO_TSRA(0,CID,NR),BEN,VAL); \
} else if((NR) <= 11) { \
WRITE_TCM(SC, HE_REGO_TSRB((SC)->tsrb,CID,(NR-8)),BEN,VAL);\
} else if((NR) <= 13) { \
WRITE_TCM(SC, HE_REGO_TSRC((SC)->tsrc,CID,(NR-12)),BEN,VAL);\
} else { \
WRITE_TCM(SC, HE_REGO_TSRD((SC)->tsrd,CID),BEN,VAL); \
} \
} while(0)
#define READ_RSR(SC,CID,NR) \
({ \
uint32_t _v; \
if((NR) <= 7) { \
_v = READ_RCM4(SC, HE_REGO_RSRA(0,CID,NR)); \
} else { \
_v = READ_RCM4(SC, HE_REGO_RSRB((SC)->rsrb,CID,(NR-8)));\
} \
_v; \
})
#define WRITE_RSR(SC,CID,NR,BEN,VAL) \
do { \
if((NR) <= 7) { \
WRITE_RCM(SC, HE_REGO_RSRA(0,CID,NR),BEN,VAL); \
} else { \
WRITE_RCM(SC, HE_REGO_RSRB((SC)->rsrb,CID,(NR-8)),BEN,VAL);\
} \
} while(0)
#ifdef HATM_DEBUG
#define DBG(SC, FL, PRINT) do { \
if((SC)->debug & DBG_##FL) { \
if_printf((SC)->ifp, "%s: ", __func__); \
printf PRINT; \
printf("\n"); \
} \
} while (0)
enum {
DBG_DUMMY = 0x0001, /* default value for -DHATM_DEBUG */
DBG_RX = 0x0002,
DBG_TX = 0x0004,
DBG_VCC = 0x0008,
DBG_IOCTL = 0x0010,
DBG_ATTACH = 0x0020,
DBG_INTR = 0x0040,
DBG_DMA = 0x0080,
DBG_DMAH = 0x0100,
DBG_DUMP = 0x0200,
DBG_ALL = 0x03ff
};
#else
#define DBG(SC, FL, PRINT)
#endif
u_int hatm_cps2atmf(uint32_t);
u_int hatm_atmf2cps(uint32_t);
void hatm_intr(void *);
int hatm_ioctl(struct ifnet *, u_long, caddr_t);
void hatm_initialize(struct hatm_softc *);
void hatm_stop(struct hatm_softc *sc);
void hatm_start(struct ifnet *);
void hatm_rx(struct hatm_softc *sc, u_int cid, u_int flags, struct mbuf *m,
u_int len);
void hatm_tx_complete(struct hatm_softc *sc, struct tpd *tpd, uint32_t);
int hatm_tx_vcc_can_open(struct hatm_softc *sc, u_int cid, struct hevcc *);
void hatm_tx_vcc_open(struct hatm_softc *sc, u_int cid);
void hatm_rx_vcc_open(struct hatm_softc *sc, u_int cid);
void hatm_tx_vcc_close(struct hatm_softc *sc, u_int cid);
void hatm_rx_vcc_close(struct hatm_softc *sc, u_int cid);
void hatm_tx_vcc_closed(struct hatm_softc *sc, u_int cid);
void hatm_vcc_closed(struct hatm_softc *sc, u_int cid);
void hatm_load_vc(struct hatm_softc *sc, u_int cid, int reopen);
void hatm_ext_free(struct mbufx_free **, struct mbufx_free *);

View File

@ -1,12 +0,0 @@
# $FreeBSD$
#
# This program is used to generate the if_patm_rtables.c file
# for the idt77252 driver. It is not installed.
#
PROG= genrtab
INTERNALPROG=
WARNS?= 5
MAN=
LIBADD= m
.include <bsd.prog.mk>

View File

@ -1,458 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* This program is used to generate the different rate tables for the IDT77252
* driver. The generated tables are slightly different from those in the
* IDT manual.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <ieeefp.h>
/* verbosity flag */
static int verbose;
/* number of table entries */
static const u_int tsize = 256;
/* number of rate difference tables to create */
static const u_int ndtables = 16;
/* cell rate offset for log 0 */
static const double offset = 10.0;
/*
* Make an internal form of the interval and be sure to round down.
*/
static u_int
d2interval(double d)
{
fp_rnd_t r;
u_int s, id;
r = fpsetround(FP_RZ);
id = (u_int)rint(32 * d);
fpsetround(r);
s = 0;
while (id >= 32 * 32) {
s++;
id >>= 1;
}
return ((s << 10) | (id));
}
/*
* Convert an internal interval back to a real one.
*/
static double
interval2d(u_int id)
{
return ((1 << ((id >> 10) & 0xf)) * ((id & 0x3ff) / 32.0));
}
/*
* Convert double to ATM-Forum format. Make sure to round up.
*/
static u_int
cps2atmf(double cps)
{
fp_rnd_t r;
u_int s, id;
if (cps < 1.0)
return (0);
s = 0;
while (cps >= 2.0) {
s++;
cps /= 2;
}
r = fpsetround(FP_RP);
id = (u_int)rint(512 * cps);
fpsetround(r);
return ((1 << 14) | (s << 9) | (id & 0x1ff));
}
/*
* Convert ATM forum format to double
*/
static double
atmf2cps(u_int atmf)
{
return (((atmf >> 14) & 1) * (1 << ((atmf >> 9) & 0x1f)) *
((512 + (atmf & 0x1ff)) / 512.0));
}
/*
* A cell rate to the logarithmic one
*/
static double
cps2log(u_int alink, double lg)
{
if (lg <= offset)
return (0);
if (lg >= alink)
return (tsize - 1);
return ((tsize - 1) * (1 - log(alink / lg) / log(alink / offset)));
}
/*
* Convert log to cell rate
*/
static double
log2cps(u_int alink, u_int lg)
{
return (alink / pow(alink / offset,
(double)(tsize - lg - 1) / (tsize - 1)));
}
/*
* Convert a double to an internal scaled double
*/
static u_int
d2ifp(double fp)
{
fp_rnd_t r;
u_int s, ifp;
fp *= (1 << 16);
r = fpsetround(FP_RN);
ifp = (u_int)rint(fp);
fpsetround(r);
s = 0;
while (ifp >= 1024) {
s++;
ifp >>= 1;
}
return ((s << 10) | (ifp));
}
/*
* Convert internal scaled float to double
*/
static double
ifp2d(u_int p)
{
return ((p & 0x3ff) * (1 << ((p >> 10) & 0xf)) / 65536.0);
}
/*
* Generate log to rate conversion table
*/
static void
gen_log2rate(u_int alink)
{
u_int i, iinterval, atmf, n, nrm;
double rate, interval, xinterval, cps, xcps;
for (i = 0; i < 256; i++) {
/* get the desired rate */
rate = alink / pow(alink / offset,
(double)(tsize - i - 1) / (tsize - 1));
/* convert this to an interval */
interval = alink / rate;
/* make the internal form of this interval, be sure to
* round down */
iinterval = d2interval(interval);
/* now convert back */
xinterval = interval2d(iinterval);
/* make a cps from this interval */
cps = alink / xinterval;
/* convert this to its ATM forum format */
atmf = cps2atmf(cps);
/* and back */
xcps = atmf2cps(atmf);
/* decide on NRM */
if (xcps < 40.0) {
nrm = 0;
n = 3;
} else if (xcps < 80.0) {
nrm = 1;
n = 4;
} else if (xcps < 160.0) {
nrm = 2;
n = 8;
} else if (xcps < 320.0) {
nrm = 3;
n = 16;
} else {
nrm = 4;
n = 32;
}
/* print */
if (verbose)
printf(" 0x%08x, /* %03u: cps=%f nrm=%u int=%f */\n",
(atmf << 17) | (nrm << 14) | iinterval, i,
xcps, n, xinterval);
else
printf("0x%08x,\n", (atmf << 17) | (nrm << 14) |
iinterval);
}
}
/*
* Generate rate to log conversion table
*/
static void
gen_rate2log(u_int alink)
{
u_int i, atmf, val, ilcr;
double cps, lcr;
fp_rnd_t r;
val = 0;
for (i = 0; i < 512; i++) {
/* make ATM Forum CPS from index */
atmf = (((i & 0x1f0) >> 4) << 9) |
((i & 0xf) << 5) | (1 << 14);
/* make cps */
cps = atmf2cps(atmf);
/* convert to log */
lcr = cps2log(alink, cps);
r = fpsetround(FP_RN);
ilcr = (u_int)rint(lcr);
fpsetround(r);
/* put together */
val |= ilcr << (8 * (i % 4));
/* print */
if (i % 4 == 3) {
if (verbose)
printf(" 0x%08x,\t", val);
else
printf("0x%08x,\n", val);
val = 0;
} else if (verbose)
printf("\t\t");
if (verbose)
printf("/* %03u: %f -> %f */\n", i,
cps, log2cps(alink, ilcr));
}
}
/*
* Generate one entry into the global table
*/
static void
gen_glob_entry(u_int alink, u_int fill, u_int ci, u_int ni)
{
if (verbose)
printf(" 0x%08x, /* %2u/32 %8.6f, %6u, ci=%u, ni=%u */\n",
cps2atmf(alink * fill / 32.0) | (ci << 17) | (ni << 16),
fill, fill / 32.0, alink * fill / 32, ci, ni);
else
printf("0x%08x,\n",
cps2atmf(alink * fill / 32.0) | (ci << 17) | (ni << 16));
}
/*
* Generate global parameter table
*/
static void
gen_glob(u_int alink)
{
u_int i;
gen_glob_entry(alink, 32, 0, 0);
gen_glob_entry(alink, 16, 0, 0);
gen_glob_entry(alink, 8, 0, 1);
gen_glob_entry(alink, 4, 0, 1);
gen_glob_entry(alink, 2, 1, 1);
gen_glob_entry(alink, 1, 1, 1);
gen_glob_entry(alink, 0, 1, 1);
gen_glob_entry(alink, 0, 1, 1);
for (i = 0; i < tsize/2 - 8; i++) {
if (i % 16 == 0)
printf(" ");
printf(" 0,");
if (i % 16 == 15)
printf("\n");
}
printf("\n");
}
/*
* Generate additive rate increase tables
*/
static void
gen_air(u_int alink)
{
u_int t, i;
double diff; /* cell rate to increase by */
double cps;
double add;
u_int val, a;
for (t = 0; t < ndtables; t++) {
diff = (double)alink / (1 << t);
printf("/* AIR %u: diff=%f */\n", t, diff);
val = 0;
for (i = 0; i < tsize; i++) {
cps = log2cps(alink, i);
cps += diff;
if (cps > alink)
cps = alink;
add = cps2log(alink, cps) - i;
a = d2ifp(add);
if (i % 2) {
val |= a << 16;
if (verbose)
printf(" 0x%08x,\t", val);
else
printf("0x%08x,\n", val);
} else {
val = a;
if (verbose)
printf("\t\t");
}
if (verbose)
printf("/* %3u: %f */\n", i, ifp2d(add));
}
}
}
/*
* Generate rate decrease table
*/
static void
gen_rdf(u_int alink)
{
double d;
u_int t, i, f, val, diff;
for (t = 0; t < ndtables; t++) {
/* compute the log index difference */
if (t == 0) {
d = tsize - 1;
} else {
f = 1 << t;
d = (tsize - 1) / log(alink / offset);
d *= log((double)f / (f - 1));
}
printf(" /* RDF %u: 1/%u: %f */\n", t, 1 << t, d);
val = 0;
for (i = 0; i < tsize; i++) {
if (i < d)
diff = d2ifp(i);
else
diff = d2ifp(d);
if (i % 2) {
val |= diff << 16;
if (verbose)
printf(" 0x%08x,\t", val);
else
printf("0x%08x,\n", val);
} else {
val = diff;
if (verbose)
printf("\t\t");
}
if (verbose)
printf("/* %3u: %f */\n", i, ifp2d(diff));
}
}
}
/*
* Create all the tables for a given link cell rate and link bit rate.
* The link bit rate is only used to name the table.
*/
static void
gen_tables(u_int alink, u_int mbps)
{
printf("\n");
printf("/*\n");
printf(" * Tables for %ucps and %uMbps\n", alink, mbps);
printf(" */\n");
printf("const uint32_t patm_rtables%u[128 * (4 + 2 * %u)] = {\n",
mbps, ndtables);
gen_log2rate(alink);
gen_rate2log(alink);
gen_glob(alink);
gen_air(alink);
gen_rdf(alink);
printf("};\n");
}
int
main(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "v")) != -1)
switch (opt) {
case 'v':
verbose = 1;
break;
}
printf("/*\n");
printf(" * This file was generated by `%s'\n", argv[0]);
printf(" */\n");
printf("\n");
printf("#include <sys/cdefs.h>\n");
printf("__FBSDID(\"$FreeBSD$\");\n");
printf("\n");
printf("#include <sys/types.h>\n");
printf("\n");
printf("const u_int patm_rtables_size = 128 * (4 + 2 * %u);\n",
ndtables);
printf("const u_int patm_rtables_ntab = %u;\n", ndtables);
gen_tables(352768, 155);
gen_tables( 59259, 25);
return (0);
}

View File

@ -1,476 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*
* Register definitions for the IDT77252 chip.
*/
#define PCI_VENDOR_IDT 0x111D
#define PCI_DEVICE_IDT77252 3
#define PCI_DEVICE_IDT77v252 4
#define PCI_DEVICE_IDT77v222 5
#define IDT_PCI_REG_MEMBASE 0x14
#define IDT_NOR_D0 0x00 /* R/W Data register 0 */
#define IDT_NOR_D1 0x04 /* R/W Data register 1 */
#define IDT_NOR_D2 0x08 /* R/W Data register 2 */
#define IDT_NOR_D3 0x0C /* R/W Data register 3 */
#define IDT_NOR_CMD 0x10 /* R/W Command */
#define IDT_NOR_CFG 0x14 /* R/W Configuration */
#define IDT_NOR_STAT 0x18 /* R/W Status */
#define IDT_NOR_RSQB 0x1C /* R/W Receive status queue base */
#define IDT_NOR_RSQT 0x20 /* R Receive status queue tail */
#define IDT_NOR_RSQH 0x24 /* R/W Receive status queue tail */
#define IDT_NOR_CDC 0x28 /* R/W Cell drop counter */
#define IDT_NOR_VPEC 0x2C /* R/W VPI/VCI Lookup error counter */
#define IDT_NOR_ICC 0x30 /* R/W Invalid cell counter */
#define IDT_NOR_RAWCT 0x34 /* R Raw cell tail */
#define IDT_NOR_TMR 0x38 /* R Timer */
#define IDT_NOR_TSTB 0x3C /* R/W Transmit schedule table base */
#define IDT_NOR_TSQB 0x40 /* R/W Transmit Status queue base */
#define IDT_NOR_TSQT 0x44 /* R/W Transmit Status queue tail */
#define IDT_NOR_TSQH 0x48 /* R/W Transmit Status queue head */
#define IDT_NOR_GP 0x4C /* R/W General purpose */
#define IDT_NOR_VPM 0x50 /* R/W VPI/VCI mask */
#define IDT_NOR_RXFD 0x54 /* R/W Receive FIFO descriptor */
#define IDT_NOR_RXFT 0x58 /* R/W Receive FIFO tail */
#define IDT_NOR_RXFH 0x5C /* R/W Receive FIFO head */
#define IDT_NOR_RAWHND 0x60 /* R/W Raw cell handle */
#define IDT_NOR_RXSTAT 0x64 /* R Receive connection state */
#define IDT_NOR_ABRSTD 0x68 /* R/W ABR & VBR Schedule table descriptor */
#define IDT_NOR_ABRRQ 0x6C /* R/W ABR Ready queue pointer */
#define IDT_NOR_VBRRQ 0x70 /* R/W VBR Ready queue pointer */
#define IDT_NOR_RTBL 0x74 /* R/W Rate table descriptor */
#define IDT_NOR_MXDFCT 0x78 /* R/W Maximum deficit counter */
#define IDT_NOR_TXSTAT 0x7C /* R/W Transmit connection state */
#define IDT_NOR_TCMDQ 0x80 /* W Transmit command queue */
#define IDT_NOR_IRCP 0x84 /* R/W Inactive receive connection pointer */
#define IDT_NOR_FBQP0 0x88 /* R/W Free buffer queue 0 pointer */
#define IDT_NOR_FBQP1 0x8C /* R/W Free buffer queue 1 pointer */
#define IDT_NOR_FBQP2 0x90 /* R/W Free buffer queue 2 pointer */
#define IDT_NOR_FBQP3 0x94 /* R/W Free buffer queue 3 pointer */
#define IDT_NOR_FBQS0 0x98 /* R/W Free buffer queue 0 size */
#define IDT_NOR_FBQS1 0x9C /* R/W Free buffer queue 1 size */
#define IDT_NOR_FBQS2 0xA0 /* R/W Free buffer queue 2 size */
#define IDT_NOR_FBQS3 0xA4 /* R/W Free buffer queue 3 size */
#define IDT_NOR_FBQWP0 0xA8 /* R/W Free buffer queue 0 write pointer */
#define IDT_NOR_FBQWP1 0xAC /* R/W Free buffer queue 1 write pointer */
#define IDT_NOR_FBQWP2 0xB0 /* R/W Free buffer queue 2 write pointer */
#define IDT_NOR_FBQWP3 0xB4 /* R/W Free buffer queue 3 write pointer */
#define IDT_NOR_NOW 0xB8 /* R Current transmit schedule table addr */
#define IDT_NOR_DNOW 0xBC /* R Dynamic Now register */
#define IDT_NOR_END 0xC0
/*
* Command (IDT_NOR_CMD)
*/
#define IDT_CMD_NOP 0x00000000 /* No operation */
#define IDT_CMD_OPCL 0x20000000 /* Open/Close connection */
#define IDT_CMD_WSRAM 0x40000000 /* Write SRAM */
#define IDT_CMD_RSRAM 0x50000000 /* Read SRAM */
#define IDT_CMD_WFBQ 0x60000000 /* Write free buffer queue */
#define IDT_CMD_RUTIL 0x80000000 /* Read utility bus */
#define IDT_CMD_WUTIL 0x90000000 /* Write utility bus */
#define IDT_MKCMD_OPEN(VC) (IDT_CMD_OPCL | (1 << 19) | ((V) << 4))
#define IDT_MKCMD_CLOSE(VC) (IDT_CMD_OPCL | (0 << 19) | ((V) << 4))
#define IDT_MKCMD_WSRAM(A, S) (IDT_CMD_WSRAM | ((A) << 2) | (S))
#define IDT_MKCMD_RSRAM(A) (IDT_CMD_RSRAM | ((A) << 2))
#define IDT_MKCMD_WFBQ(Q) (IDT_CMD_WFBQ | (Q))
#define IDT_MKCMD_RUTIL(S0, S1, A) \
(IDT_CMD_RUTIL | ((S1) << 9) | ((S0) << 8) | (A))
#define IDT_MKCMD_WUTIL(S0, S1, A) \
(IDT_CMD_WUTIL | ((S1) << 9) | ((S0) << 8) | (A))
/*
* Configuration register (CFG)
*/
#define IDT_CFG_SWRST 0x80000000 /* software reset */
#define IDT_CFG_LOOP 0x40000000 /* internal loopback enable */
#define IDT_CFG_RXPTH 0x20000000 /* receive path enable */
#define IDT_CFG_IDLECLP 0x10000000 /* set CLP in null cells */
#define IDT_CFG_TXFIFO9 0x00000000 /* Tx FIFO 9 cells */
#define IDT_CFG_TXFIFO1 0x04000000 /* Tx FIFO 1 cells */
#define IDT_CFG_TXFIFO2 0x08000000 /* Tx FIFO 2 cells */
#define IDT_CFG_TXFIFO4 0x0C000000 /* Tx FIFO 4 cells */
#define IDT_CFG_NOIDLE 0x02000000 /* don't send idle cells */
#define IDT_CFG_RXQ128 0x00000000 /* Rx Status Queue 128 entries */
#define IDT_CFG_RXQ256 0x00400000 /* Rx Status Queue 256 entries */
#define IDT_CFG_RXQ512 0x00800000 /* Rx Status Queue 512 entries */
#define IDT_CFG_ICAPT 0x00200000 /* Invalid cell accept */
#define IDT_CFG_IGGFC 0x00100000 /* Ignore GFC field */
#define IDT_CFG_VP0 0x00000000 /* 0 VPI bits */
#define IDT_CFG_VP1 0x00040000 /* 1 VPI bit */
#define IDT_CFG_VP2 0x00080000 /* 2 VPI bits */
#define IDT_CFG_VP8 0x000C0000 /* 8 VPI bits */
#define IDT_CFG_CTS1K 0x00000000 /* Rx Connection table 1024 entries */
#define IDT_CFG_CTS4K 0x00010000 /* Rx Connection table 4096 entries */
#define IDT_CFG_CTS16K 0x00020000 /* Rx Connection table 16384 entries */
#define IDT_CFG_CTS512 0x00030000 /* Rx Connection table 512 entries */
#define IDT_CFG_VPECA 0x00008000 /* VPI/VCI error cell accept */
#define IDT_CFG_RXINONE 0x00000000 /* No interrupt on receive */
#define IDT_CFG_RXIIMM 0x00001000 /* immediate interrupt */
#define IDT_CFG_RXI28 0x00002000 /* every 0x2800 clocks */
#define IDT_CFG_RXI4F 0x00003000 /* every 0x4F00 clocks */
#define IDT_CFG_RXI74 0x00004000 /* every 0x7400 clocks */
#define IDT_CFG_RAWIE 0x00000800 /* raw cell queue interrupt enable */
#define IDT_CFG_RQFIE 0x00000400 /* Rx status queue almost full IE */
#define IDT_CFG_CACHE 0x00000100 /* begin DMA on cache line */
#define IDT_CFG_TIMOIE 0x00000080 /* timer roll over interrupt enable */
#define IDT_CFG_FBIE 0x00000040 /* free buffer queue interrupt enable */
#define IDT_CFG_TXENB 0x00000020 /* Tx enable */
#define IDT_CFG_TXINT 0x00000010 /* Tx status interrupt enable */
#define IDT_CFG_TXUIE 0x00000008 /* Tx underrun interrupt enable */
#define IDT_CFG_UMODE 0x00000004 /* utopia byte mode */
#define IDT_CFG_TXSFI 0x00000002 /* Tx status full interrupt enable */
#define IDT_CFG_PHYIE 0x00000001 /* PHY interrupt enable */
/*
* Status register (STAT)
*/
#define IDT_STAT_FRAC3(S) (((S) >> 28) & 0xf) /* FBQ3 valid */
#define IDT_STAT_FRAC2(S) (((S) >> 24) & 0xf) /* FBQ2 valid */
#define IDT_STAT_FRAC1(S) (((S) >> 20) & 0xf) /* FBQ1 valid */
#define IDT_STAT_FRAC0(S) (((S) >> 16) & 0xf) /* FBQ0 valid */
#define IDT_STAT_TSIF 0x00008000 /* Tx status indicator flag */
#define IDT_STAT_TXICP 0x00004000 /* Tx incomplete PDU */
#define IDT_STAT_TSQF 0x00001000 /* Tx status queue full */
#define IDT_STAT_TMROF 0x00000800 /* Timer overflow */
#define IDT_STAT_PHYI 0x00000400 /* PHY interrupt */
#define IDT_STAT_CMDBZ 0x00000200 /* command busy */
#define IDT_STAT_FBQ3A 0x00000100 /* FBQ 3 attention flag */
#define IDT_STAT_FBQ2A 0x00000080 /* FBQ 2 attention flag */
#define IDT_STAT_RSQF 0x00000040 /* Rx status queue full */
#define IDT_STAT_EPDU 0x00000020 /* end of CS-PDU */
#define IDT_STAT_RAWCF 0x00000010 /* raw cell flag */
#define IDT_STAT_FBQ1A 0x00000008 /* FBQ 1 attention flag */
#define IDT_STAT_FBQ0A 0x00000004 /* FBQ 0 attention flag */
#define IDT_STAT_RSQAF 0x00000002 /* Rx status queue almost full */
/*
* Cell drop count (CDC)
*/
#define IDT_CDC_RMID 0x00400000 /* RM cell ID error */
#define IDT_CDC_CTE 0x00200000 /* Rx connection table error */
#define IDT_CDC_NFB 0x00100000 /* No free buffers */
#define IDT_CDC_OAMCRC 0x00080000 /* bad OAM CRC */
#define IDT_CDC_RMCRC 0x00040000 /* bad RM CRC */
#define IDT_CDC_RMFIFO 0x00020000 /* RM FIFO full */
#define IDT_CDC_RXFIFO 0x00010000 /* Rx FIFO full */
#define IDT_CDC(S) ((S) & 0xffff) /* cell drop counter */
/*
* VPI/VCI lookup error count (VPEC)
*/
#define IDT_VPEC(S) ((S) & 0xffff)
/*
* Invalid cell count (ICC)
*/
#define IDT_ICC(S) ((S) & 0xffff)
/*
* General purpose register
*/
#define IDT_GP_TXNCC(S) (((S) >> 24) & 0xff) /* Tx negative cell count */
#define IDT_GP_EEDI 0x00010000 /* EEPROM data in */
#define IDT_GP_BIGE 0x00008000 /* big endian enable */
#define IDT_GP_RM 0x00000000 /* process RM cells */
#define IDT_GP_RM_TEE 0x00002000 /* process RM cells and put in RawQ */
#define IDT_GP_RM_RAW 0x00006000 /* put RM cells in RawQ */
#define IDT_GP_DLOOP 0x00001000 /* double loopback */
#define IDT_GP_PCIPAR 0x00000010 /* force PCI parity error */
#define IDT_GP_PCIPERR 0x00000020 /* force PERR */
#define IDT_GP_PCISERR 0x00000040 /* force SERR */
#define IDT_GP_PHY_RST 0x00000008 /* PHY reset */
#define IDT_GP_EESCLK 0x00000004 /* EEPROM clock */
#define IDT_GP_EECS 0x00000002 /* EEPROM chip select */
#define IDT_GP_EEDO 0x00000001 /* EEPROM data out */
/*
* Receive FIFO descriptor register (RXFD)
*/
#define IDT_RXFD(A, S) (((S) << 24) | ((A) << 2))
#define IDT_RXFDS(V) (((V) >> 24) & 0xf)
#define IDT_RXFDA(V) (((V) & 0x1ffffc) >> 2)
/*
* ABR & VBR schedule table descriptor register
*/
#define IDT_ABRSTD(A, S) (((S) << 24) | ((A) << 2))
#define IDT_ABRSTDS(V) (((V) >> 24) & 0x7)
#define IDT_ABRSTDA(V) (((V) & 0x1ffffc) >> 2)
/*
* ABR/VBR ready queue register
*/
#define IDT_ABRRQH(V) (((V) >> 16) & 0x3fff)
#define IDT_ABRRQT(V) (((V) >> 0) & 0x3fff)
#define IDT_VBRRQH(V) (((V) >> 16) & 0x3fff)
#define IDT_VBRRQT(V) (((V) >> 0) & 0x3fff)
/*
* Maximum deficit limit register
*/
#define IDT_MDFCT_LCI 0x00020000 /* local congestion indicator enable */
#define IDT_MDFCT_LNI 0x00010000 /* local no incread enable */
/*
* Transmit command queue register
*/
#define IDT_TCMDQ_NOP() ((0x0 << 24)) /* no operation */
#define IDT_TCMDQ_START(C) ((0x1 << 24) | (C)) /* start connection */
#define IDT_TCMDQ_ULACR(C, L) ((0x2 << 24) | (C) | ((L) << 16))
/* update LACR */
#define IDT_TCMDQ_SLACR(C, L) ((0x3 << 24) | (C) | ((L) << 16))
/* start and update LACR */
#define IDT_TCMDQ_UIER(C, L) ((0x4 << 24) | (C) | ((L) << 16))
/* update Int ER */
#define IDT_TCMDQ_HALT(C) ((0x5 << 24) | (C)) /* halt connection */
/*
* Free buffer queue size registers
*/
#define IDT_FBQS(T, N, C, S) (((T) << 28) | ((N) << 24) | ((C) << 20) | (S))
/*
* Receive status queue
*/
struct idt_rsqe {
uint32_t cid; /* VPI/VCI */
uint32_t handle; /* buffer handle */
uint32_t crc; /* AAL-5 CRC */
uint32_t stat; /* div. flags */
};
#define IDT_RSQE_SIZE 16 /* bytes */
#define IDT_RSQE_VPI(CID) (((CID) >> 16) & 0xff)
#define IDT_RSQE_VCI(CID) ((CID) & 0xffff)
#define IDT_RSQE_TYPE(S) (((S) >> 30) & 0x3)
#define IDT_RSQE_DATA 0x2
#define IDT_RSQE_IDLE 0x3
#define IDT_RSQE_VALID 0x80000000
#define IDT_RSQE_POOL(S) (((S) >> 16) & 0x3)
#define IDT_RSQE_BUF 0x8000
#define IDT_RSQE_NZGFC 0x4000
#define IDT_RSQE_EPDU 0x2000
#define IDT_RSQE_CBUF 0x1000
#define IDT_RSQE_EFCIE 0x0800
#define IDT_RSQE_CLP 0x0400
#define IDT_RSQE_CRC 0x0200
#define IDT_RSQE_CNT(S) ((S) & 0x1ff)
#define IDT_RSQH(R) (((R) & 0x1ffc) >> 2)
#define IDT_RSQT(R) (((R) & 0x1ffc) >> 2)
/*
* Transmit status queue
*/
#define IDT_TSQ_SIZE 1024 /* no. of entries */
#define IDT_TSQE_SIZE 8 /* bytes */
#define IDT_TSQE_SHIFT 3
struct idt_tsqe {
uint32_t stat;
uint32_t stamp;
};
#define IDT_TSQE_EMPTY 0x80000000
#define IDT_TSQE_TYPE(E) (((E) >> 29) & 0x3)
#define IDT_TSQE_TIMER 0x0
#define IDT_TSQE_TSR 0x1
#define IDT_TSQE_IDLE 0x2
#define IDT_TSQE_TBD 0x3
#define IDT_TSQE_TAG(E) (((E) >> 24) & 0x1f)
#define IDT_TSQE_HALTED 0x10
#define IDT_TSQE_STAMP(E) ((E) & 0xffffff)
#define IDT_TSQE_TAG_SPACE 32
/*
* Raw cell handle
*/
struct idt_rawhnd {
uint32_t tail;
uint32_t handle;
};
#define IDT_RAWHND_SIZE 8
/*
* TST
*/
#define IDT_TST_NULL (0 << 29) /* transmit NULL cell */
#define IDT_TST_CBR (1 << 29) /* transmit CBR cell */
#define IDT_TST_VBR (2 << 29) /* transmit [AVU]BR cell */
#define IDT_TST_BR (3 << 29) /* branch */
#define IDT_TST_MASK 0x7ffff
/*
* Free buffer queue
*/
#define IDT_FBQ_SIZE 512 /* entries */
/*
* Receive connection table
*/
#define IDT_RCT_FBP2 0x00400000 /* use FBQ 2 */
#define IDT_RCT_OPEN 0x00080000 /* connection open */
#define IDT_RCT_AAL0 0x00000000 /* AAL 0 */
#define IDT_RCT_AAL34 0x00010000 /* AAL 3/4 */
#define IDT_RCT_AAL5 0x00020000 /* AAL 5 */
#define IDT_RCT_AALRAW 0x00030000 /* raw cells */
#define IDT_RCT_AALOAM 0x00040000 /* OAM cells */
#define IDT_RCT_RCI 0x00008000 /* raw cell interrupt enable */
#define IDT_RCT_IACT_CNT_MASK 0x1c000000
#define IDT_RCT_IACT_CNT_SHIFT 26
#define IDT_RCT_ENTRY_SIZE 4 /* words */
/*
* Transmit connection table
*/
#define IDT_TCT_CBR 0x00000000
#define IDT_TCT_VBR 0x40000000
#define IDT_TCT_ABR 0x80000000
#define IDT_TCT_UBR 0x00000000
#define IDT_TCT_UBR_FLG 0x80000000 /* word8 flag */
#define IDT_TCT_HALT 0x80000000 /* connection halted */
#define IDT_TCT_IDLE 0x40000000 /* connection idle */
#define IDT_TCT_TSIF 0x00004000
#define IDT_TCT_MAXIDLE 0x7f000000
#define IDT_TCT_MBS_SHIFT 16
#define IDT_TCT_CRM_SHIFT 29
#define IDT_TCT_NAGE_SHIFT 21
#define IDT_TCT_LMCR_SHIFT 24
#define IDT_TCT_CDF_SHIFT 20
#define IDT_TCT_RDF_SHIFT 14
#define IDT_TCT_AIR_SHIFT 8
#define IDT_TCT_ACRI_SHIFT 16
/*
* Segmentation channel queue
*/
#define IDT_SCQ_SIZE 64 /* number of entries */
struct idt_tbd {
uint32_t flags;
uint32_t addr;
uint32_t aal5;
uint32_t hdr;
};
#define IDT_TBD_SIZE 16 /* bytes */
#define IDT_TBD_SHIFT 4
#define IDT_TBD_TSR 0x80000000 /* TSR entry */
#define IDT_TBD_EPDU 0x40000000 /* end of AAL PDU */
#define IDT_TBD_TSIF 0x20000000 /* generate status */
#define IDT_TBD_AAL0 0x00000000 /* AAL0 */
#define IDT_TBD_AAL34 0x04000000 /* AAL3/4 */
#define IDT_TBD_AAL5 0x08000000 /* AAL5 */
#define IDT_TBD_AALOAM 0x10000000 /* OAM cells */
#define IDT_TBD_GTSI 0x02000000 /* generate transmit status entry */
#define IDT_TBD_TAG_SHIFT 20
#define IDT_TBD_HDR(VPI, VCI, PTI, CLP) \
(((VPI) << 20) | ((VCI) << 4) | ((PTI) << 1) | (CLP))
#define IDT_TBD_VPI(H) (((H) >> 20) & 0xff)
#define IDT_TBD_VCI(H) (((H) >> 4) & 0xffff)
/*
* Segmentation channel descriptor
*/
#define IDT_SCD_SIZE 12 /* words */
/*
* Memory map for the different RAM sizes
*
* 16k 32k 128k 512k
*
* TxCT 0x00000/4k 0x00000/8x 0x00000/32k 0x00000/128k
* RxCT 0x01000/2k 0x02000/4k 0x08000/16k 0x20000/64k
* FBQ0 0x01800/1k 0x03000/1k 0x0c000/1k 0x30000/1k
* FBQ1 0x01c00/1k 0x03400/1k 0x0c400/1k 0x30400/1k
* FBQ2 0x02000/1k 0x03800/1k 0x0c800/1k 0x30800/1k
* FBQ3 - - - -
* RT 0x02400/4.5k 0x03c00/4.5k 0x0cc00/4.5k 0x30c00/4.5k
* SCD 0x03600/597 0x04e00/1621 0x0de00/9358 0x31e00/43036
* TST 0x06000/2x2k 0x0c000/2x4k 0x37000/2x8k 0xef000/2x16k
* ABR ST 0x07000/2x1k 0x0e000/2x2k 0x3b000/2x8k 0xf7000/2x16k
* RxFIFO 0x07800/2k 0x0f000/4k 0x3f000/4k 0xff000/4k
* End 0x08000 0x10000 0x40000 0x100000
*/
struct idt_mmap {
u_int sram; /* K SRAM */
u_int max_conn; /* connections */
u_int vcbits; /* VPI + VCI bits */
u_int rxtab; /* CFG word for CNTBL field */
u_int rct; /* RCT base */
u_int rtables; /* rate table address */
u_int scd_base; /* SCD area base address */
u_int scd_num; /* number of SCDs */
u_int tst1base; /* base address of TST 1 */
u_int tst_size; /* TST size in words */
u_int abrstd_addr; /* schedule table address */
u_int abrstd_size; /* schedule table size */
u_int abrstd_code; /* schedule table size */
u_int rxfifo_addr; /* address */
u_int rxfifo_size; /* in words */
u_int rxfifo_code; /* size */
};
#define IDT_MMAP { \
{ /* 16k x 32, 512 connections */ \
16, 512, 9, IDT_CFG_CTS512, /* RAM, connections, VC bits */ \
0x01000, /* RCT base */ \
0x02400, /* rate table address */ \
0x03600, 597, /* SCD base and num */ \
0x06000, 2048, /* TST/words, base */ \
0x07000, 2048, 0x1, /* ABR schedule table */ \
0x07800, 2048, 0x2 /* RxFIFO size in words */ \
}, \
{ /* 32k x 32, 1024 connections */ \
32, 1024, 10, IDT_CFG_CTS1K, /* RAM, connections, VC bits */ \
0x02000, /* RCT base */ \
0x03c00, /* rate table address */ \
0x04e00, 1621, /* SCD base and num */ \
0x0c000, 4096, /* TST/words, base */ \
0x0e000, 4096, 0x2, /* ABR schedule table */ \
0x0f000, 4096, 0x3 /* RxFIFO size in words */ \
}, \
{ /* 128k x 32, 4096 connections */ \
128, 4096, 12, IDT_CFG_CTS4K, /* RAM, connections, VC bits */ \
0x08000, /* RCT base */ \
0x0cc00, /* rate table address */ \
0x0de00, 9358, /* SCD base and num */ \
0x37000, 8192, /* TST/words, base */ \
0x3b000, 16384, 0x4, /* ABR schedule table */ \
0x3f000, 4096, 0x3 /* RxFIFO size in words */ \
}, \
{ /* 512k x 32, 512 connections */ \
512, 16384, 14, IDT_CFG_CTS16K, /* RAM, connections, VC bits */\
0x20000, /* RCT base */ \
0x30c00, /* rate table address */ \
0x31e00, 43036, /* SCD base and num */ \
0xef000, 16384, /* TST/words, base */ \
0xf7000, 16384, 0x5, /* ABR schedule table */ \
0xff000, 4096, 0x3 /* RxFIFO size in words */ \
}, \
}

View File

@ -1,512 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* Driver for IDT77252 based cards like ProSum's.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_natm.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/condvar.h>
#include <sys/endian.h>
#include <vm/uma.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_atm.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_atm.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/mbpool.h>
#include <dev/utopia/utopia.h>
#include <dev/patm/idt77252reg.h>
#include <dev/patm/if_patmvar.h>
static void patm_tst_init(struct patm_softc *sc);
static void patm_scd_init(struct patm_softc *sc);
/*
* Start the card. This assumes the mutex to be held
*/
void
patm_initialize(struct patm_softc *sc)
{
uint32_t cfg;
u_int i;
patm_debug(sc, ATTACH, "configuring...");
/* clear SRAM */
for (i = 0; i < sc->mmap->sram * 1024; i += 4)
patm_sram_write4(sc, i, 0, 0, 0, 0);
patm_scd_init(sc);
/* configuration register. Setting NOIDLE makes the timing wrong! */
cfg = IDT_CFG_TXFIFO9 | IDT_CFG_RXQ512 | PATM_CFG_VPI |
/* IDT_CFG_NOIDLE | */ sc->mmap->rxtab;
if (!(sc->flags & PATM_UNASS))
cfg |= IDT_CFG_IDLECLP;
patm_nor_write(sc, IDT_NOR_CFG, cfg);
/* clean all the status queues and the Raw handle */
memset(sc->tsq, 0, sc->sq_size);
/* initialize RSQ */
patm_debug(sc, ATTACH, "RSQ %llx", (unsigned long long)sc->rsq_phy);
patm_nor_write(sc, IDT_NOR_RSQB, sc->rsq_phy);
patm_nor_write(sc, IDT_NOR_RSQT, sc->rsq_phy);
patm_nor_write(sc, IDT_NOR_RSQH, 0);
sc->rsq_last = PATM_RSQ_SIZE - 1;
/* initialize TSTB */
patm_nor_write(sc, IDT_NOR_TSTB, sc->mmap->tst1base << 2);
patm_tst_init(sc);
/* initialize TSQ */
for (i = 0; i < IDT_TSQ_SIZE; i++)
sc->tsq[i].stamp = htole32(IDT_TSQE_EMPTY);
patm_nor_write(sc, IDT_NOR_TSQB, sc->tsq_phy);
patm_nor_write(sc, IDT_NOR_TSQH, 0);
patm_nor_write(sc, IDT_NOR_TSQT, 0);
sc->tsq_next = sc->tsq;
/* GP */
#if BYTE_ORDER == BIG_ENDIAN && 0
patm_nor_write(sc, IDT_NOR_GP, IDT_GP_BIGE);
#else
patm_nor_write(sc, IDT_NOR_GP, 0);
#endif
/* VPM */
patm_nor_write(sc, IDT_NOR_VPM, 0);
/* RxFIFO */
patm_nor_write(sc, IDT_NOR_RXFD,
IDT_RXFD(sc->mmap->rxfifo_addr, sc->mmap->rxfifo_code));
patm_nor_write(sc, IDT_NOR_RXFT, 0);
patm_nor_write(sc, IDT_NOR_RXFH, 0);
/* RAWHND */
patm_debug(sc, ATTACH, "RWH %llx",
(unsigned long long)sc->rawhnd_phy);
patm_nor_write(sc, IDT_NOR_RAWHND, sc->rawhnd_phy);
/* ABRSTD */
patm_nor_write(sc, IDT_NOR_ABRSTD,
IDT_ABRSTD(sc->mmap->abrstd_addr, sc->mmap->abrstd_code));
for (i = 0; i < sc->mmap->abrstd_size; i++)
patm_sram_write(sc, sc->mmap->abrstd_addr + i, 0);
patm_nor_write(sc, IDT_NOR_ABRRQ, 0);
patm_nor_write(sc, IDT_NOR_VBRRQ, 0);
/* rate tables */
if (sc->flags & PATM_25M) {
for (i = 0; i < patm_rtables_size; i++)
patm_sram_write(sc, sc->mmap->rtables + i,
patm_rtables25[i]);
} else {
for (i = 0; i < patm_rtables_size; i++)
patm_sram_write(sc, sc->mmap->rtables + i,
patm_rtables155[i]);
}
patm_nor_write(sc, IDT_NOR_RTBL, sc->mmap->rtables << 2);
/* Maximum deficit */
patm_nor_write(sc, IDT_NOR_MXDFCT, 32 | IDT_MDFCT_LCI | IDT_MDFCT_LNI);
/* Free buffer queues */
patm_nor_write(sc, IDT_NOR_FBQP0, 0);
patm_nor_write(sc, IDT_NOR_FBQP1, 0);
patm_nor_write(sc, IDT_NOR_FBQP2, 0);
patm_nor_write(sc, IDT_NOR_FBQP3, 0);
patm_nor_write(sc, IDT_NOR_FBQWP0, 0);
patm_nor_write(sc, IDT_NOR_FBQWP1, 0);
patm_nor_write(sc, IDT_NOR_FBQWP2, 0);
patm_nor_write(sc, IDT_NOR_FBQWP3, 0);
patm_nor_write(sc, IDT_NOR_FBQS0,
(SMBUF_THRESHOLD << 28) |
(SMBUF_NI_THRESH << 24) |
(SMBUF_CI_THRESH << 20) |
SMBUF_CELLS);
patm_nor_write(sc, IDT_NOR_FBQS1,
(LMBUF_THRESHOLD << 28) |
(LMBUF_NI_THRESH << 24) |
(LMBUF_CI_THRESH << 20) |
LMBUF_CELLS);
patm_nor_write(sc, IDT_NOR_FBQS2,
(VMBUF_THRESHOLD << 28) | VMBUF_CELLS);
patm_nor_write(sc, IDT_NOR_FBQS3, 0);
/* make SCD0 for UBR0 */
if ((sc->scd0 = patm_scd_alloc(sc)) == NULL) {
patm_printf(sc, "cannot create UBR0 SCD\n");
patm_reset(sc);
return;
}
sc->scd0->q.ifq_maxlen = PATM_DLFT_MAXQ;
patm_scd_setup(sc, sc->scd0);
patm_tct_setup(sc, sc->scd0, NULL);
patm_debug(sc, ATTACH, "go...");
sc->utopia.flags &= ~UTP_FL_POLL_CARRIER;
sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
/* enable interrupts, Tx and Rx paths */
cfg |= IDT_CFG_RXPTH | IDT_CFG_RXIIMM | IDT_CFG_RAWIE | IDT_CFG_RQFIE |
IDT_CFG_TIMOIE | IDT_CFG_FBIE | IDT_CFG_TXENB | IDT_CFG_TXINT |
IDT_CFG_TXUIE | IDT_CFG_TXSFI | IDT_CFG_PHYIE;
patm_nor_write(sc, IDT_NOR_CFG, cfg);
for (i = 0; i < sc->mmap->max_conn; i++)
if (sc->vccs[i] != NULL)
patm_load_vc(sc, sc->vccs[i], 1);
ATMEV_SEND_IFSTATE_CHANGED(IFP2IFATM(sc->ifp),
sc->utopia.carrier == UTP_CARR_OK);
}
/*
* External callable start function
*/
void
patm_init(void *p)
{
struct patm_softc *sc = p;
mtx_lock(&sc->mtx);
patm_stop(sc);
patm_initialize(sc);
mtx_unlock(&sc->mtx);
}
/*
* Stop the interface
*/
void
patm_stop(struct patm_softc *sc)
{
u_int i;
struct mbuf *m;
struct patm_txmap *map;
struct patm_scd *scd;
sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
sc->utopia.flags |= UTP_FL_POLL_CARRIER;
patm_reset(sc);
mtx_lock(&sc->tst_lock);
i = sc->tst_state;
sc->tst_state = 0;
callout_stop(&sc->tst_callout);
mtx_unlock(&sc->tst_lock);
if (i != 0) {
/* this means we are just entering or leaving the timeout.
* wait a little bit. Doing this correctly would be more
* involved */
DELAY(1000);
}
/*
* Give any waiters on closing a VCC a chance. They will stop
* to wait if they see that IFF_DRV_RUNNING disappeared.
*/
cv_broadcast(&sc->vcc_cv);
/* free large buffers */
patm_debug(sc, ATTACH, "freeing large buffers...");
for (i = 0; i < sc->lbuf_max; i++)
if (sc->lbufs[i].m != NULL)
patm_lbuf_free(sc, &sc->lbufs[i]);
/* free small buffers that are on the card */
patm_debug(sc, ATTACH, "freeing small buffers...");
mbp_card_free(sc->sbuf_pool);
/* free aal0 buffers that are on the card */
patm_debug(sc, ATTACH, "freeing aal0 buffers...");
mbp_card_free(sc->vbuf_pool);
/* freeing partial receive chains and reset vcc state */
for (i = 0; i < sc->mmap->max_conn; i++) {
if (sc->vccs[i] != NULL) {
if (sc->vccs[i]->chain != NULL) {
m_freem(sc->vccs[i]->chain);
sc->vccs[i]->chain = NULL;
sc->vccs[i]->last = NULL;
}
if (sc->vccs[i]->vflags & (PATM_VCC_RX_CLOSING |
PATM_VCC_TX_CLOSING)) {
uma_zfree(sc->vcc_zone, sc->vccs[i]);
sc->vccs[i] = NULL;
} else {
/* keep */
sc->vccs[i]->vflags &= ~PATM_VCC_OPEN;
sc->vccs[i]->cps = 0;
sc->vccs[i]->scd = NULL;
}
}
}
/* stop all active SCDs */
while ((scd = LIST_FIRST(&sc->scd_list)) != NULL) {
/* free queue packets */
for (;;) {
_IF_DEQUEUE(&scd->q, m);
if (m == NULL)
break;
m_freem(m);
}
/* free transmitting packets */
for (i = 0; i < IDT_TSQE_TAG_SPACE; i++) {
if ((m = scd->on_card[i]) != NULL) {
scd->on_card[i] = 0;
map = m->m_pkthdr.PH_loc.ptr;
bus_dmamap_unload(sc->tx_tag, map->map);
SLIST_INSERT_HEAD(&sc->tx_maps_free, map, link);
m_freem(m);
}
}
patm_scd_free(sc, scd);
}
sc->scd0 = NULL;
sc->flags &= ~PATM_CLR;
/* reset raw cell queue */
sc->rawh = NULL;
ATMEV_SEND_IFSTATE_CHANGED(IFP2IFATM(sc->ifp),
sc->utopia.carrier == UTP_CARR_OK);
}
/*
* Stop the card and reset it
*/
void
patm_reset(struct patm_softc *sc)
{
patm_debug(sc, ATTACH, "resetting...");
patm_nor_write(sc, IDT_NOR_CFG, IDT_CFG_SWRST);
DELAY(200);
patm_nor_write(sc, IDT_NOR_CFG, 0);
DELAY(200);
patm_nor_write(sc, IDT_NOR_RSQH, 0);
patm_nor_write(sc, IDT_NOR_TSQH, 0);
patm_nor_write(sc, IDT_NOR_GP, IDT_GP_PHY_RST);
DELAY(50);
patm_nor_write(sc, IDT_NOR_GP, IDT_GP_EEDO | IDT_GP_EECS);
DELAY(50);
}
/*
* Initialize the soft TST to contain only ABR scheduling and
* write it to SRAM
*/
static void
patm_tst_init(struct patm_softc *sc)
{
u_int i;
u_int base, idle;
base = sc->mmap->tst1base;
idle = sc->mmap->tst1base + sc->mmap->tst_size;
/* soft */
for (i = 0; i < sc->mmap->tst_size - 1; i++)
sc->tst_soft[i] = IDT_TST_VBR;
sc->tst_state = 0;
sc->tst_jump[0] = base + sc->mmap->tst_size - 1;
sc->tst_jump[1] = idle + sc->mmap->tst_size - 1;
sc->tst_base[0] = base;
sc->tst_base[1] = idle;
/* TST1 */
for (i = 0; i < sc->mmap->tst_size - 1; i++)
patm_sram_write(sc, base + i, IDT_TST_VBR);
patm_sram_write(sc, sc->tst_jump[0], IDT_TST_BR | (base << 2));
/* TST2 */
for (i = 0; i < sc->mmap->tst_size - 1; i++)
patm_sram_write(sc, idle + i, IDT_TST_VBR);
patm_sram_write(sc, sc->tst_jump[1], IDT_TST_BR | (idle << 2));
sc->tst_free = sc->mmap->tst_size - 1;
sc->tst_reserve = sc->tst_free * PATM_TST_RESERVE / 100;
sc->bwrem = IFP2IFATM(sc->ifp)->mib.pcr;
}
/*
* Initialize the SCDs. This is done by building a list of all free
* SCDs in SRAM. The first word of each potential SCD is used as a
* link to the next free SCD. The list is rooted in softc.
*/
static void
patm_scd_init(struct patm_softc *sc)
{
u_int s; /* SRAM address of current SCD */
sc->scd_free = 0;
for (s = sc->mmap->scd_base; s + 12 <= sc->mmap->tst1base; s += 12) {
patm_sram_write(sc, s, sc->scd_free);
sc->scd_free = s;
}
}
/*
* allocate an SCQ
*/
struct patm_scd *
patm_scd_alloc(struct patm_softc *sc)
{
u_int sram, next; /* SRAM address of this and next SCD */
int error;
void *p;
struct patm_scd *scd;
bus_dmamap_t map;
bus_addr_t phy;
/* get an SCD from the free list */
if ((sram = sc->scd_free) == 0)
return (NULL);
next = patm_sram_read(sc, sram);
/* allocate memory for the queue and our host stuff */
error = bus_dmamem_alloc(sc->scd_tag, &p, BUS_DMA_NOWAIT, &map);
if (error != 0)
return (NULL);
phy = 0x3ff;
error = bus_dmamap_load(sc->scd_tag, map, p, sizeof(scd->scq),
patm_load_callback, &phy, BUS_DMA_NOWAIT);
if (error != 0) {
bus_dmamem_free(sc->scd_tag, p, map);
return (NULL);
}
KASSERT((phy & 0x1ff) == 0, ("SCD not aligned %lx", (u_long)phy));
scd = p;
bzero(scd, sizeof(*scd));
scd->sram = sram;
scd->phy = phy;
scd->map = map;
scd->space = IDT_SCQ_SIZE;
scd->last_tag = IDT_TSQE_TAG_SPACE - 1;
scd->q.ifq_maxlen = PATM_TX_IFQLEN;
/* remove the scd from the free list */
sc->scd_free = next;
LIST_INSERT_HEAD(&sc->scd_list, scd, link);
return (scd);
}
/*
* Free an SCD
*/
void
patm_scd_free(struct patm_softc *sc, struct patm_scd *scd)
{
LIST_REMOVE(scd, link);
/* clear SCD and insert link word */
patm_sram_write4(sc, scd->sram, sc->scd_free, 0, 0, 0);
patm_sram_write4(sc, scd->sram, 0, 0, 0, 0);
patm_sram_write4(sc, scd->sram, 0, 0, 0, 0);
/* put on free list */
sc->scd_free = scd->sram;
/* free memory */
bus_dmamap_unload(sc->scd_tag, scd->map);
bus_dmamem_free(sc->scd_tag, scd, scd->map);
}
/*
* DMA loading helper function. This function handles the loading of
* all one segment DMA maps. The argument is a pointer to a bus_addr_t
* which must contain the desired alignment of the address as a bitmap.
*/
void
patm_load_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
bus_addr_t *phy = arg;
if (error)
return;
KASSERT(nsegs == 1,
("too many segments for DMA: %d", nsegs));
KASSERT(segs[0].ds_addr <= 0xffffffffUL,
("phys addr too large %lx", (u_long)segs[0].ds_addr));
KASSERT((segs[0].ds_addr & *phy) == 0,
("bad alignment %lx:%lx", (u_long)segs[0].ds_addr, (u_long)*phy));
*phy = segs[0].ds_addr;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,554 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* Driver for IDT77252 based cards like ProSum's.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_natm.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/condvar.h>
#include <sys/endian.h>
#include <vm/uma.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_atm.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_atm.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/mbpool.h>
#include <dev/utopia/utopia.h>
#include <dev/patm/idt77252reg.h>
#include <dev/patm/if_patmvar.h>
static void patm_feed_sbufs(struct patm_softc *sc);
static void patm_feed_lbufs(struct patm_softc *sc);
static void patm_feed_vbufs(struct patm_softc *sc);
static void patm_intr_tsif(struct patm_softc *sc);
static void patm_intr_raw(struct patm_softc *sc);
#ifdef PATM_DEBUG
static int patm_mbuf_cnt(u_int unit) __unused;
#endif
/*
* Write free buf Q
*/
static __inline void
patm_fbq_write(struct patm_softc *sc, u_int queue, uint32_t h0,
uint32_t p0, uint32_t h1, uint32_t p1)
{
patm_debug(sc, FREEQ, "supplying(%u,%#x,%#x,%#x,%#x)",
queue, h0, p0, h1, p1);
patm_nor_write(sc, IDT_NOR_D0, h0);
patm_nor_write(sc, IDT_NOR_D1, p0);
patm_nor_write(sc, IDT_NOR_D2, h1);
patm_nor_write(sc, IDT_NOR_D3, p1);
patm_cmd_exec(sc, IDT_CMD_WFBQ | queue);
}
/*
* Interrupt
*/
void
patm_intr(void *p)
{
struct patm_softc *sc = p;
uint32_t stat, cfg;
u_int cnt;
const uint32_t ints = IDT_STAT_TSIF | IDT_STAT_TXICP | IDT_STAT_TSQF |
IDT_STAT_TMROF | IDT_STAT_PHYI | IDT_STAT_RSQF | IDT_STAT_EPDU |
IDT_STAT_RAWCF | IDT_STAT_RSQAF;
const uint32_t fbqa = IDT_STAT_FBQ3A | IDT_STAT_FBQ2A |
IDT_STAT_FBQ1A | IDT_STAT_FBQ0A;
mtx_lock(&sc->mtx);
stat = patm_nor_read(sc, IDT_NOR_STAT);
patm_nor_write(sc, IDT_NOR_STAT, stat & (ints | fbqa));
if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
/* if we are stopped ack all interrupts and handle PHYI */
if (stat & IDT_STAT_PHYI) {
patm_debug(sc, INTR, "PHYI (stopped)");
utopia_intr(&sc->utopia);
}
mtx_unlock(&sc->mtx);
return;
}
patm_debug(sc, INTR, "stat=%08x", stat);
/*
* If the buffer queues are empty try to fill them. If this fails
* disable the interrupt. Otherwise enable the interrupt.
*/
if (stat & fbqa) {
cfg = patm_nor_read(sc, IDT_NOR_CFG);
if (stat & IDT_STAT_FBQ0A)
patm_feed_sbufs(sc);
if (stat & IDT_STAT_FBQ1A)
patm_feed_lbufs(sc);
if (stat & IDT_STAT_FBQ2A) {
/*
* Workaround for missing interrupt on AAL0. Check the
* receive status queue if the FBQ2 is not full.
*/
patm_intr_rsq(sc);
patm_feed_vbufs(sc);
}
if ((patm_nor_read(sc, IDT_NOR_STAT) & fbqa) &&
(cfg & IDT_CFG_FBIE)) {
/* failed */
patm_nor_write(sc, IDT_NOR_CFG, cfg & ~IDT_CFG_FBIE);
patm_printf(sc, "out of buffers -- intr disabled\n");
} else if (!(cfg & IDT_CFG_FBIE)) {
patm_printf(sc, "bufQ intr re-enabled\n");
patm_nor_write(sc, IDT_NOR_CFG, cfg | IDT_CFG_FBIE);
}
patm_nor_write(sc, IDT_NOR_STAT, fbqa);
}
cnt = 0;
while ((stat & ints) != 0) {
if (++cnt == 200) {
patm_printf(sc, "%s: excessive interrupts\n", __func__);
patm_stop(sc);
break;
}
if (stat & IDT_STAT_TSIF) {
patm_debug(sc, INTR, "TSIF");
patm_intr_tsif(sc);
}
if (stat & IDT_STAT_TXICP) {
patm_printf(sc, "incomplete PDU transmitted\n");
}
if (stat & IDT_STAT_TSQF) {
patm_printf(sc, "TSQF\n");
patm_intr_tsif(sc);
}
if (stat & IDT_STAT_TMROF) {
patm_debug(sc, INTR, "TMROF");
patm_intr_tsif(sc);
}
if (stat & IDT_STAT_PHYI) {
patm_debug(sc, INTR, "PHYI");
utopia_intr(&sc->utopia);
}
if (stat & IDT_STAT_RSQF) {
patm_printf(sc, "RSQF\n");
patm_intr_rsq(sc);
}
if (stat & IDT_STAT_EPDU) {
patm_debug(sc, INTR, "EPDU");
patm_intr_rsq(sc);
}
if (stat & IDT_STAT_RAWCF) {
patm_debug(sc, INTR, "RAWCF");
patm_intr_raw(sc);
}
if (stat & IDT_STAT_RSQAF) {
patm_debug(sc, INTR, "RSQAF");
patm_intr_rsq(sc);
} else if (IDT_STAT_FRAC2(stat) != 0xf) {
/*
* Workaround for missing interrupt on AAL0. Check the
* receive status queue if the FBQ2 is not full.
*/
patm_intr_rsq(sc);
}
stat = patm_nor_read(sc, IDT_NOR_STAT);
patm_nor_write(sc, IDT_NOR_STAT, ints & stat);
patm_debug(sc, INTR, "stat=%08x", stat);
}
mtx_unlock(&sc->mtx);
patm_debug(sc, INTR, "... exit");
}
/*
* Compute the amount of buffers to feed into a given free buffer queue
*
* Feeding buffers is actually not so easy as it seems. We cannot use the
* fraction fields in the status registers, because they round down, i.e.
* if we have 34 buffers in the queue, it will show 1. If we now feed
* 512 - 1 * 32 buffers, we lose two buffers. The only reliable way to know
* how many buffers are in the queue are the FBQP registers.
*/
static u_int
patm_feed_cnt(struct patm_softc *sc, u_int q)
{
u_int w, r, reg;
u_int feed;
int free;
/* get the FBQ read and write pointers */
reg = patm_nor_read(sc, IDT_NOR_FBQP0 + 4 * q);
r = (reg & 0x7ff) >> 1;
w = ((reg >> 16) & 0x7ff) >> 1;
/* compute amount of free buffers */
if ((free = w - r) < 0)
free += 0x400;
KASSERT(free <= 512, ("bad FBQP 0x%x", reg));
feed = 512 - free;
/* can only feed pairs of buffers */
feed &= ~1;
if (feed > 0)
feed -= 2;
patm_debug(sc, FREEQ, "feeding %u buffers into queue %u", feed, q);
return (feed);
}
/*
* Feed small buffers into buffer queue 0
*
*/
static void
patm_feed_sbufs(struct patm_softc *sc)
{
u_int feed;
bus_addr_t p0, p1;
void *v0;
uint32_t h0, h1;
feed = patm_feed_cnt(sc, 0);
while (feed > 0) {
if ((v0 = mbp_alloc(sc->sbuf_pool, &p0, &h0)) == NULL)
break;
if (mbp_alloc(sc->sbuf_pool, &p1, &h1) == NULL) {
mbp_free(sc->sbuf_pool, v0);
break;
}
patm_fbq_write(sc, 0,
h0 | MBUF_SHANDLE, (p0 + SMBUF_OFFSET),
h1 | MBUF_SHANDLE, (p1 + SMBUF_OFFSET));
feed -= 2;
}
}
/*
* Feed small buffers into buffer queue 0
*/
static void
patm_feed_vbufs(struct patm_softc *sc)
{
u_int feed;
bus_addr_t p0, p1;
void *v0;
uint32_t h0, h1;
feed = patm_feed_cnt(sc, 2);
while (feed > 0) {
if ((v0 = mbp_alloc(sc->vbuf_pool, &p0, &h0)) == NULL)
break;
if (mbp_alloc(sc->vbuf_pool, &p1, &h1) == NULL) {
mbp_free(sc->vbuf_pool, v0);
break;
}
patm_fbq_write(sc, 2,
h0 | MBUF_VHANDLE, (p0 + VMBUF_OFFSET),
h1 | MBUF_VHANDLE, (p1 + VMBUF_OFFSET));
feed -= 2;
}
}
/*
* Allocate a large buffer
*/
static struct lmbuf *
patm_lmbuf_alloc(struct patm_softc *sc)
{
int error;
struct mbuf *m;
struct lmbuf *b;
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL)
return (NULL);
m->m_data += LMBUF_OFFSET;
if ((b = SLIST_FIRST(&sc->lbuf_free_list)) == NULL) {
m_freem(m);
return (NULL);
}
b->phy = 0; /* alignment */
error = bus_dmamap_load(sc->lbuf_tag, b->map, m->m_data, LMBUF_SIZE,
patm_load_callback, &b->phy, BUS_DMA_NOWAIT);
if (error) {
patm_printf(sc, "%s -- bus_dmamap_load: %d\n", __func__, error);
m_free(m);
return (NULL);
}
SLIST_REMOVE_HEAD(&sc->lbuf_free_list, link);
b->m = m;
return (b);
}
/*
* Feed large buffers into buffer queue 1
*/
static void
patm_feed_lbufs(struct patm_softc *sc)
{
u_int feed;
struct lmbuf *b0, *b1;
feed = patm_feed_cnt(sc, 1);
while (feed > 0) {
if ((b0 = patm_lmbuf_alloc(sc)) == NULL)
break;
if ((b1 = patm_lmbuf_alloc(sc)) == NULL) {
patm_lbuf_free(sc, b0);
break;
}
patm_fbq_write(sc, 1,
LMBUF_HANDLE | b0->handle, b0->phy,
LMBUF_HANDLE | b1->handle, b1->phy);
feed -= 2;
}
}
/*
* Handle transmit status interrupt
*/
static void
patm_intr_tsif(struct patm_softc *sc)
{
struct idt_tsqe *tsqe = sc->tsq_next;
struct idt_tsqe *prev = NULL;
uint32_t stamp;
stamp = le32toh(tsqe->stamp);
if (stamp & IDT_TSQE_EMPTY)
return;
do {
switch (IDT_TSQE_TYPE(stamp)) {
case IDT_TSQE_TBD:
patm_tx(sc, stamp, le32toh(tsqe->stat));
break;
case IDT_TSQE_IDLE:
patm_tx_idle(sc, le32toh(tsqe->stat));
break;
}
/* recycle */
tsqe->stat = 0;
tsqe->stamp = htole32(IDT_TSQE_EMPTY);
/* save pointer to this entry and advance */
prev = tsqe;
if (++tsqe == &sc->tsq[IDT_TSQ_SIZE])
tsqe = &sc->tsq[0];
stamp = le32toh(tsqe->stamp);
} while (!(stamp & IDT_TSQE_EMPTY));
sc->tsq_next = tsqe;
patm_nor_write(sc, IDT_NOR_TSQH, ((prev - sc->tsq) << IDT_TSQE_SHIFT));
}
/*
* Handle receive interrupt
*/
void
patm_intr_rsq(struct patm_softc *sc)
{
struct idt_rsqe *rsqe;
u_int stat;
if (sc->rsq_last + 1 == PATM_RSQ_SIZE)
rsqe = &sc->rsq[0];
else
rsqe = &sc->rsq[sc->rsq_last + 1];
stat = le32toh(rsqe->stat);
if (!(stat & IDT_RSQE_VALID))
return;
while (stat & IDT_RSQE_VALID) {
patm_rx(sc, rsqe);
/* recycle RSQE */
rsqe->cid = 0;
rsqe->handle = 0;
rsqe->crc = 0;
rsqe->stat = 0;
/* save pointer to this entry and advance */
if (++sc->rsq_last == PATM_RSQ_SIZE)
sc->rsq_last = 0;
if (++rsqe == &sc->rsq[PATM_RSQ_SIZE])
rsqe = sc->rsq;
stat = le32toh(rsqe->stat);
}
patm_nor_write(sc, IDT_NOR_RSQH, sc->rsq_phy | (sc->rsq_last << 2));
patm_feed_sbufs(sc);
patm_feed_lbufs(sc);
patm_feed_vbufs(sc);
}
/*
* Handle raw cell receive.
*
* Note that the description on page 3-8 is wrong. The RAWHND contains not
* the same value as RAWCT. RAWCT points to the next address the chip is
* going to write to whike RAWHND points to the last cell's address the chip
* has written to.
*/
static void
patm_intr_raw(struct patm_softc *sc)
{
uint32_t tail;
uint32_t h, *cell;
#ifdef notyet
bus_dma_sync_size(sc->sq_tag, sc->sq_map, IDT_TSQ_SIZE * IDT_TSQE_SIZE +
PATM_RSQ_SIZE * IDT_RSQE_SIZE, sizeof(*sc->rawhnd),
BUS_DMASYNC_POSTREAD);
#endif
/* first turn */
if (sc->rawh == NULL) {
sc->rawh = &sc->lbufs[le32toh(sc->rawhnd->handle) & MBUF_HMASK];
}
tail = le32toh(sc->rawhnd->tail);
if (tail == sc->rawh->phy)
/* not really a raw interrupt */
return;
while (tail + 64 != sc->rawh->phy + sc->rawi * 64) {
#ifdef notyet
bus_dmamap_sync_size(sc->lbuf_tag, sc->rawh->map,
sc->rawi * 64, 64, BUS_DMASYNC_POSTREAD);
#endif
cell = (uint32_t *)(mtod(sc->rawh->m, u_char *) +
sc->rawi * 64);
if (sc->rawi == (LMBUF_SIZE / 64) - 1) {
/* chain */
h = le32toh(cell[1]);
patm_lbuf_free(sc, sc->rawh);
sc->rawh = &sc->lbufs[h & MBUF_HMASK];
sc->rawi = 0;
continue;
}
patm_rx_raw(sc, (u_char *)cell);
sc->rawi++;
}
}
/*
* Free a large mbuf. This is called by us.
*/
void
patm_lbuf_free(struct patm_softc *sc, struct lmbuf *b)
{
bus_dmamap_unload(sc->lbuf_tag, b->map);
if (b->m != NULL) {
m_free(b->m);
b->m = NULL;
}
SLIST_INSERT_HEAD(&sc->lbuf_free_list, b, link);
}
#ifdef PATM_DEBUG
static int
patm_mbuf_cnt(u_int unit)
{
devclass_t dc;
struct patm_softc *sc;
u_int used, card, free;
dc = devclass_find("patm");
if (dc == NULL) {
printf("%s: can't find devclass\n", __func__);
return (0);
}
sc = devclass_get_softc(dc, unit);
if (sc == NULL) {
printf("%s: invalid unit number: %d\n", __func__, unit);
return (0);
}
mbp_count(sc->sbuf_pool, &used, &card, &free);
printf("sbufs: %u on card, %u used, %u free\n", card, used, free);
mbp_count(sc->vbuf_pool, &used, &card, &free);
printf("aal0 bufs: %u on card, %u used, %u free\n", card, used, free);
return (0);
}
#endif

View File

@ -1,412 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* Driver for IDT77252 based cards like ProSum's.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_natm.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/condvar.h>
#include <vm/uma.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_atm.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/if_atm.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/mbpool.h>
#include <dev/utopia/utopia.h>
#include <dev/patm/idt77252reg.h>
#include <dev/patm/if_patmvar.h>
/*
* Open the VCC with the given parameters
*/
static int
patm_open_vcc(struct patm_softc *sc, struct atmio_openvcc *arg)
{
u_int cid;
struct patm_vcc *vcc;
int error = 0;
patm_debug(sc, VCC, "Open VCC: %u.%u flags=%#x", arg->param.vpi,
arg->param.vci, arg->param.flags);
if (!LEGAL_VPI(sc, arg->param.vpi) || !LEGAL_VCI(sc, arg->param.vci))
return (EINVAL);
if (arg->param.vci == 0 && (arg->param.vpi != 0 ||
!(arg->param.flags & ATMIO_FLAG_NOTX) ||
arg->param.aal != ATMIO_AAL_RAW))
return (EINVAL);
cid = PATM_CID(sc, arg->param.vpi, arg->param.vci);
if ((arg->param.flags & ATMIO_FLAG_NOTX) &&
(arg->param.flags & ATMIO_FLAG_NORX))
return (EINVAL);
if ((arg->param.traffic == ATMIO_TRAFFIC_ABR) &&
(arg->param.flags & (ATMIO_FLAG_NOTX | ATMIO_FLAG_NORX)))
return (EINVAL);
/* allocate vcc */
vcc = uma_zalloc(sc->vcc_zone, M_NOWAIT | M_ZERO);
if (vcc == NULL)
return (ENOMEM);
mtx_lock(&sc->mtx);
if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
/* stopped while we have analyzed the arguments */
error = EIO;
goto done;
}
if (sc->vccs[cid] != NULL) {
/* ups, already open */
error = EBUSY;
goto done;
}
/* check some parameters */
vcc->cid = cid;
vcc->vcc = arg->param;
vcc->vflags = 0;
vcc->rxhand = arg->rxhand;
switch (vcc->vcc.aal) {
case ATMIO_AAL_0:
case ATMIO_AAL_34:
case ATMIO_AAL_5:
break;
case ATMIO_AAL_RAW:
if (arg->param.vci == 0 &&
!(arg->param.flags & ATMIO_FLAG_NOTX)) {
error = EINVAL;
goto done;
}
break;
default:
error = EINVAL;
goto done;
}
switch (vcc->vcc.traffic) {
case ATMIO_TRAFFIC_VBR:
case ATMIO_TRAFFIC_UBR:
case ATMIO_TRAFFIC_CBR:
case ATMIO_TRAFFIC_ABR:
break;
default:
error = EINVAL;
goto done;
}
/* initialize */
vcc->chain = NULL;
vcc->last = NULL;
vcc->ibytes = vcc->ipackets = 0;
vcc->obytes = vcc->opackets = 0;
/* ask the TX and RX sides */
patm_debug(sc, VCC, "Open VCC: asking Rx/Tx");
if (!(vcc->vcc.flags & ATMIO_FLAG_NOTX) &&
(error = patm_tx_vcc_can_open(sc, vcc)) != 0)
goto done;
if (!(vcc->vcc.flags & ATMIO_FLAG_NORX) &&
(error = patm_rx_vcc_can_open(sc, vcc)) != 0)
goto done;
/* ok - go ahead */
sc->vccs[cid] = vcc;
patm_load_vc(sc, vcc, 0);
/* don't free below */
vcc = NULL;
sc->vccs_open++;
/* done */
done:
mtx_unlock(&sc->mtx);
if (vcc != NULL)
uma_zfree(sc->vcc_zone, vcc);
return (error);
}
void
patm_load_vc(struct patm_softc *sc, struct patm_vcc *vcc, int reload)
{
patm_debug(sc, VCC, "Open VCC: opening");
if (!(vcc->vcc.flags & ATMIO_FLAG_NOTX))
patm_tx_vcc_open(sc, vcc);
if (!(vcc->vcc.flags & ATMIO_FLAG_NORX))
patm_rx_vcc_open(sc, vcc);
if (!reload) {
/* inform management about non-NG and NG-PVCs */
if (!(vcc->vcc.flags & ATMIO_FLAG_NG) ||
(vcc->vcc.flags & ATMIO_FLAG_PVC))
ATMEV_SEND_VCC_CHANGED(IFP2IFATM(sc->ifp), vcc->vcc.vpi,
vcc->vcc.vci, 1);
}
patm_debug(sc, VCC, "Open VCC: now open");
}
/*
* Try to close the given VCC
*/
static int
patm_close_vcc(struct patm_softc *sc, struct atmio_closevcc *arg)
{
u_int cid;
struct patm_vcc *vcc;
int error = 0;
patm_debug(sc, VCC, "Close VCC: %u.%u", arg->vpi, arg->vci);
if (!LEGAL_VPI(sc, arg->vpi) || !LEGAL_VCI(sc, arg->vci))
return (EINVAL);
cid = PATM_CID(sc, arg->vpi, arg->vci);
mtx_lock(&sc->mtx);
if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
/* stopped while we have analyzed the arguments */
error = EIO;
goto done;
}
vcc = sc->vccs[cid];
if (vcc == NULL || !(vcc->vflags & PATM_VCC_OPEN)) {
error = ENOENT;
goto done;
}
if (vcc->vflags & PATM_VCC_TX_OPEN)
patm_tx_vcc_close(sc, vcc);
if (vcc->vflags & PATM_VCC_RX_OPEN)
patm_rx_vcc_close(sc, vcc);
if (vcc->vcc.flags & ATMIO_FLAG_ASYNC)
goto done;
while (vcc->vflags & (PATM_VCC_TX_CLOSING | PATM_VCC_RX_CLOSING)) {
cv_wait(&sc->vcc_cv, &sc->mtx);
if (!(sc->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
/* ups, has been stopped */
error = EIO;
goto done;
}
}
if (!(vcc->vcc.flags & ATMIO_FLAG_NOTX))
patm_tx_vcc_closed(sc, vcc);
if (!(vcc->vcc.flags & ATMIO_FLAG_NORX))
patm_rx_vcc_closed(sc, vcc);
patm_vcc_closed(sc, vcc);
done:
mtx_unlock(&sc->mtx);
return (error);
}
/*
* VCC has been finally closed.
*/
void
patm_vcc_closed(struct patm_softc *sc, struct patm_vcc *vcc)
{
/* inform management about non-NG and NG-PVCs */
if (!(vcc->vcc.flags & ATMIO_FLAG_NG) ||
(vcc->vcc.flags & ATMIO_FLAG_PVC))
ATMEV_SEND_VCC_CHANGED(IFP2IFATM(sc->ifp), vcc->vcc.vpi,
vcc->vcc.vci, 0);
sc->vccs_open--;
sc->vccs[vcc->cid] = NULL;
uma_zfree(sc->vcc_zone, vcc);
}
int
patm_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct ifreq *ifr = (struct ifreq *)data;
struct ifaddr *ifa = (struct ifaddr *)data;
struct patm_softc *sc = ifp->if_softc;
int error = 0;
uint32_t cfg;
struct atmio_vcctable *vtab;
switch (cmd) {
case SIOCSIFADDR:
mtx_lock(&sc->mtx);
ifp->if_flags |= IFF_UP;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
patm_initialize(sc);
switch (ifa->ifa_addr->sa_family) {
#ifdef INET
case AF_INET:
case AF_INET6:
ifa->ifa_rtrequest = atm_rtrequest;
break;
#endif
default:
break;
}
mtx_unlock(&sc->mtx);
break;
case SIOCSIFFLAGS:
mtx_lock(&sc->mtx);
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
patm_initialize(sc);
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
patm_stop(sc);
}
}
mtx_unlock(&sc->mtx);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd);
/*
* We need to toggle unassigned/idle cells ourself because
* the 77252 generates null cells for spacing. When switching
* null cells of it gets the timing wrong.
*/
mtx_lock(&sc->mtx);
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
if (sc->utopia.state & UTP_ST_UNASS) {
if (!(sc->flags & PATM_UNASS)) {
cfg = patm_nor_read(sc, IDT_NOR_CFG);
cfg &= ~IDT_CFG_IDLECLP;
patm_nor_write(sc, IDT_NOR_CFG, cfg);
sc->flags |= PATM_UNASS;
}
} else {
if (sc->flags & PATM_UNASS) {
cfg = patm_nor_read(sc, IDT_NOR_CFG);
cfg |= IDT_CFG_IDLECLP;
patm_nor_write(sc, IDT_NOR_CFG, cfg);
sc->flags &= ~PATM_UNASS;
}
}
} else {
if (sc->utopia.state & UTP_ST_UNASS)
sc->flags |= PATM_UNASS;
else
sc->flags &= ~PATM_UNASS;
}
mtx_unlock(&sc->mtx);
break;
case SIOCSIFMTU:
/*
* Set the interface MTU.
*/
if (ifr->ifr_mtu > ATMMTU)
error = EINVAL;
else
ifp->if_mtu = ifr->ifr_mtu;
break;
case SIOCATMOPENVCC: /* kernel internal use */
error = patm_open_vcc(sc, (struct atmio_openvcc *)data);
break;
case SIOCATMCLOSEVCC: /* kernel internal use */
error = patm_close_vcc(sc, (struct atmio_closevcc *)data);
break;
case SIOCATMGVCCS: /* external use */
/* return vcc table */
vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
sc->mmap->max_conn, sc->vccs_open, &sc->mtx, 1);
error = copyout(vtab, ifr->ifr_data, sizeof(*vtab) +
vtab->count * sizeof(vtab->vccs[0]));
free(vtab, M_DEVBUF);
break;
case SIOCATMGETVCCS: /* netgraph internal use */
vtab = atm_getvccs((struct atmio_vcc **)sc->vccs,
sc->mmap->max_conn, sc->vccs_open, &sc->mtx, 0);
if (vtab == NULL) {
error = ENOMEM;
break;
}
*(void **)data = vtab;
break;
default:
patm_debug(sc, IOCTL, "unknown cmd=%08lx arg=%p", cmd, data);
error = EINVAL;
break;
}
return (error);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,526 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* Driver for IDT77252 based cards like ProSum's.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_natm.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/condvar.h>
#include <sys/endian.h>
#include <vm/uma.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_atm.h>
#include <net/route.h>
#ifdef ENABLE_BPF
#include <net/bpf.h>
#endif
#include <netinet/in.h>
#include <netinet/if_atm.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/mbpool.h>
#include <dev/utopia/utopia.h>
#include <dev/patm/idt77252reg.h>
#include <dev/patm/if_patmvar.h>
static void *patm_rcv_handle(struct patm_softc *sc, u_int handle);
static void patm_rcv_free(struct patm_softc *, void *, u_int handle);
static struct mbuf *patm_rcv_mbuf(struct patm_softc *, void *, u_int, int);
static __inline void
rct_write(struct patm_softc *sc, u_int cid, u_int w, u_int val)
{
patm_sram_write(sc, sc->mmap->rct + cid * IDT_RCT_ENTRY_SIZE + w, val);
}
static __inline u_int
rct_read(struct patm_softc *sc, u_int cid, u_int w)
{
return (patm_sram_read(sc, sc->mmap->rct +
cid * IDT_RCT_ENTRY_SIZE + w));
}
/* check if we can open this one */
int
patm_rx_vcc_can_open(struct patm_softc *sc, struct patm_vcc *vcc)
{
return (0);
}
/*
* open the VCC
*/
void
patm_rx_vcc_open(struct patm_softc *sc, struct patm_vcc *vcc)
{
uint32_t w1 = IDT_RCT_OPEN;
patm_debug(sc, VCC, "%u.%u RX opening", vcc->vcc.vpi, vcc->vcc.vci);
switch (vcc->vcc.aal) {
case ATMIO_AAL_0:
w1 |= IDT_RCT_AAL0 | IDT_RCT_FBP2 | IDT_RCT_RCI;
break;
case ATMIO_AAL_34:
w1 |= IDT_RCT_AAL34;
break;
case ATMIO_AAL_5:
w1 |= IDT_RCT_AAL5;
break;
case ATMIO_AAL_RAW:
w1 |= IDT_RCT_AALRAW | IDT_RCT_RCI;
break;
}
if (vcc->cid != 0)
patm_sram_write4(sc, sc->mmap->rct + vcc->cid *
IDT_RCT_ENTRY_SIZE, w1, 0, 0, 0xffffffff);
else {
/* switch the interface into promiscuous mode */
patm_nor_write(sc, IDT_NOR_CFG, patm_nor_read(sc, IDT_NOR_CFG) |
IDT_CFG_ICAPT | IDT_CFG_VPECA);
}
vcc->vflags |= PATM_VCC_RX_OPEN;
}
/* close the given vcc for transmission */
void
patm_rx_vcc_close(struct patm_softc *sc, struct patm_vcc *vcc)
{
u_int w1;
patm_debug(sc, VCC, "%u.%u RX closing", vcc->vcc.vpi, vcc->vcc.vci);
if (vcc->cid == 0) {
/* switch off promiscuous mode */
patm_nor_write(sc, IDT_NOR_CFG, patm_nor_read(sc, IDT_NOR_CFG) &
~(IDT_CFG_ICAPT | IDT_CFG_VPECA));
vcc->vflags &= ~PATM_VCC_RX_OPEN;
return;
}
/* close the connection but keep state */
w1 = rct_read(sc, vcc->cid, 0);
w1 &= ~IDT_RCT_OPEN;
rct_write(sc, vcc->cid, 0, w1);
/* minimum idle count */
w1 = (w1 & ~IDT_RCT_IACT_CNT_MASK) | (1 << IDT_RCT_IACT_CNT_SHIFT);
rct_write(sc, vcc->cid, 0, w1);
/* initialize scan */
patm_nor_write(sc, IDT_NOR_IRCP, vcc->cid);
vcc->vflags &= ~PATM_VCC_RX_OPEN;
vcc->vflags |= PATM_VCC_RX_CLOSING;
/*
* check the RSQ
* This is a hack. The problem is, that although an entry is written
* to the RSQ, no interrupt is generated. Also we must wait 1 cell
* time for the SAR to process the scan of our connection.
*/
DELAY(1);
patm_intr_rsq(sc);
}
/* transmission side finally closed */
void
patm_rx_vcc_closed(struct patm_softc *sc, struct patm_vcc *vcc)
{
patm_debug(sc, VCC, "%u.%u RX finally closed",
vcc->vcc.vpi, vcc->vcc.vci);
}
/*
* Handle the given receive status queue entry
*/
void
patm_rx(struct patm_softc *sc, struct idt_rsqe *rsqe)
{
struct mbuf *m;
void *buf;
u_int stat, cid, w, cells, len, h;
struct patm_vcc *vcc;
struct atm_pseudohdr aph;
u_char *trail;
cid = le32toh(rsqe->cid);
stat = le32toh(rsqe->stat);
h = le32toh(rsqe->handle);
cid = PATM_CID(sc, IDT_RSQE_VPI(cid), IDT_RSQE_VCI(cid));
vcc = sc->vccs[cid];
if (IDT_RSQE_TYPE(stat) == IDT_RSQE_IDLE) {
/* connection has gone idle */
if (stat & IDT_RSQE_BUF)
patm_rcv_free(sc, patm_rcv_handle(sc, h), h);
w = rct_read(sc, cid, 0);
if (w != 0 && !(w & IDT_RCT_OPEN))
rct_write(sc, cid, 0, 0);
if (vcc != NULL && (vcc->vflags & PATM_VCC_RX_CLOSING)) {
patm_debug(sc, VCC, "%u.%u RX closed", vcc->vcc.vpi,
vcc->vcc.vci);
vcc->vflags &= ~PATM_VCC_RX_CLOSING;
if (vcc->vcc.flags & ATMIO_FLAG_ASYNC) {
patm_rx_vcc_closed(sc, vcc);
if (!(vcc->vflags & PATM_VCC_OPEN))
patm_vcc_closed(sc, vcc);
} else
cv_signal(&sc->vcc_cv);
}
return;
}
buf = patm_rcv_handle(sc, h);
if (vcc == NULL || (vcc->vflags & PATM_VCC_RX_OPEN) == 0) {
patm_rcv_free(sc, buf, h);
return;
}
cells = IDT_RSQE_CNT(stat);
KASSERT(cells > 0, ("zero cell count"));
if (vcc->vcc.aal == ATMIO_AAL_0) {
/* deliver this packet as it is */
if ((m = patm_rcv_mbuf(sc, buf, h, 1)) == NULL)
return;
m->m_len = cells * 48;
m->m_pkthdr.len = m->m_len;
m->m_pkthdr.rcvif = sc->ifp;
} else if (vcc->vcc.aal == ATMIO_AAL_34) {
/* XXX AAL3/4 */
patm_rcv_free(sc, buf, h);
return;
} else if (vcc->vcc.aal == ATMIO_AAL_5) {
if (stat & IDT_RSQE_CRC) {
if_inc_counter(sc->ifp, IFCOUNTER_IERRORS, 1);
if (vcc->chain != NULL) {
m_freem(vcc->chain);
vcc->chain = vcc->last = NULL;
}
return;
}
/* append to current chain */
if (vcc->chain == NULL) {
if ((m = patm_rcv_mbuf(sc, buf, h, 1)) == NULL)
return;
m->m_len = cells * 48;
m->m_pkthdr.len = m->m_len;
m->m_pkthdr.rcvif = sc->ifp;
vcc->chain = vcc->last = m;
} else {
if ((m = patm_rcv_mbuf(sc, buf, h, 0)) == NULL)
return;
m->m_len = cells * 48;
vcc->last->m_next = m;
vcc->last = m;
vcc->chain->m_pkthdr.len += m->m_len;
}
if (!(stat & IDT_RSQE_EPDU))
return;
trail = mtod(m, u_char *) + m->m_len - 6;
len = (trail[0] << 8) + trail[1];
if ((u_int)vcc->chain->m_pkthdr.len < len + 8) {
patm_printf(sc, "%s: bad aal5 lengths %u %u\n",
__func__, (u_int)m->m_pkthdr.len, len);
m_freem(vcc->chain);
vcc->chain = vcc->last = NULL;
return;
}
m->m_len -= vcc->chain->m_pkthdr.len - len;
KASSERT(m->m_len >= 0, ("bad last mbuf"));
m = vcc->chain;
vcc->chain = vcc->last = NULL;
m->m_pkthdr.len = len;
} else
panic("bad aal");
#if 0
{
u_int i;
for (i = 0; i < m->m_len; i++) {
printf("%02x ", mtod(m, u_char *)[i]);
}
printf("\n");
}
#endif
if_inc_counter(sc->ifp, IFCOUNTER_IPACKETS, 1);
/* this is in if_atmsubr.c */
/* if_inc_counter(sc->ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); */
vcc->ibytes += m->m_pkthdr.len;
vcc->ipackets++;
ATM_PH_FLAGS(&aph) = vcc->vcc.flags & 0xff;
ATM_PH_VPI(&aph) = IDT_RSQE_VPI(cid);
ATM_PH_SETVCI(&aph, IDT_RSQE_VCI(cid));
#ifdef ENABLE_BPF
if (!(vcc->vcc.flags & ATMIO_FLAG_NG) &&
(vcc->vcc.aal == ATMIO_AAL_5) &&
(vcc->vcc.flags & ATM_PH_LLCSNAP))
BPF_MTAP(sc->ifp, m);
#endif
atm_input(sc->ifp, &aph, m, vcc->rxhand);
}
/*
* Get the buffer for a receive handle. This is either an mbuf for
* a large handle or a pool buffer for the others.
*/
static void *
patm_rcv_handle(struct patm_softc *sc, u_int handle)
{
void *buf;
u_int c;
if ((handle & ~MBUF_HMASK) == LMBUF_HANDLE) {
struct lmbuf *b;
c = handle & MBUF_HMASK;
b = &sc->lbufs[c];
buf = b->m;
b->m = NULL;
bus_dmamap_sync(sc->lbuf_tag, b->map, BUS_DMASYNC_POSTREAD);
patm_lbuf_free(sc, b);
} else if ((handle & ~MBUF_HMASK) == MBUF_VHANDLE) {
mbp_sync(sc->vbuf_pool, handle,
0, VMBUF_SIZE, BUS_DMASYNC_POSTREAD);
buf = mbp_get(sc->vbuf_pool, handle);
} else {
mbp_sync(sc->sbuf_pool, handle,
0, SMBUF_SIZE, BUS_DMASYNC_POSTREAD);
buf = mbp_get(sc->sbuf_pool, handle);
}
return (buf);
}
/*
* Free a buffer.
*/
static void
patm_rcv_free(struct patm_softc *sc, void *p, u_int handle)
{
if ((handle & ~MBUF_HMASK) == LMBUF_HANDLE)
m_free((struct mbuf *)p);
else if ((handle & ~MBUF_HMASK) == MBUF_VHANDLE)
mbp_free(sc->vbuf_pool, p);
else
mbp_free(sc->sbuf_pool, p);
}
/*
* Make an mbuf around the buffer
*/
static struct mbuf *
patm_rcv_mbuf(struct patm_softc *sc, void *buf, u_int h, int hdr)
{
struct mbuf *m;
if ((h & ~MBUF_HMASK) == MBUF_LHANDLE)
return ((struct mbuf *)buf);
if (hdr)
MGETHDR(m, M_NOWAIT, MT_DATA);
else
MGET(m, M_NOWAIT, MT_DATA);
if (m == NULL) {
patm_rcv_free(sc, buf, h);
return (NULL);
}
if ((h & ~MBUF_HMASK) == MBUF_VHANDLE) {
MEXTADD(m, (caddr_t)buf, VMBUF_SIZE, mbp_ext_free,
buf, sc->vbuf_pool, M_PKTHDR, EXT_NET_DRV);
m->m_data += VMBUF_OFFSET;
} else {
MEXTADD(m, (caddr_t)buf, SMBUF_SIZE, mbp_ext_free,
buf, sc->sbuf_pool, M_PKTHDR, EXT_NET_DRV);
m->m_data += SMBUF_OFFSET;
}
if (!(m->m_flags & M_EXT)) {
patm_rcv_free(sc, buf, h);
m_free(m);
return (NULL);
}
return (m);
}
/*
* Process the raw cell at the given address.
*/
void
patm_rx_raw(struct patm_softc *sc, u_char *cell)
{
u_int vpi, vci, cid;
struct patm_vcc *vcc;
struct mbuf *m;
u_char *dst;
struct timespec ts;
struct atm_pseudohdr aph;
uint64_t cts;
sc->stats.raw_cells++;
/*
* For some non-appearant reason the cell header
* is in the wrong endian.
*/
*(uint32_t *)cell = bswap32(*(uint32_t *)cell);
vpi = ((cell[0] & 0xf) << 4) | ((cell[1] & 0xf0) >> 4);
vci = ((cell[1] & 0xf) << 12) | (cell[2] << 4) | ((cell[3] & 0xf0) >> 4);
cid = PATM_CID(sc, vpi, vci);
vcc = sc->vccs[cid];
if (vcc == NULL || !(vcc->vflags & PATM_VCC_RX_OPEN) ||
vcc->vcc.aal != ATMIO_AAL_RAW) {
vcc = sc->vccs[0];
if (vcc == NULL || !(vcc->vflags & PATM_VCC_RX_OPEN)) {
sc->stats.raw_no_vcc++;
return;
}
}
MGETHDR(m, M_NOWAIT, MT_DATA);
if (m == NULL) {
sc->stats.raw_no_buf++;
return;
}
m->m_pkthdr.rcvif = sc->ifp;
switch (vcc->vflags & PATM_RAW_FORMAT) {
default:
case PATM_RAW_CELL:
m->m_len = m->m_pkthdr.len = 53;
M_ALIGN(m, 53);
dst = mtod(m, u_char *);
*dst++ = *cell++;
*dst++ = *cell++;
*dst++ = *cell++;
*dst++ = *cell++;
*dst++ = 0; /* HEC */
bcopy(cell + 12, dst, 48);
break;
case PATM_RAW_NOHEC:
m->m_len = m->m_pkthdr.len = 52;
M_ALIGN(m, 52);
dst = mtod(m, u_char *);
*dst++ = *cell++;
*dst++ = *cell++;
*dst++ = *cell++;
*dst++ = *cell++;
bcopy(cell + 12, dst, 48);
break;
case PATM_RAW_CS:
m->m_len = m->m_pkthdr.len = 64;
M_ALIGN(m, 64);
dst = mtod(m, u_char *);
*dst++ = *cell++;
*dst++ = *cell++;
*dst++ = *cell++;
*dst++ = *cell++;
*dst++ = 0; /* HEC */
*dst++ = 0; /* flags */
*dst++ = 0; /* reserved */
*dst++ = 0; /* reserved */
nanotime(&ts);
cts = ts.tv_sec * 1000000000ULL + ts.tv_nsec;
bcopy(dst, &cts, 8);
bcopy(cell + 12, dst + 8, 48);
break;
}
if_inc_counter(sc->ifp, IFCOUNTER_IPACKETS, 1);
/* this is in if_atmsubr.c */
/* if_inc_counter(sc->ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); */
vcc->ibytes += m->m_pkthdr.len;
vcc->ipackets++;
ATM_PH_FLAGS(&aph) = vcc->vcc.flags & 0xff;
ATM_PH_VPI(&aph) = vcc->vcc.vpi;
ATM_PH_SETVCI(&aph, vcc->vcc.vci);
atm_input(sc->ifp, &aph, m, vcc->rxhand);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,520 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*
* Driver for IDT77252 (ABR) based cards like ProSum's.
*/
/* legal values are 0, 1, 2 and 8 */
#define PATM_VPI_BITS 2
#define PATM_CFG_VPI IDT_CFG_VP2
/* receive status queue size */
#define PATM_RSQ_SIZE 512
#define PATM_CFQ_RSQ_SIZE IDT_CFG_RXQ512
/* alignment for SQ memory */
#define PATM_SQ_ALIGNMENT 8192
#define PATM_PROATM_NAME_OFFSET 060
#define PATM_PROATM_NAME "PROATM"
#define PATM_PROATM_MAC_OFFSET 044
#define PATM_IDT_MAC_OFFSET 0154
/* maximum number of packets on UBR queue */
#define PATM_DLFT_MAXQ 1000
/* maximum number of packets on other queues. This should depend on the
* traffic contract. */
#define PATM_TX_IFQLEN 100
/*
* Maximum number of DMA maps we allocate. This is the minimum that can be
* set larger via a sysctl.
* Starting number of DMA maps.
* Step for growing.
*/
#define PATM_CFG_TXMAPS_MAX 1024
#define PATM_CFG_TXMAPS_INIT 128
#define PATM_CFG_TXMAPS_STEP 128
/* percents of TST slots to keep for non-CBR traffic */
#define PATM_TST_RESERVE 2
/*
* Structure to hold TX DMA maps
*/
struct patm_txmap {
SLIST_ENTRY(patm_txmap) link;
bus_dmamap_t map;
};
/*
* Receive buffers.
*
* We manage our own external mbufs for small receive buffers for two reasons:
* the card may consume a rather large number of buffers. Mapping each buffer
* would consume a lot of iospace on sparc64. Also the card allows us to set
* a 32-bit handle for identification of the buffers. On a 64-bit system this
* requires us to use a mapping between buffers and handles.
*
* For large buffers we use mbuf clusters directly. We track these by using
* an array of pointers (lbufs) to special structs and a free list of these
* structs.
*
* For AAL0 cell we use FBQ2 and make the 1 cell long.
*/
/*
* Define the small buffer chunk so that we have at least 16 byte free
* at the end of the chunk and that there is an integral number of chunks
* in a page.
*/
#define SMBUF_PAGE_SIZE 16384 /* 16k pages */
#define SMBUF_MAX_PAGES 64 /* maximum number of pages */
#define SMBUF_CHUNK_SIZE 256 /* 256 bytes per chunk */
#define SMBUF_CELLS 5
#define SMBUF_SIZE (SMBUF_CELLS * 48)
#define SMBUF_THRESHOLD 9 /* 9/16 of queue size */
#define SMBUF_NI_THRESH 3
#define SMBUF_CI_THRESH 1
#define VMBUF_PAGE_SIZE 16384 /* 16k pages */
#define VMBUF_MAX_PAGES 16 /* maximum number of pages */
#define VMBUF_CHUNK_SIZE 64 /* 64 bytes per chunk */
#define VMBUF_CELLS 1
#define VMBUF_SIZE (VMBUF_CELLS * 48)
#define VMBUF_THRESHOLD 15 /* 15/16 of size */
#define SMBUF_OFFSET (SMBUF_CHUNK_SIZE - 8 - SMBUF_SIZE)
#define VMBUF_OFFSET 0
#define MBUF_SHANDLE 0x00000000
#define MBUF_LHANDLE 0x80000000
#define MBUF_VHANDLE 0x40000000
#define MBUF_HMASK 0x3fffffff
/*
* Large buffers
*
* The problem with these is the maximum count. When the card assembles
* a AAL5 pdu it moves a buffer from the FBQ to the VC. This frees space
* in the FBQ, put the buffer may pend on the card for an unlimited amount
* of time (we don't idle connections). This means that the upper limit
* on buffers on the card may be (no-of-open-vcs + FBQ_SIZE). Because
* this is far too much, make this a tuneable. We could also make
* this dynamic by allocating pages of several lbufs at once during run time.
*/
#define LMBUF_MAX (IDT_FBQ_SIZE * 2)
#define LMBUF_CELLS (MCLBYTES / 48) /* 42 cells = 2048 byte */
#define LMBUF_SIZE (LMBUF_CELLS * 48)
#define LMBUF_THRESHOLD 9 /* 9/16 of queue size */
#define LMBUF_OFFSET (MCLBYTES - LMBUF_SIZE)
#define LMBUF_NI_THRESH 3
#define LMBUF_CI_THRESH 1
#define LMBUF_HANDLE 0x80000000
struct lmbuf {
SLIST_ENTRY(lmbuf) link; /* free list link */
bus_dmamap_t map; /* DMA map */
u_int handle; /* this is the handle index */
struct mbuf *m; /* the current mbuf */
bus_addr_t phy; /* phy addr */
};
#define PATM_CID(SC, VPI, VCI) \
(((VPI) << IFP2IFATM((SC)->ifp)->mib.vci_bits) | (VCI))
/*
* Internal driver statistics
*/
struct patm_stats {
uint32_t raw_cells;
uint32_t raw_no_vcc;
uint32_t raw_no_buf;
uint32_t tx_qfull;
uint32_t tx_out_of_tbds;
uint32_t tx_out_of_maps;
uint32_t tx_load_err;
};
/*
* These are allocated as DMA able memory
*/
struct patm_scd {
struct idt_tbd scq[IDT_SCQ_SIZE];
LIST_ENTRY(patm_scd) link; /* all active SCDs */
uint32_t sram; /* SRAM address */
bus_addr_t phy; /* physical address */
bus_dmamap_t map; /* DMA map */
u_int tail; /* next free entry for host */
int space; /* number of free entries (minus one) */
u_int slots; /* CBR slots allocated */
uint8_t tag; /* next tag for TSI */
uint8_t last_tag; /* last tag checked in interrupt */
uint8_t num_on_card; /* number of PDUs on tx queue */
uint8_t lacr; /* LogACR value */
uint8_t init_er; /* LogER value */
struct ifqueue q; /* queue of packets */
struct mbuf *on_card[IDT_TSQE_TAG_SPACE];
};
/*
* Per-VCC data
*/
struct patm_vcc {
struct atmio_vcc vcc; /* caller's parameters */
void *rxhand; /* NATM handle */
u_int vflags; /* open and other flags */
uint32_t ipackets; /* packets received */
uint32_t opackets; /* packets sent */
uint64_t ibytes; /* bytes received */
uint64_t obytes; /* bytes sent */
struct mbuf *chain; /* currently received chain */
struct mbuf *last; /* end of chain */
u_int cid; /* index */
u_int cps; /* last ABR cps */
struct patm_scd *scd;
};
#define PATM_VCC_TX_OPEN 0x0001
#define PATM_VCC_RX_OPEN 0x0002
#define PATM_VCC_TX_CLOSING 0x0004
#define PATM_VCC_RX_CLOSING 0x0008
#define PATM_VCC_OPEN 0x000f /* all the above */
#define PATM_RAW_CELL 0x0000 /* 53 byte cells */
#define PATM_RAW_NOHEC 0x0100 /* 52 byte cells */
#define PATM_RAW_CS 0x0200 /* 64 byte cell stream */
#define PATM_RAW_FORMAT 0x0300 /* format mask */
/*
* Per adapter data
*/
struct patm_softc {
struct ifnet *ifp; /* common ATM stuff */
struct mtx mtx; /* lock */
struct ifmedia media; /* media */
device_t dev; /* device */
struct resource * memres; /* memory resource */
bus_space_handle_t memh; /* handle */
bus_space_tag_t memt; /* ... and tag */
int irqid; /* resource id */
struct resource * irqres; /* resource */
void * ih; /* interrupt handle */
struct utopia utopia; /* phy state */
const struct idt_mmap *mmap; /* SRAM memory map */
u_int flags; /* see below */
u_int revision; /* chip revision */
/* DMAable status queue memory */
size_t sq_size; /* size of memory area */
bus_dma_tag_t sq_tag; /* DMA tag */
bus_dmamap_t sq_map; /* map */
bus_addr_t tsq_phy; /* phys addr. */
struct idt_tsqe *tsq; /* transmit status queue */
struct idt_tsqe *tsq_next; /* last processed entry */
struct idt_rsqe *rsq; /* receive status queue */
bus_addr_t rsq_phy; /* phys addr. */
u_int rsq_last; /* last processed entry */
struct idt_rawhnd *rawhnd; /* raw cell handle */
bus_addr_t rawhnd_phy; /* phys addr. */
/* TST */
u_int tst_state; /* active TST and others */
u_int tst_jump[2]; /* address of the jumps */
u_int tst_base[2]; /* base address of TST */
u_int *tst_soft; /* soft TST */
struct mtx tst_lock;
struct callout tst_callout;
u_int tst_free; /* free slots */
u_int tst_reserve; /* non-CBR reserve */
u_int bwrem; /* remaining bandwidth */
/* sysctl support */
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
/* EEPROM contents */
uint8_t eeprom[256];
/* large buffer mapping */
bus_dma_tag_t lbuf_tag; /* DMA tag */
u_int lbuf_max; /* maximum number */
struct lmbuf *lbufs; /* array for indexing */
SLIST_HEAD(,lmbuf) lbuf_free_list; /* free list */
/* small buffer handling */
bus_dma_tag_t sbuf_tag; /* DMA tag */
struct mbpool *sbuf_pool; /* pool */
struct mbpool *vbuf_pool; /* pool */
/* raw cell queue */
struct lmbuf *rawh; /* current header buf */
u_int rawi; /* cell index into buffer */
/* statistics */
struct patm_stats stats; /* statistics */
/* Vccs */
struct patm_vcc **vccs; /* channel pointer array */
u_int vccs_open; /* number of open channels */
uma_zone_t vcc_zone;
struct cv vcc_cv;
/* SCDs */
uint32_t scd_free; /* SRAM of first free SCD */
bus_dma_tag_t scd_tag;
struct patm_scd *scd0;
LIST_HEAD(, patm_scd) scd_list; /* list of all active SCDs */
/* Tx */
bus_dma_tag_t tx_tag; /* for transmission */
SLIST_HEAD(, patm_txmap) tx_maps_free; /* free maps */
u_int tx_nmaps; /* allocated maps */
u_int tx_maxmaps; /* maximum number */
struct uma_zone *tx_mapzone; /* zone for maps */
#ifdef PATM_DEBUG
/* debugging */
u_int debug;
#endif
};
/* flags */
#define PATM_25M 0x0001 /* 25MBit card */
#define PATM_SBUFW 0x0002 /* warned */
#define PATM_VBUFW 0x0004 /* warned */
#define PATM_UNASS 0x0010 /* unassigned cells */
#define PATM_CLR 0x0007 /* clear on stop */
/* tst - uses unused fields */
#define TST_BOTH 0x03000000
#define TST_CH0 0x01000000
#define TST_CH1 0x02000000
/* tst_state */
#define TST_ACT1 0x0001 /* active TST */
#define TST_PENDING 0x0002 /* need update */
#define TST_WAIT 0x0004 /* wait fo jump */
#define patm_printf(SC, ...) if_printf((SC)->ifp, __VA_ARGS__);
#ifdef PATM_DEBUG
/*
* Debugging
*/
enum {
DBG_ATTACH = 0x0001, /* attaching the card */
DBG_INTR = 0x0002, /* interrupts */
DBG_REG = 0x0004, /* register access */
DBG_SRAM = 0x0008, /* SRAM access */
DBG_PHY = 0x0010, /* PHY access */
DBG_IOCTL = 0x0020, /* ioctl */
DBG_FREEQ = 0x0040, /* free bufq supply */
DBG_VCC = 0x0080, /* open/close */
DBG_TX = 0x0100, /* transmission */
DBG_TST = 0x0200, /* TST */
DBG_ALL = 0xffff
};
#define patm_debug(SC, FLAG, ...) do { \
if((SC)->debug & DBG_##FLAG) { \
if_printf((SC)->ifp, "%s: ", __func__); \
printf(__VA_ARGS__); \
printf("\n"); \
} \
} while (0)
#else
#define patm_debug(SC, FLAG, ...) do { } while (0)
#endif
/* start output */
void patm_start(struct ifnet *);
/* ioctl handler */
int patm_ioctl(struct ifnet *, u_long, caddr_t);
/* start the interface */
void patm_init(void *);
/* start the interface with the lock held */
void patm_initialize(struct patm_softc *);
/* stop the interface */
void patm_stop(struct patm_softc *);
/* software reset of interface */
void patm_reset(struct patm_softc *);
/* interrupt handler */
void patm_intr(void *);
/* check RSQ */
void patm_intr_rsq(struct patm_softc *sc);
/* enable the vcc */
void patm_load_vc(struct patm_softc *sc, struct patm_vcc *vcc, int reload);
/* close the given vcc for transmission */
void patm_tx_vcc_close(struct patm_softc *, struct patm_vcc *);
/* close the given vcc for receive */
void patm_rx_vcc_close(struct patm_softc *, struct patm_vcc *);
/* transmission side finally closed */
void patm_tx_vcc_closed(struct patm_softc *, struct patm_vcc *);
/* receive side finally closed */
void patm_rx_vcc_closed(struct patm_softc *, struct patm_vcc *);
/* vcc closed */
void patm_vcc_closed(struct patm_softc *, struct patm_vcc *);
/* check if we can open this one */
int patm_tx_vcc_can_open(struct patm_softc *, struct patm_vcc *);
/* check if we can open this one */
int patm_rx_vcc_can_open(struct patm_softc *, struct patm_vcc *);
/* open it */
void patm_tx_vcc_open(struct patm_softc *, struct patm_vcc *);
/* open it */
void patm_rx_vcc_open(struct patm_softc *, struct patm_vcc *);
/* receive packet */
void patm_rx(struct patm_softc *, struct idt_rsqe *);
/* packet transmitted */
void patm_tx(struct patm_softc *, u_int, u_int);
/* VBR connection went idle */
void patm_tx_idle(struct patm_softc *, u_int);
/* allocate an SCQ */
struct patm_scd *patm_scd_alloc(struct patm_softc *);
/* free an SCD */
void patm_scd_free(struct patm_softc *sc, struct patm_scd *scd);
/* setup SCD in SRAM */
void patm_scd_setup(struct patm_softc *sc, struct patm_scd *scd);
/* setup TCT entry in SRAM */
void patm_tct_setup(struct patm_softc *, struct patm_scd *, struct patm_vcc *);
/* free a large buffer */
void patm_lbuf_free(struct patm_softc *sc, struct lmbuf *b);
/* Process the raw cell at the given address */
void patm_rx_raw(struct patm_softc *sc, u_char *cell);
/* load a one segment DMA map */
void patm_load_callback(void *, bus_dma_segment_t *, int, int);
/* network operation register access */
static __inline uint32_t
patm_nor_read(struct patm_softc *sc, u_int reg)
{
uint32_t val;
val = bus_space_read_4(sc->memt, sc->memh, reg);
patm_debug(sc, REG, "reg(0x%x)=%04x", reg, val);
return (val);
}
static __inline void
patm_nor_write(struct patm_softc *sc, u_int reg, uint32_t val)
{
patm_debug(sc, REG, "reg(0x%x)=%04x", reg, val);
bus_space_write_4(sc->memt, sc->memh, reg, val);
}
/* Execute command */
static __inline void
patm_cmd_wait(struct patm_softc *sc)
{
while (patm_nor_read(sc, IDT_NOR_STAT) & IDT_STAT_CMDBZ)
;
}
static __inline void
patm_cmd_exec(struct patm_softc *sc, uint32_t cmd)
{
patm_cmd_wait(sc);
patm_nor_write(sc, IDT_NOR_CMD, cmd);
}
/* Read/write SRAM at the given word address. */
static __inline uint32_t
patm_sram_read(struct patm_softc *sc, u_int addr)
{
uint32_t val;
patm_cmd_exec(sc, IDT_MKCMD_RSRAM(addr));
patm_cmd_wait(sc);
val = patm_nor_read(sc, IDT_NOR_D0);
patm_debug(sc, SRAM, "read %04x=%08x", addr, val);
return (val);
}
static __inline void
patm_sram_write(struct patm_softc *sc, u_int addr, uint32_t val)
{
patm_debug(sc, SRAM, "write %04x=%08x", addr, val);
patm_cmd_wait(sc);
patm_nor_write(sc, IDT_NOR_D0, val);
patm_cmd_exec(sc, IDT_MKCMD_WSRAM(addr, 0));
}
static __inline void
patm_sram_write4(struct patm_softc *sc, u_int addr, uint32_t v0, uint32_t v1,
uint32_t v2, uint32_t v3)
{
patm_debug(sc, SRAM, "write %04x=%08x,%08x,%08x,%08x",
addr, v0, v1, v2, v3);
patm_cmd_wait(sc);
patm_nor_write(sc, IDT_NOR_D0, v0);
patm_nor_write(sc, IDT_NOR_D1, v1);
patm_nor_write(sc, IDT_NOR_D2, v2);
patm_nor_write(sc, IDT_NOR_D3, v3);
patm_cmd_exec(sc, IDT_MKCMD_WSRAM(addr, 3));
}
#define LEGAL_VPI(SC, VPI) \
(((VPI) & ~((1 << IFP2IFATM((SC)->ifp)->mib.vpi_bits) - 1)) == 0)
#define LEGAL_VCI(SC, VCI) \
(((VCI) & ~((1 << IFP2IFATM((SC)->ifp)->mib.vci_bits) - 1)) == 0)
extern const uint32_t patm_rtables155[];
extern const uint32_t patm_rtables25[];
extern const u_int patm_rtables_size;
extern const u_int patm_rtables_ntab;

View File

@ -1,494 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/unistd.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/proc.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_atm.h>
#include <dev/utopia/idtphy.h>
#include <dev/utopia/utopia.h>
#include <dev/utopia/utopia_priv.h>
/*
* Reset IDT77105. There is really no way to reset this thing by acessing
* the registers. Load the registers with default values.
*/
static int
idt77105_reset(struct utopia *utp)
{
int err = 0;
u_int n;
uint8_t val[2];
err |= UTP_WRITEREG(utp, IDTPHY_REGO_MCR, 0xff,
IDTPHY_REGM_MCR_DRIC | IDTPHY_REGM_MCR_EI);
n = 1;
err |= UTP_READREGS(utp, IDTPHY_REGO_ISTAT, val, &n);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_DIAG, 0xff, 0);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_LHEC, 0xff, 0);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_SEC);
n = 2;
err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_TX);
n = 2;
err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_RX);
n = 2;
err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, IDTPHY_REGM_CNTS_HECE);
n = 2;
err |= UTP_READREGS(utp, IDTPHY_REGO_CNT, val, &n);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_MCR, IDTPHY_REGM_MCR_DREC,
IDTPHY_REGM_MCR_DREC);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_DIAG, IDTPHY_REGM_DIAG_RFLUSH,
IDTPHY_REGM_DIAG_RFLUSH);
/* loopback */
err |= utopia_set_loopback(utp, utp->loopback);
/* update carrier state */
err |= utopia_update_carrier(utp);
return (err ? EIO : 0);
}
static int
idt77105_inval(struct utopia *utp, int what __unused)
{
return (EINVAL);
}
static int
idt77105_update_carrier(struct utopia *utp)
{
int err;
uint8_t reg;
u_int n = 1;
if ((err = UTP_READREGS(utp, IDTPHY_REGO_ISTAT, &reg, &n)) != 0) {
utp->carrier = UTP_CARR_UNKNOWN;
return (err);
}
utopia_check_carrier(utp, reg & IDTPHY_REGM_ISTAT_GOOD);
return (0);
}
static int
idt77105_set_loopback(struct utopia *utp, u_int mode)
{
int err;
switch (mode) {
case UTP_LOOP_NONE:
err = UTP_WRITEREG(utp, IDTPHY_REGO_DIAG,
IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_NONE);
break;
case UTP_LOOP_DIAG:
err = UTP_WRITEREG(utp, IDTPHY_REGO_DIAG,
IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_PHY);
break;
case UTP_LOOP_LINE:
err = UTP_WRITEREG(utp, IDTPHY_REGO_DIAG,
IDTPHY_REGM_DIAG_LOOP, IDTPHY_REGM_DIAG_LOOP_LINE);
break;
default:
return (EINVAL);
}
if (err)
return (err);
utp->loopback = mode;
return (0);
}
/*
* Handle interrupt on IDT77105 chip
*/
static void
idt77105_intr(struct utopia *utp)
{
uint8_t reg;
u_int n = 1;
int err;
/* Interrupt status and ack the interrupt */
if ((err = UTP_READREGS(utp, IDTPHY_REGO_ISTAT, &reg, &n)) != 0) {
printf("IDT77105 read error %d\n", err);
return;
}
/* check for signal condition */
utopia_check_carrier(utp, reg & IDTPHY_REGM_ISTAT_GOOD);
}
static void
idt77105_update_stats(struct utopia *utp)
{
int err = 0;
uint8_t regs[2];
u_int n;
#ifdef DIAGNOSTIC
#define UDIAG(F,A,B) printf(F, A, B)
#else
#define UDIAG(F,A,B) do { } while (0)
#endif
#define UPD(FIELD, CODE, N, MASK) \
err = UTP_WRITEREG(utp, IDTPHY_REGO_CNTS, 0xff, CODE); \
if (err != 0) { \
UDIAG("%s: cannot write CNTS: %d\n", __func__, err); \
return; \
} \
n = N; \
err = UTP_READREGS(utp, IDTPHY_REGO_CNT, regs, &n); \
if (err != 0) { \
UDIAG("%s: cannot read CNT: %d\n", __func__, err); \
return; \
} \
if (n != N) { \
UDIAG("%s: got only %u registers\n", __func__, n); \
return; \
} \
if (N == 1) \
utp->stats.FIELD += (regs[0] & MASK); \
else \
utp->stats.FIELD += (regs[0] | (regs[1] << 8)) & MASK;
UPD(rx_symerr, IDTPHY_REGM_CNTS_SEC, 1, 0xff);
UPD(tx_cells, IDTPHY_REGM_CNTS_TX, 2, 0xffff);
UPD(rx_cells, IDTPHY_REGM_CNTS_RX, 2, 0xffff);
UPD(rx_uncorr, IDTPHY_REGM_CNTS_HECE, 1, 0x1f);
#undef UDIAG
#undef UPD
}
struct utopia_chip utopia_chip_idt77105 = {
UTP_TYPE_IDT77105,
"IDT77105",
7,
idt77105_reset,
idt77105_inval,
idt77105_inval,
idt77105_inval,
idt77105_update_carrier,
idt77105_set_loopback,
idt77105_intr,
idt77105_update_stats,
};
/*
* Update the carrier status
*/
static int
idt77155_update_carrier(struct utopia *utp)
{
int err;
uint8_t reg;
u_int n = 1;
if ((err = UTP_READREGS(utp, IDTPHY_REGO_RSOS, &reg, &n)) != 0) {
utp->carrier = UTP_CARR_UNKNOWN;
return (err);
}
utopia_check_carrier(utp, !(reg & IDTPHY_REGM_RSOS_LOS));
return (0);
}
/*
* Handle interrupt on IDT77155 chip
*/
static void
idt77155_intr(struct utopia *utp)
{
uint8_t reg;
u_int n = 1;
int err;
if ((err = UTP_READREGS(utp, IDTPHY_REGO_RSOS, &reg, &n)) != 0) {
printf("IDT77105 read error %d\n", err);
return;
}
utopia_check_carrier(utp, !(reg & IDTPHY_REGM_RSOS_LOS));
}
/*
* set SONET/SDH mode
*/
static int
idt77155_set_sdh(struct utopia *utp, int sdh)
{
int err;
if (sdh)
err = UTP_WRITEREG(utp, IDTPHY_REGO_PTRM,
IDTPHY_REGM_PTRM_SS, IDTPHY_REGM_PTRM_SDH);
else
err = UTP_WRITEREG(utp, IDTPHY_REGO_PTRM,
IDTPHY_REGM_PTRM_SS, IDTPHY_REGM_PTRM_SONET);
if (err != 0)
return (err);
utp->state &= ~UTP_ST_SDH;
if (sdh)
utp->state |= UTP_ST_SDH;
return (0);
}
/*
* set idle/unassigned cells
*/
static int
idt77155_set_unass(struct utopia *utp, int unass)
{
int err;
if (unass)
err = UTP_WRITEREG(utp, IDTPHY_REGO_TCHP, 0xff, 0);
else
err = UTP_WRITEREG(utp, IDTPHY_REGO_TCHP, 0xff, 1);
if (err != 0)
return (err);
utp->state &= ~UTP_ST_UNASS;
if (unass)
utp->state |= UTP_ST_UNASS;
return (0);
}
/*
* enable/disable scrambling
*/
static int
idt77155_set_noscramb(struct utopia *utp, int noscramb)
{
int err;
if (noscramb) {
err = UTP_WRITEREG(utp, IDTPHY_REGO_TCC,
IDTPHY_REGM_TCC_DSCR, IDTPHY_REGM_TCC_DSCR);
if (err)
return (err);
err = UTP_WRITEREG(utp, IDTPHY_REGO_RCC,
IDTPHY_REGM_RCC_DSCR, IDTPHY_REGM_RCC_DSCR);
if (err)
return (err);
utp->state |= UTP_ST_NOSCRAMB;
} else {
err = UTP_WRITEREG(utp, IDTPHY_REGO_TCC,
IDTPHY_REGM_TCC_DSCR, 0);
if (err)
return (err);
err = UTP_WRITEREG(utp, IDTPHY_REGO_RCC,
IDTPHY_REGM_RCC_DSCR, 0);
if (err)
return (err);
utp->state &= ~UTP_ST_NOSCRAMB;
}
return (0);
}
/*
* Set loopback mode for the 77155
*/
static int
idt77155_set_loopback(struct utopia *utp, u_int mode)
{
int err;
uint32_t val;
u_int nmode;
val = 0;
nmode = mode;
if (mode & UTP_LOOP_TIME) {
nmode &= ~UTP_LOOP_TIME;
val |= IDTPHY_REGM_MCTL_TLOOP;
}
if (mode & UTP_LOOP_DIAG) {
nmode &= ~UTP_LOOP_DIAG;
val |= IDTPHY_REGM_MCTL_DLOOP;
}
if (mode & UTP_LOOP_LINE) {
nmode &= ~UTP_LOOP_LINE;
val |= IDTPHY_REGM_MCTL_LLOOP;
}
if (nmode != 0)
return (EINVAL);
err = UTP_WRITEREG(utp, IDTPHY_REGO_MCTL, IDTPHY_REGM_MCTL_TLOOP |
IDTPHY_REGM_MCTL_DLOOP | IDTPHY_REGM_MCTL_LLOOP, val);
if (err)
return (err);
utp->loopback = mode;
return (0);
}
/*
* Set the chip to reflect the current state in utopia.
* Assume, that the chip has been reset.
*/
static int
idt77155_set_chip(struct utopia *utp)
{
int err = 0;
/* set sonet/sdh */
err |= idt77155_set_sdh(utp, utp->state & UTP_ST_SDH);
/* unassigned or idle cells */
err |= idt77155_set_unass(utp, utp->state & UTP_ST_UNASS);
/* loopback */
err |= idt77155_set_loopback(utp, utp->loopback);
/* update carrier state */
err |= idt77155_update_carrier(utp);
/* enable interrupts on LOS */
err |= UTP_WRITEREG(utp, IDTPHY_REGO_INT,
IDTPHY_REGM_INT_RXSOHI, IDTPHY_REGM_INT_RXSOHI);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_RSOC,
IDTPHY_REGM_RSOC_LOSI, IDTPHY_REGM_RSOC_LOSI);
return (err ? EIO : 0);
}
/*
* Reset the chip to reflect the current state of utopia.
*/
static int
idt77155_reset(struct utopia *utp)
{
int err = 0;
if (!(utp->flags & UTP_FL_NORESET)) {
err |= UTP_WRITEREG(utp, IDTPHY_REGO_MRID,
IDTPHY_REGM_MRID_RESET, IDTPHY_REGM_MRID_RESET);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_MRID,
IDTPHY_REGM_MRID_RESET, 0);
}
err |= idt77155_set_chip(utp);
return (err ? EIO : 0);
}
/*
* Update statistics from a IDT77155
* This appears to be the same as for the Suni/Lite and Ultra. IDT however
* makes no assessment about the transfer time. Assume 7us.
*/
static void
idt77155_update_stats(struct utopia *utp)
{
int err;
/* write to the master if we can */
if (!(utp->flags & UTP_FL_NORESET)) {
err = UTP_WRITEREG(utp, IDTPHY_REGO_MRID, 0, 0);
} else {
err = UTP_WRITEREG(utp, IDTPHY_REGO_BIPC, 0, 0);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_B2EC, 0, 0);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_B3EC, 0, 0);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_CEC, 0, 0);
err |= UTP_WRITEREG(utp, IDTPHY_REGO_TXCNT, 0, 0);
}
if (err) {
#ifdef DIAGNOSTIC
printf("%s: register write error %s: %d\n", __func__,
utp->chip->name, err);
#endif
return;
}
DELAY(8);
utp->stats.rx_sbip += utopia_update(utp,
IDTPHY_REGO_BIPC, 2, 0xffff);
utp->stats.rx_lbip += utopia_update(utp,
IDTPHY_REGO_B2EC, 3, 0xfffff);
utp->stats.rx_lfebe += utopia_update(utp,
IDTPHY_REGO_FEBEC, 3, 0xfffff);
utp->stats.rx_pbip += utopia_update(utp,
IDTPHY_REGO_B3EC, 2, 0xffff);
utp->stats.rx_pfebe += utopia_update(utp,
IDTPHY_REGO_PFEBEC, 2, 0xffff);
utp->stats.rx_corr += utopia_update(utp,
IDTPHY_REGO_CEC, 1, 0xff);
utp->stats.rx_uncorr += utopia_update(utp,
IDTPHY_REGO_UEC, 1, 0xff);
utp->stats.rx_cells += utopia_update(utp,
IDTPHY_REGO_RCCNT, 3, 0x7ffff);
utp->stats.tx_cells += utopia_update(utp,
IDTPHY_REGO_TXCNT, 3, 0x7ffff);
}
const struct utopia_chip utopia_chip_idt77155 = {
UTP_TYPE_IDT77155,
"IDT77155",
0x80,
idt77155_reset,
idt77155_set_sdh,
idt77155_set_unass,
idt77155_set_noscramb,
idt77155_update_carrier,
idt77155_set_loopback,
idt77155_intr,
idt77155_update_stats,
};

View File

@ -1,761 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*
* Register definitions for the following chips:
* IDT 77105
* IDT 77155
*/
#ifndef _DEV_UTOPIA_IDTPHY_H
#define _DEV_UTOPIA_IDTPHY_H
#define IDTPHY_REGO_MCR 0x00
#define IDTPHY_REGN_MCR "Master Control Register"
#define IDTPHY_REGX_MCR "\020\010UPLO\7DREC\6ECEI\5TDPC\4DRIC\3HALTTX\2BYTEM\1EI"
#define IDTPHY_REGM_MCR_UPL0 0x80
#define IDTPHY_REGM_MCR_DREC 0x40
#define IDTPHY_REGM_MCR_ECEI 0x20
#define IDTPHY_REGM_MCR_TDPC 0x10
#define IDTPHY_REGM_MCR_DRIC 0x08
#define IDTPHY_REGM_MCR_HALTTX 0x04
#define IDTPHY_REGM_MCR_BYTEM 0x02
#define IDTPHY_REGM_MCR_EI 0x01
#define IDTPHY_REGO_ISTAT 0x01
#define IDTPHY_REGN_ISTAT "Interrupt Status"
#define IDTPHY_REGX_ISTAT "\020\7GOOD\6HECE\5SCRE\4TPE\3RSCC\2RSE\1RFO"
#define IDTPHY_REGM_ISTAT_GOOD 0x40 /* good signal bit */
#define IDTPHY_REGM_ISTAT_HECE 0x20 /* HEC error */
#define IDTPHY_REGM_ISTAT_SCRE 0x10 /* short cell received error */
#define IDTPHY_REGM_ISTAT_TPE 0x08 /* transmit parity error */
#define IDTPHY_REGM_ISTAT_RSCC 0x04 /* receive signal condition change */
#define IDTPHY_REGM_ISTAT_RSE 0x02 /* receive symbol error */
#define IDTPHY_REGM_ISTAT_RFO 0x01 /* read FIFO overrun */
#define IDTPHY_REGO_DIAG 0x02
#define IDTPHY_REGN_DIAG "Diagnostic Control"
#define IDTPHY_REGX_DIAG "\020\010FTD\7ROS\6MULTI\5RFLUSH\4ITPE\3IHECE\11\3\0NORM\11\3\2PLOOP\11\3\3LLOOP"
#define IDTPHY_REGM_DIAG_FTD 0x80 /* Force TxClav Deassert */
#define IDTPHY_REGM_DIAG_ROS 0x40 /* RxClav Operation Select */
#define IDTPHY_REGM_DIAG_MULTI 0x20 /* Multi-phy operation */
#define IDTPHY_REGM_DIAG_RFLUSH 0x10 /* clear receive Fifo */
#define IDTPHY_REGM_DIAG_ITPE 0x08 /* insert transmit payload error */
#define IDTPHY_REGM_DIAG_IHECE 0x04 /* insert transmit HEC error */
#define IDTPHY_REGM_DIAG_LOOP 0x03 /* loopback mode */
#define IDTPHY_REGM_DIAG_LOOP_NONE 0x00 /* normal */
#define IDTPHY_REGM_DIAG_LOOP_PHY 0x02 /* PHY loopback */
#define IDTPHY_REGM_DIAG_LOOP_LINE 0x03 /* Line loopback */
#define IDTPHY_REGO_LHEC 0x03
#define IDTPHY_REGN_LHEC "LED Driver and HEC Status/Control"
#define IDTPHY_REGX_LHEC "\020\7DRHEC\6DTHEC\11\x18\0CYC1\11\x18\1CYC2\11\x18\2CYC4\11\x18\3CYC8\3FIFOE\2TXLED\1RXLED"
#define IDTPHY_REGM_LHEC_DRHEC 0x40 /* disable receive HEC */
#define IDTPHY_REGM_LHEC_DTHEC 0x20 /* disable transmit HEC */
#define IDTPHY_REGM_LHEC_RXREF 0x18 /* RxRef pulse width */
#define IDTPHY_REGM_LHEC_RXREF1 0x00 /* 1 pulse */
#define IDTPHY_REGM_LHEC_RXREF2 0x08 /* 2 pulse */
#define IDTPHY_REGM_LHEC_RXREF4 0x10 /* 4 pulse */
#define IDTPHY_REGM_LHEC_RXREF8 0x18 /* 8 pulse */
#define IDTPHY_REGM_LHEC_FIFOE 0x04 /* Fifo empty */
#define IDTPHY_REGM_LHEC_TXLED 0x02 /* Tx LED status */
#define IDTPHY_REGM_LHEC_RXLED 0x01 /* Rx LED status */
#define IDTPHY_REGO_CNT 0x04 /* +0x05 */
#define IDTPHY_REGN_CNT "Counter"
#define IDTPHY_REGO_CNTS 0x06
#define IDTPHY_REGN_CNTS "Counter select"
#define IDTPHY_REGX_CNTS "\020\4SEC\3TX\2RX\1HECE"
#define IDTPHY_REGM_CNTS_SEC 0x08 /* symbol error counter */
#define IDTPHY_REGM_CNTS_TX 0x04 /* Tx cells */
#define IDTPHY_REGM_CNTS_RX 0x02 /* Rx cells */
#define IDTPHY_REGM_CNTS_HECE 0x01 /* HEC errors */
#define IDTPHY_PRINT_77105 \
{ /* 00 */ \
UTP_REGT_BITS, IDTPHY_REGO_MCR, \
IDTPHY_REGN_MCR, IDTPHY_REGX_MCR }, \
{ /* 01 */ \
UTP_REGT_BITS, IDTPHY_REGO_ISTAT, \
IDTPHY_REGN_ISTAT, IDTPHY_REGX_ISTAT }, \
{ /* 02 */ \
UTP_REGT_BITS, IDTPHY_REGO_DIAG, \
IDTPHY_REGN_DIAG, IDTPHY_REGX_DIAG }, \
{ /* 03 */ \
UTP_REGT_BITS, IDTPHY_REGO_LHEC, \
IDTPHY_REGN_LHEC, IDTPHY_REGX_LHEC }, \
{ /* 04, 05 */ \
UTP_REGT_INT16, IDTPHY_REGO_CNT, \
IDTPHY_REGN_CNT, NULL }, \
{ /* 06 */ \
UTP_REGT_BITS, IDTPHY_REGO_CNTS, \
IDTPHY_REGN_CNTS, IDTPHY_REGX_CNTS }
#define IDTPHY_REGO_MRID 0x00
#define IDTPHY_REGN_MRID "Master Reset & ID"
#define IDTPHY_REGM_MRID_RESET 0x80 /* software reset */
#define IDTPHY_REGM_MRID_TYPE 0x70 /* type */
#define IDTPHY_REGM_MRID_155 0x30 /* idt77155 type */
#define IDTPHY_REGM_MRID_ID 0x0f /* revision */
#define IDTPHY_REGX_MRID \
"\020\010mstReset\12\x70\12type\12\xf\12id"
#define IDTPHY_REGO_CONF 0x01
#define IDTPHY_REGN_CONF "Configuration"
#define IDTPHY_REGM_CONF_AFEBE 0x40 /* autoFEBE */
#define IDTPHY_REGM_CONF_ALRDI 0x20 /* autoLRDI */
#define IDTPHY_REGM_CONF_APRDI 0x10 /* autoPRDI */
#define IDTPHY_REGM_CONF_TCAIN 0x08 /* TCAInv */
#define IDTPHY_REGM_CONF_RCAIN 0x04 /* RCAInv */
#define IDTPHY_REGM_CONF_RXDIN 0x02 /* RXDInv */
#define IDTPHY_REGM_CONF_RESV 0x81
#define IDTPHY_REGX_CONF \
"\020\07autoFEBE\6autoLRDI\5autoPRDI\4TCAInv\3RCAInv\2RXDInv"
#define IDTPHY_REGO_INT 0x02
#define IDTPHY_REGN_INT "Interrupt"
#define IDTPHY_REGM_INT_TXOOLI 0x80 /* txOOLInt */
#define IDTPHY_REGM_INT_RXLOCI 0x40 /* rxLOCInt */
#define IDTPHY_REGM_INT_RXOOLI 0x20 /* rxOOLInt */
#define IDTPHY_REGM_INT_TXCDI 0x10 /* txCDi */
#define IDTPHY_REGM_INT_RXCDI 0x08 /* rxCDi */
#define IDTPHY_REGM_INT_RXPOHI 0x04 /* rxPOHi */
#define IDTPHY_REGM_INT_RXLOHI 0x02 /* rxLOHi */
#define IDTPHY_REGM_INT_RXSOHI 0x01 /* rxSOHi */
#define IDTPHY_REGX_INT \
"\020\10txOOLInt\7rxLOCInt\6rxOOLInt\5txCDi\4rxCDi\3rxPOHi" \
"\2rxLOHi\1rxSOHi"
#define IDTPHY_REGO_MCM 0x04
#define IDTPHY_REGN_MCM "Master Clock Monitor"
#define IDTPHY_REGM_MCM_RRCLK 0x08 /* rrclkReg */
#define IDTPHY_REGM_MCM_TRCLK 0x04 /* trclkReg */
#define IDTPHY_REGM_MCM_RCLK 0x02 /* rclkReg */
#define IDTPHY_REGM_MCM_TCLK 0x01 /* tclkReg */
#define IDTPHY_REGM_MCM_RESV 0xf0
#define IDTPHY_REGX_MCM \
"\020\4rrclkReg\3trclkReg\2rclkReg\1tclkReg"
#define IDTPHY_REGO_MCTL 0x05
#define IDTPHY_REGN_MCTL "Master Control"
#define IDTPHY_REGM_MCTL_LOCI 0x80 /* rxLOCIEn */
#define IDTPHY_REGM_MCTL_LOC 0x40 /* LOC */
#define IDTPHY_REGM_MCTL_FIXP 0x20 /* txFixptr */
#define IDTPHY_REGM_MCTL_LLOOP 0x04 /* txLLoop */
#define IDTPHY_REGM_MCTL_DLOOP 0x02 /* rxDLoop */
#define IDTPHY_REGM_MCTL_TLOOP 0x01 /* rxLoopT */
#define IDTPHY_REGM_MCTL_RESV 0x18
#define IDTPHY_REGX_MCTL \
"\020\10rxLOCIEn\7LOC\6txFixptr\3txLLoop\2rxDLoop\1rxLoopT"
#define IDTPHY_REGO_TXC 0x06
#define IDTPHY_REGN_TXC "Transmit Clock Synthesis C/S"
#define IDTPHY_REGM_TXC_TXOOL 0x08 /* txOOL */
#define IDTPHY_REGM_TXC_TXOOLI 0x02 /* txOOLIEn */
#define IDTPHY_REGM_TXC_TXREF 0x01 /* txrefSel */
#define IDTPHY_REGM_TXC_RESV 0xf4
#define IDTPHY_REGX_TXC \
"\020\4txOOL\2txOOLIEn\1txrefSel"
#define IDTPHY_REGO_RXC 0x07
#define IDTPHY_REGN_RXC "Receive Clock/Data Recovery C/S"
#define IDTPHY_REGM_RXC_RXOOL 0x08 /* rxOOL */
#define IDTPHY_REGM_RXC_RXOOLI 0x02 /* rxOOLIEn */
#define IDTPHY_REGM_RXC_RXREF 0x01 /* rxrefSel */
#define IDTPHY_REGM_RXC_RESV 0xf4
#define IDTPHY_REGX_RXC \
"\020\4rxOOL\2rxOOLIEn\1rxrefSel"
#define IDTPHY_REGO_RSOC 0x10
#define IDTPHY_REGN_RSOC "Receive Overhead Control"
#define IDTPHY_REGM_RSOC_DSCR 0x40 /* scrDis */
#define IDTPHY_REGM_RSOC_FOOF 0x20 /* frcOOF */
#define IDTPHY_REGM_RSOC_B1IE 0x08 /* B1ErrIEn */
#define IDTPHY_REGM_RSOC_LOSI 0x04 /* LOSIEn */
#define IDTPHY_REGM_RSOC_LOFI 0x02 /* LOFIEn */
#define IDTPHY_REGM_RSOC_OOFI 0x01 /* OOFIEn */
#define IDTPHY_REGM_RSOC_RESV 0x90
#define IDTPHY_REGX_RSOC \
"\020\7scrDis\6frcOOF\4B1ErrIEn\3LOSIEn\2LOFIEn\1OOFIEn"
#define IDTPHY_REGO_RSOS 0x11
#define IDTPHY_REGN_RSOS "Receive Overhead Status"
#define IDTPHY_REGM_RSOS_C1INT 0x80 /* C1Int */
#define IDTPHY_REGM_RSOS_B1INT 0x40 /* B1ErrInt */
#define IDTPHY_REGM_RSOS_LOSI 0x20 /* LOSInt */
#define IDTPHY_REGM_RSOS_LOFI 0x10 /* LOFInt */
#define IDTPHY_REGM_RSOS_OOFI 0x08 /* OOFInt */
#define IDTPHY_REGM_RSOS_LOS 0x04 /* LOS */
#define IDTPHY_REGM_RSOS_LOF 0x02 /* LOF */
#define IDTPHY_REGM_RSOS_OOF 0x01 /* OOF */
#define IDTPHY_REGX_RSOS \
"\020\10C1Int\7B1ErrInt\6LOSInt\5LOFInt\4OOFint\3LOS\2LOF\1OOF"
#define IDTPHY_REGO_BIPC 0x12 /* + 0x13 LE */
#define IDTPHY_REGN_BIPC "Receive Section BIP Errors"
#define IDTPHY_REGO_TSOC 0x14
#define IDTPHY_REGN_TSOC "Transmit Overhead Control"
#define IDTPHY_REGM_TSOC_DSCR 0x40 /* scrDis */
#define IDTPHY_REGM_TSOC_LAISI 0x01 /* LAISIns */
#define IDTPHY_REGM_TSOC_RESV 0xbe
#define IDTPHY_REGX_TSOC \
"\020\7scrDis\1LAISIns"
#define IDTPHY_REGO_TSOC2 0x15
#define IDTPHY_REGN_TSOC2 "Transmit Overhead Control 2"
#define IDTPHY_REGM_TSOC2_LOSI 0x04 /* LOSIns */
#define IDTPHY_REGM_TSOC2_B1INV 0x02 /* B1Inv */
#define IDTPHY_REGM_TSOC2_IFE 0x01 /* frErrIns */
#define IDTPHY_REGM_TSOC2_RESV 0xf8
#define IDTPHY_REGX_TSOC2 \
"\020\3LOSIns\2B1Inv\1frErrIns"
#define IDTPHY_REGO_RLOS 0x18
#define IDTPHY_REGN_RLOS "Receive Line Overhead Status"
#define IDTPHY_REGM_RLOS_B2W 0x80 /* B2Word */
#define IDTPHY_REGM_RLOS_LAIS 0x02 /* LAIS */
#define IDTPHY_REGM_RLOS_LRDI 0x01 /* LRDI */
#define IDTPHY_REGM_RLOS_RESV 0x7c
#define IDTPHY_REGX_RLOS \
"\020\10B2Word\2LAIS\1LRDI"
#define IDTPHY_REGO_RLOI 0x19
#define IDTPHY_REGN_RLOI "Receive Line Overhead Interrupt"
#define IDTPHY_REGM_RLOI_LFEBEE 0x80 /* LFEBEIEn */
#define IDTPHY_REGM_RLOI_B2EE 0x40 /* B2ErrIEn */
#define IDTPHY_REGM_RLOI_LAISE 0x20 /* LAISIEn */
#define IDTPHY_REGM_RLOI_LRDIE 0x10 /* LRDIIEn */
#define IDTPHY_REGM_RLOI_LFEBEI 0x08 /* LFEBEInt */
#define IDTPHY_REGM_RLOI_B2EI 0x04 /* B2ErrInt */
#define IDTPHY_REGM_RLOI_LAISI 0x02 /* LAISInt */
#define IDTPHY_REGM_RLOI_LRDII 0x01 /* LRDIInt */
#define IDTPHY_REGX_RLOI \
"\020\10LFEBEIEn\7B2ErrIEn\6LAISIEn\5LRDIIEn\4LFEBEInt\3B2ErrInt" \
"\2LAISInt\1LRDIInt"
#define IDTPHY_REGO_B2EC 0x1a /* + 0x1b, 0x1c, 20bit LE */
#define IDTPHY_REGN_B2EC "B2 Errors"
#define IDTPHY_REGO_FEBEC 0x1d /* + 0x1e, 0x1f, 20bit LE */
#define IDTPHY_REGN_FEBEC "Line FEBE Errors"
#define IDTPHY_REGO_TLOS 0x20
#define IDTPHY_REGN_TLOS "Transmit Line Overhead Status"
#define IDTPHY_REGM_TLOS_LRDI 0x01 /* LRDI */
#define IDTPHY_REGM_TLOS_RESV 0xfe
#define IDTPHY_REGX_TLOS \
"\020\1LRDI"
#define IDTPHY_REGO_TLOC 0x21
#define IDTPHY_REGN_TLOC "Transmit Line Overhead Control"
#define IDTPHY_REGM_TLOC_B2INV 0x01 /* B2Inv */
#define IDTPHY_REGM_TLOC_RESV 0xfe
#define IDTPHY_REGX_TLOC \
"\020\1B2Inv"
#define IDTPHY_REGO_TK1 0x24
#define IDTPHY_REGN_TK1 "Transmit K1"
#define IDTPHY_REGO_TK2 0x25
#define IDTPHY_REGN_TK2 "Transmit K2"
#define IDTPHY_REGO_RK1 0x26
#define IDTPHY_REGN_RK1 "Receive K1"
#define IDTPHY_REGO_RK2 0x27
#define IDTPHY_REGN_RK2 "Receive K2"
#define IDTPHY_REGO_RPOS 0x30
#define IDTPHY_REGN_RPOS "Receive Path Overhead Status"
#define IDTPHY_REGM_RPOS_LOP 0x20 /* LOP */
#define IDTPHY_REGM_RPOS_PAIS 0x08 /* PAIS */
#define IDTPHY_REGM_RPOS_PRDI 0x04 /* PRDI */
#define IDTPHY_REGM_RPOS_RESV 0xd3
#define IDTPHY_REGX_RPOS \
"\020\6LOP\4PAIS\3PRDI"
#define IDTPHY_REGO_RPOI 0x31
#define IDTPHY_REGN_RPOI "Receive Path Overhead Interrupt"
#define IDTPHY_REGM_RPOI_C2I 0x80 /* C2Int */
#define IDTPHY_REGM_RPOI_LOPI 0x20 /* LOPInt */
#define IDTPHY_REGM_RPOI_PAISI 0x08 /* PAISInt */
#define IDTPHY_REGM_RPOI_PRDII 0x04 /* PRDIInt */
#define IDTPHY_REGM_RPOI_B3EI 0x02 /* B3ErrInt */
#define IDTPHY_REGM_RPOI_PFEBEI 0x01 /* PFEBEInt */
#define IDTPHY_REGM_RPOI_RESV 0x50
#define IDTPHY_REGX_RPOI \
"\020\10C2Int\6LOPInt\4PAISInt\3PRDIInt\2B3ErrInt\1PFEBEInt"
#define IDTPHY_REGO_RPIE 0x33
#define IDTPHY_REGN_RPIE "Receive Path Interrupt Enable"
#define IDTPHY_REGM_RPIE_C2E 0x80 /* C2IEn */
#define IDTPHY_REGM_RPIE_LOPE 0x20 /* LOPIEn */
#define IDTPHY_REGM_RPIE_PAISE 0x08 /* PAISIEn */
#define IDTPHY_REGM_RPIE_PRDIE 0x04 /* PRDIIEn */
#define IDTPHY_REGM_RPIE_B3EE 0x02 /* B3ErrIEn */
#define IDTPHY_REGM_RPIE_PFEBEE 0x01 /* PFEBEIEn */
#define IDTPHY_REGM_RPIE_RESV 0x50
#define IDTPHY_REGX_RPIE \
"\020\10CSIEn\6LOPIEn\4PAISIEn\3PRDIIEn\2B3ErrIEn\1PFEBEIEn"
#define IDTPHY_REGO_RC2 0x37
#define IDTPHY_REGN_RC2 "Receive C2"
#define IDTPHY_REGO_B3EC 0x38 /* + 0x39, LE, 16bit */
#define IDTPHY_REGN_B3EC "B3 Errors"
#define IDTPHY_REGO_PFEBEC 0x3a /* + 0x3b, LE, 16bit */
#define IDTPHY_REGN_PFEBEC "Path FEBE Errors"
#define IDTPHY_REGO_RPEC 0x3d
#define IDTPHY_REGN_RPEC "Receive Path BIP Error Control"
#define IDTPHY_REGM_RPEC_B3C 0x20 /* blkBIP */
#define IDTPHY_REGM_RPEC_RESV 0xdf
#define IDTPHY_REGX_RPEC \
"\020\6blkBIP"
#define IDTPHY_REGO_TPOC 0x40
#define IDTPHY_REGN_TPOC "Transmit Path Control"
#define IDTPHY_REGM_TPOC_B3INV 0x02 /* B3Inv */
#define IDTPHY_REGM_TPOC_PAISI 0x01 /* PAISIns */
#define IDTPHY_REGM_TPOC_RESC 0xfc
#define IDTPHY_REGX_TPOC \
"\020\2B3Inv\1PAISIns"
#define IDTPHY_REGO_TPTC 0x41
#define IDTPHY_REGN_TPTC "Transmit Pointer Control"
#define IDTPHY_REGM_TPTC_FPTR 0x40 /* frcPtr */
#define IDTPHY_REGM_TPTC_STUFF 0x20 /* stuffCtl */
#define IDTPHY_REGM_TPTC_PTR 0x10 /* Ptr */
#define IDTPHY_REGM_TPTC_NDF 0x08 /* NDF */
#define IDTPHY_REGM_TPTC_DECP 0x04 /* decPtr */
#define IDTPHY_REGM_TPTC_INCP 0x02 /* incPtr */
#define IDTPHY_REGM_TPTC_RESV 0x81
#define IDTPHY_REGX_TPTC \
"\020\7frcPtr\6stuffCtl\5Ptr\4NDF\3decPtr\2incPtr"
#define IDTPHY_REGO_PTRL 0x45
#define IDTPHY_REGN_PTRL "Transmit Pointer LSB"
#define IDTPHY_REGX_PTRL \
"\020\12\xff\20arbPtr"
#define IDTPHY_REGO_PTRM 0x46
#define IDTPHY_REGN_PTRM "Transmit Pointer MSB"
#define IDTPHY_REGM_PTRM_NDF 0xf0 /* NDFVal */
#define IDTPHY_REGS_PTRM_NDF 4
#define IDTPHY_REGM_PTRM_SS 0x0c /* ssBit */
#define IDTPHY_REGM_PTRM_SONET 0x00
#define IDTPHY_REGM_PTRM_SDH 0x08
#define IDTPHY_REGM_PTRM_PTR 0x03
#define IDTPHY_REGX_PTRM \
"\020\12\xf0\20NDFVal\12\xc\20ssBit\12\x3\20arbPtr"
#define IDTPHY_REGO_TC2 0x48
#define IDTPHY_REGN_TC2 "Transmit C2"
#define IDTPHY_REGO_TPOC2 0x49
#define IDTPHY_REGN_TPOC2 "Transmit Path Control 2"
#define IDTPHY_REGM_TPOC2_FEBE 0xf0 /* PFEBEIns */
#define IDTPHY_REGS_TPOC2_FEBE 4
#define IDTPHY_REGM_TPOC2_PRDII 0x08 /* PRDIIns */
#define IDTPHY_REGM_TPOC2_G1 0x07 /* G1Ins */
#define IDTPHY_REGX_TPOC2 \
"\020\12\xf0\20PFEBEIns\4PRDIIns\12\x7\20G1Ins"
#define IDTPHY_REGO_RCC 0x50
#define IDTPHY_REGN_RCC "Receive Cell Control"
#define IDTPHY_REGM_RCC_OCD 0x80 /* OCD */
#define IDTPHY_REGM_RCC_PARTY 0x40 /* parity */
#define IDTPHY_REGM_RCC_PASS 0x20 /* pass */
#define IDTPHY_REGM_RCC_DCOR 0x10 /* corDis */
#define IDTPHY_REGM_RCC_DHEC 0x08 /* HECdis */
#define IDTPHY_REGM_RCC_ADD 0x04 /* csetAdd */
#define IDTPHY_REGM_RCC_DSCR 0x02 /* scrDis */
#define IDTPHY_REGM_RCC_RFIFO 0x01 /* rxFIFOrst */
#define IDTPHY_REGX_RCC \
"\020\10OCD\7parity\6pass\5corDis\4HECdis\3csetAdd" \
"\2scrDis\1rxFIFOrst"
#define IDTPHY_REGO_RCI 0x51
#define IDTPHY_REGN_RCI "Receive Cell Interrupt"
#define IDTPHY_REGM_RCI_OCDE 0x80 /* OCDIEn */
#define IDTPHY_REGM_RCI_HECE 0x40 /* HECIEn */
#define IDTPHY_REGM_RCI_OVFE 0x20 /* ovfIEn */
#define IDTPHY_REGM_RCI_OCDI 0x10 /* OCDInt */
#define IDTPHY_REGM_RCI_CORI 0x08 /* corInt */
#define IDTPHY_REGM_RCI_UCORI 0x04 /* uncorInt */
#define IDTPHY_REGM_RCI_OVFI 0x02 /* ovfInt */
#define IDTPHY_REGM_RCI_RESV 0x01
#define IDTPHY_REGX_RCI \
"\020\10OCDIEn\7HECIEn\6ovfIEn\5OCDInt\4corInt\3uncorInt\2ovfInt"
#define IDTPHY_REGO_CMH 0x52
#define IDTPHY_REGN_CMH "Receive Cell Match Header"
#define IDTPHY_REGM_CMH_GFC 0xf0 /* GFC */
#define IDTPHY_REGS_CMH_GFC 4
#define IDTPHY_REGM_CMH_PTI 0x0e /* PTI */
#define IDTPHY_REGS_CMH_PTI 1
#define IDTPHY_REGM_CMH_CLP 0x01 /* CLP */
#define IDTPHY_REGX_CMH \
"\020\12\xf0\20GFC\12\xe\20PTI\12\x1\20CLP"
#define IDTPHY_REGO_CMHM 0x53
#define IDTPHY_REGN_CMHM "Receive Cell Match Header Mask"
#define IDTPHY_REGM_CMHM_GFC 0xf0 /* mskGFC */
#define IDTPHY_REGS_CMHM_GFC 4
#define IDTPHY_REGM_CMHM_PTI 0x0e /* mskPTI */
#define IDTPHY_REGS_CMHM_PTI 1
#define IDTPHY_REGM_CMHM_CLP 0x01 /* mskCLP */
#define IDTPHY_REGX_CMHM \
"\020\12\xf0\20mskGFC\12\xe\20mskPTI\12\x1\20mskCLP"
#define IDTPHY_REGO_CEC 0x54
#define IDTPHY_REGN_CEC "Correctable Errors"
#define IDTPHY_REGO_UEC 0x55
#define IDTPHY_REGN_UEC "Uncorrectable Errors"
#define IDTPHY_REGO_RCCNT 0x56 /* +0x57, 0x58, LE, 19bit */
#define IDTPHY_REGN_RCCNT "Receive Cells"
#define IDTPHY_REGO_RCCF 0x59
#define IDTPHY_REGN_RCCF "Receive Cell Configuration"
#define IDTPHY_REGM_RCCF_GFCE 0xf0 /* GFCen */
#define IDTPHY_REGS_RCCF_GFCE 4
#define IDTPHY_REGM_RCCF_FIXS 0x08 /* FixSen */
#define IDTPHY_REGM_RCCF_RCAL 0x04 /* RCAlevel */
#define IDTPHY_REGM_RCCF_HECF 0x03 /* HECftr */
#define IDTPHY_REGX_RCCF \
"\020\12\xf0\20GFCen\4FixSen\3RCAlevel\12\x3\20HECftr"
#define IDTPHY_REGO_RXID 0x5a
#define IDTPHY_REGN_RXID "Receive ID Address"
#define IDTPHY_REGM_RXID_ID 0x03 /* IDAddr */
#define IDTPHY_REGM_RXID_RESV 0xfc
#define IDTPHY_REGX_RXID \
"\020\12\x3\20IDAddr"
#define IDTPHY_REGO_TCC 0x60
#define IDTPHY_REGN_TCC "Transmit Cell Control"
#define IDTPHY_REGM_TCC_FIFOE 0x80 /* fovrIEn */
#define IDTPHY_REGM_TCC_SOCI 0x40 /* socInt */
#define IDTPHY_REGM_TCC_FIFOI 0x20 /* fovrInt */
#define IDTPHY_REGM_TCC_HECINV 0x10 /* HECInv */
#define IDTPHY_REGM_TCC_HECDIS 0x08 /* HECDis */
#define IDTPHY_REGM_TCC_ADD 0x04 /* csetAdd */
#define IDTPHY_REGM_TCC_DSCR 0x02 /* scrDis */
#define IDTPHY_REGM_TCC_FIFOR 0x01 /* txFIFOrst */
#define IDTPHY_REGX_TCC \
"\020\10fovrIEn\7socInt\6fovrInt\5HECInv\4HECDis\3csetAdd" \
"\2scrDis\1txFIFOrst"
#define IDTPHY_REGO_TCHP 0x61
#define IDTPHY_REGN_TCHP "Transmit Idle Cell Header"
#define IDTPHY_REGM_TCHP_GFC 0xf0 /* GFCtx */
#define IDTPHY_REGS_TCHP_GFC 4
#define IDTPHY_REGM_TCHP_PTI 0x0e /* PTItx */
#define IDTPHY_REGS_TCHP_PTI 1
#define IDTPHY_REGM_TCHP_CLP 0x01 /* CLPtx */
#define IDTPHY_REGX_TCHP \
"\020\12\xf0\20GFCtx\12\xe\20PTItx\12\x1\20CLPtx"
#define IDTPHY_REGO_TPLD 0x62
#define IDTPHY_REGN_TPLD "Transmit Idle Cell Payload"
#define IDTPHY_REGO_TCC2 0x63
#define IDTPHY_REGN_TCC2 "Transmit Cell Configuration 2"
#define IDTPHY_REGM_TCC2_PARITY 0x80 /* parity */
#define IDTPHY_REGM_TCC2_PARE 0x40 /* parIEn */
#define IDTPHY_REGM_TCC2_PARI 0x10 /* parInt */
#define IDTPHY_REGM_TCC2_FIFO 0x0c /* FIFOdpth */
#define IDTPHY_REGS_TCC2_FIFO 2
#define IDTPHY_REGM_TCC2_TCAL 0x02 /* TCAlevel */
#define IDTPHY_REGM_TCC2_RESV 0x01
#define IDTPHY_REGX_TCC2 \
"\020\10parity\7parIEn\5parInt\12\xc\20FIFOdpth\2TCAlevel"
#define IDTPHY_REGO_TXCNT 0x64 /* +65,66 LE 19bit */
#define IDTPHY_REGN_TXCNT "Transmit Cells"
#define IDTPHY_REGO_TCC3 0x67
#define IDTPHY_REGN_TCC3 "Transmit Cell Configuration 3"
#define IDTPHY_REGM_TCC3_GFCE 0xf0 /* txGFCen */
#define IDTPHY_REGS_TCC3_GFCE 4
#define IDTPHY_REGM_TCC3_FIXE 0x08 /* txFixSen */
#define IDTPHY_REGM_TCC3_H4ID 0x04 /* H4InsDis */
#define IDTPHY_REGM_TCC3_FIXB 0x03 /* fixByte */
#define IDTPHY_REGM_TCC3_FIX00 0x00 /* 0x00 */
#define IDTPHY_REGM_TCC3_FIX55 0x01 /* 0x55 */
#define IDTPHY_REGM_TCC3_FIXAA 0x02 /* 0xAA */
#define IDTPHY_REGM_TCC3_FIXFF 0x03 /* 0xFF */
#define IDTPHY_REGX_TCC3 \
"\020\12\xf0\20txGFCen\4txFixSen\3H4InsDis" \
"\11\x3\x0FIX00\11\x3\x1FIX55\11\x3\x2FIXAA\11\x3\x3FIXFF"
#define IDTPHY_REGO_TXID 0x68
#define IDTPHY_REGN_TXID "Transmit ID Address"
#define IDTPHY_REGM_TXID_ID 0x03 /* txIDAddr */
#define IDTPHY_REGM_TXID_RESV 0xfc
#define IDTPHY_REGX_TXID \
"\020\12\x3\20txIDAddr"
#define IDTPHY_REGO_RBER 0x70
#define IDTPHY_REGN_RBER "Receive BER S/C"
#define IDTPHY_REGM_RBER_FAILE 0x08 /* FailIEn */
#define IDTPHY_REGM_RBER_WARNE 0x04 /* WarnIEn */
#define IDTPHY_REGM_RBER_FAIL 0x02 /* BERfail */
#define IDTPHY_REGM_RBER_WARN 0x01 /* BERwarn */
#define IDTPHY_REGM_RBER_RESV 0xf0
#define IDTPHY_REGX_RBER \
"\020\4FailIEn\3WarnIEn\2BERfail\1BERwarn"
#define IDTPHY_REGO_BFTH 0x71
#define IDTPHY_REGN_BFTH "Receive BER Fail Threshold"
#define IDTPHY_REGO_BFWIN 0x72
#define IDTPHY_REGN_BFWIN "Receive BER Fail Window"
#define IDTPHY_REGO_BFDEN 0x73 /* +74, 16bit LE */
#define IDTPHY_REGN_BFDEN "Receive BER Fail Denominator"
#define IDTPHY_REGO_BWTH 0x75
#define IDTPHY_REGN_BWTH "Receive BER Warn Threshold"
#define IDTPHY_REGO_BWWIN 0x76
#define IDTPHY_REGN_BWWIN "Receive BER Warn Window"
#define IDTPHY_REGO_BWDEN 0x77 /* +78, 16bit LE */
#define IDTPHY_REGN_BWDEN "Receive BER Warn Denomiator"
#define IDTPHY_REGO_OPEC 0x7f
#define IDTPHY_REGN_OPEC "Output PECL Control"
#define IDTPHY_REGM_OPEC_TXC 0x04 /* pcctl_tc */
#define IDTPHY_REGM_OPEC_TXD 0x02 /* pcctl_td */
#define IDTPHY_REGM_OPEC_RXDO 0x01 /* pcctl_r */
#define IDTPHY_REGM_OPEC_RESV 0xf8
#define IDTPHY_REGX_OPEC \
"\020\3pctl_tc\2pcctl_td\1pcctl_r"
#define IDTPHY_PRINT_77155 \
{ /* 00 */ \
UTP_REGT_BITS, IDTPHY_REGO_MRID, \
IDTPHY_REGN_MRID, IDTPHY_REGX_MRID }, \
{ /* 01 */ \
UTP_REGT_BITS, IDTPHY_REGO_CONF, \
IDTPHY_REGN_CONF, IDTPHY_REGX_CONF }, \
{ /* 02 */ \
UTP_REGT_BITS, IDTPHY_REGO_INT, \
IDTPHY_REGN_INT, IDTPHY_REGX_INT }, \
/* 03 unused */ \
{ /* 04 */ \
UTP_REGT_BITS, IDTPHY_REGO_MCM, \
IDTPHY_REGN_MCM, IDTPHY_REGX_MCM }, \
{ /* 05 */ \
UTP_REGT_BITS, IDTPHY_REGO_MCTL, \
IDTPHY_REGN_MCTL, IDTPHY_REGX_MCTL }, \
{ /* 06 */ \
UTP_REGT_BITS, IDTPHY_REGO_TXC, \
IDTPHY_REGN_TXC, IDTPHY_REGX_TXC }, \
{ /* 07 */ \
UTP_REGT_BITS, IDTPHY_REGO_RXC, \
IDTPHY_REGN_RXC, IDTPHY_REGX_RXC }, \
/* 08-0f unused */ \
{ /* 10 */ \
UTP_REGT_BITS, IDTPHY_REGO_RSOC, \
IDTPHY_REGN_RSOC, IDTPHY_REGX_RSOC }, \
{ /* 11 */ \
UTP_REGT_BITS, IDTPHY_REGO_RSOS, \
IDTPHY_REGN_RSOS, IDTPHY_REGX_RSOS }, \
{ /* 12, 13 */ \
UTP_REGT_INT16, IDTPHY_REGO_BIPC, \
IDTPHY_REGN_BIPC, NULL }, \
{ /* 14 */ \
UTP_REGT_BITS, IDTPHY_REGO_TSOC, \
IDTPHY_REGN_TSOC, IDTPHY_REGX_TSOC }, \
{ /* 15 */ \
UTP_REGT_BITS, IDTPHY_REGO_TSOC2, \
IDTPHY_REGN_TSOC2, IDTPHY_REGX_TSOC2 }, \
/* 16, 17 unused */ \
{ /* 18 */ \
UTP_REGT_BITS, IDTPHY_REGO_RLOS, \
IDTPHY_REGN_RLOS, IDTPHY_REGX_RLOS }, \
{ /* 19 */ \
UTP_REGT_BITS, IDTPHY_REGO_RLOI, \
IDTPHY_REGN_RLOI, IDTPHY_REGX_RLOI }, \
{ /* 1a-1c */ \
UTP_REGT_INT20, IDTPHY_REGO_B2EC, \
IDTPHY_REGN_B2EC, NULL }, \
{ /* 1d-1f */ \
UTP_REGT_INT20, IDTPHY_REGO_FEBEC, \
IDTPHY_REGN_FEBEC, NULL }, \
{ /* 20 */ \
UTP_REGT_BITS, IDTPHY_REGO_TLOS, \
IDTPHY_REGN_TLOS, IDTPHY_REGX_TLOS }, \
{ /* 21 */ \
UTP_REGT_BITS, IDTPHY_REGO_TLOC, \
IDTPHY_REGN_TLOC, IDTPHY_REGX_TLOC }, \
/* 22, 23 unused */ \
{ /* 24 */ \
UTP_REGT_INT8, IDTPHY_REGO_TK1, \
IDTPHY_REGN_TK1, NULL }, \
{ /* 25 */ \
UTP_REGT_INT8, IDTPHY_REGO_TK2, \
IDTPHY_REGN_TK2, NULL }, \
{ /* 26 */ \
UTP_REGT_INT8, IDTPHY_REGO_RK1, \
IDTPHY_REGN_RK1, NULL }, \
{ /* 27 */ \
UTP_REGT_INT8, IDTPHY_REGO_RK2, \
IDTPHY_REGN_RK2, NULL }, \
/* 28-2f unused */ \
{ /* 30 */ \
UTP_REGT_BITS, IDTPHY_REGO_RPOS, \
IDTPHY_REGN_RPOS, IDTPHY_REGX_RPOS }, \
{ /* 31 */ \
UTP_REGT_BITS, IDTPHY_REGO_RPOI, \
IDTPHY_REGN_RPOI, IDTPHY_REGX_RPOI }, \
/* 32 unused */ \
{ /* 33 */ \
UTP_REGT_BITS, IDTPHY_REGO_RPIE, \
IDTPHY_REGN_RPIE, IDTPHY_REGX_RPIE }, \
/* 34-36 unused */ \
{ /* 37 */ \
UTP_REGT_INT8, IDTPHY_REGO_RC2, \
IDTPHY_REGN_RC2, NULL }, \
{ /* 38-39 */ \
UTP_REGT_INT16, IDTPHY_REGO_B3EC, \
IDTPHY_REGN_B3EC, NULL }, \
{ /* 3a-3b */ \
UTP_REGT_INT16, IDTPHY_REGO_PFEBEC, \
IDTPHY_REGN_PFEBEC, NULL }, \
/* 3c unused */ \
{ /* 3d */ \
UTP_REGT_BITS, IDTPHY_REGO_RPEC, \
IDTPHY_REGN_RPEC, IDTPHY_REGX_RPEC }, \
/* 3e, 3f unused */ \
{ /* 40 */ \
UTP_REGT_BITS, IDTPHY_REGO_TPOC, \
IDTPHY_REGN_TPOC, IDTPHY_REGX_TPOC }, \
{ /* 41 */ \
UTP_REGT_BITS, IDTPHY_REGO_TPTC, \
IDTPHY_REGN_TPTC, IDTPHY_REGX_TPTC }, \
/* 42-44 unused */ \
{ /* 45 */ \
UTP_REGT_BITS, IDTPHY_REGO_PTRL, \
IDTPHY_REGN_PTRL, IDTPHY_REGX_PTRL }, \
{ /* 46 */ \
UTP_REGT_BITS, IDTPHY_REGO_PTRM, \
IDTPHY_REGN_PTRM, IDTPHY_REGX_PTRM }, \
/* 47 unused */ \
{ /* 48 */ \
UTP_REGT_INT8, IDTPHY_REGO_TC2, \
IDTPHY_REGN_TC2, NULL }, \
{ /* 49 */ \
UTP_REGT_BITS, IDTPHY_REGO_TPOC2, \
IDTPHY_REGN_TPOC2, IDTPHY_REGX_TPOC2 }, \
/* 4a-4f unused */ \
{ /* 50 */ \
UTP_REGT_BITS, IDTPHY_REGO_RCC, \
IDTPHY_REGN_RCC, IDTPHY_REGX_RCC }, \
{ /* 51 */ \
UTP_REGT_BITS, IDTPHY_REGO_RCI, \
IDTPHY_REGN_RCI, IDTPHY_REGX_RCI }, \
{ /* 52 */ \
UTP_REGT_BITS, IDTPHY_REGO_CMH, \
IDTPHY_REGN_CMH, IDTPHY_REGX_CMH }, \
{ /* 53 */ \
UTP_REGT_BITS, IDTPHY_REGO_CMHM, \
IDTPHY_REGN_CMHM, IDTPHY_REGX_CMHM }, \
{ /* 54 */ \
UTP_REGT_INT8, IDTPHY_REGO_CEC, \
IDTPHY_REGN_CEC, NULL }, \
{ /* 55 */ \
UTP_REGT_INT8, IDTPHY_REGO_UEC, \
IDTPHY_REGN_UEC, NULL }, \
{ /* 56-58 */ \
UTP_REGT_INT19, IDTPHY_REGO_RCCNT, \
IDTPHY_REGN_RCCNT, NULL }, \
{ /* 59 */ \
UTP_REGT_BITS, IDTPHY_REGO_RCCF, \
IDTPHY_REGN_RCCF, IDTPHY_REGX_RCCF }, \
{ /* 5a */ \
UTP_REGT_BITS, IDTPHY_REGO_RXID, \
IDTPHY_REGN_RXID, IDTPHY_REGX_RXID }, \
/* 5b-5f unused */ \
{ /* 60 */ \
UTP_REGT_BITS, IDTPHY_REGO_TCC, \
IDTPHY_REGN_TCC, IDTPHY_REGX_TCC }, \
{ /* 61 */ \
UTP_REGT_BITS, IDTPHY_REGO_TCHP, \
IDTPHY_REGN_TCHP, IDTPHY_REGX_TCHP }, \
{ /* 62 */ \
UTP_REGT_INT8, IDTPHY_REGO_TPLD, \
IDTPHY_REGN_TPLD, NULL }, \
{ /* 63 */ \
UTP_REGT_BITS, IDTPHY_REGO_TCC2, \
IDTPHY_REGN_TCC2, IDTPHY_REGX_TCC2 }, \
{ /* 64-66 */ \
UTP_REGT_INT19, IDTPHY_REGO_TXCNT, \
IDTPHY_REGN_TXCNT, NULL }, \
{ /* 67 */ \
UTP_REGT_BITS, IDTPHY_REGO_TCC3, \
IDTPHY_REGN_TCC3, IDTPHY_REGX_TCC3 }, \
{ /* 68 */ \
UTP_REGT_BITS, IDTPHY_REGO_TXID, \
IDTPHY_REGN_TXID, IDTPHY_REGX_TXID }, \
/* 69-6f unused */ \
{ /* 70 */ \
UTP_REGT_BITS, IDTPHY_REGO_RBER, \
IDTPHY_REGN_RBER, IDTPHY_REGX_RBER }, \
{ /* 71 */ \
UTP_REGT_INT8, IDTPHY_REGO_BFTH, \
IDTPHY_REGN_BFTH, NULL }, \
{ /* 72 */ \
UTP_REGT_INT8, IDTPHY_REGO_BFWIN, \
IDTPHY_REGN_BFWIN, NULL }, \
{ /* 73,74 */ \
UTP_REGT_INT16, IDTPHY_REGO_BFDEN, \
IDTPHY_REGN_BFDEN, NULL }, \
{ /* 75 */ \
UTP_REGT_INT8, IDTPHY_REGO_BWTH, \
IDTPHY_REGN_BWTH, NULL }, \
{ /* 76 */ \
UTP_REGT_INT8, IDTPHY_REGO_BWWIN, \
IDTPHY_REGN_BWWIN, NULL }, \
{ /* 77,78 */ \
UTP_REGT_INT16, IDTPHY_REGO_BWDEN, \
IDTPHY_REGN_BWDEN, NULL }, \
/* 79-7e unused */ \
{ /* 7f */ \
UTP_REGT_BITS, IDTPHY_REGO_OPEC, \
IDTPHY_REGN_OPEC, IDTPHY_REGX_OPEC }
#endif /* _DEV_UTOPIA_IDTPHY_H */

View File

@ -1,545 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/unistd.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/proc.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_atm.h>
#include <dev/utopia/suni.h>
#include <dev/utopia/utopia.h>
#include <dev/utopia/utopia_priv.h>
/*
* set SONET/SDH mode
*/
static int
suni_set_sdh(struct utopia *utp, int sdh)
{
int err;
if (sdh)
err = UTP_WRITEREG(utp, SUNI_REGO_TPOPAPTR + 1,
SUNI_REGM_TPOPAPTR_S,
SUNI_REGM_SDH << SUNI_REGS_TPOPAPTR_S);
else
err = UTP_WRITEREG(utp, SUNI_REGO_TPOPAPTR + 1,
SUNI_REGM_TPOPAPTR_S,
SUNI_REGM_SONET << SUNI_REGS_TPOPAPTR_S);
if (err != 0)
return (err);
utp->state &= ~UTP_ST_SDH;
if (sdh)
utp->state |= UTP_ST_SDH;
return (0);
}
/*
* set idle/unassigned cells
*/
static int
suni_set_unass(struct utopia *utp, int unass)
{
int err;
if (unass)
err = UTP_WRITEREG(utp, SUNI_REGO_TACPIDLEH,
0xff, (0 << SUNI_REGS_TACPIDLEH_CLP));
else
err = UTP_WRITEREG(utp, SUNI_REGO_TACPIDLEH,
0xff, (1 << SUNI_REGS_TACPIDLEH_CLP));
if (err != 0)
return (err);
utp->state &= ~UTP_ST_UNASS;
if (unass)
utp->state |= UTP_ST_UNASS;
return (0);
}
/*
* enable/disable scrambling
*/
static int
suni_set_noscramb(struct utopia *utp, int noscramb)
{
int err;
if (noscramb) {
err = UTP_WRITEREG(utp, SUNI_REGO_TACPCTRL,
SUNI_REGM_TACPCTRL_DSCR, SUNI_REGM_TACPCTRL_DSCR);
if (err)
return (err);
err = UTP_WRITEREG(utp, SUNI_REGO_RACPCTRL,
SUNI_REGM_RACPCTRL_DDSCR, SUNI_REGM_RACPCTRL_DDSCR);
if (err)
return (err);
utp->state |= UTP_ST_NOSCRAMB;
} else {
err = UTP_WRITEREG(utp, SUNI_REGO_TACPCTRL,
SUNI_REGM_TACPCTRL_DSCR, 0);
if (err)
return (err);
err = UTP_WRITEREG(utp, SUNI_REGO_RACPCTRL,
SUNI_REGM_RACPCTRL_DDSCR, 0);
if (err)
return (err);
utp->state &= ~UTP_ST_NOSCRAMB;
}
return (0);
}
/*
* Get current carrier state
*/
static int
suni_update_carrier(struct utopia *utp)
{
int err;
uint8_t reg;
u_int n = 1;
if ((err = UTP_READREGS(utp, SUNI_REGO_RSOPSIS, &reg, &n)) != 0) {
utp->carrier = UTP_CARR_UNKNOWN;
return (err);
}
utopia_check_carrier(utp, !(reg & SUNI_REGM_RSOPSIS_LOSV));
return (0);
}
/*
* Set the SUNI chip to reflect the current state in utopia.
* Assume, that the chip has been reset.
*/
static int
suni_set_chip(struct utopia *utp)
{
int err = 0;
/* set sonet/sdh */
err |= utopia_set_sdh(utp, utp->state & UTP_ST_SDH);
/* unassigned or idle cells */
err |= utopia_set_unass(utp, utp->state & UTP_ST_UNASS);
err |= UTP_WRITEREG(utp, SUNI_REGO_TACPIDLEP, 0xff, 0x6a);
/* set scrambling */
err |= utopia_set_noscramb(utp, utp->state & UTP_ST_NOSCRAMB);
/* loopback */
err |= utopia_set_loopback(utp, utp->loopback);
/* update carrier state */
err |= utopia_update_carrier(utp);
/* enable interrupts on LOS */
err |= UTP_WRITEREG(utp, SUNI_REGO_RSOPCIE,
SUNI_REGM_RSOPCIE_LOSE, SUNI_REGM_RSOPCIE_LOSE);
return (err ? EIO : 0);
}
/*
* Reset the SUNI chip to reflect the current state of utopia.
*/
static int
suni_reset_default(struct utopia *utp)
{
int err = 0;
if (!(utp->flags & UTP_FL_NORESET)) {
err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
SUNI_REGM_MRESET_RESET, SUNI_REGM_MRESET_RESET);
err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
SUNI_REGM_MRESET_RESET, 0);
}
/* disable test mode */
err |= UTP_WRITEREG(utp, SUNI_REGO_MTEST, 0xff, 0x00);
err |= suni_set_chip(utp);
return (err ? EIO : 0);
}
/*
* Set loopback mode for the Lite
*/
static int
suni_set_loopback_lite(struct utopia *utp, u_int mode)
{
int err;
uint32_t val;
u_int nmode;
val = 0;
nmode = mode;
if (mode & UTP_LOOP_TIME) {
nmode &= ~UTP_LOOP_TIME;
val |= SUNI_REGM_MCTRL_LOOPT;
}
if (mode & UTP_LOOP_DIAG) {
nmode &= ~UTP_LOOP_DIAG;
val |= SUNI_REGM_MCTRL_DLE;
}
if (mode & UTP_LOOP_LINE) {
nmode &= ~UTP_LOOP_LINE;
if (val & SUNI_REGM_MCTRL_DLE)
return (EINVAL);
val |= SUNI_REGM_MCTRL_LLE;
}
if (nmode != 0)
return (EINVAL);
err = UTP_WRITEREG(utp, SUNI_REGO_MCTRL,
SUNI_REGM_MCTRL_LLE | SUNI_REGM_MCTRL_DLE | SUNI_REGM_MCTRL_LOOPT,
val);
if (err)
return (err);
utp->loopback = mode;
return (0);
}
/*
* Update statistics from a SUNI/LITE or SUNI/ULTRA
*/
static void
suni_lite_update_stats(struct utopia *utp)
{
int err;
/* write to the master if we can */
if (!(utp->flags & UTP_FL_NORESET)) {
err = UTP_WRITEREG(utp, SUNI_REGO_MRESET, 0, 0);
} else {
err = UTP_WRITEREG(utp, SUNI_REGO_RSOP_BIP8, 0, 0);
err |= UTP_WRITEREG(utp, SUNI_REGO_RLOPBIP8_24, 0, 0);
err |= UTP_WRITEREG(utp, SUNI_REGO_RPOPBIP8, 0, 0);
err |= UTP_WRITEREG(utp, SUNI_REGO_RACPCHCS, 0, 0);
err |= UTP_WRITEREG(utp, SUNI_REGO_TACPCNT, 0, 0);
}
if (err) {
#ifdef DIAGNOSTIC
printf("%s: register write error %s: %d\n", __func__,
utp->chip->name, err);
#endif
return;
}
DELAY(8);
utp->stats.rx_sbip += utopia_update(utp,
SUNI_REGO_RSOP_BIP8, 2, 0xffff);
utp->stats.rx_lbip += utopia_update(utp,
SUNI_REGO_RLOPBIP8_24, 3, 0xfffff);
utp->stats.rx_lfebe += utopia_update(utp,
SUNI_REGO_RLOPFEBE, 3, 0xfffff);
utp->stats.rx_pbip += utopia_update(utp,
SUNI_REGO_RPOPBIP8, 2, 0xffff);
utp->stats.rx_pfebe += utopia_update(utp,
SUNI_REGO_RPOPFEBE, 2, 0xffff);
utp->stats.rx_corr += utopia_update(utp,
SUNI_REGO_RACPCHCS, 1, 0xff);
utp->stats.rx_uncorr += utopia_update(utp,
SUNI_REGO_RACPUHCS, 1, 0xff);
utp->stats.rx_cells += utopia_update(utp,
SUNI_REGO_RACPCNT, 3, 0x7ffff);
utp->stats.tx_cells += utopia_update(utp,
SUNI_REGO_TACPCNT, 3, 0x7ffff);
}
/*
* Handle interrupt on SUNI chip
*/
static void
suni_intr_default(struct utopia *utp)
{
uint8_t regs[SUNI_REGO_MTEST];
u_int n = SUNI_REGO_MTEST;
int err;
/* Read all registers. This acks the interrupts */
if ((err = UTP_READREGS(utp, SUNI_REGO_MRESET, regs, &n)) != 0) {
printf("SUNI read error %d\n", err);
return;
}
if (n <= SUNI_REGO_RSOPSIS) {
printf("%s: could not read RSOPSIS", __func__);
return;
}
/* check for LOSI (loss of signal) */
if ((regs[SUNI_REGO_MISTATUS] & SUNI_REGM_MISTATUS_RSOPI) &&
(regs[SUNI_REGO_RSOPSIS] & SUNI_REGM_RSOPSIS_LOSI))
utopia_check_carrier(utp, !(regs[SUNI_REGO_RSOPSIS]
& SUNI_REGM_RSOPSIS_LOSV));
}
const struct utopia_chip utopia_chip_lite = {
UTP_TYPE_SUNI_LITE,
"Suni/Lite (PMC-5346)",
256,
suni_reset_default,
suni_set_sdh,
suni_set_unass,
suni_set_noscramb,
suni_update_carrier,
suni_set_loopback_lite,
suni_intr_default,
suni_lite_update_stats,
};
/*
* Set loopback mode for the Ultra
*/
static int
suni_set_loopback_ultra(struct utopia *utp, u_int mode)
{
int err;
uint32_t val;
u_int nmode;
val = 0;
nmode = mode;
if (mode & UTP_LOOP_TIME) {
nmode &= ~UTP_LOOP_TIME;
val |= SUNI_REGM_MCTRL_LOOPT;
}
if (mode & UTP_LOOP_DIAG) {
nmode &= ~UTP_LOOP_DIAG;
if (val & SUNI_REGM_MCTRL_LOOPT)
return (EINVAL);
val |= SUNI_REGM_MCTRL_SDLE;
}
if (mode & UTP_LOOP_LINE) {
nmode &= ~UTP_LOOP_LINE;
if (val & (SUNI_REGM_MCTRL_LOOPT | SUNI_REGM_MCTRL_SDLE))
return (EINVAL);
val |= SUNI_REGM_MCTRL_LLE;
}
if (mode & UTP_LOOP_PARAL) {
nmode &= ~UTP_LOOP_PARAL;
val |= SUNI_REGM_MCTRL_PDLE;
}
if (mode & UTP_LOOP_TWIST) {
nmode &= ~UTP_LOOP_TWIST;
val |= SUNI_REGM_MCTRL_TPLE;
}
if (nmode != 0)
return (EINVAL);
err = UTP_WRITEREG(utp, SUNI_REGO_MCTRL,
SUNI_REGM_MCTRL_LLE | SUNI_REGM_MCTRL_SDLE | SUNI_REGM_MCTRL_LOOPT |
SUNI_REGM_MCTRL_PDLE | SUNI_REGM_MCTRL_TPLE, val);
if (err)
return (err);
utp->loopback = mode;
return (0);
}
const struct utopia_chip utopia_chip_ultra = {
UTP_TYPE_SUNI_ULTRA,
"Suni/Ultra (PMC-5350)",
256,
suni_reset_default,
suni_set_sdh,
suni_set_unass,
suni_set_noscramb,
suni_update_carrier,
suni_set_loopback_ultra,
suni_intr_default,
suni_lite_update_stats,
};
/*
* Set loopback mode for the 622
*/
static int
suni_set_loopback_622(struct utopia *utp, u_int mode)
{
int err;
uint32_t val;
uint8_t config;
int smode;
u_int nmode;
u_int n = 1;
val = 0;
nmode = mode;
if (mode & UTP_LOOP_PATH) {
nmode &= ~UTP_LOOP_PATH;
val |= SUNI_REGM_MCTRLM_DPLE;
}
err = UTP_READREGS(utp, SUNI_REGO_MCONFIG, &config, &n);
if (err != 0)
return (err);
smode = ((config & SUNI_REGM_MCONFIG_TMODE_622) ==
SUNI_REGM_MCONFIG_TMODE_STS1_BIT &&
(config & SUNI_REGM_MCONFIG_RMODE_622) ==
SUNI_REGM_MCONFIG_RMODE_STS1_BIT);
if (mode & UTP_LOOP_TIME) {
if (!smode)
return (EINVAL);
nmode &= ~UTP_LOOP_TIME;
val |= SUNI_REGM_MCTRLM_LOOPT;
}
if (mode & UTP_LOOP_DIAG) {
nmode &= ~UTP_LOOP_DIAG;
if (val & SUNI_REGM_MCTRLM_LOOPT)
return (EINVAL);
val |= SUNI_REGM_MCTRLM_DLE;
}
if (mode & UTP_LOOP_LINE) {
nmode &= ~UTP_LOOP_LINE;
if (val & (SUNI_REGM_MCTRLM_LOOPT | SUNI_REGM_MCTRLM_DLE))
return (EINVAL);
val |= SUNI_REGM_MCTRLM_LLE;
}
if (nmode != 0)
return (EINVAL);
err = UTP_WRITEREG(utp, SUNI_REGO_MCTRLM,
SUNI_REGM_MCTRLM_LLE | SUNI_REGM_MCTRLM_DLE |
SUNI_REGM_MCTRLM_DPLE | SUNI_REGM_MCTRL_LOOPT, val);
if (err)
return (err);
utp->loopback = mode;
return (0);
}
/*
* Reset the SUNI chip to reflect the current state of utopia.
*/
static int
suni_reset_622(struct utopia *utp)
{
int err = 0;
if (!(utp->flags & UTP_FL_NORESET)) {
err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
SUNI_REGM_MRESET_RESET, SUNI_REGM_MRESET_RESET);
err |= UTP_WRITEREG(utp, SUNI_REGO_MRESET,
SUNI_REGM_MRESET_RESET, 0);
}
/* disable test mode */
err |= UTP_WRITEREG(utp, SUNI_REGO_MTEST, 0xff,
SUNI_REGM_MTEST_DS27_53_622);
err |= suni_set_chip(utp);
return (err ? EIO : 0);
}
/*
* Update statistics from a SUNI/622
*/
static void
suni_622_update_stats(struct utopia *utp)
{
int err;
/* write to the master if we can */
if (!(utp->flags & UTP_FL_NORESET)) {
err = UTP_WRITEREG(utp, SUNI_REGO_MRESET, 0, 0);
} else {
err = UTP_WRITEREG(utp, SUNI_REGO_RSOP_BIP8, 0, 0);
err |= UTP_WRITEREG(utp, SUNI_REGO_RLOPBIP8_24, 0, 0);
err |= UTP_WRITEREG(utp, SUNI_REGO_RPOPBIP8, 0, 0);
err |= UTP_WRITEREG(utp, SUNI_REGO_RACPCHCS, 0, 0);
err |= UTP_WRITEREG(utp, SUNI_REGO_TACPCNT, 0, 0);
}
if (err) {
#ifdef DIAGNOSTIC
printf("%s: register write error %s: %d\n", __func__,
utp->chip->name, err);
#endif
return;
}
DELAY(8);
utp->stats.rx_sbip += utopia_update(utp,
SUNI_REGO_RSOP_BIP8, 2, 0xffff);
utp->stats.rx_lbip += utopia_update(utp,
SUNI_REGO_RLOPBIP8_24, 3, 0xfffff);
utp->stats.rx_lfebe += utopia_update(utp,
SUNI_REGO_RLOPFEBE, 3, 0xfffff);
utp->stats.rx_pbip += utopia_update(utp,
SUNI_REGO_RPOPBIP8, 2, 0xffff);
utp->stats.rx_pfebe += utopia_update(utp,
SUNI_REGO_RPOPFEBE, 2, 0xffff);
utp->stats.rx_corr += utopia_update(utp,
SUNI_REGO_RACPCHCS_622, 2, 0xfff);
utp->stats.rx_uncorr += utopia_update(utp,
SUNI_REGO_RACPUHCS_622, 2, 0xfff);
utp->stats.rx_cells += utopia_update(utp,
SUNI_REGO_RACPCNT_622, 3, 0x1fffff);
utp->stats.tx_cells += utopia_update(utp,
SUNI_REGO_TACPCNT, 3, 0x1fffff);
}
const struct utopia_chip utopia_chip_622 = {
UTP_TYPE_SUNI_622,
"Suni/622 (PMC-5355)",
256,
suni_reset_622,
suni_set_sdh,
suni_set_unass,
suni_set_noscramb,
suni_update_carrier,
suni_set_loopback_622,
suni_intr_default,
suni_622_update_stats,
};

File diff suppressed because it is too large Load Diff

View File

@ -1,675 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/unistd.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/proc.h>
#include <sys/bus.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/if_atm.h>
#include <dev/utopia/suni.h>
#include <dev/utopia/idtphy.h>
#include <dev/utopia/utopia.h>
#include <dev/utopia/utopia_priv.h>
/* known chips */
extern const struct utopia_chip utopia_chip_idt77155;
extern const struct utopia_chip utopia_chip_idt77105;
extern const struct utopia_chip utopia_chip_lite;
extern const struct utopia_chip utopia_chip_ultra;
extern const struct utopia_chip utopia_chip_622;
/*
* Global list of all registered interfaces
*/
static struct mtx utopia_list_mtx;
static LIST_HEAD(, utopia) utopia_list = LIST_HEAD_INITIALIZER(utopia_list);
#define UTP_RLOCK_LIST() mtx_lock(&utopia_list_mtx)
#define UTP_RUNLOCK_LIST() mtx_unlock(&utopia_list_mtx)
#define UTP_WLOCK_LIST() mtx_lock(&utopia_list_mtx)
#define UTP_WUNLOCK_LIST() mtx_unlock(&utopia_list_mtx)
#define UTP_LOCK(UTP) mtx_lock((UTP)->lock)
#define UTP_UNLOCK(UTP) mtx_unlock((UTP)->lock)
#define UTP_LOCK_ASSERT(UTP) mtx_assert((UTP)->lock, MA_OWNED)
static struct proc *utopia_kproc;
static void utopia_dump(struct utopia *) __unused;
/*
* Read a multi-register value.
*/
uint32_t
utopia_update(struct utopia *utp, u_int reg, u_int nreg, uint32_t mask)
{
int err;
u_int n;
uint8_t regs[4];
uint32_t val;
n = nreg;
if ((err = UTP_READREGS(utp, reg, regs, &n)) != 0) {
#ifdef DIAGNOSTIC
printf("%s: register read error %s(%u,%u): %d\n", __func__,
utp->chip->name, reg, nreg, err);
#endif
return (0);
}
if (n < nreg) {
#ifdef DIAGNOSTIC
printf("%s: got only %u regs %s(%u,%u): %d\n", __func__, n,
utp->chip->name, reg, nreg, err);
#endif
return (0);
}
val = 0;
for (n = nreg; n > 0; n--) {
val <<= 8;
val |= regs[n - 1];
}
return (val & mask);
}
/*
* Debugging - dump all registers.
*/
static void
utopia_dump(struct utopia *utp)
{
uint8_t regs[256];
u_int n = 256, i;
int err;
if ((err = UTP_READREGS(utp, 0, regs, &n)) != 0) {
printf("UTOPIA reg read error %d\n", err);
return;
}
for (i = 0; i < n; i++) {
if (i % 16 == 0)
printf("%02x:", i);
if (i % 16 == 8)
printf(" ");
printf(" %02x", regs[i]);
if (i % 16 == 15)
printf("\n");
}
if (i % 16 != 0)
printf("\n");
}
/*
* Update the carrier status
*/
void
utopia_check_carrier(struct utopia *utp, u_int carr_ok)
{
int old;
old = utp->carrier;
if (carr_ok) {
/* carrier */
utp->carrier = UTP_CARR_OK;
if (old != UTP_CARR_OK) {
if_printf(utp->ifatm->ifp, "carrier detected\n");
ATMEV_SEND_IFSTATE_CHANGED(utp->ifatm, 1);
}
} else {
/* no carrier */
utp->carrier = UTP_CARR_LOST;
if (old == UTP_CARR_OK) {
if_printf(utp->ifatm->ifp, "carrier lost\n");
ATMEV_SEND_IFSTATE_CHANGED(utp->ifatm, 0);
}
}
}
static int
unknown_inval(struct utopia *utp, int what __unused)
{
return (EINVAL);
}
static int
unknown_reset(struct utopia *utp __unused)
{
return (EIO);
}
static int
unknown_update_carrier(struct utopia *utp)
{
utp->carrier = UTP_CARR_UNKNOWN;
return (0);
}
static int
unknown_set_loopback(struct utopia *utp __unused, u_int mode __unused)
{
return (EINVAL);
}
static void
unknown_intr(struct utopia *utp __unused)
{
}
static void
unknown_update_stats(struct utopia *utp __unused)
{
}
static const struct utopia_chip utopia_chip_unknown = {
UTP_TYPE_UNKNOWN,
"unknown",
0,
unknown_reset,
unknown_inval,
unknown_inval,
unknown_inval,
unknown_update_carrier,
unknown_set_loopback,
unknown_intr,
unknown_update_stats,
};
/*
* Callbacks for the ifmedia infrastructure.
*/
static int
utopia_media_change(struct ifnet *ifp)
{
struct ifatm *ifatm = IFP2IFATM(ifp);
struct utopia *utp = ifatm->phy;
int error = 0;
UTP_LOCK(utp);
if (utp->chip->type != UTP_TYPE_UNKNOWN && utp->state & UTP_ST_ACTIVE) {
if (utp->media->ifm_media & IFM_ATM_SDH) {
if (!(utp->state & UTP_ST_SDH))
error = utopia_set_sdh(utp, 1);
} else {
if (utp->state & UTP_ST_SDH)
error = utopia_set_sdh(utp, 0);
}
if (utp->media->ifm_media & IFM_ATM_UNASSIGNED) {
if (!(utp->state & UTP_ST_UNASS))
error = utopia_set_unass(utp, 1);
} else {
if (utp->state & UTP_ST_UNASS)
error = utopia_set_unass(utp, 0);
}
if (utp->media->ifm_media & IFM_ATM_NOSCRAMB) {
if (!(utp->state & UTP_ST_NOSCRAMB))
error = utopia_set_noscramb(utp, 1);
} else {
if (utp->state & UTP_ST_NOSCRAMB)
error = utopia_set_noscramb(utp, 0);
}
} else
error = EIO;
UTP_UNLOCK(utp);
return (error);
}
/*
* Look at the carrier status.
*/
static void
utopia_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct utopia *utp = IFP2IFATM(ifp)->phy;
UTP_LOCK(utp);
if (utp->chip->type != UTP_TYPE_UNKNOWN && utp->state & UTP_ST_ACTIVE) {
ifmr->ifm_active = IFM_ATM | utp->ifatm->mib.media;
switch (utp->carrier) {
case UTP_CARR_OK:
ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
break;
case UTP_CARR_LOST:
ifmr->ifm_status = IFM_AVALID;
break;
default:
ifmr->ifm_status = 0;
break;
}
if (utp->state & UTP_ST_SDH) {
ifmr->ifm_active |= IFM_ATM_SDH;
ifmr->ifm_current |= IFM_ATM_SDH;
}
if (utp->state & UTP_ST_UNASS) {
ifmr->ifm_active |= IFM_ATM_UNASSIGNED;
ifmr->ifm_current |= IFM_ATM_UNASSIGNED;
}
if (utp->state & UTP_ST_NOSCRAMB) {
ifmr->ifm_active |= IFM_ATM_NOSCRAMB;
ifmr->ifm_current |= IFM_ATM_NOSCRAMB;
}
} else {
ifmr->ifm_active = 0;
ifmr->ifm_status = 0;
}
UTP_UNLOCK(utp);
}
/*
* Initialize media from the mib
*/
void
utopia_init_media(struct utopia *utp)
{
ifmedia_removeall(utp->media);
ifmedia_add(utp->media, IFM_ATM | utp->ifatm->mib.media, 0, NULL);
ifmedia_set(utp->media, IFM_ATM | utp->ifatm->mib.media);
}
/*
* Reset all media
*/
void
utopia_reset_media(struct utopia *utp)
{
ifmedia_removeall(utp->media);
}
/*
* This is called by the driver as soon as the SUNI registers are accessible.
* This may be either in the attach routine or the init routine of the driver.
*/
int
utopia_start(struct utopia *utp)
{
uint8_t reg;
int err;
u_int n = 1;
/*
* Try to find out what chip we have
*/
if ((err = UTP_READREGS(utp, SUNI_REGO_MRESET, &reg, &n)) != 0)
return (err);
switch (reg & SUNI_REGM_MRESET_TYPE) {
case SUNI_REGM_MRESET_TYPE_622:
utp->chip = &utopia_chip_622;
break;
case SUNI_REGM_MRESET_TYPE_LITE:
/* this may be either a SUNI LITE or a IDT77155 *
* Read register 0x70. The SUNI doesn't have it */
n = 1;
if ((err = UTP_READREGS(utp, IDTPHY_REGO_RBER, &reg, &n)) != 0)
return (err);
if ((reg & ~IDTPHY_REGM_RBER_RESV) ==
(IDTPHY_REGM_RBER_FAIL | IDTPHY_REGM_RBER_WARN))
utp->chip = &utopia_chip_idt77155;
else
utp->chip = &utopia_chip_lite;
break;
case SUNI_REGM_MRESET_TYPE_ULTRA:
utp->chip = &utopia_chip_ultra;
break;
default:
if (reg == (IDTPHY_REGM_MCR_DRIC | IDTPHY_REGM_MCR_EI))
utp->chip = &utopia_chip_idt77105;
else {
if_printf(utp->ifatm->ifp,
"unknown ATM-PHY chip %#x\n", reg);
utp->chip = &utopia_chip_unknown;
}
break;
}
utp->state |= UTP_ST_ACTIVE;
return (0);
}
/*
* Stop the chip
*/
void
utopia_stop(struct utopia *utp)
{
utp->state &= ~UTP_ST_ACTIVE;
}
/*
* Handle the sysctls
*/
static int
utopia_sysctl_regs(SYSCTL_HANDLER_ARGS)
{
struct utopia *utp = (struct utopia *)arg1;
int error;
u_int n;
uint8_t *val;
uint8_t new[3];
if ((n = utp->chip->nregs) == 0)
return (EIO);
val = malloc(sizeof(uint8_t) * n, M_TEMP, M_WAITOK);
UTP_LOCK(utp);
error = UTP_READREGS(utp, 0, val, &n);
UTP_UNLOCK(utp);
if (error) {
free(val, M_TEMP);
return (error);
}
error = SYSCTL_OUT(req, val, sizeof(uint8_t) * n);
free(val, M_TEMP);
if (error != 0 || req->newptr == NULL)
return (error);
error = SYSCTL_IN(req, new, sizeof(new));
if (error)
return (error);
UTP_LOCK(utp);
error = UTP_WRITEREG(utp, new[0], new[1], new[2]);
UTP_UNLOCK(utp);
return (error);
}
static int
utopia_sysctl_stats(SYSCTL_HANDLER_ARGS)
{
struct utopia *utp = (struct utopia *)arg1;
void *val;
int error;
val = malloc(sizeof(utp->stats), M_TEMP, M_WAITOK);
UTP_LOCK(utp);
bcopy(&utp->stats, val, sizeof(utp->stats));
if (req->newptr != NULL)
bzero((char *)&utp->stats + sizeof(utp->stats.version),
sizeof(utp->stats) - sizeof(utp->stats.version));
UTP_UNLOCK(utp);
error = SYSCTL_OUT(req, val, sizeof(utp->stats));
if (error && req->newptr != NULL)
bcopy(val, &utp->stats, sizeof(utp->stats));
free(val, M_TEMP);
/* ignore actual new value */
return (error);
}
/*
* Handle the loopback sysctl
*/
static int
utopia_sysctl_loopback(SYSCTL_HANDLER_ARGS)
{
struct utopia *utp = (struct utopia *)arg1;
int error;
u_int loopback;
error = SYSCTL_OUT(req, &utp->loopback, sizeof(u_int));
if (error != 0 || req->newptr == NULL)
return (error);
error = SYSCTL_IN(req, &loopback, sizeof(u_int));
if (error)
return (error);
UTP_LOCK(utp);
error = utopia_set_loopback(utp, loopback);
UTP_UNLOCK(utp);
return (error);
}
/*
* Handle the type sysctl
*/
static int
utopia_sysctl_type(SYSCTL_HANDLER_ARGS)
{
struct utopia *utp = (struct utopia *)arg1;
return (SYSCTL_OUT(req, &utp->chip->type, sizeof(utp->chip->type)));
}
/*
* Handle the name sysctl
*/
static int
utopia_sysctl_name(SYSCTL_HANDLER_ARGS)
{
struct utopia *utp = (struct utopia *)arg1;
return (SYSCTL_OUT(req, utp->chip->name, strlen(utp->chip->name) + 1));
}
/*
* Initialize the state. This is called from the drivers attach
* function. The mutex must be already initialized.
*/
int
utopia_attach(struct utopia *utp, struct ifatm *ifatm, struct ifmedia *media,
struct mtx *lock, struct sysctl_ctx_list *ctx,
struct sysctl_oid_list *children, const struct utopia_methods *m)
{
bzero(utp, sizeof(*utp));
utp->ifatm = ifatm;
utp->methods = m;
utp->media = media;
utp->lock = lock;
utp->chip = &utopia_chip_unknown;
utp->stats.version = 1;
ifmedia_init(media,
IFM_ATM_SDH | IFM_ATM_UNASSIGNED | IFM_ATM_NOSCRAMB,
utopia_media_change, utopia_media_status);
if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_regs",
CTLFLAG_RW | CTLTYPE_OPAQUE, utp, 0, utopia_sysctl_regs, "S",
"phy registers") == NULL)
return (-1);
if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_loopback",
CTLFLAG_RW | CTLTYPE_UINT, utp, 0, utopia_sysctl_loopback, "IU",
"phy loopback mode") == NULL)
return (-1);
if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_type",
CTLFLAG_RD | CTLTYPE_UINT, utp, 0, utopia_sysctl_type, "IU",
"phy type") == NULL)
return (-1);
if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_name",
CTLFLAG_RD | CTLTYPE_STRING, utp, 0, utopia_sysctl_name, "A",
"phy name") == NULL)
return (-1);
if (SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "phy_stats",
CTLFLAG_RW | CTLTYPE_OPAQUE, utp, 0, utopia_sysctl_stats, "S",
"phy statistics") == NULL)
return (-1);
if (SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "phy_state",
CTLFLAG_RD, &utp->state, 0, "phy state") == NULL)
return (-1);
if (SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "phy_carrier",
CTLFLAG_RD, &utp->carrier, 0, "phy carrier") == NULL)
return (-1);
UTP_WLOCK_LIST();
LIST_INSERT_HEAD(&utopia_list, utp, link);
UTP_WUNLOCK_LIST();
utp->state |= UTP_ST_ATTACHED;
return (0);
}
/*
* Detach. We set a flag here, wakeup the daemon and let him do it.
* Here we need the lock for synchronisation with the daemon.
*/
void
utopia_detach(struct utopia *utp)
{
UTP_LOCK_ASSERT(utp);
if (utp->state & UTP_ST_ATTACHED) {
utp->state |= UTP_ST_DETACH;
while (utp->state & UTP_ST_DETACH) {
wakeup(&utopia_list);
msleep(utp, utp->lock, PZERO, "utopia_detach", hz);
}
}
}
/*
* The carrier state kernel proc for those adapters that do not interrupt.
*
* We assume, that utopia_attach can safely add a new utopia while we are going
* through the list without disturbing us (we lock the list while getting
* the address of the first element, adding is always done at the head).
* Removing is entirely handled here.
*/
static void
utopia_daemon(void *arg __unused)
{
struct utopia *utp, *next;
UTP_RLOCK_LIST();
while (utopia_kproc != NULL) {
utp = LIST_FIRST(&utopia_list);
UTP_RUNLOCK_LIST();
while (utp != NULL) {
mtx_lock(&Giant); /* XXX depend on MPSAFE */
UTP_LOCK(utp);
next = LIST_NEXT(utp, link);
if (utp->state & UTP_ST_DETACH) {
LIST_REMOVE(utp, link);
utp->state &= ~UTP_ST_DETACH;
wakeup_one(utp);
} else if (utp->state & UTP_ST_ACTIVE) {
if (utp->flags & UTP_FL_POLL_CARRIER)
utopia_update_carrier(utp);
utopia_update_stats(utp);
}
UTP_UNLOCK(utp);
mtx_unlock(&Giant); /* XXX depend on MPSAFE */
utp = next;
}
UTP_RLOCK_LIST();
msleep(&utopia_list, &utopia_list_mtx, PZERO, "*idle*", hz);
}
wakeup_one(&utopia_list);
UTP_RUNLOCK_LIST();
kproc_exit(0);
}
/*
* Module initialisation
*/
static int
utopia_mod_init(module_t mod, int what, void *arg)
{
int err;
struct proc *kp;
switch (what) {
case MOD_LOAD:
mtx_init(&utopia_list_mtx, "utopia list mutex", NULL, MTX_DEF);
err = kproc_create(utopia_daemon, NULL, &utopia_kproc,
RFHIGHPID, 0, "utopia");
if (err != 0) {
printf("cannot created utopia thread %d\n", err);
return (err);
}
break;
case MOD_UNLOAD:
UTP_WLOCK_LIST();
if ((kp = utopia_kproc) != NULL) {
utopia_kproc = NULL;
wakeup_one(&utopia_list);
PROC_LOCK(kp);
UTP_WUNLOCK_LIST();
msleep(kp, &kp->p_mtx, PWAIT, "utopia_destroy", 0);
PROC_UNLOCK(kp);
} else
UTP_WUNLOCK_LIST();
mtx_destroy(&utopia_list_mtx);
break;
default:
return (EOPNOTSUPP);
}
return (0);
}
static moduledata_t utopia_mod = {
"utopia",
utopia_mod_init,
0
};
DECLARE_MODULE(utopia, utopia_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
MODULE_VERSION(utopia, 1);

View File

@ -1,203 +0,0 @@
/*-
* Copyright (c) 2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*/
#ifndef _DEV_UTOPIA_UTOPIA_H
#define _DEV_UTOPIA_UTOPIA_H
/* Structure for user-level register formatting */
struct utopia_print {
uint8_t type; /* register type */
uint8_t reg; /* register number */
const char *name; /* register name */
const char *fmt; /* format for printing */
};
/*
* Types of registers
*/
#define UTP_REGT_BITS 0x0 /* use printb to print */
#define UTP_REGT_INT8 0x1 /* 8 bit hex number */
#define UTP_REGT_INT10BITS 0x2 /* 10 bit hex number + 6 bit printb */
#define UTP_REGT_INT12 0x3 /* 12 bit LE hex */
#define UTP_REGT_INT16 0x4 /* 16 bit LE hex */
#define UTP_REGT_INT19 0x5 /* 19 bit LE hex */
#define UTP_REGT_INT20 0x6 /* 20 bit LE hex */
#define UTP_REGT_INT21 0x7 /* 21 bit LE hex */
#define UTP_REGT_INT18 0x8 /* 18 bit LE hex */
/* number of additional registers per type */
#define UTP_REG_ADD 0, 0, 1, 1, 1, 2, 2, 2, 2
/* flags field */
#define UTP_FL_NORESET 0x0001 /* cannot write MRESET register */
#define UTP_FL_POLL_CARRIER 0x0002 /* need to poll for carrier */
/* state field */
#define UTP_ST_ACTIVE 0x0001 /* registers accessible */
#define UTP_ST_SDH 0x0002 /* SDH or SONET */
#define UTP_ST_UNASS 0x0004 /* produce unassigned cells */
#define UTP_ST_NOSCRAMB 0x0008 /* no scrambling */
#define UTP_ST_DETACH 0x0010 /* detaching */
#define UTP_ST_ATTACHED 0x0020 /* successful attached */
/* carrier field */
#define UTP_CARR_UNKNOWN 0
#define UTP_CARR_OK 1
#define UTP_CARR_LOST 2
/* loopback field */
#define UTP_LOOP_NONE 0x0000
#define UTP_LOOP_TIME 0x0001 /* timing source loopback */
#define UTP_LOOP_DIAG 0x0002 /* diagnostic loopback */
#define UTP_LOOP_LINE 0x0004 /* serial line loopback */
#define UTP_LOOP_PARAL 0x0008 /* parallel diagnostic loopback */
#define UTP_LOOP_TWIST 0x0010 /* twisted pair diagnostic loopback */
#define UTP_LOOP_PATH 0x0020 /* diagnostic path loopback */
/* type */
#define UTP_TYPE_UNKNOWN 0
#define UTP_TYPE_SUNI_LITE 1
#define UTP_TYPE_SUNI_ULTRA 2
#define UTP_TYPE_SUNI_622 3
#define UTP_TYPE_IDT77105 4
#define UTP_TYPE_IDT77155 5
#define UTP_TYPE_CX28250 6
/*
* Statistics. These structures are versioned.
*/
struct utopia_stats1 {
uint32_t version; /* version of this statistics struct */
uint32_t fill;
uint64_t rx_sbip; /* rx section BIP errors */
uint64_t rx_lbip; /* rx line BIP errors */
uint64_t rx_lfebe; /* rx line far end block errors */
uint64_t rx_pbip; /* rx path BIP errors */
uint64_t rx_pfebe; /* rx path far end block errors */
uint64_t rx_cells; /* received cells */
uint64_t rx_corr; /* correctable cell errors */
uint64_t rx_uncorr; /* uncorrectable cell errors */
uint64_t rx_symerr; /* symbol errors */
uint64_t tx_cells; /* transmitted cells */
};
#ifdef _KERNEL
#include <sys/queue.h>
/*
* These must be implemented by the card driver
*/
struct utopia_methods {
/* read at most n PHY registers starting at reg into val */
int (*readregs)(struct ifatm *, u_int reg, uint8_t *val, u_int *n);
/* change the bits given by mask to them in val in register reg */
int (*writereg)(struct ifatm *, u_int reg, u_int mask, u_int val);
};
/*
* Public state
*/
struct utopia {
struct ifatm *ifatm; /* driver data */
struct ifmedia *media; /* driver supplied */
struct mtx *lock; /* driver supplied */
const struct utopia_methods *methods;
LIST_ENTRY(utopia) link; /* list of these structures */
u_int flags; /* flags set by the driver */
u_int state; /* current state */
u_int carrier; /* carrier state */
u_int loopback; /* loopback mode */
const struct utopia_chip *chip; /* chip operations */
struct utopia_stats1 stats; /* statistics */
};
struct utopia_chip {
/* type and name of the chip */
u_int type;
const char *const name;
/* number of registers */
u_int nregs;
/* reset chip to known state */
int (*reset)(struct utopia *);
/* set SONET/SDH mode */
int (*set_sdh)(struct utopia *, int sdh);
/* set idle/unassigned cells */
int (*set_unass)(struct utopia *, int unass);
/* enable/disable scrambling */
int (*set_noscramb)(struct utopia *, int noscramb);
/* update carrier status */
int (*update_carrier)(struct utopia *);
/* set loopback mode */
int (*set_loopback)(struct utopia *, u_int mode);
/* handle interrupt */
void (*intr)(struct utopia *);
/* update statistics */
void (*update_stats)(struct utopia *);
};
/*
* These are implemented in the common utopia code
*/
int utopia_attach(struct utopia *, struct ifatm *, struct ifmedia *,
struct mtx *, struct sysctl_ctx_list *, struct sysctl_oid_list *,
const struct utopia_methods *);
void utopia_detach(struct utopia *);
int utopia_start(struct utopia *);
void utopia_stop(struct utopia *);
void utopia_init_media(struct utopia *);
void utopia_reset_media(struct utopia *);
#define utopia_reset(S) ((S)->chip->reset((S)))
#define utopia_set_sdh(S, SDH) ((S)->chip->set_sdh((S), (SDH)))
#define utopia_set_unass(S, U) ((S)->chip->set_unass((S), (U)))
#define utopia_set_noscramb(S, N) ((S)->chip->set_noscramb((S), (N)))
#define utopia_update_carrier(S) ((S)->chip->update_carrier((S)))
#define utopia_update_stats(S) ((S)->chip->update_stats((S)))
#define utopia_set_loopback(S, L) ((S)->chip->set_loopback((S), (L)))
#define utopia_intr(S) ((S)->chip->intr((S)))
#endif /* _KERNEL */
#endif /* _DEV_UTOPIA_UTOPIA_H */

View File

@ -1,46 +0,0 @@
/*-
* Copyright (c) 2005
* Hartmut Brandt.
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*
* Private include file for the interface between chip files and
* the utopia main stuff.
*/
#ifndef _DEV_UTOPIA_UTOPIA_PRIV_H
#define _DEV_UTOPIA_UTOPIA_PRIV_H
#define UTP_READREGS(UTOPIA, REG, VALP, NP) \
(UTOPIA)->methods->readregs((UTOPIA)->ifatm, REG, VALP, NP)
#define UTP_WRITEREG(UTOPIA, REG, MASK, VAL) \
(UTOPIA)->methods->writereg((UTOPIA)->ifatm, REG, MASK, VAL)
uint32_t utopia_update(struct utopia *, u_int, u_int, uint32_t);
void utopia_check_carrier(struct utopia *, u_int);
#endif /* _DEV_UTOPIA_UTOPIA_PRIV_H */

View File

@ -107,7 +107,6 @@ SUBDIR= \
${_efirt} \
${_elink} \
${_em} \
en \
${_ep} \
${_epic} \
esp \
@ -116,7 +115,6 @@ SUBDIR= \
${_ex} \
${_exca} \
ext2fs \
${_fatm} \
fdc \
fdescfs \
${_fe} \
@ -130,7 +128,6 @@ SUBDIR= \
${_glxiic} \
${_glxsb} \
gpio \
hatm \
hifn \
hme \
${_hpt27xx} \
@ -289,7 +286,6 @@ SUBDIR= \
ow \
${_padlock} \
${_padlock_rng} \
patm \
${_pccard} \
${_pcfclock} \
pcn \
@ -380,7 +376,6 @@ SUBDIR= \
uinput \
unionfs \
usb \
utopia \
${_vesa} \
${_virtio} \
vge \
@ -500,7 +495,6 @@ _pfsync= pfsync
.if ${MK_SOURCELESS_UCODE} != "no"
_bce= bce
_fatm= fatm
_fxp= fxp
_ispfw= ispfw
_sf= sf

View File

@ -1,11 +0,0 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/dev/en
KMOD= if_en
SRCS= if_en_pci.c midway.c device_if.h bus_if.h pci_if.h
SRCS+= opt_inet.h opt_natm.h opt_ddb.h
CFLAGS+= -DENABLE_BPF
# CFLAGS+= -DINVARIANT_SUPPORT -DINVARIANTS -DEN_DEBUG=0
.include <bsd.kmod.mk>

View File

@ -1,12 +0,0 @@
# $FreeBSD$
#
# Author: Harti Brandt <harti@freebsd.org>
#
.PATH: ${SRCTOP}/sys/dev/fatm
KMOD= if_fatm
SRCS= if_fatm.c device_if.h bus_if.h pci_if.h opt_inet.h opt_natm.h
# CFLAGS+= -DFATM_DEBUG=0 -DINVARIANT_SUPPORT -DINVARIANTS
.include <bsd.kmod.mk>

View File

@ -1,14 +0,0 @@
# $FreeBSD$
#
# Author: Harti Brandt <harti@freebsd.org>
#
.PATH: ${SRCTOP}/sys/dev/hatm
KMOD= if_hatm
SRCS= if_hatm.c if_hatm_intr.c if_hatm_ioctl.c if_hatm_tx.c if_hatm_rx.c \
device_if.h bus_if.h pci_if.h opt_inet.h opt_natm.h
CFLAGS+= -DENABLE_BPF
# CFLAGS+= -DHATM_DEBUG -DINVARIANT_SUPPORT -DINVARIANTS
.include <bsd.kmod.mk>

View File

@ -1,7 +1,6 @@
# $FreeBSD$
SUBDIR= \
atm \
atmbase \
ccatm \
sscfu \

View File

@ -1,11 +0,0 @@
# $FreeBSD$
#
# Author: Harti Brandt <harti@freebsd.org>
#
.PATH: ${SRCTOP}/sys/netgraph/atm
KMOD= ng_atm
SRCS= ng_atm.c
# CFLAGS+= -DNGATM_DEBUG
.include <bsd.kmod.mk>

View File

@ -1,15 +0,0 @@
# $FreeBSD$
#
# Author: Harti Brandt <harti@freebsd.org>
#
.PATH: ${SRCTOP}/sys/dev/patm
KMOD= if_patm
SRCS= if_patm.c if_patm_attach.c if_patm_ioctl.c if_patm_intr.c \
if_patm_tx.c if_patm_rx.c if_patm_rtables.c \
device_if.h bus_if.h pci_if.h opt_inet.h opt_natm.h
CFLAGS+= -DENABLE_BPF
# CFLAGS+= -DPATM_DEBUG=0x0 -DINVARIANT_SUPPORT -DINVARIANTS -DDIAGNOSTIC
.include <bsd.kmod.mk>

View File

@ -1,8 +0,0 @@
# $FreeBSD$
.PATH: ${SRCTOP}/sys/dev/utopia
KMOD= utopia
SRCS= utopia.c suni.c idtphy.c bus_if.h device_if.h
.include <bsd.kmod.mk>

View File

@ -1,337 +0,0 @@
/* $NetBSD: if_atm.h,v 1.7 1996/11/09 23:02:27 chuck Exp $ */
/* $FreeBSD$ */
/*-
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED 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.
*/
/*
* net/if_atm.h
*/
/*
* Classification of ATM cards.
*/
#define ATM_DEVICE_UNKNOWN 0
#define ATM_DEVICE_PCA200E 1 /* Fore/Marconi PCA200-E */
#define ATM_DEVICE_HE155 2 /* Fore/Marconi HE155 */
#define ATM_DEVICE_HE622 3 /* Fore/Marconi HE622 */
#define ATM_DEVICE_ENI155P 4 /* Efficient networks 155p */
#define ATM_DEVICE_ADP155P 5 /* Adaptec 155p */
#define ATM_DEVICE_FORELE25 6 /* ForeRunnerLE 25 */
#define ATM_DEVICE_FORELE155 7 /* ForeRunnerLE 155 */
#define ATM_DEVICE_NICSTAR25 8 /* other 77211 25.6MBit */
#define ATM_DEVICE_NICSTAR155 9 /* other 77211 155MBit */
#define ATM_DEVICE_IDTABR25 10 /* 77252 based card 25MBit */
#define ATM_DEVICE_IDTABR155 11 /* 77252 based card 155MBit */
#define ATM_DEVICE_PROATM25 12 /* 77252 based ProSum card 25MBit */
#define ATM_DEVICE_PROATM155 13 /* 77252 based ProSum card 155MBit */
#define ATM_DEVICE_VIRTUAL 14 /* virtual ATM device (netgraph) */
/* map to strings and vendors */
#define ATM_DEVICE_NAMES \
{ "Unknown", "Unknown" }, \
{ "PCA200-E", "Fore/Marconi" }, \
{ "HE155", "Fore/Marconi" }, \
{ "HE622", "Fore/Marconi" }, \
{ "ENI155p", "Efficient Networks" }, \
{ "ADP155p", "Adaptec" }, \
{ "ForeRunnerLE25", "Fore/Marconi" }, \
{ "ForeRunnerLE155", "Fore/Marconi" }, \
{ "IDT77211/25", "IDT" }, \
{ "IDT77211/155", "IDT" }, \
{ "IDT77252/25", "IDT" }, \
{ "IDT77252/155", "IDT" }, \
{ "ProATM/25", "ProSum" }, \
{ "ProATM/155", "ProSum" }, \
{ "Virtual", "NetGraph" },
/*
* This is the common link layer MIB for all ATM interfaces. Much of the
* information here is needed for ILMI. This will be augmented by statistics
* at some point.
*/
struct ifatm_mib {
/* configuration data */
uint8_t device; /* type of card */
u_char esi[6]; /* end system identifier (MAC) */
uint32_t serial; /* card serial number */
uint32_t hw_version; /* card version */
uint32_t sw_version; /* firmware version (if any) */
uint32_t pcr; /* supported peak cell rate */
uint32_t media; /* physical media */
uint8_t vpi_bits; /* number of used bits in VPI field */
uint8_t vci_bits; /* number of used bits in VCI field */
uint16_t max_vpcs; /* maximum number of VPCs */
uint32_t max_vccs; /* maximum number of VCCs */
};
/*
* Traffic parameters for ATM connections. This contains all parameters
* to accommodate UBR, UBR+MCR, CBR, VBR and ABR connections.
*
* Keep in sync with ng_atm.h
*/
struct atmio_tparam {
uint32_t pcr; /* 24bit: Peak Cell Rate */
uint32_t scr; /* 24bit: VBR Sustainable Cell Rate */
uint32_t mbs; /* 24bit: VBR Maximum burst size */
uint32_t mcr; /* 24bit: ABR/VBR/UBR+MCR MCR */
uint32_t icr; /* 24bit: ABR ICR */
uint32_t tbe; /* 24bit: ABR TBE (1...2^24-1) */
uint8_t nrm; /* 3bit: ABR Nrm */
uint8_t trm; /* 3bit: ABR Trm */
uint16_t adtf; /* 10bit: ABR ADTF */
uint8_t rif; /* 4bit: ABR RIF */
uint8_t rdf; /* 4bit: ABR RDF */
uint8_t cdf; /* 3bit: ABR CDF */
};
/*
* VCC parameters
*
* Keep in sync with ng_atm.h
*/
struct atmio_vcc {
uint16_t flags; /* VCC flags */
uint16_t vpi;
uint16_t vci;
uint16_t rmtu; /* maximum receive PDU */
uint16_t tmtu; /* maximum transmit PDU */
uint8_t aal; /* aal type */
uint8_t traffic; /* traffic type */
struct atmio_tparam tparam; /* traffic parameters */
};
/* VCC flags */
#define ATMIO_FLAG_LLCSNAP 0x0002 /* same as ATM_PH_LLCSNAP */
#define ATMIO_FLAG_NG 0x0010 /* owned by netgraph */
#define ATMIO_FLAG_HARP 0x0020 /* owned by HARP */
#define ATMIO_FLAG_NORX 0x0100 /* not receiving on this VCC */
#define ATMIO_FLAG_NOTX 0x0200 /* not transmitting on this VCC */
#define ATMIO_FLAG_PVC 0x0400 /* this is a PVC */
#define ATMIO_FLAG_ASYNC 0x0800 /* async open/close */
#define ATMIO_FLAGS "\020\2LLCSNAP\5NG\6HARP\11NORX\12NOTX\13PVC\14ASYNC"
#define ATMIO_AAL_0 0 /* pure cells */
#define ATMIO_AAL_34 4 /* AAL3 and 4 */
#define ATMIO_AAL_5 5 /* AAL5 */
#define ATMIO_AAL_RAW 10 /* whatever the card does */
#define ATMIO_TRAFFIC_UBR 0
#define ATMIO_TRAFFIC_CBR 1
#define ATMIO_TRAFFIC_ABR 2
#define ATMIO_TRAFFIC_VBR 3
/*
* VCC table
*
* Keep in sync with ng_atm.h
*/
struct atmio_vcctable {
uint32_t count; /* number of vccs */
struct atmio_vcc vccs[0]; /* array of VCCs */
};
/*
* Peak cell rates for various physical media. Note, that there are
* different opinions on what the correct values are.
*/
#define ATM_RATE_25_6M 59259
#define ATM_RATE_155M 353208
#define ATM_RATE_622M 1412830
#define ATM_RATE_2_4G 5651320
#ifdef _KERNEL
/*
* Common fields for all ATM interfaces. Each driver's softc must start with
* this structure.
*/
struct ifatm {
struct ifnet *ifp;
struct ifatm_mib mib; /* exported data */
void *phy; /* usually SUNI */
void *ngpriv; /* netgraph link */
};
#define IFP2IFATM(ifp) ((struct ifatm *)(ifp)->if_l2com)
#endif
/*
* Keep structures in sync with ng_atm.h
*
* These are used by netgraph/harp to call the driver
* NATM uses the atm_pseudoioctl instead.
*/
struct atmio_openvcc {
void *rxhand; /* handle argument */
struct atmio_vcc param; /* parameters */
};
struct atmio_closevcc {
uint16_t vpi;
uint16_t vci;
};
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
#define RTALLOC1(A,B) rtalloc1((A),(B))
#elif defined(__FreeBSD__)
#define RTALLOC1(A,B) rtalloc1((A),(B),0UL)
#endif
/*
* pseudo header for packet transmission
*/
struct atm_pseudohdr {
uint8_t atm_ph[4]; /* flags+VPI+VCI1(msb)+VCI2(lsb) */
};
#define ATM_PH_FLAGS(X) ((X)->atm_ph[0])
#define ATM_PH_VPI(X) ((X)->atm_ph[1])
#define ATM_PH_VCI(X) ((((X)->atm_ph[2]) << 8) | ((X)->atm_ph[3]))
#define ATM_PH_SETVCI(X,V) { \
(X)->atm_ph[2] = ((V) >> 8) & 0xff; \
(X)->atm_ph[3] = ((V) & 0xff); \
}
/* use AAL5? (0 == aal0) */
#define ATM_PH_AAL5 0x01
/* use the LLC SNAP encoding (iff aal5) */
#define ATM_PH_LLCSNAP ATMIO_FLAG_LLCSNAP
#define ATM_PH_DRIVER7 0x40 /* reserve for driver's use */
#define ATM_PH_DRIVER8 0x80 /* reserve for driver's use */
#define ATMMTU 9180 /* ATM MTU size for IP */
/* XXX: could be 9188 with LLC/SNAP according
to comer */
#define SIOCATMGETVCCS _IOW('a', 125, struct atmio_vcctable)
#define SIOCATMOPENVCC _IOR('a', 126, struct atmio_openvcc)
#define SIOCATMCLOSEVCC _IOR('a', 127, struct atmio_closevcc)
#define SIOCATMGVCCS _IOWR('i', 230, struct ifreq)
/*
* XXX forget all the garbage in if_llc.h and do it the easy way
*/
#define ATMLLC_HDR "\252\252\3\0\0\0"
struct atmllc {
uint8_t llchdr[6]; /* aa.aa.03.00.00.00 */
uint8_t type[2]; /* "ethernet" type */
};
/* ATM_LLC macros: note type code in host byte order */
#define ATM_LLC_TYPE(X) (((X)->type[0] << 8) | ((X)->type[1]))
#define ATM_LLC_SETTYPE(X, V) do { \
(X)->type[0] = ((V) >> 8) & 0xff; \
(X)->type[1] = ((V) & 0xff); \
} while (0)
/*
* Events that are emitted by the driver. Currently the only consumer
* of this is the netgraph node.
*/
#define ATMEV_FLOW_CONTROL 0x0001 /* channel busy state changed */
#define ATMEV_IFSTATE_CHANGED 0x0002 /* up/down or carrier */
#define ATMEV_VCC_CHANGED 0x0003 /* PVC deleted/create */
#define ATMEV_ACR_CHANGED 0x0004 /* ABR ACR has changed */
struct atmev_flow_control {
uint16_t vpi; /* channel that is changed */
uint16_t vci;
u_int busy : 1; /* != 0 -> ATM layer busy */
};
struct atmev_ifstate_changed {
u_int running : 1; /* interface is running now */
u_int carrier : 1; /* carrier detected (or not) */
};
struct atmev_vcc_changed {
uint16_t vpi; /* channel that is changed */
uint16_t vci;
u_int up : 1; /* 1 - created, 0 - deleted */
};
struct atmev_acr_changed {
uint16_t vpi; /* channel that is changed */
uint16_t vci;
uint32_t acr; /* new ACR */
};
#ifdef _KERNEL
void atm_ifattach(struct ifnet *);
void atm_ifdetach(struct ifnet *);
void atm_input(struct ifnet *, struct atm_pseudohdr *,
struct mbuf *, void *);
int atm_output(struct ifnet *, struct mbuf *, const struct sockaddr *,
struct route *);
struct atmio_vcctable *atm_getvccs(struct atmio_vcc **, u_int, u_int,
struct mtx *, int);
void atm_event(struct ifnet *, u_int, void *);
#define ATMEV_SEND_FLOW_CONTROL(ATMIF, VPI, VCI, BUSY) \
do { \
struct atmev_flow_control _arg; \
_arg.vpi = (VPI); \
_arg.vci = (VCI); \
_arg.busy = (BUSY); \
atm_event((ATMIF)->ifp, ATMEV_FLOW_CONTROL, &_arg); \
} while (0)
#define ATMEV_SEND_VCC_CHANGED(ATMIF, VPI, VCI, UP) \
do { \
struct atmev_vcc_changed _arg; \
_arg.vpi = (VPI); \
_arg.vci = (VCI); \
_arg.up = (UP); \
atm_event((ATMIF)->ifp, ATMEV_VCC_CHANGED, &_arg); \
} while (0)
#define ATMEV_SEND_IFSTATE_CHANGED(ATMIF, CARRIER) \
do { \
struct atmev_ifstate_changed _arg; \
_arg.running = (((ATMIF)->ifp->if_drv_flags & \
IFF_DRV_RUNNING) != 0); \
_arg.carrier = ((CARRIER) != 0); \
atm_event((ATMIF)->ifp, ATMEV_IFSTATE_CHANGED, &_arg); \
} while (0)
#define ATMEV_SEND_ACR_CHANGED(ATMIF, VPI, VCI, ACR) \
do { \
struct atmev_acr_changed _arg; \
_arg.vpi = (VPI); \
_arg.vci = (VCI); \
_arg.acr= (ACR); \
atm_event((ATMIF)->ifp, ATMEV_ACR_CHANGED, &_arg); \
} while (0)
#endif

View File

@ -1,504 +0,0 @@
/* $NetBSD: if_atmsubr.c,v 1.10 1997/03/11 23:19:51 chuck Exp $ */
/*-
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED 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.
*
* if_atmsubr.c
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_natm.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/errno.h>
#include <sys/sysctl.h>
#include <sys/malloc.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/netisr.h>
#include <net/route.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_atm.h>
#include <netinet/in.h>
#include <netinet/if_atm.h>
#include <netinet/if_ether.h> /* XXX: for ETHERTYPE_* */
#if defined(INET) || defined(INET6)
#include <netinet/in_var.h>
#endif
#ifdef NATM
#include <netnatm/natm.h>
#endif
#include <security/mac/mac_framework.h>
/*
* Netgraph interface functions.
* These need not be protected by a lock, because ng_atm nodes are persitent.
* The ng_atm module can be unloaded only if all ATM interfaces have been
* unloaded, so nobody should be in the code paths accessing these function
* pointers.
*/
void (*ng_atm_attach_p)(struct ifnet *);
void (*ng_atm_detach_p)(struct ifnet *);
int (*ng_atm_output_p)(struct ifnet *, struct mbuf **);
void (*ng_atm_input_p)(struct ifnet *, struct mbuf **,
struct atm_pseudohdr *, void *);
void (*ng_atm_input_orphan_p)(struct ifnet *, struct mbuf *,
struct atm_pseudohdr *, void *);
void (*ng_atm_event_p)(struct ifnet *, uint32_t, void *);
/*
* Harp pseudo interface hooks
*/
void (*atm_harp_input_p)(struct ifnet *ifp, struct mbuf **m,
struct atm_pseudohdr *ah, void *rxhand);
void (*atm_harp_attach_p)(struct ifnet *);
void (*atm_harp_detach_p)(struct ifnet *);
void (*atm_harp_event_p)(struct ifnet *, uint32_t, void *);
SYSCTL_NODE(_hw, OID_AUTO, atm, CTLFLAG_RW, 0, "ATM hardware");
static MALLOC_DEFINE(M_IFATM, "ifatm", "atm interface internals");
#ifndef ETHERTYPE_IPV6
#define ETHERTYPE_IPV6 0x86dd
#endif
#define senderr(e) do { error = (e); goto bad; } while (0)
/*
* atm_output: ATM output routine
* inputs:
* "ifp" = ATM interface to output to
* "m0" = the packet to output
* "dst" = the sockaddr to send to (either IP addr, or raw VPI/VCI)
* "ro" = the route to use
* returns: error code [0 == ok]
*
* note: special semantic: if (dst == NULL) then we assume "m" already
* has an atm_pseudohdr on it and just send it directly.
* [for native mode ATM output] if dst is null, then
* ro->ro_rt must also be NULL.
*/
int
atm_output(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst,
struct route *ro)
{
u_int16_t etype = 0; /* if using LLC/SNAP */
int error = 0, sz;
struct atm_pseudohdr atmdst, *ad;
struct mbuf *m = m0;
struct atmllc *atmllc;
const struct atmllc *llc_hdr = NULL;
u_int32_t atm_flags;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
if (error)
senderr(error);
#endif
if (!((ifp->if_flags & IFF_UP) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING)))
senderr(ENETDOWN);
/*
* check for non-native ATM traffic (dst != NULL)
*/
if (dst) {
switch (dst->sa_family) {
#if defined(INET) || defined(INET6)
case AF_INET:
case AF_INET6:
{
if (dst->sa_family == AF_INET6)
etype = ETHERTYPE_IPV6;
else
etype = ETHERTYPE_IP;
if (!atmresolve(ro->ro_rt, m, dst, &atmdst)) {
m = NULL;
/* XXX: atmresolve already free'd it */
senderr(EHOSTUNREACH);
/* XXX: put ATMARP stuff here */
/* XXX: watch who frees m on failure */
}
}
break;
#endif /* INET || INET6 */
case AF_UNSPEC:
/*
* XXX: bpfwrite. assuming dst contains 12 bytes
* (atm pseudo header (4) + LLC/SNAP (8))
*/
bcopy(dst->sa_data, &atmdst, sizeof(atmdst));
llc_hdr = (const struct atmllc *)(dst->sa_data +
sizeof(atmdst));
break;
default:
printf("%s: can't handle af%d\n", ifp->if_xname,
dst->sa_family);
senderr(EAFNOSUPPORT);
}
/*
* must add atm_pseudohdr to data
*/
sz = sizeof(atmdst);
atm_flags = ATM_PH_FLAGS(&atmdst);
if (atm_flags & ATM_PH_LLCSNAP)
sz += 8; /* sizeof snap == 8 */
M_PREPEND(m, sz, M_NOWAIT);
if (m == NULL)
senderr(ENOBUFS);
ad = mtod(m, struct atm_pseudohdr *);
*ad = atmdst;
if (atm_flags & ATM_PH_LLCSNAP) {
atmllc = (struct atmllc *)(ad + 1);
if (llc_hdr == NULL) {
bcopy(ATMLLC_HDR, atmllc->llchdr,
sizeof(atmllc->llchdr));
/* note: in host order */
ATM_LLC_SETTYPE(atmllc, etype);
}
else
bcopy(llc_hdr, atmllc, sizeof(struct atmllc));
}
}
if (ng_atm_output_p != NULL) {
if ((error = (*ng_atm_output_p)(ifp, &m)) != 0) {
if (m != NULL)
m_freem(m);
return (error);
}
if (m == NULL)
return (0);
}
/*
* Queue message on interface, and start output if interface
* not yet active.
*/
if (!IF_HANDOFF_ADJ(&ifp->if_snd, m, ifp,
-(int)sizeof(struct atm_pseudohdr)))
return (ENOBUFS);
return (error);
bad:
if (m)
m_freem(m);
return (error);
}
/*
* Process a received ATM packet;
* the packet is in the mbuf chain m.
*/
void
atm_input(struct ifnet *ifp, struct atm_pseudohdr *ah, struct mbuf *m,
void *rxhand)
{
int isr;
u_int16_t etype = ETHERTYPE_IP; /* default */
if ((ifp->if_flags & IFF_UP) == 0) {
m_freem(m);
return;
}
#ifdef MAC
mac_ifnet_create_mbuf(ifp, m);
#endif
if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
if (ng_atm_input_p != NULL) {
(*ng_atm_input_p)(ifp, &m, ah, rxhand);
if (m == NULL)
return;
}
/* not eaten by ng_atm. Maybe it's a pseudo-harp PDU? */
if (atm_harp_input_p != NULL) {
(*atm_harp_input_p)(ifp, &m, ah, rxhand);
if (m == NULL)
return;
}
if (rxhand) {
#ifdef NATM
struct natmpcb *npcb;
/*
* XXXRW: this use of 'rxhand' is not a very good idea, and
* was subject to races even before SMPng due to the release
* of spl here.
*/
NATM_LOCK();
npcb = rxhand;
npcb->npcb_inq++; /* count # in queue */
isr = NETISR_NATM;
m->m_pkthdr.rcvif = rxhand; /* XXX: overload */
NATM_UNLOCK();
#else
printf("atm_input: NATM detected but not "
"configured in kernel\n");
goto dropit;
#endif
} else {
/*
* handle LLC/SNAP header, if present
*/
if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) {
struct atmllc *alc;
if (m->m_len < sizeof(*alc) &&
(m = m_pullup(m, sizeof(*alc))) == NULL)
return; /* failed */
alc = mtod(m, struct atmllc *);
if (bcmp(alc, ATMLLC_HDR, 6)) {
printf("%s: recv'd invalid LLC/SNAP frame "
"[vp=%d,vc=%d]\n", ifp->if_xname,
ATM_PH_VPI(ah), ATM_PH_VCI(ah));
m_freem(m);
return;
}
etype = ATM_LLC_TYPE(alc);
m_adj(m, sizeof(*alc));
}
switch (etype) {
#ifdef INET
case ETHERTYPE_IP:
isr = NETISR_IP;
break;
#endif
#ifdef INET6
case ETHERTYPE_IPV6:
isr = NETISR_IPV6;
break;
#endif
default:
#ifndef NATM
dropit:
#endif
if (ng_atm_input_orphan_p != NULL)
(*ng_atm_input_orphan_p)(ifp, m, ah, rxhand);
else
m_freem(m);
return;
}
}
M_SETFIB(m, ifp->if_fib);
netisr_dispatch(isr, m);
}
/*
* Perform common duties while attaching to interface list.
*/
void
atm_ifattach(struct ifnet *ifp)
{
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
struct ifatm *ifatm = ifp->if_l2com;
ifp->if_addrlen = 0;
ifp->if_hdrlen = 0;
if_attach(ifp);
ifp->if_mtu = ATMMTU;
ifp->if_output = atm_output;
#if 0
ifp->if_input = atm_input;
#endif
ifp->if_snd.ifq_maxlen = 50; /* dummy */
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (ifa->ifa_addr->sa_family == AF_LINK) {
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
sdl->sdl_type = IFT_ATM;
sdl->sdl_alen = ifp->if_addrlen;
#ifdef notyet /* if using ATMARP, store hardware address using the next line */
bcopy(ifp->hw_addr, LLADDR(sdl), ifp->if_addrlen);
#endif
break;
}
ifp->if_linkmib = &ifatm->mib;
ifp->if_linkmiblen = sizeof(ifatm->mib);
if(ng_atm_attach_p)
(*ng_atm_attach_p)(ifp);
if (atm_harp_attach_p)
(*atm_harp_attach_p)(ifp);
}
/*
* Common stuff for detaching an ATM interface
*/
void
atm_ifdetach(struct ifnet *ifp)
{
if (atm_harp_detach_p)
(*atm_harp_detach_p)(ifp);
if(ng_atm_detach_p)
(*ng_atm_detach_p)(ifp);
if_detach(ifp);
}
/*
* Support routine for the SIOCATMGVCCS ioctl().
*
* This routine assumes, that the private VCC structures used by the driver
* begin with a struct atmio_vcc.
*
* Return a table of VCCs in a freshly allocated memory area.
* Here we have a problem: we first count, how many vccs we need
* to return. The we allocate the memory and finally fill it in.
* Because we cannot lock while calling malloc, the number of active
* vccs may change while we're in malloc. So we allocate a couple of
* vccs more and if space anyway is not enough re-iterate.
*
* We could use an sx lock for the vcc tables.
*/
struct atmio_vcctable *
atm_getvccs(struct atmio_vcc **table, u_int size, u_int start,
struct mtx *lock, int waitok)
{
u_int cid, alloc;
size_t len;
struct atmio_vcctable *vccs;
struct atmio_vcc *v;
alloc = start + 10;
vccs = NULL;
for (;;) {
len = sizeof(*vccs) + alloc * sizeof(vccs->vccs[0]);
vccs = reallocf(vccs, len, M_TEMP,
waitok ? M_WAITOK : M_NOWAIT);
if (vccs == NULL)
return (NULL);
bzero(vccs, len);
vccs->count = 0;
v = vccs->vccs;
mtx_lock(lock);
for (cid = 0; cid < size; cid++)
if (table[cid] != NULL) {
if (++vccs->count == alloc)
/* too many - try again */
break;
*v++ = *table[cid];
}
mtx_unlock(lock);
if (cid == size)
break;
alloc *= 2;
}
return (vccs);
}
/*
* Driver or channel state has changed. Inform whoever is interested
* in these events.
*/
void
atm_event(struct ifnet *ifp, u_int event, void *arg)
{
if (ng_atm_event_p != NULL)
(*ng_atm_event_p)(ifp, event, arg);
if (atm_harp_event_p != NULL)
(*atm_harp_event_p)(ifp, event, arg);
}
static void *
atm_alloc(u_char type, struct ifnet *ifp)
{
struct ifatm *ifatm;
ifatm = malloc(sizeof(struct ifatm), M_IFATM, M_WAITOK | M_ZERO);
ifatm->ifp = ifp;
return (ifatm);
}
static void
atm_free(void *com, u_char type)
{
free(com, M_IFATM);
}
static int
atm_modevent(module_t mod, int type, void *data)
{
switch (type) {
case MOD_LOAD:
if_register_com_alloc(IFT_ATM, atm_alloc, atm_free);
break;
case MOD_UNLOAD:
if_deregister_com_alloc(IFT_ATM);
break;
default:
return (EOPNOTSUPP);
}
return (0);
}
static moduledata_t atm_mod = {
"atm",
atm_modevent,
0
};
DECLARE_MODULE(atm, atm_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
MODULE_VERSION(atm, 1);

View File

@ -55,7 +55,6 @@
#define NETISR_ARP 4 /* same as AF_LINK */
#define NETISR_ETHER 5 /* ethernet input */
#define NETISR_IPV6 6
#define NETISR_NATM 7
#define NETISR_EPAIR 8 /* if_epair(4) */
#define NETISR_IP_DIRECT 9 /* direct-dispatch IPv4 */
#define NETISR_IPV6_DIRECT 10 /* direct-dispatch IPv6 */

File diff suppressed because it is too large Load Diff

View File

@ -1,248 +0,0 @@
/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* Author: Harti Brandt <harti@freebsd.org>
*/
/*
* Netgraph module to connect NATM interfaces to netgraph.
*
* $FreeBSD$
*/
#ifndef _NETGRAPH_ATM_NG_ATM_H_
#define _NETGRAPH_ATM_NG_ATM_H_
#define NG_ATM_NODE_TYPE "atm"
#define NGM_ATM_COOKIE 960802260
/* Netgraph control messages */
enum {
NGM_ATM_GET_IFNAME = 1, /* get the interface name */
NGM_ATM_GET_CONFIG, /* get configuration */
NGM_ATM_GET_VCCS, /* get a list of all active vccs */
NGM_ATM_CPCS_INIT, /* start the channel */
NGM_ATM_CPCS_TERM, /* stop the channel */
NGM_ATM_GET_VCC, /* get VCC config */
NGM_ATM_GET_VCCID, /* get VCC by VCI/VPI */
NGM_ATM_GET_STATS, /* get global statistics */
/* messages from the node */
NGM_ATM_CARRIER_CHANGE = 1000, /* UNUSED: carrier changed */
NGM_ATM_VCC_CHANGE, /* permanent VCC changed */
NGM_ATM_ACR_CHANGE, /* ABR ACR has changed */
NGM_ATM_IF_CHANGE, /* interface state change */
};
/*
* Hardware interface configuration
*/
struct ngm_atm_config {
uint32_t pcr; /* peak cell rate */
uint32_t vpi_bits; /* number of active VPI bits */
uint32_t vci_bits; /* number of active VCI bits */
uint32_t max_vpcs; /* maximum number of VPCs */
uint32_t max_vccs; /* maximum number of VCCs */
};
#define NGM_ATM_CONFIG_INFO \
{ \
{ "pcr", &ng_parse_uint32_type }, \
{ "vpi_bits", &ng_parse_uint32_type }, \
{ "vci_bits", &ng_parse_uint32_type }, \
{ "max_vpcs", &ng_parse_uint32_type }, \
{ "max_vccs", &ng_parse_uint32_type }, \
{ NULL } \
}
/*
* Information about an open VCC
* See net/if_atm.h. Keep in sync.
*/
#define NGM_ATM_TPARAM_INFO \
{ \
{ "pcr", &ng_parse_uint32_type }, \
{ "scr", &ng_parse_uint32_type }, \
{ "mbs", &ng_parse_uint32_type }, \
{ "mcr", &ng_parse_uint32_type }, \
{ "icr", &ng_parse_uint32_type }, \
{ "tbe", &ng_parse_uint32_type }, \
{ "nrm", &ng_parse_uint8_type }, \
{ "trm", &ng_parse_uint8_type }, \
{ "adtf", &ng_parse_uint16_type }, \
{ "rif", &ng_parse_uint8_type }, \
{ "rdf", &ng_parse_uint8_type }, \
{ "cdf", &ng_parse_uint8_type }, \
{ NULL } \
}
#define NGM_ATM_VCC_INFO \
{ \
{ "flags", &ng_parse_hint16_type }, \
{ "vpi", &ng_parse_uint16_type }, \
{ "vci", &ng_parse_uint16_type }, \
{ "rmtu", &ng_parse_uint16_type }, \
{ "tmtu", &ng_parse_uint16_type }, \
{ "aal", &ng_parse_uint8_type }, \
{ "traffic", &ng_parse_uint8_type }, \
{ "tparam", &ng_atm_tparam_type }, \
{ NULL } \
}
#define NGM_ATM_VCCARRAY_INFO \
{ \
&ng_atm_vcc_type, \
ng_atm_vccarray_getlen, \
NULL \
}
#define NGM_ATM_VCCTABLE_INFO \
{ \
{ "count", &ng_parse_uint32_type }, \
{ "vccs", &ng_atm_vccarray_type }, \
{ NULL } \
}
/*
* Structure to open a VCC.
*/
struct ngm_atm_cpcs_init {
char name[NG_HOOKSIZ];
uint32_t flags; /* flags. (if_atm.h) */
uint16_t vci; /* VCI to open */
uint16_t vpi; /* VPI to open */
uint16_t rmtu; /* Receive maximum CPCS size */
uint16_t tmtu; /* Transmit maximum CPCS size */
uint8_t aal; /* AAL type (if_atm.h) */
uint8_t traffic; /* traffic type (if_atm.h) */
uint32_t pcr; /* Peak cell rate */
uint32_t scr; /* VBR: Sustainable cell rate */
uint32_t mbs; /* VBR: Maximum burst rate */
uint32_t mcr; /* UBR+: Minimum cell rate */
uint32_t icr; /* ABR: Initial cell rate */
uint32_t tbe; /* ABR: Transmit buffer exposure */
uint8_t nrm; /* ABR: Nrm */
uint8_t trm; /* ABR: Trm */
uint16_t adtf; /* ABR: ADTF */
uint8_t rif; /* ABR: RIF */
uint8_t rdf; /* ABR: RDF */
uint8_t cdf; /* ABR: CDF */
};
#define NGM_ATM_CPCS_INIT_INFO \
{ \
{ "name", &ng_parse_hookbuf_type }, \
{ "flags", &ng_parse_hint32_type }, \
{ "vci", &ng_parse_uint16_type }, \
{ "vpi", &ng_parse_uint16_type }, \
{ "rmtu", &ng_parse_uint16_type }, \
{ "tmtu", &ng_parse_uint16_type }, \
{ "aal", &ng_parse_uint8_type }, \
{ "traffic", &ng_parse_uint8_type }, \
{ "pcr", &ng_parse_uint32_type }, \
{ "scr", &ng_parse_uint32_type }, \
{ "mbs", &ng_parse_uint32_type }, \
{ "mcr", &ng_parse_uint32_type }, \
{ "icr", &ng_parse_uint32_type }, \
{ "tbe", &ng_parse_uint32_type }, \
{ "nrm", &ng_parse_uint8_type }, \
{ "trm", &ng_parse_uint8_type }, \
{ "adtf", &ng_parse_uint16_type }, \
{ "rif", &ng_parse_uint8_type }, \
{ "rdf", &ng_parse_uint8_type }, \
{ "cdf", &ng_parse_uint8_type }, \
{ NULL } \
}
/*
* Structure to close a VCI without disconnecting the hook
*/
struct ngm_atm_cpcs_term {
char name[NG_HOOKSIZ];
};
#define NGM_ATM_CPCS_TERM_INFO \
{ \
{ "name", &ng_parse_hookbuf_type }, \
{ NULL } \
}
struct ngm_atm_stats {
uint64_t in_packets;
uint64_t in_errors;
uint64_t out_packets;
uint64_t out_errors;
};
#define NGM_ATM_STATS_INFO \
{ \
{ "in_packets", &ng_parse_uint64_type }, \
{ "in_errors", &ng_parse_uint64_type }, \
{ "out_packets", &ng_parse_uint64_type }, \
{ "out_errors", &ng_parse_uint64_type }, \
{ NULL } \
}
struct ngm_atm_if_change {
uint32_t node;
uint8_t carrier;
uint8_t running;
};
#define NGM_ATM_IF_CHANGE_INFO \
{ \
{ "node", &ng_parse_hint32_type }, \
{ "carrier", &ng_parse_uint8_type }, \
{ "running", &ng_parse_uint8_type }, \
{ NULL } \
}
struct ngm_atm_vcc_change {
uint32_t node;
uint16_t vci;
uint8_t vpi;
uint8_t state;
};
#define NGM_ATM_VCC_CHANGE_INFO \
{ \
{ "node", &ng_parse_hint32_type }, \
{ "vci", &ng_parse_uint16_type }, \
{ "vpi", &ng_parse_uint8_type }, \
{ "state", &ng_parse_uint8_type }, \
{ NULL } \
}
struct ngm_atm_acr_change {
uint32_t node;
uint16_t vci;
uint8_t vpi;
uint32_t acr;
};
#define NGM_ATM_ACR_CHANGE_INFO \
{ \
{ "node", &ng_parse_hint32_type }, \
{ "vci", &ng_parse_uint16_type }, \
{ "vpi", &ng_parse_uint8_type }, \
{ "acr", &ng_parse_uint32_type }, \
{ NULL } \
}
#endif /* _NETGRAPH_ATM_NG_ATM_H */

View File

@ -40,7 +40,6 @@
#include <net/if.h>
#include <net/ethernet.h> /* for M_HASFCS and ETHER_HDR_LEN */
#include <net/if_atm.h> /* for struct atmllc */
#define NG_ATMLLC_HEADER "\252\252\3\0\200\302"
#define NG_ATMLLC_HEADER_LEN (sizeof(struct atmllc))
@ -55,6 +54,18 @@ struct ng_atmllc_priv {
hook_p fddi;
};
struct atmllc {
uint8_t llchdr[6]; /* aa.aa.03.00.00.00 */
uint8_t type[2]; /* "ethernet" type */
};
/* ATM_LLC macros: note type code in host byte order */
#define ATM_LLC_TYPE(X) (((X)->type[0] << 8) | ((X)->type[1]))
#define ATM_LLC_SETTYPE(X, V) do { \
(X)->type[0] = ((V) >> 8) & 0xff; \
(X)->type[1] = ((V) & 0xff); \
} while (0)
/* Netgraph methods. */
static ng_constructor_t ng_atmllc_constructor;
static ng_shutdown_t ng_atmllc_shutdown;

View File

@ -1,372 +0,0 @@
/* $NetBSD: if_atm.c,v 1.6 1996/10/13 02:03:01 christos Exp $ */
/*-
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* IP <=> ATM address resolution.
*/
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_natm.h"
#if defined(INET) || defined(INET6)
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/queue.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/syslog.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <net/if_atm.h>
#include <netinet/in.h>
#include <netinet/if_atm.h>
#ifdef NATM
#include <netnatm/natm.h>
#endif
#define SDL(s) ((struct sockaddr_dl *)s)
#define GET3BYTE(V, A, L) do { \
(V) = ((A)[0] << 16) | ((A)[1] << 8) | (A)[2]; \
(A) += 3; \
(L) -= 3; \
} while (0)
#define GET2BYTE(V, A, L) do { \
(V) = ((A)[0] << 8) | (A)[1]; \
(A) += 2; \
(L) -= 2; \
} while (0)
#define GET1BYTE(V, A, L) do { \
(V) = *(A)++; \
(L)--; \
} while (0)
/*
* atm_rtrequest: handle ATM rt request (in support of generic code)
* inputs: "req" = request code
* "rt" = route entry
* "info" = rt_addrinfo
*/
void
atm_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
{
struct sockaddr *gate = rt->rt_gateway;
struct atmio_openvcc op;
struct atmio_closevcc cl;
u_char *addr;
u_int alen;
#ifdef NATM
struct sockaddr_in *sin;
struct natmpcb *npcb = NULL;
#endif
static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
if (rt->rt_flags & RTF_GATEWAY) /* link level requests only */
return;
switch (req) {
case RTM_RESOLVE: /* resolve: only happens when cloning */
printf("atm_rtrequest: RTM_RESOLVE request detected?\n");
break;
case RTM_ADD:
/*
* route added by a command (e.g. ifconfig, route, arp...).
*
* first check to see if this is not a host route, in which
* case we are being called via "ifconfig" to set the address.
*/
if ((rt->rt_flags & RTF_HOST) == 0) {
rt_setgate(rt,rt_key(rt),(struct sockaddr *)&null_sdl);
gate = rt->rt_gateway;
SDL(gate)->sdl_type = rt->rt_ifp->if_type;
SDL(gate)->sdl_index = rt->rt_ifp->if_index;
break;
}
if (gate->sa_family != AF_LINK ||
gate->sa_len < sizeof(null_sdl)) {
log(LOG_DEBUG, "atm_rtrequest: bad gateway value");
break;
}
KASSERT(rt->rt_ifp->if_ioctl != NULL,
("atm_rtrequest: null ioctl"));
/*
* Parse and verify the link level address as
* an open request
*/
#ifdef NATM
NATM_LOCK();
#endif
bzero(&op, sizeof(op));
addr = LLADDR(SDL(gate));
alen = SDL(gate)->sdl_alen;
if (alen < 4) {
printf("%s: bad link-level address\n", __func__);
goto failed;
}
if (alen == 4) {
/* old type address */
GET1BYTE(op.param.flags, addr, alen);
GET1BYTE(op.param.vpi, addr, alen);
GET2BYTE(op.param.vci, addr, alen);
op.param.traffic = ATMIO_TRAFFIC_UBR;
op.param.aal = (op.param.flags & ATM_PH_AAL5) ?
ATMIO_AAL_5 : ATMIO_AAL_0;
} else {
/* new address */
op.param.aal = ATMIO_AAL_5;
GET1BYTE(op.param.flags, addr, alen);
op.param.flags &= ATM_PH_LLCSNAP;
GET1BYTE(op.param.vpi, addr, alen);
GET2BYTE(op.param.vci, addr, alen);
GET1BYTE(op.param.traffic, addr, alen);
switch (op.param.traffic) {
case ATMIO_TRAFFIC_UBR:
if (alen >= 3)
GET3BYTE(op.param.tparam.pcr,
addr, alen);
break;
case ATMIO_TRAFFIC_CBR:
if (alen < 3)
goto bad_param;
GET3BYTE(op.param.tparam.pcr, addr, alen);
break;
case ATMIO_TRAFFIC_VBR:
if (alen < 3 * 3)
goto bad_param;
GET3BYTE(op.param.tparam.pcr, addr, alen);
GET3BYTE(op.param.tparam.scr, addr, alen);
GET3BYTE(op.param.tparam.mbs, addr, alen);
break;
case ATMIO_TRAFFIC_ABR:
if (alen < 4 * 3 + 2 + 1 * 2 + 3)
goto bad_param;
GET3BYTE(op.param.tparam.pcr, addr, alen);
GET3BYTE(op.param.tparam.mcr, addr, alen);
GET3BYTE(op.param.tparam.icr, addr, alen);
GET3BYTE(op.param.tparam.tbe, addr, alen);
GET1BYTE(op.param.tparam.nrm, addr, alen);
GET1BYTE(op.param.tparam.trm, addr, alen);
GET2BYTE(op.param.tparam.adtf, addr, alen);
GET1BYTE(op.param.tparam.rif, addr, alen);
GET1BYTE(op.param.tparam.rdf, addr, alen);
GET1BYTE(op.param.tparam.cdf, addr, alen);
break;
default:
bad_param:
printf("%s: bad traffic params\n", __func__);
goto failed;
}
}
op.param.rmtu = op.param.tmtu = rt->rt_ifp->if_mtu;
#ifdef NATM
/*
* let native ATM know we are using this VCI/VPI
* (i.e. reserve it)
*/
sin = (struct sockaddr_in *) rt_key(rt);
if (sin->sin_family != AF_INET)
goto failed;
npcb = npcb_add(NULL, rt->rt_ifp, op.param.vci, op.param.vpi);
if (npcb == NULL)
goto failed;
npcb->npcb_flags |= NPCB_IP;
npcb->ipaddr.s_addr = sin->sin_addr.s_addr;
/* XXX: move npcb to llinfo when ATM ARP is ready */
#ifdef __notyet_restored__
rt->rt_llinfo = (caddr_t) npcb;
#endif
rt->rt_flags |= RTF_LLINFO;
#endif
/*
* let the lower level know this circuit is active
*/
op.rxhand = NULL;
op.param.flags |= ATMIO_FLAG_ASYNC;
if (rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMOPENVCC,
(caddr_t)&op) != 0) {
printf("atm: couldn't add VC\n");
goto failed;
}
SDL(gate)->sdl_type = rt->rt_ifp->if_type;
SDL(gate)->sdl_index = rt->rt_ifp->if_index;
#ifdef NATM
NATM_UNLOCK();
#endif
break;
failed:
#ifdef NATM
if (npcb) {
npcb_free(npcb, NPCB_DESTROY);
#ifdef __notyet_restored__
rt->rt_llinfo = NULL;
#endif
rt->rt_flags &= ~RTF_LLINFO;
}
NATM_UNLOCK();
#endif
/* mark as invalid. We cannot RTM_DELETE the route from
* here, because the recursive call to rtrequest1 does
* not really work. */
rt->rt_flags |= RTF_REJECT;
break;
case RTM_DELETE:
#ifdef NATM
/*
* tell native ATM we are done with this VC
*/
if (rt->rt_flags & RTF_LLINFO) {
NATM_LOCK();
#ifdef __notyet_restored__
npcb_free((struct natmpcb *)rt->rt_llinfo,
NPCB_DESTROY);
rt->rt_llinfo = NULL;
#endif
rt->rt_flags &= ~RTF_LLINFO;
NATM_UNLOCK();
}
#endif
/*
* tell the lower layer to disable this circuit
*/
bzero(&op, sizeof(op));
addr = LLADDR(SDL(gate));
addr++;
cl.vpi = *addr++;
cl.vci = *addr++ << 8;
cl.vci |= *addr++;
(void)rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMCLOSEVCC,
(caddr_t)&cl);
break;
}
}
/*
* atmresolve:
* inputs:
* [1] "rt" = the link level route to use (or null if need to look one up)
* [2] "m" = mbuf containing the data to be sent
* [3] "dst" = sockaddr_in (IP) address of dest.
* output:
* [4] "desten" = ATM pseudo header which we will fill in VPI/VCI info
* return:
* 0 == resolve FAILED; note that "m" gets m_freem'd in this case
* 1 == resolve OK; desten contains result
*
* XXX: will need more work if we wish to support ATMARP in the kernel,
* but this is enough for PVCs entered via the "route" command.
*/
int
atmresolve(struct rtentry *rt, struct mbuf *m, const struct sockaddr *dst,
struct atm_pseudohdr *desten)
{
struct sockaddr_dl *sdl;
if (m->m_flags & (M_BCAST | M_MCAST)) {
log(LOG_INFO,
"atmresolve: BCAST/MCAST packet detected/dumped\n");
goto bad;
}
if (rt == NULL) {
/* link level on table 0 XXX MRT */
rt = RTALLOC1(__DECONST(struct sockaddr *, dst), 0);
if (rt == NULL)
goto bad; /* failed */
RT_REMREF(rt); /* don't keep LL references */
if ((rt->rt_flags & RTF_GATEWAY) != 0 ||
rt->rt_gateway->sa_family != AF_LINK) {
RT_UNLOCK(rt);
goto bad;
}
RT_UNLOCK(rt);
}
/*
* note that rt_gateway is a sockaddr_dl which contains the
* atm_pseudohdr data structure for this route. we currently
* don't need any rt_llinfo info (but will if we want to support
* ATM ARP [c.f. if_ether.c]).
*/
sdl = SDL(rt->rt_gateway);
/*
* Check the address family and length is valid, the address
* is resolved; otherwise, try to resolve.
*/
if (sdl->sdl_family == AF_LINK && sdl->sdl_alen >= sizeof(*desten)) {
bcopy(LLADDR(sdl), desten, sizeof(*desten));
return (1); /* ok, go for it! */
}
/*
* we got an entry, but it doesn't have valid link address
* info in it (it is prob. the interface route, which has
* sdl_alen == 0). dump packet. (fall through to "bad").
*/
bad:
m_freem(m);
return (0);
}
#endif /* INET */

View File

@ -1,47 +0,0 @@
/* $FreeBSD$ */
/* $NetBSD: if_atm.h,v 1.2 1996/07/03 17:17:17 chuck Exp $ */
/*-
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED 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.
*/
/*
* if_atm.h
*/
struct atm_pseudohdr;
struct mbuf;
struct rtentry;
struct sockaddr;
void atm_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
int atmresolve(struct rtentry *, struct mbuf *, const struct sockaddr *,
struct atm_pseudohdr *);

View File

@ -1,490 +0,0 @@
/*-
* Copyright (c) 2005-2006 Robert N. M. Watson
* 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.
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED 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.
*
* $NetBSD: natm.c,v 1.5 1996/11/09 03:26:26 chuck Exp $
*/
/*
* natm.c: Native mode ATM access (both aal0 and aal5).
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sockio.h>
#include <sys/sx.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_atm.h>
#include <net/netisr.h>
#include <netinet/in.h>
#include <netnatm/natm.h>
static const u_long natm5_sendspace = 16*1024;
static const u_long natm5_recvspace = 16*1024;
static const u_long natm0_sendspace = 16*1024;
static const u_long natm0_recvspace = 16*1024;
/*
* netnatm global subsystem lock, protects all global data structures in
* netnatm.
*/
struct mtx natm_mtx;
/*
* User socket requests.
*/
static int natm_usr_attach(struct socket *, int, struct thread *);
static void natm_usr_detach(struct socket *);
static int natm_usr_connect(struct socket *, struct sockaddr *,
struct thread *);
static int natm_usr_disconnect(struct socket *);
static int natm_usr_shutdown(struct socket *);
static int natm_usr_send(struct socket *, int, struct mbuf *,
struct sockaddr *, struct mbuf *, struct thread *);
static int natm_usr_peeraddr(struct socket *, struct sockaddr **);
static int natm_usr_control(struct socket *, u_long, caddr_t,
struct ifnet *, struct thread *);
static void natm_usr_abort(struct socket *);
static int natm_usr_bind(struct socket *, struct sockaddr *,
struct thread *);
static int natm_usr_sockaddr(struct socket *, struct sockaddr **);
static int
natm_usr_attach(struct socket *so, int proto, struct thread *p)
{
struct natmpcb *npcb;
int error = 0;
npcb = (struct natmpcb *)so->so_pcb;
KASSERT(npcb == NULL, ("natm_usr_attach: so_pcb != NULL"));
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
if (proto == PROTO_NATMAAL5)
error = soreserve(so, natm5_sendspace,
natm5_recvspace);
else
error = soreserve(so, natm0_sendspace,
natm0_recvspace);
if (error)
return (error);
}
so->so_pcb = npcb = npcb_alloc(M_WAITOK);
npcb->npcb_socket = so;
return (error);
}
static void
natm_usr_detach(struct socket *so)
{
struct natmpcb *npcb;
npcb = (struct natmpcb *)so->so_pcb;
KASSERT(npcb != NULL, ("natm_usr_detach: npcb == NULL"));
NATM_LOCK();
npcb_free(npcb, NPCB_DESTROY); /* drain */
so->so_pcb = NULL;
NATM_UNLOCK();
}
static int
natm_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *p)
{
struct natmpcb *npcb;
struct sockaddr_natm *snatm;
struct atmio_openvcc op;
struct ifnet *ifp;
int error = 0;
int proto = so->so_proto->pr_protocol;
npcb = (struct natmpcb *)so->so_pcb;
KASSERT(npcb != NULL, ("natm_usr_connect: npcb == NULL"));
/*
* Validate nam and npcb.
*/
NATM_LOCK();
snatm = (struct sockaddr_natm *)nam;
if (snatm->snatm_len != sizeof(*snatm) ||
(npcb->npcb_flags & NPCB_FREE) == 0) {
NATM_UNLOCK();
return (EINVAL);
}
if (snatm->snatm_family != AF_NATM) {
NATM_UNLOCK();
return (EAFNOSUPPORT);
}
snatm->snatm_if[IFNAMSIZ - 1] = '\0'; /* XXX ensure null termination
since ifunit() uses strcmp */
/*
* Convert interface string to ifp, validate.
*/
ifp = ifunit(snatm->snatm_if);
if (ifp == NULL || (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
NATM_UNLOCK();
return (ENXIO);
}
if (ifp->if_output != atm_output) {
NATM_UNLOCK();
return (EAFNOSUPPORT);
}
/*
* Register us with the NATM PCB layer.
*/
if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
NATM_UNLOCK();
return (EADDRINUSE);
}
/*
* Open the channel.
*
* XXXRW: Eventually desirable to hold mutex over ioctl?
*/
bzero(&op, sizeof(op));
op.rxhand = npcb;
op.param.flags = ATMIO_FLAG_PVC;
op.param.vpi = npcb->npcb_vpi;
op.param.vci = npcb->npcb_vci;
op.param.rmtu = op.param.tmtu = ifp->if_mtu;
op.param.aal = (proto == PROTO_NATMAAL5) ? ATMIO_AAL_5 : ATMIO_AAL_0;
op.param.traffic = ATMIO_TRAFFIC_UBR;
NATM_UNLOCK();
if (ifp->if_ioctl == NULL ||
ifp->if_ioctl(ifp, SIOCATMOPENVCC, (caddr_t)&op) != 0)
return (EIO);
soisconnected(so);
return (error);
}
static int
natm_usr_disconnect(struct socket *so)
{
struct natmpcb *npcb;
struct atmio_closevcc cl;
struct ifnet *ifp;
int error = 0;
npcb = (struct natmpcb *)so->so_pcb;
KASSERT(npcb != NULL, ("natm_usr_disconnect: npcb == NULL"));
NATM_LOCK();
if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
NATM_UNLOCK();
printf("natm: disconnected check\n");
return (EIO);
}
ifp = npcb->npcb_ifp;
/*
* Disable rx.
*
* XXXRW: Eventually desirable to hold mutex over ioctl?
*/
cl.vpi = npcb->npcb_vpi;
cl.vci = npcb->npcb_vci;
NATM_UNLOCK();
if (ifp->if_ioctl != NULL)
ifp->if_ioctl(ifp, SIOCATMCLOSEVCC, (caddr_t)&cl);
soisdisconnected(so);
return (error);
}
static int
natm_usr_shutdown(struct socket *so)
{
socantsendmore(so);
return (0);
}
static int
natm_usr_send(struct socket *so, int flags, struct mbuf *m,
struct sockaddr *nam, struct mbuf *control, struct thread *p)
{
struct natmpcb *npcb;
struct atm_pseudohdr *aph;
int error = 0;
int proto = so->so_proto->pr_protocol;
npcb = (struct natmpcb *)so->so_pcb;
KASSERT(npcb != NULL, ("natm_usr_send: npcb == NULL"));
NATM_LOCK();
if (control && control->m_len) {
NATM_UNLOCK();
m_freem(control);
m_freem(m);
return (EINVAL);
}
/*
* Send the data. We must put an atm_pseudohdr on first.
*/
M_PREPEND(m, sizeof(*aph), M_NOWAIT);
if (m == NULL) {
NATM_UNLOCK();
m_freem(control);
return (ENOBUFS);
}
aph = mtod(m, struct atm_pseudohdr *);
ATM_PH_VPI(aph) = npcb->npcb_vpi;
ATM_PH_SETVCI(aph, npcb->npcb_vci);
ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
NATM_UNLOCK();
return (error);
}
static int
natm_usr_peeraddr(struct socket *so, struct sockaddr **nam)
{
struct natmpcb *npcb;
struct sockaddr_natm *snatm, ssnatm;
npcb = (struct natmpcb *)so->so_pcb;
KASSERT(npcb != NULL, ("natm_usr_peeraddr: npcb == NULL"));
NATM_LOCK();
snatm = &ssnatm;
bzero(snatm, sizeof(*snatm));
snatm->snatm_len = sizeof(*snatm);
snatm->snatm_family = AF_NATM;
strlcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname,
sizeof(snatm->snatm_if));
snatm->snatm_vci = npcb->npcb_vci;
snatm->snatm_vpi = npcb->npcb_vpi;
NATM_UNLOCK();
*nam = sodupsockaddr((struct sockaddr *)snatm, M_WAITOK);
return (0);
}
static int
natm_usr_control(struct socket *so, u_long cmd, caddr_t arg,
struct ifnet *ifp, struct thread *p)
{
struct natmpcb *npcb;
npcb = (struct natmpcb *)so->so_pcb;
KASSERT(npcb != NULL, ("natm_usr_control: npcb == NULL"));
switch (cmd) {
case SIOCSIFADDR:
case SIOCSIFBRDADDR:
case SIOCSIFDSTADDR:
case SIOCSIFNETMASK:
/*
* Although we should pass any non-ATM ioctl requests
* down to driver, we filter some legacy INET requests.
* Drivers trust SIOCSIFADDR et al to come from an already
* privileged layer, and do not perform any credentials
* checks or input validation.
*/
return (EINVAL);
}
if (ifp == NULL || ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
return ((*ifp->if_ioctl)(ifp, cmd, arg));
}
static void
natm_usr_abort(struct socket *so)
{
}
static void
natm_usr_close(struct socket *so)
{
}
static int
natm_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *p)
{
return (EOPNOTSUPP);
}
static int
natm_usr_sockaddr(struct socket *so, struct sockaddr **nam)
{
return (EOPNOTSUPP);
}
/* xxx - should be const */
struct pr_usrreqs natm_usrreqs = {
.pru_abort = natm_usr_abort,
.pru_attach = natm_usr_attach,
.pru_bind = natm_usr_bind,
.pru_connect = natm_usr_connect,
.pru_control = natm_usr_control,
.pru_detach = natm_usr_detach,
.pru_disconnect = natm_usr_disconnect,
.pru_peeraddr = natm_usr_peeraddr,
.pru_send = natm_usr_send,
.pru_shutdown = natm_usr_shutdown,
.pru_sockaddr = natm_usr_sockaddr,
.pru_close = natm_usr_close,
};
/*
* natmintr: interrupt
*
* Note: we expect a socket pointer in rcvif rather than an interface
* pointer. We can get the interface pointer from the so's PCB if we really
* need it.
*/
void
natmintr(struct mbuf *m)
{
struct socket *so;
struct natmpcb *npcb;
#ifdef DIAGNOSTIC
M_ASSERTPKTHDR(m);
#endif
NATM_LOCK();
npcb = (struct natmpcb *)m->m_pkthdr.rcvif; /* XXX: overloaded */
so = npcb->npcb_socket;
npcb->npcb_inq--;
if (npcb->npcb_flags & NPCB_DRAIN) {
if (npcb->npcb_inq == 0)
free(npcb, M_PCB); /* done! */
NATM_UNLOCK();
m_freem(m);
return;
}
if (npcb->npcb_flags & NPCB_FREE) {
NATM_UNLOCK();
m_freem(m); /* drop */
return;
}
#ifdef NEED_TO_RESTORE_IFP
m->m_pkthdr.rcvif = npcb->npcb_ifp;
#else
#ifdef DIAGNOSTIC
m->m_pkthdr.rcvif = NULL; /* null it out to be safe */
#endif
#endif
if (sbspace(&so->so_rcv) > m->m_pkthdr.len) {
#ifdef NATM_STAT
natm_sookcnt++;
natm_sookbytes += m->m_pkthdr.len;
#endif
sbappendrecord(&so->so_rcv, m);
sorwakeup(so);
NATM_UNLOCK();
} else {
#ifdef NATM_STAT
natm_sodropcnt++;
natm_sodropbytes += m->m_pkthdr.len;
#endif
NATM_UNLOCK();
m_freem(m);
}
}
/*
* natm0_sysctl: not used, but here in case we want to add something
* later...
*/
int
natm0_sysctl(SYSCTL_HANDLER_ARGS)
{
/* All sysctl names at this level are terminal. */
return (ENOENT);
}
/*
* natm5_sysctl: not used, but here in case we want to add something
* later...
*/
int
natm5_sysctl(SYSCTL_HANDLER_ARGS)
{
/* All sysctl names at this level are terminal. */
return (ENOENT);
}

View File

@ -1,120 +0,0 @@
/*-
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED 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.
*
* $NetBSD: natm.h,v 1.1 1996/07/04 03:20:12 chuck Exp $
* $FreeBSD$
*/
/*
* natm.h: native mode atm
*/
/*
* supported protocols
*/
#define PROTO_NATMAAL0 1
#define PROTO_NATMAAL5 2
/*
* sockaddr_natm
*/
struct sockaddr_natm {
unsigned char snatm_len; /* length */
sa_family_t snatm_family; /* AF_NATM */
char snatm_if[IFNAMSIZ]; /* interface name */
u_int16_t snatm_vci; /* vci */
u_int8_t snatm_vpi; /* vpi */
};
#ifdef _KERNEL
/*
* natm protocol control block
*/
struct natmpcb {
LIST_ENTRY(natmpcb) pcblist; /* list pointers */
u_int npcb_inq; /* # of our pkts in proto q */
struct socket *npcb_socket; /* backpointer to socket */
struct ifnet *npcb_ifp; /* pointer to hardware */
struct in_addr ipaddr; /* remote IP address, if APCB_IP */
u_int16_t npcb_vci; /* VCI */
u_int8_t npcb_vpi; /* VPI */
u_int8_t npcb_flags; /* flags */
};
/* flags */
#define NPCB_FREE 0x01 /* free (not on any list) */
#define NPCB_CONNECTED 0x02 /* connected */
#define NPCB_IP 0x04 /* used by IP */
#define NPCB_DRAIN 0x08 /* destroy as soon as inq == 0 */
/* flag arg to npcb_free */
#define NPCB_REMOVE 0 /* remove from global list */
#define NPCB_DESTROY 1 /* destroy and be free */
LIST_HEAD(npcblist, natmpcb);
/* global data structures */
extern struct mtx natm_mtx; /* global netnatm lock */
extern struct npcblist natm_pcbs; /* global list of pcbs */
#define NATM_STAT
#ifdef NATM_STAT
extern u_int natm_sodropcnt;
extern u_int natm_sodropbytes; /* account of droppage */
extern u_int natm_sookcnt;
extern u_int natm_sookbytes; /* account of ok */
#endif
/* locking macros */
#define NATM_LOCK_INIT() mtx_init(&natm_mtx, "natm_mtx", NULL, MTX_DEF)
#define NATM_LOCK() mtx_lock(&natm_mtx)
#define NATM_UNLOCK() mtx_unlock(&natm_mtx)
#define NATM_LOCK_ASSERT() mtx_assert(&natm_mtx, MA_OWNED)
/* external functions */
/* natm_pcb.c */
struct natmpcb *npcb_alloc(int);
void npcb_free(struct natmpcb *, int);
struct natmpcb *npcb_add(struct natmpcb *, struct ifnet *, uint16_t, uint8_t);
/* natm.c */
extern struct pr_usrreqs natm_usrreqs;
#ifdef SYSCTL_HANDLER_ARGS
int natm0_sysctl(SYSCTL_HANDLER_ARGS);
int natm5_sysctl(SYSCTL_HANDLER_ARGS);
#endif
void natmintr(struct mbuf *);
#endif

View File

@ -1,167 +0,0 @@
/*-
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED 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.
*
* $NetBSD: natm_pcb.c,v 1.4 1996/11/09 03:26:27 chuck Exp $
*/
/*
* atm_pcb.c: manage atm protocol control blocks and keep IP and NATM
* from trying to use each other's VCs.
*/
#include "opt_ddb.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <net/if.h>
#include <net/if_var.h> /* XXX: db_show_natm() */
#include <netinet/in.h>
#include <netnatm/natm.h>
#include <ddb/ddb.h>
struct npcblist natm_pcbs;
/*
* npcb_alloc: allocate a npcb [in the free state]
*/
struct natmpcb *
npcb_alloc(int wait)
{
struct natmpcb *npcb;
npcb = malloc(sizeof(*npcb), M_PCB, wait | M_ZERO);
if (npcb != NULL)
npcb->npcb_flags = NPCB_FREE;
return (npcb);
}
/*
* npcb_free: free a npcb
*/
void
npcb_free(struct natmpcb *npcb, int op)
{
NATM_LOCK_ASSERT();
if ((npcb->npcb_flags & NPCB_FREE) == 0) {
LIST_REMOVE(npcb, pcblist);
npcb->npcb_flags = NPCB_FREE;
}
if (op == NPCB_DESTROY) {
if (npcb->npcb_inq) {
npcb->npcb_flags = NPCB_DRAIN; /* flag for distruct. */
} else {
free(npcb, M_PCB); /* kill it! */
}
}
}
/*
* npcb_add: add or remove npcb from main list
* returns npcb if ok
*/
struct natmpcb *
npcb_add(struct natmpcb *npcb, struct ifnet *ifp, u_int16_t vci, u_int8_t vpi)
{
struct natmpcb *cpcb = NULL; /* current pcb */
NATM_LOCK_ASSERT();
/*
* lookup required
*/
LIST_FOREACH(cpcb, &natm_pcbs, pcblist)
if (ifp == cpcb->npcb_ifp && vci == cpcb->npcb_vci &&
vpi == cpcb->npcb_vpi)
break;
/*
* add & something already there?
*/
if (cpcb) {
cpcb = NULL;
goto done; /* fail */
}
/*
* need to allocate a pcb?
*/
if (npcb == NULL) {
/* could be called from lower half */
cpcb = npcb_alloc(M_NOWAIT);
if (cpcb == NULL)
goto done; /* fail */
} else {
cpcb = npcb;
}
cpcb->npcb_ifp = ifp;
cpcb->ipaddr.s_addr = 0;
cpcb->npcb_vci = vci;
cpcb->npcb_vpi = vpi;
cpcb->npcb_flags = NPCB_CONNECTED;
LIST_INSERT_HEAD(&natm_pcbs, cpcb, pcblist);
done:
return (cpcb);
}
#ifdef DDB
DB_SHOW_COMMAND(natm, db_show_natm)
{
struct natmpcb *cpcb;
db_printf("npcb dump:\n");
LIST_FOREACH(cpcb, &natm_pcbs, pcblist) {
db_printf("if=%s, vci=%d, vpi=%d, IP=0x%x, sock=%p, "
"flags=0x%x, inq=%d\n", cpcb->npcb_ifp->if_xname,
cpcb->npcb_vci, cpcb->npcb_vpi, cpcb->ipaddr.s_addr,
cpcb->npcb_socket, cpcb->npcb_flags, cpcb->npcb_inq);
}
}
#endif

View File

@ -1,116 +0,0 @@
/*-
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED 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.
*
* $NetBSD: natm_proto.c,v 1.3 1996/09/18 00:56:41 chuck Exp $
*/
/*
* protocol layer for access to native mode ATM
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/domain.h>
#include <net/if.h>
#include <net/netisr.h>
#include <netinet/in.h>
#include <netnatm/natm.h>
static void natm_init(void);
static struct domain natmdomain;
static struct protosw natmsw[] = {
{
.pr_type = SOCK_STREAM,
.pr_domain = &natmdomain,
.pr_protocol = PROTO_NATMAAL5,
.pr_flags = PR_CONNREQUIRED,
.pr_usrreqs = &natm_usrreqs
},
{
.pr_type = SOCK_DGRAM,
.pr_domain = &natmdomain,
.pr_protocol = PROTO_NATMAAL5,
.pr_flags = PR_CONNREQUIRED|PR_ATOMIC,
.pr_usrreqs = &natm_usrreqs
},
{
.pr_type = SOCK_STREAM,
.pr_domain = &natmdomain,
.pr_protocol = PROTO_NATMAAL0,
.pr_flags = PR_CONNREQUIRED,
.pr_usrreqs = &natm_usrreqs
},
};
static struct domain natmdomain = {
.dom_family = AF_NATM,
.dom_name = "natm",
.dom_init = natm_init,
.dom_protosw = natmsw,
.dom_protoswNPROTOSW = &natmsw[nitems(natmsw)],
};
static struct netisr_handler natm_nh = {
.nh_name = "natm",
.nh_handler = natmintr,
.nh_proto = NETISR_NATM,
.nh_qlimit = 1000,
.nh_policy = NETISR_POLICY_SOURCE,
};
#ifdef NATM_STAT
u_int natm_sodropcnt; /* # mbufs dropped due to full sb */
u_int natm_sodropbytes; /* # of bytes dropped */
u_int natm_sookcnt; /* # mbufs ok */
u_int natm_sookbytes; /* # of bytes ok */
#endif
static void
natm_init(void)
{
LIST_INIT(&natm_pcbs);
NATM_LOCK_INIT();
netisr_register(&natm_nh);
}
DOMAIN_SET(natm);

View File

@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
#define __FreeBSD_version 1200029 /* Master, propagated to newvers */
#define __FreeBSD_version 1200030 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

View File

@ -4,11 +4,7 @@
.PATH: ${SRCTOP}/contrib/bsnmp/snmpd
.if ${MK_ATM} != "no"
_snmp_atm= snmp_atm
.endif
SUBDIR= ${_snmp_atm} \
SUBDIR= \
snmp_bridge \
snmp_hostres \
snmp_lm75 \

View File

@ -1,101 +0,0 @@
--
-- Copyright (c) 2004
-- Hartmut Brandt.
-- All rights reserved.
--
-- Author: Hartmut Brandt <harti@freebsd.org>
--
-- 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 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 AUTHOR OR CONTRIBUTORS BE LIABLE
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-- SUCH DAMAGE.
--
-- $FreeBSD$
--
-- Private Begemot MIB for ATM interfaces on FreeBSD
--
BEGEMOT-ATM-FREEBSD-MIB DEFINITIONS ::= BEGIN
IMPORTS
MODULE-IDENTITY, OBJECT-TYPE
FROM SNMPv2-SMI
NgNodeIdOrZero
FROM BEGEMOT-NETGRAPH-MIB
begemotAtmSysGroup, begemotAtmIfEntry
FROM BEGEMOT-ATM-MIB;
begemotAtmFreeBSDGroup MODULE-IDENTITY
LAST-UPDATED "200408060000Z"
ORGANIZATION "German Aerospace Centre"
CONTACT-INFO
" Hartmut Brandt
Postal: German Aerospace Centre (DLR)
Institute of Communications and Navigation
82234 Wessling
Germany
Fax: +49 8153 28 2844
E-mail: harti@freebsd.org"
DESCRIPTION
"The FreeBSD specific Begemot MIB for ATM interfaces."
REVISION "200408060000Z"
DESCRIPTION
"Initial revision."
::= { begemotAtmSysGroup 1 }
-- Netgraph
begemotAtmNgGroup OBJECT IDENTIFIER ::= { begemotAtmFreeBSDGroup 1 }
--
-- Interfaces table
--
begemotAtmNgIfTable OBJECT-TYPE
SYNTAX SEQUENCE OF BegemotAtmNgIfEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"This table contains an entry for each hardware ATM
interface. The table is indexed by the interface index."
::= { begemotAtmNgGroup 1 }
begemotAtmNgIfEntry OBJECT-TYPE
SYNTAX BegemotAtmNgIfEntry
MAX-ACCESS not-accessible
STATUS current
DESCRIPTION
"This is a table entry describing one ATM hardware interface."
AUGMENTS { begemotAtmIfEntry }
::= { begemotAtmNgIfTable 1 }
BegemotAtmNgIfEntry ::= SEQUENCE {
begemotAtmNgIfNodeId NgNodeIdOrZero
}
begemotAtmNgIfNodeId OBJECT-TYPE
SYNTAX NgNodeIdOrZero
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The netgraph node id of the interface. If there is no
node corresponding to the interface, this is 0."
::= { begemotAtmNgIfEntry 1 }
END

View File

@ -1,21 +0,0 @@
# $FreeBSD$
#
# Author: Harti Brandt <harti@freebsd.org>
CONTRIB= ${SRCTOP}/contrib/ngatm
.PATH: ${CONTRIB}/snmp_atm
MOD= atm
SRCS= snmp_atm.c atm_sys.c
XSYM= begemotAtm
MAN= snmp_atm.3
BMIBS= BEGEMOT-ATM.txt BEGEMOT-ATM-FREEBSD-MIB.txt
DEFS= ${MOD}_tree.def atm_freebsd.def
INCS= snmp_${MOD}.h
EXTRAMIBDEFS= atm_freebsd.def
CFLAGS+= -I${CONTRIB}/snmp_atm
.include <bsd.snmpmod.mk>

View File

@ -1,22 +0,0 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libbsnmp/libbsnmp \
lib/libc \
lib/libcompiler_rt \
usr.sbin/bsnmpd/modules \
usr.sbin/bsnmpd/modules/snmp_mibII \
usr.sbin/bsnmpd/modules/snmp_netgraph \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -1,56 +0,0 @@
#
# Copyright (c) 2004
# Hartmut Brandt.
# All rights reserved.
#
# Author: Hartmut Brandt <harti@freebsd.org>
#
# 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 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 AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
# SNMP module for ATM hardware interfaces.
#
# $Begemot: libunimsg/snmp_atm/atm_tree.def,v 1.2 2004/08/05 07:14:22 brandt Exp $
#
(1 internet
(4 private
(1 enterprises
(12325 fokus
(1 begemot
(101 begemotAtm
(1 begemotAtmObjects
(4 begemotAtmSysGroup
(1 begemotAtmFreeBSDGroup
(1 begemotAtmNgGroup
(1 begemotAtmNgIfTable
(1 begemotAtmNgIfEntry : INTEGER op_atmif_ng
(1 begemotAtmIfNodeId UNSIGNED32 GET)
))
)
)
)
)
))
)
)
))

View File

@ -1,301 +0,0 @@
/*
* Copyright (c) 2001-2002
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
* Copyright (c) 2003-2004
* Hartmut Brandt.
* All rights reserved.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* 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 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 AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*
* SNMP module for ATM hardware interfaces - FreeBSD/Ng specific part.
*/
#include "atm.h"
#include "atm_tree.h"
#include "atm_oid.h"
#include <stdlib.h>
#include <syslog.h>
#include <string.h>
#include <net/if_atm.h>
#include <bsnmp/snmp_netgraph.h>
#include <netgraph/ng_message.h>
#include <netgraph/atm/ng_atm.h>
static const struct hwinfo {
const char *device;
const char *vendor;
} hwinfo[] = {
ATM_DEVICE_NAMES
};
struct atmif_sys {
ng_ID_t atm_node;
void *regc; /* cookie registration */
};
/*
* Find the interface for a given node
*/
struct atmif *
atm_node2if(u_int node)
{
struct atmif_priv *aif;
if (node != 0)
TAILQ_FOREACH(aif, &atmif_list, link)
if (aif->sys->atm_node == node)
return (&aif->pub);
return (NULL);
}
u_int
atm_if2node(struct atmif *pub)
{
struct atmif_priv *aif = (struct atmif_priv *)pub;
return (aif->sys->atm_node);
}
/*
* Destroy system dependend stuff.
*/
void
atmif_sys_destroy(struct atmif_priv *aif)
{
ng_unregister_cookie(aif->sys->regc);
free(aif->sys);
free(aif->pub.mib);
}
/*
* Handle a message from the ATM node
*/
static void
handle_atm_message(const struct ng_mesg *mesg, const char *path __unused,
ng_ID_t node, void *uarg)
{
struct atmif_priv *aif = uarg;
enum atmif_carrier_state ost;
switch (mesg->header.cmd) {
case NGM_ATM_IF_CHANGE:
{
const struct ngm_atm_if_change *arg;
ost = aif->pub.carrier;
if (mesg->header.arglen != sizeof(*arg)) {
syslog(LOG_ERR, "ATM_IF_CHANGE: wrong size");
atmif_check_carrier(aif);
return;
}
arg = (const struct ngm_atm_if_change *)
(const void *)mesg->data;
if (arg->carrier)
aif->pub.carrier = ATMIF_CARRIER_ON;
else
aif->pub.carrier = ATMIF_CARRIER_OFF;
if (ost != aif->pub.carrier)
atmif_send_notification(aif, ATMIF_NOTIFY_CARRIER,
(uintptr_t)ost);
return;
}
case NGM_ATM_VCC_CHANGE:
{
const struct ngm_atm_vcc_change *arg;
if (mesg->header.arglen != sizeof(*arg)) {
syslog(LOG_ERR, "ATM_VCC_CHANGE: wrong size");
return;
}
arg = (const struct ngm_atm_vcc_change *)
(const void *)mesg->data;
atmif_send_notification(aif, ATMIF_NOTIFY_VCC,
(uintptr_t)(((arg->vpi & 0xff) << 24) |
((arg->vci & 0xffff) << 8) | (arg->state & 1)));
return;
}
}
syslog(LOG_WARNING, "spurious message %u from node [%x]",
mesg->header.cmd, node);
}
/*
* Attach to an ATM interface
*/
int
atmif_sys_attach_if(struct atmif_priv *aif)
{
struct ng_mesg *resp, *resp1;
struct namelist *list;
u_int i;
if ((aif->sys = malloc(sizeof(*aif->sys))) == NULL) {
syslog(LOG_CRIT, "out of memory");
return (-1);
}
memset(aif->sys, 0, sizeof(*aif->sys));
if ((aif->pub.mib = malloc(sizeof(*aif->pub.mib))) == NULL) {
free(aif->sys);
syslog(LOG_CRIT, "out of memory");
return (-1);
}
atmif_sys_fill_mib(aif);
/*
* Get ATM node Id. Must do it the hard way by scanning all nodes
* because the name may be wrong.
*/
if ((resp = ng_dialog_id(snmp_node, NGM_GENERIC_COOKIE, NGM_LISTNODES,
NULL, 0)) == NULL) {
syslog(LOG_ERR, "cannot fetch node list: %m");
free(aif->sys);
return (-1);
}
list = (struct namelist *)(void *)resp->data;
for (i = 0; i < list->numnames; i++) {
if (strcmp(list->nodeinfo[i].type, NG_ATM_NODE_TYPE) != 0)
continue;
if ((resp1 = ng_dialog_id(list->nodeinfo[i].id,
NGM_ATM_COOKIE, NGM_ATM_GET_IFNAME, NULL, 0)) == NULL)
continue;
if (strcmp(resp1->data, aif->pub.ifp->name) == 0) {
free(resp1);
break;
}
free(resp1);
}
if (i == list->numnames)
aif->sys->atm_node = 0;
else
aif->sys->atm_node = list->nodeinfo[i].id;
free(resp);
if ((aif->sys->regc = ng_register_cookie(module, NGM_ATM_COOKIE,
aif->sys->atm_node, handle_atm_message, aif)) == NULL) {
syslog(LOG_ERR, "cannot register cookie: %m");
free(aif->sys);
return (-1);
}
return (0);
}
/*
* Table of all ATM interfaces - Ng part
*/
int
op_atmif_ng(struct snmp_context *ctx __unused, struct snmp_value *value,
u_int sub, u_int vindex __unused, enum snmp_op op)
{
struct atmif_priv *aif;
int err;
if ((err = atmif_get_aif(value, sub, op, &aif)) != SNMP_ERR_NOERROR)
return (err);
if (op == SNMP_OP_SET) {
switch (value->var.subs[sub - 1]) {
default:
return (SNMP_ERR_NOT_WRITEABLE);
}
}
switch (value->var.subs[sub - 1]) {
case LEAF_begemotAtmIfNodeId:
value->v.uint32 = aif->sys->atm_node;
return (SNMP_ERR_NOERROR);
}
abort();
}
/*
* Get vendor string
*/
int
atm_sys_get_hw_vendor(struct atmif_priv *aif, struct snmp_value *value)
{
if (aif->pub.mib->device >= sizeof(hwinfo) / sizeof(hwinfo[0]))
return (string_get(value, "unknown", -1));
return (string_get(value, hwinfo[aif->pub.mib->device].vendor, -1));
}
/*
* Get device string
*/
int
atm_sys_get_hw_device(struct atmif_priv *aif, struct snmp_value *value)
{
if (aif->pub.mib->device >= sizeof(hwinfo) / sizeof(hwinfo[0]))
return (string_get(value, "unknown", -1));
return (string_get(value, hwinfo[aif->pub.mib->device].device, -1));
}
/*
* Extract the ATM MIB from the interface's private MIB
*/
void
atmif_sys_fill_mib(struct atmif_priv *aif)
{
struct ifatm_mib *mib;
if (aif->pub.ifp->specmiblen != sizeof(struct ifatm_mib)) {
syslog(LOG_ERR, "atmif MIB has wrong size %zu",
aif->pub.ifp->specmiblen);
memset(aif->pub.mib, 0, sizeof(*aif->pub.mib));
aif->pub.mib->version = 0;
return;
}
mib = (struct ifatm_mib *)aif->pub.ifp->specmib;
aif->pub.mib->device = mib->device;
aif->pub.mib->serial = mib->serial;
aif->pub.mib->hw_version = mib->hw_version;
aif->pub.mib->sw_version = mib->sw_version;
aif->pub.mib->media = mib->media;
memcpy(aif->pub.mib->esi, mib->esi, 6);
aif->pub.mib->pcr = mib->pcr;
aif->pub.mib->vpi_bits = mib->vpi_bits;
aif->pub.mib->vci_bits = mib->vci_bits;
aif->pub.mib->max_vpcs = mib->max_vpcs;
aif->pub.mib->max_vccs = mib->max_vccs;
}

View File

@ -13,7 +13,6 @@ SRCS= acf.c arp.c async.c auth.c bundle.c cbcp.c ccp.c chap.c chat.c \
WARNS?= 3
.if defined(RELEASE_CRUNCH)
CFLAGS+=-DRELEASE_CRUNCH
PPP_NO_ATM=
PPP_NO_DES=
PPP_NO_KLDLOAD=
PPP_NO_NAT=
@ -25,9 +24,6 @@ CONFS= ppp.conf
CONFSDIR= ${CONFDIR}/ppp
CONFSMODE= 600
.if ${MK_ATM} == "no"
PPP_NO_ATM=
.endif
.if ${MK_NETGRAPH} == "no"
PPP_NO_NETGRAPH=
.endif
@ -68,12 +64,6 @@ SRCS+= nat_cmd.c
LIBADD+= alias
.endif
.if defined(PPP_NO_ATM)
CFLAGS+=-DNOATM
.else
SRCS+= atm.c
.endif
.if defined(PPP_NO_SUID)
CFLAGS+=-DNOSUID
.else

View File

@ -1,237 +0,0 @@
/*-
* Copyright (c) 2000 Jakob Stoklund Olesen <stoklund@taxidriver.dk>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netnatm/natm.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <sys/uio.h>
#include <termios.h>
#include <unistd.h>
#include "layer.h"
#include "defs.h"
#include "mbuf.h"
#include "log.h"
#include "timer.h"
#include "lqr.h"
#include "hdlc.h"
#include "throughput.h"
#include "fsm.h"
#include "lcp.h"
#include "ccp.h"
#include "link.h"
#include "async.h"
#include "descriptor.h"
#include "physical.h"
#include "main.h"
#include "atm.h"
/* String identifying PPPoA */
#define PPPOA "PPPoA"
#define PPPOA_LEN (sizeof(PPPOA) - 1)
struct atmdevice {
struct device dev; /* What struct physical knows about */
};
#define device2atm(d) ((d)->type == ATM_DEVICE ? (struct atmdevice *)d : NULL)
unsigned
atm_DeviceSize(void)
{
return sizeof(struct atmdevice);
}
static ssize_t
atm_Sendto(struct physical *p, const void *v, size_t n)
{
ssize_t ret = write(p->fd, v, n);
if (ret < 0) {
log_Printf(LogDEBUG, "atm_Sendto(%ld): %s\n", (long)n, strerror(errno));
return ret;
}
return ret;
}
static ssize_t
atm_Recvfrom(struct physical *p, void *v, size_t n)
{
ssize_t ret = read(p->fd, (char*)v, n);
if (ret < 0) {
log_Printf(LogDEBUG, "atm_Recvfrom(%ld): %s\n", (long)n, strerror(errno));
return ret;
}
return ret;
}
static void
atm_Free(struct physical *p)
{
struct atmdevice *dev = device2atm(p->handler);
free(dev);
}
static void
atm_device2iov(struct device *d, struct iovec *iov, int *niov,
int maxiov __unused, int *auxfd __unused, int *nauxfd __unused)
{
int sz = physical_MaxDeviceSize();
iov[*niov].iov_base = realloc(d, sz);
if (iov[*niov].iov_base == NULL) {
log_Printf(LogALERT, "Failed to allocate memory: %d\n", sz);
AbortProgram(EX_OSERR);
}
iov[*niov].iov_len = sz;
(*niov)++;
}
static const struct device baseatmdevice = {
ATM_DEVICE,
"atm",
0,
{ CD_NOTREQUIRED, 0 },
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
atm_Free,
atm_Recvfrom,
atm_Sendto,
atm_device2iov,
NULL,
NULL,
NULL
};
struct device *
atm_iov2device(int type, struct physical *p, struct iovec *iov, int *niov,
int maxiov __unused, int *auxfd __unused, int *nauxfd __unused)
{
if (type == ATM_DEVICE) {
struct atmdevice *dev = (struct atmdevice *)iov[(*niov)++].iov_base;
dev = realloc(dev, sizeof *dev); /* Reduce to the correct size */
if (dev == NULL) {
log_Printf(LogALERT, "Failed to allocate memory: %d\n",
(int)(sizeof *dev));
AbortProgram(EX_OSERR);
}
/* Refresh function pointers etc */
memcpy(&dev->dev, &baseatmdevice, sizeof dev->dev);
physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF);
return &dev->dev;
}
return NULL;
}
static struct atmdevice *
atm_CreateDevice(struct physical *p, const char *iface, unsigned vpi,
unsigned vci)
{
struct atmdevice *dev;
struct sockaddr_natm sock;
if ((dev = calloc(1, sizeof *dev)) == NULL) {
log_Printf(LogWARN, "%s: Cannot allocate an atm device: %s\n",
p->link.name, strerror(errno));
return NULL;
}
sock.snatm_len = sizeof sock;
sock.snatm_family = AF_NATM;
strncpy(sock.snatm_if, iface, IFNAMSIZ);
sock.snatm_vpi = vpi;
sock.snatm_vci = vci;
log_Printf(LogPHASE, "%s: Connecting to %s:%u.%u\n", p->link.name,
iface, vpi, vci);
p->fd = socket(PF_NATM, SOCK_DGRAM, PROTO_NATMAAL5);
if (p->fd >= 0) {
log_Printf(LogDEBUG, "%s: Opened atm socket %s\n", p->link.name,
p->name.full);
if (connect(p->fd, (struct sockaddr *)&sock, sizeof sock) == 0)
return dev;
else
log_Printf(LogWARN, "%s: connect: %s\n", p->name.full, strerror(errno));
} else
log_Printf(LogWARN, "%s: socket: %s\n", p->name.full, strerror(errno));
close(p->fd);
p->fd = -1;
free(dev);
return NULL;
}
struct device *
atm_Create(struct physical *p)
{
struct atmdevice *dev;
dev = NULL;
if (p->fd < 0 && !strncasecmp(p->name.full, PPPOA, PPPOA_LEN)
&& p->name.full[PPPOA_LEN] == ':') {
char iface[25];
unsigned vci, vpi;
if (sscanf(p->name.full + PPPOA_LEN + 1, "%25[A-Za-z0-9]:%u.%u", iface,
&vpi, &vci) != 3) {
log_Printf(LogWARN, "Malformed ATM device name \'%s\', "
"PPPoA:if:vpi.vci expected\n", p->name.full);
return NULL;
}
dev = atm_CreateDevice(p, iface, vpi, vci);
}
if (dev) {
memcpy(&dev->dev, &baseatmdevice, sizeof dev->dev);
physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF);
if (p->cfg.cd.necessity != CD_DEFAULT)
log_Printf(LogWARN, "Carrier settings ignored\n");
return &dev->dev;
}
return NULL;
}

Some files were not shown because too many files have changed in this diff Show More