This commit was manufactured by cvs2svn to create branch 'RELENG_6'.

This commit is contained in:
cvs2svn 2006-08-07 23:35:50 +00:00
parent ce539f4975
commit c222d1afc4
22 changed files with 6690 additions and 0 deletions

200
etc/rc.d/mdconfig Normal file
View File

@ -0,0 +1,200 @@
#!/bin/sh
#
# Copyright (c) 2006 The FreeBSD Project
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
# PROVIDE: mdconfig
# REQUIRE: localswap
# BEFORE: mountcritlocal
. /etc/rc.subr
name="mdconfig"
stop_cmd="mdconfig_stop"
start_cmd="mdconfig_start"
is_readonly()
{
local _mp _ret
_mp=$1
_ret=`mount | while read _line; do
case ${_line} in
*" ${_mp} "*read-only*)
echo "yes"
;;
*)
;;
esac;
done`
if [ -n "${_ret}" ]; then
return 0
else
return 1
fi
}
init_variables()
{
local _i
_fs=""
_mp=""
_dev="/dev/${_md}"
eval _config=\$mdconfig_${_md}
eval _newfs=\$mdconfig_${_md}_newfs
_type=${_config##*-t\ }
_type=${_type%%\ *}
if [ -z "${_type}" ]; then
err 1 "You need to specify \"-t <type>\" in mdconfig_${_md}"
fi
if [ "${_type}" = "vnode" ]; then
_file=${_config##*-f\ }
_file=${_file%%\ *}
if [ -z "${_file}" ]; then
err 2 "You need to specify \"-f <file>\" in mdconfig_${_md} for vnode devices"
fi
if [ "${_file}" != "${_file%.uzip}" ]; then
# Load geom_uzip kernel module if needed
kldstat -q -m g_uzip || kldload geom_uzip || err 1 "geom_uzip failed to load."
_dev="/dev/${_md}.uzip"
fi
for _i in `df ${_file} 2>/dev/null`; do _fs=${_i}; done
fi
# Debugging help.
debug "${_md} config: ${_config}"
debug "${_md} type: ${_type}"
debug "${_md} dev: ${_dev}"
debug "${_md} file: ${_file}"
debug "${_md} fs: ${_fs}"
debug "${_md} newfs flags: ${_newfs}"
}
mdconfig_start()
{
local _md _mp _config _type _dev _file _fs _newfs _fsck_cmd
# If there are no devices return before loading geom_md.ko.
if [ -z "${_mdconfig_list}" ]; then
return
fi
kldstat -q -m g_md || kldload geom_md || err 1 "geom_md failed to load."
for _md in ${_mdconfig_list}; do
init_variables ${_md}
# Create md(4) devices of types swap, malloc and vnode if the
# file is on the root partition.
if [ "${_type}" != "vnode" -o "${_fs}" = "/" ]; then
if [ "${_type}" = "vnode" ]; then
if is_readonly ${_fs}; then
warn "${_fs} is mounted read-only, skipping ${_md}."
continue
fi
fi
if mdconfig -l -u ${_md} >/dev/null 2>&1; then
err 3 "${_md} already exists"
fi
echo "Creating ${_md} device (${_type})."
if ! mdconfig -a ${_config} -u ${_md}; then
echo "Creating ${_md} device failed, moving on."
continue
fi
# Skip fsck for uzip devices.
if [ "${_type}" = "vnode" ]; then
if [ "${_file}" != "${_file%.uzip}" ]; then
_fsck_cmd=":"
elif checkyesno background_fsck; then
_fsck_cmd="fsck -F"
else
_fsck_cmd="fsck"
fi
if ! eval ${_fsck_cmd} -p ${_dev} >/dev/null; then
echo "Fsck failed on ${_dev}, not mounting the filesystem."
continue
fi
else
newfs ${_newfs} ${_dev} >/dev/null
fi
if mount -d ${_dev} 2>&1 >/dev/null; then
echo "Mounting ${_dev}."
mount ${_dev}
fi
fi
done
}
mdconfig_stop()
{
local _md _mp _config _type _dev _file _fs _newfs _i
for _md in ${_mdconfig_list}; do
init_variables ${_md}
if [ "${_type}" != "vnode" -o "${_fs}" = "/" ]; then
for _i in `df ${_dev} 2>/dev/null`; do _mp=${_i}; done
if [ -z "${_mp}" -o "${_mp}" != "${_mp%%%}" ]; then
echo "Device ${_dev} isn't mounted."
else
echo "Umounting ${_dev}."
umount ${_dev}
fi
if mdconfig -l -u ${_md} >/dev/null 2>&1; then
echo "Destroying ${_md}."
mdconfig -d -u ${_md}
fi
fi
done
}
_mdconfig_cmd="$1"
if [ $# -gt 0 ]; then
shift
fi
[ -n "$*" ] && _mdconfig_list="$*"
load_rc_config $name
_mdconfig_unit=0
if [ -z "${_mdconfig_list}" ]; then
while :; do
eval _mdconfig_config=\$mdconfig_md${_mdconfig_unit}
if [ -z "${_mdconfig_config}" ]; then
break
else
_mdconfig_list="${_mdconfig_list}${_mdconfig_list:+ }md${_mdconfig_unit}"
_mdconfig_unit=$((${_mdconfig_unit} + 1))
fi
done
fi
run_rc_command "${_mdconfig_cmd}"

231
etc/rc.d/mdconfig2 Normal file
View File

@ -0,0 +1,231 @@
#!/bin/sh
#
# Copyright (c) 2006 The FreeBSD Project
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
# PROVIDE: mdconfig2
# REQUIRE: mountcritremote
# BEFORE: SERVERS
. /etc/rc.subr
name="mdconfig2"
stop_cmd="mdconfig2_stop"
start_cmd="mdconfig2_start"
is_readonly()
{
local _mp _ret
_mp=$1
_ret=`mount | while read _line; do
case ${_line} in
*" ${_mp} "*read-only*)
echo "yes"
;;
*)
;;
esac;
done`
if [ -n "${_ret}" ]; then
return 0
else
return 1
fi
}
init_variables()
{
local _i
_fs=""
_mp=""
_mounted="no"
_dev="/dev/${_md}"
eval _config=\$mdconfig_${_md}
eval _owner=\$mdconfig_${_md}_owner
eval _perms=\$mdconfig_${_md}_perms
eval _files=\$mdconfig_${_md}_files
eval _populate=\$mdconfig_${_md}_cmd
_type=${_config##*-t\ }
_type=${_type%%\ *}
if [ -z "${_type}" ]; then
err 1 "You need to specify \"-t <type>\" in mdconfig_${_md}"
fi
if [ "${_type}" = "vnode" ]; then
_file=${_config##*-f\ }
_file=${_file%%\ *}
if [ -z "${_file}" ]; then
err 2 "You need to specify \"-f <file>\" in mdconfig_${_md} for vnode devices"
fi
if [ "${_file}" != "${_file%.uzip}" ]; then
# Load geom_uzip kernel module if needed
kldstat -q -m g_uzip || kldload geom_uzip || err 1 "geom_uzip failed to load."
_dev="/dev/${_md}.uzip"
fi
for _i in `df ${_file} 2>/dev/null`; do _fs=${_i}; done
fi
# Debugging help.
debug "${_md} config: ${_config}"
debug "${_md} type: ${_type}"
debug "${_md} dev: ${_dev}"
debug "${_md} file: ${_file}"
debug "${_md} fs: ${_fs}"
debug "${_md} owner: ${_owner}"
debug "${_md} perms: ${_perms}"
debug "${_md} files: ${_files}"
debug "${_md} populate cmd: ${_populate}"
}
mdconfig2_start()
{
local _md _fs _mp _mounted _dev _config _type _file _owner _perms _files _populate _fsck_cmd _i
# If there are no devices return before loading geom_md.ko.
if [ -z "${_mdconfig2_list}" ]; then
return
fi
kldstat -q -m g_md || kldload geom_md || err 1 "geom_md failed to load."
for _md in ${_mdconfig2_list}; do
init_variables ${_md}
if [ ! -r ${_file} ]; then
err 3 "${_file} doesn't exist"
continue
fi
# First pass: create md(4) vnode devices from files stored on
# non-root partition. Swap and malloc md(4) devices have already
# been created.
if [ "${_type}" = "vnode" -a "${_fs}" != "/" ]; then
if is_readonly ${_fs}; then
warn "${_fs} is mounted read-only, skipping ${_md}."
continue
fi
if mdconfig -l -u ${_md} >/dev/null 2>&1; then
err 3 "${_md} already exists"
fi
echo "Creating ${_md} device (${_type})."
if ! mdconfig -a ${_config} -u ${_md}; then
echo "Creating ${_md} device failed, moving on."
continue
fi
# Skip fsck for uzip devices.
if [ "${_file}" != "${_file%.uzip}" ]; then
_fsck_cmd=":"
elif checkyesno background_fsck; then
_fsck_cmd="fsck -F"
else
_fsck_cmd="fsck"
fi
if ! eval ${_fsck_cmd} -p ${_dev} >/dev/null; then
echo "Fsck failed on ${_dev}, not mounting the filesystem."
continue
fi
if mount -d ${_dev} >/dev/null 2>&1; then
echo "Mounting ${_dev}."
mount ${_dev}
fi
fi
for _i in `df ${_dev} 2>/dev/null`; do _mp=${_i}; done
if [ ! -z "${_mp}" -a "${_mp}" = "${_mp%%%}" ]; then
_mounted="yes"
fi
if checkyesno _mounted; then
# Second pass: change permissions and ownership.
[ -z "${_owner}" ] || chown -f ${_owner} ${_dev} ${_mp}
[ -z "${_perms}" ] || chmod -f ${_perms} ${_dev} ${_mp}
# Third pass: populate with foreign files.
if [ -n "${_files}" -o -n "${_populate}" ]; then
echo "Populating ${_dev}."
fi
if [ -n "${_files}" ]; then
cp -Rp ${_files} ${_mp}
fi
if [ -n "${_populate}" ]; then
eval ${_populate}
fi
fi
done
}
mdconfig2_stop()
{
local _md _fs _mp _mounted _dev _config _type _file _owner _perms _files _populate
for _md in ${_mdconfig2_list}; do
init_variables ${_md}
if [ "${_type}" = "vnode" ]; then
for i in `df ${_dev} 2>/dev/null`; do _mp=$i; done
if [ ! -r "${_file}" -o "${_fs}" = "/" ]; then
continue
fi
if [ -z "${_mp}" -o "${_mp}" != "${_mp%%%}" ]; then
echo "Device ${_dev} isn't mounted."
else
echo "Umounting ${_dev}."
umount ${_dev}
fi
if mdconfig -l -u ${_md} >/dev/null 2>&1; then
echo "Destroying ${_md}."
mdconfig -d -u ${_md}
fi
fi
done
}
_mdconfig2_cmd="$1"
if [ $# -gt 0 ]; then
shift
fi
[ -n "$*" ] && _mdconfig2_list="$*"
load_rc_config $name
_mdconfig2_unit=0
if [ -z "${_mdconfig2_list}" ]; then
while :; do
eval _mdconfig2_config=\$mdconfig_md${_mdconfig2_unit}
if [ -z "${_mdconfig2_config}" ]; then
break
else
_mdconfig2_list="${_mdconfig2_list}${_mdconfig2_list:+ }md${_mdconfig2_unit}"
_mdconfig2_unit=$((${_mdconfig2_unit} + 1))
fi
done
fi
run_rc_command "${_mdconfig2_cmd}"

View File

@ -0,0 +1,4 @@
# $FreeBSD$
SRCS+= arm-dis.c
CFLAGS+= -DARCH_arm

View File

@ -0,0 +1,22 @@
# $FreeBSD$
RELN_ROOT?= ${.CURDIR}/../../..
DOC?= article
FORMATS?= html
INSTALL_COMPRESSED?= gz
INSTALL_ONLY_COMPRESSED?=
JADEFLAGS+= -V %generate-article-toc%
# SGML content
SRCS+= article.sgml
SRCS+= proc-powerpc.sgml
SRCS+= ../common/hw.ent
SRCS+= ../common/artheader.sgml
SRCS+= ../common/dev.sgml
SRCS+= ${DEV-AUTODIR}/catalog-auto
SRCS+= ${DEV-AUTODIR}/dev-auto.sgml
.include "${RELN_ROOT}/share/mk/doc.relnotes.mk"
.include "${DOC_PREFIX}/share/mk/doc.project.mk"

View File

@ -0,0 +1,31 @@
<!-- $FreeBSD$ -->
<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook V4.1-Based Extension//EN" [
<!ENTITY % articles.ent PUBLIC "-//FreeBSD//ENTITIES DocBook FreeBSD Articles Entity Set//EN">
%articles.ent;
<!ENTITY % release PUBLIC "-//FreeBSD//ENTITIES Release Specification//EN">
%release;
<!ENTITY % devauto PUBLIC "-//FreeBSD//ENTITIES Auto Generated Device Lists//EN">
%devauto;
<!ENTITY % sections SYSTEM "../common/hw.ent"> %sections;
<!-- Architecture-specific customization -->
<!ENTITY arch "powerpc">
<!ENTITY arch.print "PowerPC">
]>
<article>
&artheader;
<abstract>
<para>This is a preliminary document. It is incomplete, and in
need of additional content.</para>
</abstract>
&sect.intro;
&sect.proc.powerpc;
&sect.dev;
</article>

View File

@ -0,0 +1,9 @@
<!--
$FreeBSD$
-->
<sect1 id="proc-powerpc">
<title>Supported Processors and Motherboards</title>
<para>The information for this paragraph has yet to be compiled.</para>
</sect1>

View File

@ -0,0 +1,20 @@
# $FreeBSD$
RELN_ROOT?= ${.CURDIR}/../../..
DOC?= article
FORMATS?= html
INSTALL_COMPRESSED?= gz
INSTALL_ONLY_COMPRESSED?=
# SGML content
SRCS+= article.sgml
SRCS+= ../common/artheader.sgml
SRCS+= ../common/abstract.sgml
SRCS+= ../common/install.sgml
SRCS+= ../common/layout.sgml
SRCS+= ../common/trouble.sgml
SRCS+= ../common/upgrade.sgml
.include "${RELN_ROOT}/share/mk/doc.relnotes.mk"
.include "${DOC_PREFIX}/share/mk/doc.project.mk"

View File

@ -0,0 +1,26 @@
<!-- $FreeBSD$ -->
<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook V4.1-Based Extension//EN" [
<!ENTITY % articles.ent PUBLIC "-//FreeBSD//ENTITIES DocBook FreeBSD Articles Entity Set//EN">
%articles.ent;
<!ENTITY % release PUBLIC "-//FreeBSD//ENTITIES Release Specification//EN">
%release;
<!ENTITY % sections SYSTEM "../common/install.ent">
%sections;
<!-- Architecture-specific customization -->
<!ENTITY arch "powerpc">
<!ENTITY arch.print "PowerPC">
]>
<article>
&artheader;
&abstract;
&sect.install;
&sect.layout;
&sect.upgrade;
&sect.trouble;
</article>

229
share/man/man4/stge.4 Normal file
View File

@ -0,0 +1,229 @@
.\" $NetBSD: stge.4,v 1.7 2003/02/14 15:20:20 grant Exp $
.\"
.\" Copyright (c) 2001 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Jason R. Thorpe.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd July 25, 2006
.Dt STGE 4
.Os
.Sh NAME
.Nm stge
.Nd Sundance/Tamarack TC9021 Gigabit Ethernet adapter driver
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device miibus"
.Cd "device stge"
.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_stge_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
device driver provides support for various NICs based on the
Sundance/Tamarack TC9021 Gigabit Ethernet controller chip.
.Pp
The Sundance/Tamarack TC9021 is found on the D-Link DGE-550T
and the Antares Microsystems Gigabit Ethernet board.
It uses an external PHY or an external 10-bit interface.
.Pp
All NICs supported by the
.Nm
driver have TCP/UDP/IP checksum offload for both receive and
transmit, hardware VLAN tag stripping/insertion features, and
receive interrupt moderation mechanism as well as a 64-bit
multicast hash filter.
The Sundance/Tamarack TC9021 supports TBI (ten bit interface)
and GMII transceivers, which means it can be used with either
copper or 1000baseX fiber applications.
.Pp
The Sundance/Tamarack TC9021 also support jumbo frames, which can be
configured via the interface MTU setting.
Selecting an MTU larger than 1500 bytes with the
.Xr ifconfig 8
utility configures the adapter to receive and transmit jumbo frames.
.Pp
The
.Nm
driver supports the following media types:
.Bl -tag -width ".Cm 10baseT/UTP"
.It Cm autoselect
Enable autoselection of the media type and options.
The user can manually override
the autoselected mode by adding media options to
.Xr rc.conf 5 .
.It Cm 10baseT/UTP
Set 10Mbps operation.
The
.Xr ifconfig 8
.Cm mediaopt
option can also be used to select either
.Cm full-duplex
or
.Cm half-duplex
modes.
.It Cm 100baseTX
Set 100Mbps (Fast Ethernet) operation.
The
.Xr ifconfig 8
.Cm mediaopt
option can also be used to select either
.Cm full-duplex
or
.Cm half-duplex
modes.
.It Cm 1000baseTX
Set 1000baseTX operation over twisted pair.
The Sundance/Tamarack supports 1000Mbps in
.Cm autoselect
mode only.
.\" .It Cm 1000baseSX
.\" Set 1000Mbps (Gigabit Ethernet) operation.
.\" Both
.\" .Cm full-duplex
.\" and
.\" .Cm half-duplex
.\" modes are supported.
.El
.Pp
The
.Nm
driver supports the following media options:
.Bl -tag -width ".Cm full-duplex"
.It Cm full-duplex
Force full duplex operation.
.It Cm half-duplex
Force half duplex operation.
.El
.Pp
The
.Nm
driver also supports one special link option for 1000baseTX cards:
.Pp
.Bl -tag -width ".Cm link0"
.It Cm link0
With 1000baseTX cards, establishing a link between two ports requires
that one port is configured as master and the other one as slave.
With autonegotiation,
the master/slave settings will be chosen automatically.
However when manually selecting the link state, it is necessary to
force one side of the link to be a master and the other a slave.
The
.Nm
driver configures the ports as slaves by default.
Setting the
.Ar link0
flag with
.Xr ifconfig 8
will set a port as a master instead.
.El
.Pp
For more information on configuring this device, see
.Xr ifconfig 8 .
.Sh HARDWARE
The
.Nm
driver provides support for various NICs based on the Sundance/Tamarack
TC9021 based Gigabit Ethernet controller chips, including:
.Pp
.Bl -bullet -compact
.It
Antares Microsystems Gigabit Ethernet
.It
ASUS NX1101 Gigabit Ethernet
.It
D-Link DL-4000 Gigabit Ethernet
.It
IC Plus IP1000A Gigabit Ethernet
.It
Sundance ST-2021 Gigabit Ethernet
.It
Sundance ST-2023 Gigabit Ethernet
.It
Sundance TC9021 Gigabit Ethernet
.It
Tamarack TC9021 Gigabit Ethernet
.El
.Sh SYSCTL VARIABLES
The following variables are available as both
.Xr sysctl 8
variables and
.Xr loader 8
tunables:
.Bl -tag -width indent
.It Va dev.stge.%d.rxint_nframe
Number of frames between RxDMAComplete interrupt.
The accepted range is 1 to 255, default value is 8 frames.
The interface has to be brought down and up again before a change takes effect.
.It Va dev.stge.%d.rxint_dmawait
Maximum amount of time to wait in 1us increments before issuing
a Rx interrupt if number of frames received is less than rxint_nframe.
The accepted range is 0 to 4194, default value is 30 microseconds.
The interface has to be brought down and up again before a change takes effect.
.El
.Sh SEE ALSO
.Xr arp 4 ,
.Xr miibus 4 ,
.Xr netintro 4 ,
.Xr ng_ether 4 ,
.Xr polling 4 ,
.Xr vlan 4 ,
.Xr ifconfig 8
.Sh HISTORY
The
.Nm
driver was ported from
.Nx
and first appeared in
.Fx 6.2 .
The
.Nx
version was written by
.An Jason R. Thorpe
.Aq thorpej@NetBSD.org .
.Sh AUTHORS
The
.Nm
driver was ported by
.An Pyun YongHyeon
.Aq yongari@FreeBSD.org .

87
sys/crypto/via/padlock.h Normal file
View File

@ -0,0 +1,87 @@
/*-
* Copyright (c) 2005-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* 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 AUTHORS 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 AUTHORS 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 _PADLOCK_H_
#define _PADLOCK_H_
#include <opencrypto/cryptodev.h>
#include <crypto/rijndael/rijndael.h>
union padlock_cw {
uint64_t raw;
struct {
u_int round_count : 4;
u_int algorithm_type : 3;
u_int key_generation : 1;
u_int intermediate : 1;
u_int direction : 1;
u_int key_size : 2;
u_int filler0 : 20;
u_int filler1 : 32;
u_int filler2 : 32;
u_int filler3 : 32;
} __field;
};
#define cw_round_count __field.round_count
#define cw_algorithm_type __field.algorithm_type
#define cw_key_generation __field.key_generation
#define cw_intermediate __field.intermediate
#define cw_direction __field.direction
#define cw_key_size __field.key_size
#define cw_filler0 __field.filler0
#define cw_filler1 __field.filler1
#define cw_filler2 __field.filler2
#define cw_filler3 __field.filler3
struct padlock_session {
union padlock_cw ses_cw __aligned(16);
uint32_t ses_ekey[4 * (RIJNDAEL_MAXNR + 1) + 4] __aligned(16); /* 128 bit aligned */
uint32_t ses_dkey[4 * (RIJNDAEL_MAXNR + 1) + 4] __aligned(16); /* 128 bit aligned */
uint8_t ses_iv[16] __aligned(16); /* 128 bit aligned */
struct auth_hash *ses_axf;
uint8_t *ses_ictx;
uint8_t *ses_octx;
int ses_mlen;
int ses_used;
uint32_t ses_id;
TAILQ_ENTRY(padlock_session) ses_next;
};
#define PADLOCK_ALIGN(p) (void *)(roundup2((uintptr_t)(p), 16))
int padlock_cipher_setup(struct padlock_session *ses,
struct cryptoini *encini);
int padlock_cipher_process(struct padlock_session *ses,
struct cryptodesc *enccrd, struct cryptop *crp);
int padlock_hash_setup(struct padlock_session *ses,
struct cryptoini *macini);
int padlock_hash_process(struct padlock_session *ses,
struct cryptodesc *maccrd, struct cryptop *crp);
void padlock_hash_free(struct padlock_session *ses);
#endif /* !_PADLOCK_H_ */

View File

@ -0,0 +1,269 @@
/*-
* Copyright (c) 2005-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* Copyright (c) 2004 Mark R V Murray
* 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 AUTHORS 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 AUTHORS 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.
*/
/* $OpenBSD: via.c,v 1.3 2004/06/15 23:36:55 deraadt Exp $ */
/*-
* Copyright (c) 2003 Jason Wright
* Copyright (c) 2003, 2004 Theo de Raadt
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/libkern.h>
#include <sys/uio.h>
#include <opencrypto/cryptodev.h>
#include <crypto/rijndael/rijndael.h>
#include <crypto/via/padlock.h>
#define PADLOCK_ROUND_COUNT_AES128 10
#define PADLOCK_ROUND_COUNT_AES192 12
#define PADLOCK_ROUND_COUNT_AES256 14
#define PADLOCK_ALGORITHM_TYPE_AES 0
#define PADLOCK_KEY_GENERATION_HW 0
#define PADLOCK_KEY_GENERATION_SW 1
#define PADLOCK_DIRECTION_ENCRYPT 0
#define PADLOCK_DIRECTION_DECRYPT 1
#define PADLOCK_KEY_SIZE_128 0
#define PADLOCK_KEY_SIZE_192 1
#define PADLOCK_KEY_SIZE_256 2
MALLOC_DECLARE(M_PADLOCK);
static __inline void
padlock_cbc(void *in, void *out, size_t count, void *key, union padlock_cw *cw,
void *iv)
{
#ifdef __GNUCLIKE_ASM
/* The .byte line is really VIA C3 "xcrypt-cbc" instruction */
__asm __volatile(
"pushf \n\t"
"popf \n\t"
"rep \n\t"
".byte 0x0f, 0xa7, 0xd0"
: "+a" (iv), "+c" (count), "+D" (out), "+S" (in)
: "b" (key), "d" (cw)
: "cc", "memory"
);
#endif
}
static void
padlock_cipher_key_setup(struct padlock_session *ses, caddr_t key, int klen)
{
union padlock_cw *cw;
int i;
cw = &ses->ses_cw;
if (cw->cw_key_generation == PADLOCK_KEY_GENERATION_SW) {
/* Build expanded keys for both directions */
rijndaelKeySetupEnc(ses->ses_ekey, key, klen);
rijndaelKeySetupDec(ses->ses_dkey, key, klen);
for (i = 0; i < 4 * (RIJNDAEL_MAXNR + 1); i++) {
ses->ses_ekey[i] = ntohl(ses->ses_ekey[i]);
ses->ses_dkey[i] = ntohl(ses->ses_dkey[i]);
}
} else {
bcopy(key, ses->ses_ekey, klen);
bcopy(key, ses->ses_dkey, klen);
}
}
int
padlock_cipher_setup(struct padlock_session *ses, struct cryptoini *encini)
{
union padlock_cw *cw;
if (encini->cri_klen != 128 && encini->cri_klen != 192 &&
encini->cri_klen != 256) {
return (EINVAL);
}
cw = &ses->ses_cw;
bzero(cw, sizeof(*cw));
cw->cw_algorithm_type = PADLOCK_ALGORITHM_TYPE_AES;
cw->cw_key_generation = PADLOCK_KEY_GENERATION_SW;
cw->cw_intermediate = 0;
switch (encini->cri_klen) {
case 128:
cw->cw_round_count = PADLOCK_ROUND_COUNT_AES128;
cw->cw_key_size = PADLOCK_KEY_SIZE_128;
#ifdef HW_KEY_GENERATION
/* This doesn't buy us much, that's why it is commented out. */
cw->cw_key_generation = PADLOCK_KEY_GENERATION_HW;
#endif
break;
case 192:
cw->cw_round_count = PADLOCK_ROUND_COUNT_AES192;
cw->cw_key_size = PADLOCK_KEY_SIZE_192;
break;
case 256:
cw->cw_round_count = PADLOCK_ROUND_COUNT_AES256;
cw->cw_key_size = PADLOCK_KEY_SIZE_256;
break;
}
if (encini->cri_key != NULL) {
padlock_cipher_key_setup(ses, encini->cri_key,
encini->cri_klen);
}
arc4rand(ses->ses_iv, sizeof(ses->ses_iv), 0);
return (0);
}
/*
* Function checks if the given buffer is already 16 bytes aligned.
* If it is there is no need to allocate new buffer.
* If it isn't, new buffer is allocated.
*/
static u_char *
padlock_cipher_alloc(struct cryptodesc *enccrd, struct cryptop *crp,
int *allocated)
{
u_char *addr;
if (crp->crp_flags & CRYPTO_F_IMBUF)
goto alloc;
else {
if (crp->crp_flags & CRYPTO_F_IOV) {
struct uio *uio;
struct iovec *iov;
uio = (struct uio *)crp->crp_buf;
if (uio->uio_iovcnt != 1)
goto alloc;
iov = uio->uio_iov;
addr = (u_char *)iov->iov_base + enccrd->crd_skip;
} else {
addr = (u_char *)crp->crp_buf;
}
if (((uintptr_t)addr & 0xf) != 0) /* 16 bytes aligned? */
goto alloc;
*allocated = 0;
return (addr);
}
alloc:
*allocated = 1;
addr = malloc(enccrd->crd_len + 16, M_PADLOCK, M_NOWAIT);
return (addr);
}
int
padlock_cipher_process(struct padlock_session *ses, struct cryptodesc *enccrd,
struct cryptop *crp)
{
union padlock_cw *cw;
u_char *buf, *abuf;
uint32_t *key;
int allocated;
buf = padlock_cipher_alloc(enccrd, crp, &allocated);
if (buf == NULL)
return (ENOMEM);
/* Buffer has to be 16 bytes aligned. */
abuf = PADLOCK_ALIGN(buf);
if ((enccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0) {
padlock_cipher_key_setup(ses, enccrd->crd_key,
enccrd->crd_klen);
}
cw = &ses->ses_cw;
cw->cw_filler0 = 0;
cw->cw_filler1 = 0;
cw->cw_filler2 = 0;
cw->cw_filler3 = 0;
if ((enccrd->crd_flags & CRD_F_ENCRYPT) != 0) {
cw->cw_direction = PADLOCK_DIRECTION_ENCRYPT;
key = ses->ses_ekey;
if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
bcopy(enccrd->crd_iv, ses->ses_iv, 16);
if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
crypto_copyback(crp->crp_flags, crp->crp_buf,
enccrd->crd_inject, AES_BLOCK_LEN, ses->ses_iv);
}
} else {
cw->cw_direction = PADLOCK_DIRECTION_DECRYPT;
key = ses->ses_dkey;
if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
bcopy(enccrd->crd_iv, ses->ses_iv, AES_BLOCK_LEN);
else {
crypto_copydata(crp->crp_flags, crp->crp_buf,
enccrd->crd_inject, AES_BLOCK_LEN, ses->ses_iv);
}
}
if (allocated) {
crypto_copydata(crp->crp_flags, crp->crp_buf, enccrd->crd_skip,
enccrd->crd_len, abuf);
}
padlock_cbc(abuf, abuf, enccrd->crd_len / 16, key, cw, ses->ses_iv);
if (allocated) {
crypto_copyback(crp->crp_flags, crp->crp_buf, enccrd->crd_skip,
enccrd->crd_len, abuf);
}
/* copy out last block for use as next session IV */
if ((enccrd->crd_flags & CRD_F_ENCRYPT) != 0) {
crypto_copydata(crp->crp_flags, crp->crp_buf,
enccrd->crd_skip + enccrd->crd_len - AES_BLOCK_LEN,
AES_BLOCK_LEN, ses->ses_iv);
}
if (allocated) {
bzero(buf, enccrd->crd_len + 16);
free(buf, M_PADLOCK);
}
return (0);
}

View File

@ -0,0 +1,389 @@
/*-
* Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* 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 AUTHORS 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 AUTHORS 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/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/libkern.h>
#include <sys/endian.h>
#if defined(__i386__) && !defined(PC98)
#include <machine/cpufunc.h>
#include <machine/cputypes.h>
#include <machine/md_var.h>
#include <machine/specialreg.h>
#endif
#include <opencrypto/cryptodev.h>
#include <opencrypto/cryptosoft.h> /* for hmac_ipad_buffer and hmac_opad_buffer */
#include <opencrypto/xform.h>
#include <crypto/via/padlock.h>
/*
* Implementation notes.
*
* Some VIA CPUs provides SHA1 and SHA256 acceleration.
* We implement all HMAC algorithms provided by crypto(9) framework, but we do
* the crypto work in software unless this is HMAC/SHA1 or HMAC/SHA256 and
* our CPU can accelerate it.
*
* Additional CPU instructions, which preform SHA1 and SHA256 are one-shot
* functions - we have only one chance to give the data, CPU itself will add
* the padding and calculate hash automatically.
* This means, it is not possible to implement common init(), update(), final()
* methods.
* The way I've choosen is to keep adding data to the buffer on update()
* (reallocating the buffer if necessary) and call XSHA{1,256} instruction on
* final().
*/
struct padlock_sha_ctx {
uint8_t *psc_buf;
int psc_offset;
int psc_size;
};
CTASSERT(sizeof(struct padlock_sha_ctx) <= sizeof(union authctx));
static void padlock_sha_init(struct padlock_sha_ctx *ctx);
static int padlock_sha_update(struct padlock_sha_ctx *ctx, uint8_t *buf,
uint16_t bufsize);
static void padlock_sha1_final(uint8_t *hash, struct padlock_sha_ctx *ctx);
static void padlock_sha256_final(uint8_t *hash, struct padlock_sha_ctx *ctx);
static struct auth_hash padlock_hmac_sha1 = {
CRYPTO_SHA1_HMAC, "HMAC-SHA1",
20, SHA1_HASH_LEN, SHA1_HMAC_BLOCK_LEN, sizeof(struct padlock_sha_ctx),
(void (*)(void *))padlock_sha_init,
(int (*)(void *, uint8_t *, uint16_t))padlock_sha_update,
(void (*)(uint8_t *, void *))padlock_sha1_final
};
static struct auth_hash padlock_hmac_sha256 = {
CRYPTO_SHA2_256_HMAC, "HMAC-SHA2-256",
32, SHA2_256_HASH_LEN, SHA2_256_HMAC_BLOCK_LEN, sizeof(struct padlock_sha_ctx),
(void (*)(void *))padlock_sha_init,
(int (*)(void *, uint8_t *, uint16_t))padlock_sha_update,
(void (*)(uint8_t *, void *))padlock_sha256_final
};
MALLOC_DECLARE(M_PADLOCK);
static __inline void
padlock_output_block(uint32_t *src, uint32_t *dst, size_t count)
{
while (count-- > 0)
*dst++ = bswap32(*src++);
}
static void
padlock_do_sha1(const u_char *in, u_char *out, int count)
{
u_char buf[128+16]; /* PadLock needs at least 128 bytes buffer. */
u_char *result = PADLOCK_ALIGN(buf);
((uint32_t *)result)[0] = 0x67452301;
((uint32_t *)result)[1] = 0xEFCDAB89;
((uint32_t *)result)[2] = 0x98BADCFE;
((uint32_t *)result)[3] = 0x10325476;
((uint32_t *)result)[4] = 0xC3D2E1F0;
#ifdef __GNUCLIKE_ASM
__asm __volatile(
".byte 0xf3, 0x0f, 0xa6, 0xc8" /* rep xsha1 */
: "+S"(in), "+D"(result)
: "c"(count), "a"(0)
);
#endif
padlock_output_block((uint32_t *)result, (uint32_t *)out,
SHA1_HASH_LEN / sizeof(uint32_t));
}
static void
padlock_do_sha256(const char *in, char *out, int count)
{
char buf[128+16]; /* PadLock needs at least 128 bytes buffer. */
char *result = PADLOCK_ALIGN(buf);
((uint32_t *)result)[0] = 0x6A09E667;
((uint32_t *)result)[1] = 0xBB67AE85;
((uint32_t *)result)[2] = 0x3C6EF372;
((uint32_t *)result)[3] = 0xA54FF53A;
((uint32_t *)result)[4] = 0x510E527F;
((uint32_t *)result)[5] = 0x9B05688C;
((uint32_t *)result)[6] = 0x1F83D9AB;
((uint32_t *)result)[7] = 0x5BE0CD19;
#ifdef __GNUCLIKE_ASM
__asm __volatile(
".byte 0xf3, 0x0f, 0xa6, 0xd0" /* rep xsha256 */
: "+S"(in), "+D"(result)
: "c"(count), "a"(0)
);
#endif
padlock_output_block((uint32_t *)result, (uint32_t *)out,
SHA2_256_HASH_LEN / sizeof(uint32_t));
}
static void
padlock_sha_init(struct padlock_sha_ctx *ctx)
{
ctx->psc_buf = NULL;
ctx->psc_offset = 0;
ctx->psc_size = 0;
}
static int
padlock_sha_update(struct padlock_sha_ctx *ctx, uint8_t *buf, uint16_t bufsize)
{
if (ctx->psc_size - ctx->psc_offset < bufsize) {
ctx->psc_size = MAX(ctx->psc_size * 2, ctx->psc_size + bufsize);
ctx->psc_buf = realloc(ctx->psc_buf, ctx->psc_size, M_PADLOCK,
M_WAITOK);
}
bcopy(buf, ctx->psc_buf + ctx->psc_offset, bufsize);
ctx->psc_offset += bufsize;
return (0);
}
static void
padlock_sha_free(struct padlock_sha_ctx *ctx)
{
if (ctx->psc_buf != NULL) {
//bzero(ctx->psc_buf, ctx->psc_size);
free(ctx->psc_buf, M_PADLOCK);
ctx->psc_buf = NULL;
ctx->psc_offset = 0;
ctx->psc_size = 0;
}
}
static void
padlock_sha1_final(uint8_t *hash, struct padlock_sha_ctx *ctx)
{
padlock_do_sha1(ctx->psc_buf, hash, ctx->psc_offset);
padlock_sha_free(ctx);
}
static void
padlock_sha256_final(uint8_t *hash, struct padlock_sha_ctx *ctx)
{
padlock_do_sha256(ctx->psc_buf, hash, ctx->psc_offset);
padlock_sha_free(ctx);
}
static void
padlock_copy_ctx(struct auth_hash *axf, void *sctx, void *dctx)
{
if ((via_feature_xcrypt & VIA_HAS_SHA) != 0 &&
(axf->type == CRYPTO_SHA1_HMAC ||
axf->type == CRYPTO_SHA2_256_HMAC)) {
struct padlock_sha_ctx *spctx = sctx, *dpctx = dctx;
dpctx->psc_offset = spctx->psc_offset;
dpctx->psc_size = spctx->psc_size;
dpctx->psc_buf = malloc(dpctx->psc_size, M_PADLOCK, M_WAITOK);
bcopy(spctx->psc_buf, dpctx->psc_buf, dpctx->psc_size);
} else {
bcopy(sctx, dctx, axf->ctxsize);
}
}
static void
padlock_free_ctx(struct auth_hash *axf, void *ctx)
{
if ((via_feature_xcrypt & VIA_HAS_SHA) != 0 &&
(axf->type == CRYPTO_SHA1_HMAC ||
axf->type == CRYPTO_SHA2_256_HMAC)) {
padlock_sha_free(ctx);
}
}
static void
padlock_hash_key_setup(struct padlock_session *ses, caddr_t key, int klen)
{
struct auth_hash *axf;
int i;
klen /= 8;
axf = ses->ses_axf;
/*
* Try to free contexts before using them, because
* padlock_hash_key_setup() can be called twice - once from
* padlock_newsession() and again from padlock_process().
*/
padlock_free_ctx(axf, ses->ses_ictx);
padlock_free_ctx(axf, ses->ses_octx);
for (i = 0; i < klen; i++)
key[i] ^= HMAC_IPAD_VAL;
axf->Init(ses->ses_ictx);
axf->Update(ses->ses_ictx, key, klen);
axf->Update(ses->ses_ictx, hmac_ipad_buffer, axf->blocksize - klen);
for (i = 0; i < klen; i++)
key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
axf->Init(ses->ses_octx);
axf->Update(ses->ses_octx, key, klen);
axf->Update(ses->ses_octx, hmac_opad_buffer, axf->blocksize - klen);
for (i = 0; i < klen; i++)
key[i] ^= HMAC_OPAD_VAL;
}
/*
* Compute keyed-hash authenticator.
*/
static int
padlock_authcompute(struct padlock_session *ses, struct cryptodesc *crd,
caddr_t buf, int flags)
{
u_char hash[HASH_MAX_LEN];
struct auth_hash *axf;
union authctx ctx;
int error;
axf = ses->ses_axf;
padlock_copy_ctx(axf, ses->ses_ictx, &ctx);
error = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len,
(int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx);
if (error != 0) {
padlock_free_ctx(axf, &ctx);
return (error);
}
axf->Final(hash, &ctx);
padlock_copy_ctx(axf, ses->ses_octx, &ctx);
axf->Update(&ctx, hash, axf->hashsize);
axf->Final(hash, &ctx);
/* Inject the authentication data */
crypto_copyback(flags, buf, crd->crd_inject,
ses->ses_mlen == 0 ? axf->hashsize : ses->ses_mlen, hash);
return (0);
}
int
padlock_hash_setup(struct padlock_session *ses, struct cryptoini *macini)
{
ses->ses_mlen = macini->cri_mlen;
/* Find software structure which describes HMAC algorithm. */
switch (macini->cri_alg) {
case CRYPTO_NULL_HMAC:
ses->ses_axf = &auth_hash_null;
break;
case CRYPTO_MD5_HMAC:
ses->ses_axf = &auth_hash_hmac_md5;
break;
case CRYPTO_SHA1_HMAC:
if ((via_feature_xcrypt & VIA_HAS_SHA) != 0)
ses->ses_axf = &padlock_hmac_sha1;
else
ses->ses_axf = &auth_hash_hmac_sha1;
break;
case CRYPTO_RIPEMD160_HMAC:
ses->ses_axf = &auth_hash_hmac_ripemd_160;
break;
case CRYPTO_SHA2_256_HMAC:
if ((via_feature_xcrypt & VIA_HAS_SHA) != 0)
ses->ses_axf = &padlock_hmac_sha256;
else
ses->ses_axf = &auth_hash_hmac_sha2_256;
break;
case CRYPTO_SHA2_384_HMAC:
ses->ses_axf = &auth_hash_hmac_sha2_384;
break;
case CRYPTO_SHA2_512_HMAC:
ses->ses_axf = &auth_hash_hmac_sha2_512;
break;
}
/* Allocate memory for HMAC inner and outer contexts. */
ses->ses_ictx = malloc(ses->ses_axf->ctxsize, M_PADLOCK,
M_ZERO | M_NOWAIT);
ses->ses_octx = malloc(ses->ses_axf->ctxsize, M_PADLOCK,
M_ZERO | M_NOWAIT);
if (ses->ses_ictx == NULL || ses->ses_octx == NULL)
return (ENOMEM);
/* Setup key if given. */
if (macini->cri_key != NULL) {
padlock_hash_key_setup(ses, macini->cri_key,
macini->cri_klen);
}
return (0);
}
int
padlock_hash_process(struct padlock_session *ses, struct cryptodesc *maccrd,
struct cryptop *crp)
{
int error;
if ((maccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0)
padlock_hash_key_setup(ses, maccrd->crd_key, maccrd->crd_klen);
error = padlock_authcompute(ses, maccrd, crp->crp_buf, crp->crp_flags);
return (error);
}
void
padlock_hash_free(struct padlock_session *ses)
{
if (ses->ses_ictx != NULL) {
padlock_free_ctx(ses->ses_axf, ses->ses_ictx);
bzero(ses->ses_ictx, ses->ses_axf->ctxsize);
free(ses->ses_ictx, M_PADLOCK);
ses->ses_ictx = NULL;
}
if (ses->ses_octx != NULL) {
padlock_free_ctx(ses->ses_axf, ses->ses_octx);
bzero(ses->ses_octx, ses->ses_axf->ctxsize);
free(ses->ses_octx, M_PADLOCK);
ses->ses_octx = NULL;
}
}

314
sys/dev/mii/gentbi.c Normal file
View File

@ -0,0 +1,314 @@
/* $NetBSD: gentbi.c,v 1.15 2006/03/29 07:05:24 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1997 Manuel Bouyer. 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 Manuel Bouyer.
* 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.
*/
/*
* Driver for generic ten-bit (1000BASE-SX) interfaces, built in to
* many Gigabit Ethernet chips.
*
* All we have to do here is correctly report speed and duplex.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Driver for generic unknown ten-bit interfaces(1000BASE-{LX,SX}
* fiber interfaces).
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/bus.h>
#include <net/if.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include "miidevs.h"
#include "miibus_if.h"
static int gentbi_probe(device_t);
static int gentbi_attach(device_t);
static device_method_t gentbi_methods[] = {
/* device interface */
DEVMETHOD(device_probe, gentbi_probe),
DEVMETHOD(device_attach, gentbi_attach),
DEVMETHOD(device_detach, mii_phy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
{0, 0}
};
static devclass_t gentbi_devclass;
static driver_t gentbi_driver = {
"gentbi",
gentbi_methods,
sizeof(struct mii_softc)
};
DRIVER_MODULE(gentbi, miibus, gentbi_driver, gentbi_devclass, 0, 0);
static int gentbi_service(struct mii_softc *, struct mii_data *, int);
static void gentbi_status(struct mii_softc *);
static int
gentbi_probe(device_t dev)
{
device_t parent;
struct mii_attach_args *ma;
int bmsr, extsr;
parent = device_get_parent(dev);
ma = device_get_ivars(dev);
/*
* We match as a generic TBI if:
*
* - There is no media in the BMSR.
* - EXTSR has only 1000X.
*/
bmsr = MIIBUS_READREG(parent, ma->mii_phyno, MII_BMSR);
if ((bmsr & BMSR_EXTSTAT) == 0 || (bmsr & BMSR_MEDIAMASK) != 0)
return (ENXIO);
extsr = MIIBUS_READREG(parent, ma->mii_phyno, MII_EXTSR);
if (extsr & (EXTSR_1000TFDX|EXTSR_1000THDX))
return (ENXIO);
if (extsr & (EXTSR_1000XFDX|EXTSR_1000XHDX)) {
/*
* We think this is a generic TBI. Return a match
* priority higher than ukphy, but lower than what
* specific drivers will return.
*/
device_set_desc(dev, "Generic ten-bit interface");
return (BUS_PROBE_LOW_PRIORITY);
}
return (ENXIO);
}
static int
gentbi_attach(device_t dev)
{
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
sc = device_get_softc(dev);
ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev);
mii = device_get_softc(sc->mii_dev);
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
if (bootverbose)
device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n",
MII_OUI(ma->mii_id1, ma->mii_id2),
MII_MODEL(ma->mii_id2), MII_REV(ma->mii_id2));
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = gentbi_service;
sc->mii_pdata = mii;
sc->mii_flags |= MIIF_NOISOLATE;
mii->mii_instance++;
mii_phy_reset(sc);
/*
* Mask out all media in the BMSR. We only are really interested
* in "auto".
*/
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask & ~BMSR_MEDIAMASK;
if (sc->mii_capabilities & BMSR_EXTSTAT)
sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
device_printf(dev, " ");
if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
(sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
printf("no media present");
else
mii_phy_add_media(sc);
printf("\n");
return (0);
}
static int
gentbi_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
switch (cmd) {
case MII_POLLSTAT:
/*
* If we're not polling our PHY instance, just return.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
break;
case MII_MEDIACHG:
/*
* If the media indicates a different PHY instance,
* isolate ourselves.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
reg = PHY_READ(sc, MII_BMCR);
PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
return (0);
}
/*
* If the interface is not up, don't do anything.
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
mii_phy_setmedia(sc);
break;
case MII_TICK:
/*
* If we're not currently selected, just return.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
}
/* Update the media status. */
gentbi_status(sc);
/* Callback if something changed. */
mii_phy_update(sc, cmd);
return (0);
}
static void
gentbi_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int bmsr, bmcr, anlpar;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
bmcr = PHY_READ(sc, MII_BMCR);
if (bmcr & BMCR_ISO) {
mii->mii_media_active |= IFM_NONE;
mii->mii_media_status = 0;
return;
}
if (bmcr & BMCR_LOOP)
mii->mii_media_active |= IFM_LOOP;
if (bmcr & BMCR_AUTOEN) {
/*
* The media status bits are only valid of autonegotiation
* has completed (or it's disabled).
*/
if ((bmsr & BMSR_ACOMP) == 0) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
return;
}
/*
* The media is always 1000baseSX. Check the ANLPAR to
* see if we're doing full-duplex.
*/
mii->mii_media_active |= IFM_1000_SX;
anlpar = PHY_READ(sc, MII_ANLPAR);
if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0 &&
(anlpar & ANLPAR_X_FD) != 0)
mii->mii_media_active |= IFM_FDX;
} else
mii->mii_media_active = ife->ifm_media;
}

444
sys/dev/mii/ip1000phy.c Normal file
View File

@ -0,0 +1,444 @@
/*-
* Copyright (c) 2006, Pyun YongHyeon <yongari@FreeBSD.org>
* 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 unmodified, 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$");
/*
* Driver for the IC Plus IP1000A 10/100/1000 PHY.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/bus.h>
#include <net/if.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include "miidevs.h"
#include <dev/mii/ip1000phyreg.h>
#include "miibus_if.h"
#include <machine/bus.h>
#include <dev/stge/if_stgereg.h>
static int ip1000phy_probe(device_t);
static int ip1000phy_attach(device_t);
static device_method_t ip1000phy_methods[] = {
/* device interface */
DEVMETHOD(device_probe, ip1000phy_probe),
DEVMETHOD(device_attach, ip1000phy_attach),
DEVMETHOD(device_detach, mii_phy_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
{ 0, 0 }
};
static devclass_t ip1000phy_devclass;
static driver_t ip1000phy_driver = {
"ip1000phy",
ip1000phy_methods,
sizeof (struct mii_softc)
};
DRIVER_MODULE(ip1000phy, miibus, ip1000phy_driver, ip1000phy_devclass, 0, 0);
static int ip1000phy_service(struct mii_softc *, struct mii_data *, int);
static void ip1000phy_status(struct mii_softc *);
static void ip1000phy_reset(struct mii_softc *);
static int ip1000phy_mii_phy_auto(struct mii_softc *);
static const struct mii_phydesc ip1000phys[] = {
MII_PHY_DESC(ICPLUS, IP1000A),
MII_PHY_END
};
static int
ip1000phy_probe(device_t dev)
{
struct mii_attach_args *ma;
const struct mii_phydesc *mpd;
ma = device_get_ivars(dev);
mpd = mii_phy_match(ma, ip1000phys);
if (mpd != NULL) {
device_set_desc(dev, mpd->mpd_name);
return (BUS_PROBE_DEFAULT);
}
return (ENXIO);
}
static int
ip1000phy_attach(device_t dev)
{
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
sc = device_get_softc(dev);
ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev);
mii = device_get_softc(sc->mii_dev);
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = ip1000phy_service;
sc->mii_pdata = mii;
sc->mii_anegticks = MII_ANEGTICKS_GIGE;
sc->mii_flags |= MIIF_NOISOLATE;
mii->mii_instance++;
device_printf(dev, " ");
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
BMCR_ISO);
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
IP1000PHY_BMCR_10);
printf("10baseT, ");
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
IP1000PHY_BMCR_10 | IP1000PHY_BMCR_FDX);
printf("10baseT-FDX, ");
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
IP1000PHY_BMCR_100);
printf("100baseTX, ");
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
IP1000PHY_BMCR_100 | IP1000PHY_BMCR_FDX);
printf("100baseTX-FDX, ");
/* 1000baseT half-duplex, really supported? */
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
IP1000PHY_BMCR_1000);
printf("1000baseTX, ");
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst),
IP1000PHY_BMCR_1000 | IP1000PHY_BMCR_FDX);
printf("1000baseTX-FDX, ");
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
printf("auto\n");
#undef ADD
ip1000phy_reset(sc);
MIIBUS_MEDIAINIT(sc->mii_dev);
return(0);
}
static int
ip1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
uint32_t gig, reg, speed;
switch (cmd) {
case MII_POLLSTAT:
/*
* If we're not polling our PHY instance, just return.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
break;
case MII_MEDIACHG:
/*
* If the media indicates a different PHY instance,
* isolate ourselves.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
reg = PHY_READ(sc, IP1000PHY_MII_BMCR);
PHY_WRITE(sc, IP1000PHY_MII_BMCR,
reg | IP1000PHY_BMCR_ISO);
return (0);
}
/*
* If the interface is not up, don't do anything.
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0) {
break;
}
ip1000phy_reset(sc);
switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
(void)ip1000phy_mii_phy_auto(sc);
goto done;
break;
case IFM_1000_T:
/*
* XXX
* Manual 1000baseT setting doesn't seem to work.
*/
speed = IP1000PHY_BMCR_1000;
break;
case IFM_100_TX:
speed = IP1000PHY_BMCR_100;
break;
case IFM_10_T:
speed = IP1000PHY_BMCR_10;
break;
default:
return (EINVAL);
}
if (((ife->ifm_media & IFM_GMASK) & IFM_FDX) != 0) {
speed |= IP1000PHY_BMCR_FDX;
gig = IP1000PHY_1000CR_1000T_FDX;
} else
gig = IP1000PHY_1000CR_1000T;
PHY_WRITE(sc, IP1000PHY_MII_1000CR, 0);
PHY_WRITE(sc, IP1000PHY_MII_BMCR, speed);
if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
break;
PHY_WRITE(sc, IP1000PHY_MII_1000CR, gig);
PHY_WRITE(sc, IP1000PHY_MII_BMCR, speed);
/*
* When settning the link manually, one side must
* be the master and the other the slave. However
* ifmedia doesn't give us a good way to specify
* this, so we fake it by using one of the LINK
* flags. If LINK0 is set, we program the PHY to
* be a master, otherwise it's a slave.
*/
if ((mii->mii_ifp->if_flags & IFF_LINK0))
PHY_WRITE(sc, IP1000PHY_MII_1000CR, gig |
IP1000PHY_1000CR_MASTER |
IP1000PHY_1000CR_MMASTER |
IP1000PHY_1000CR_MANUAL);
else
PHY_WRITE(sc, IP1000PHY_MII_1000CR, gig |
IP1000PHY_1000CR_MASTER |
IP1000PHY_1000CR_MANUAL);
done:
break;
case MII_TICK:
/*
* If we're not currently selected, just return.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
/*
* Is the interface even up?
*/
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
return (0);
/*
* Only used for autonegotiation.
*/
if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
sc->mii_ticks = 0;
break;
}
/*
* check for link.
*/
reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
if (reg & BMSR_LINK) {
sc->mii_ticks = 0;
break;
}
/* Announce link loss right after it happens */
if (sc->mii_ticks++ == 0)
break;
/*
* Only retry autonegotiation every mii_anegticks seconds.
*/
if (sc->mii_ticks <= sc->mii_anegticks)
return (0);
sc->mii_ticks = 0;
ip1000phy_mii_phy_auto(sc);
break;
}
/* Update the media status. */
ip1000phy_status(sc);
/* Callback if something changed. */
mii_phy_update(sc, cmd);
return (0);
}
static void
ip1000phy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
uint32_t bmsr, bmcr, stat;
uint32_t ar, lpar;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
bmsr = PHY_READ(sc, IP1000PHY_MII_BMSR) |
PHY_READ(sc, IP1000PHY_MII_BMSR);
if ((bmsr & IP1000PHY_BMSR_LINK) != 0)
mii->mii_media_status |= IFM_ACTIVE;
bmcr = PHY_READ(sc, IP1000PHY_MII_BMCR);
if ((bmcr & IP1000PHY_BMCR_LOOP) != 0)
mii->mii_media_active |= IFM_LOOP;
if ((bmcr & IP1000PHY_BMCR_AUTOEN) != 0) {
if ((bmsr & IP1000PHY_BMSR_ANEGCOMP) == 0) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
return;
}
}
stat = PHY_READ(sc, STGE_PhyCtrl);
switch (PC_LinkSpeed(stat)) {
case PC_LinkSpeed_Down:
mii->mii_media_active |= IFM_NONE;
return;
case PC_LinkSpeed_10:
mii->mii_media_active |= IFM_10_T;
break;
case PC_LinkSpeed_100:
mii->mii_media_active |= IFM_100_TX;
break;
case PC_LinkSpeed_1000:
mii->mii_media_active |= IFM_1000_T;
break;
}
if ((stat & PC_PhyDuplexStatus) != 0)
mii->mii_media_active |= IFM_FDX;
else
mii->mii_media_active |= IFM_HDX;
ar = PHY_READ(sc, IP1000PHY_MII_ANAR);
lpar = PHY_READ(sc, IP1000PHY_MII_ANLPAR);
/*
* FLAG0 : Rx flow-control
* FLAG1 : Tx flow-control
*/
if ((ar & IP1000PHY_ANAR_PAUSE) && (lpar & IP1000PHY_ANLPAR_PAUSE))
mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1;
else if (!(ar & IP1000PHY_ANAR_PAUSE) && (ar & IP1000PHY_ANAR_APAUSE) &&
(lpar & IP1000PHY_ANLPAR_PAUSE) && (lpar & IP1000PHY_ANLPAR_APAUSE))
mii->mii_media_active |= IFM_FLAG1;
else if ((ar & IP1000PHY_ANAR_PAUSE) && (ar & IP1000PHY_ANAR_APAUSE) &&
!(lpar & IP1000PHY_ANLPAR_PAUSE) &&
(lpar & IP1000PHY_ANLPAR_APAUSE)) {
mii->mii_media_active |= IFM_FLAG0;
}
/*
* FLAG2 : local PHY resolved to MASTER
*/
if ((mii->mii_media_active & IFM_1000_T) != 0) {
stat = PHY_READ(sc, IP1000PHY_MII_1000SR);
if ((stat & IP1000PHY_1000SR_MASTER) != 0)
mii->mii_media_active |= IFM_FLAG2;
}
}
static int
ip1000phy_mii_phy_auto(struct mii_softc *mii)
{
uint32_t reg;
PHY_WRITE(mii, IP1000PHY_MII_ANAR,
IP1000PHY_ANAR_10T | IP1000PHY_ANAR_10T_FDX |
IP1000PHY_ANAR_100TX | IP1000PHY_ANAR_100TX_FDX |
IP1000PHY_ANAR_PAUSE | IP1000PHY_ANAR_APAUSE);
reg = IP1000PHY_1000CR_1000T | IP1000PHY_1000CR_1000T_FDX;
reg |= IP1000PHY_1000CR_MASTER;
PHY_WRITE(mii, IP1000PHY_MII_1000CR, reg);
PHY_WRITE(mii, IP1000PHY_MII_BMCR, (IP1000PHY_BMCR_FDX |
IP1000PHY_BMCR_AUTOEN | IP1000PHY_BMCR_STARTNEG));
return (EJUSTRETURN);
}
static void
ip1000phy_load_dspcode(struct mii_softc *sc)
{
PHY_WRITE(sc, 31, 0x0001);
PHY_WRITE(sc, 27, 0x01e0);
PHY_WRITE(sc, 31, 0x0002);
PHY_WRITE(sc, 27, 0xeb8e);
PHY_WRITE(sc, 31, 0x0000);
PHY_WRITE(sc, 30, 0x005e);
PHY_WRITE(sc, 9, 0x0700);
DELAY(50);
}
static void
ip1000phy_reset(struct mii_softc *sc)
{
struct stge_softc *stge_sc;
struct mii_data *mii;
uint32_t reg;
mii_phy_reset(sc);
/* clear autoneg/full-duplex as we don't want it after reset */
reg = PHY_READ(sc, IP1000PHY_MII_BMCR);
reg &= ~(IP1000PHY_BMCR_AUTOEN | IP1000PHY_BMCR_FDX);
PHY_WRITE(sc, MII_BMCR, reg);
mii = sc->mii_pdata;
/*
* XXX There should be more general way to pass PHY specific
* data via mii interface.
*/
if (strcmp(mii->mii_ifp->if_dname, "stge") == 0) {
stge_sc = mii->mii_ifp->if_softc;
if (stge_sc->sc_rev >= 0x40 && stge_sc->sc_rev <= 0x4e)
ip1000phy_load_dspcode(sc);
}
}

141
sys/dev/mii/ip1000phyreg.h Normal file
View File

@ -0,0 +1,141 @@
/*-
* Copyright (c) 2006, Pyun YongHyeon
* 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 unmodified, 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 _DEV_MII_IP1000PHYREG_H_
#define _DEV_MII_IP1000PHYREG_H_
/*
* Registers for the IC Plus IP1000A internal PHY.
*/
/* Control register */
#define IP1000PHY_MII_BMCR 0x00
#define IP1000PHY_BMCR_FDX 0x0100
#define IP1000PHY_BMCR_STARTNEG 0x0200
#define IP1000PHY_BMCR_ISO 0x0400
#define IP1000PHY_BMCR_PDOWN 0x0800
#define IP1000PHY_BMCR_AUTOEN 0x1000
#define IP1000PHY_BMCR_LOOP 0x4000
#define IP1000PHY_BMCR_RESET 0x8000
#define IP1000PHY_BMCR_10 0x0000
#define IP1000PHY_BMCR_100 0x2000
#define IP1000PHY_BMCR_1000 0x0040
/* Status register */
#define IP1000PHY_MII_BMSR 0x01
#define IP1000PHY_BMSR_EXT 0x0001
#define IP1000PHY_BMSR_LINK 0x0004
#define IP1000PHY_BMSR_ANEG 0x0008
#define IP1000PHY_BMSR_RFAULT 0x0010
#define IP1000PHY_BMSR_ANEGCOMP 0x0020
#define IP1000PHY_BMSR_EXTSTS 0x0100
#define IP1000PHY_MII_ID1 0x02
/* Autonegotiation advertisement register */
#define IP1000PHY_MII_ANAR 0x04
#define IP1000PHY_ANAR_10T 0x0020
#define IP1000PHY_ANAR_10T_FDX 0x0040
#define IP1000PHY_ANAR_100TX 0x0080
#define IP1000PHY_ANAR_100TX_FDX 0x0100
#define IP1000PHY_ANAR_100T4 0x0200
#define IP1000PHY_ANAR_PAUSE 0x0400
#define IP1000PHY_ANAR_APAUSE 0x0800
#define IP1000PHY_ANAR_RFAULT 0x2000
#define IP1000PHY_ANAR_NP 0x8000
/* Autonegotiation link parnet ability register */
#define IP1000PHY_MII_ANLPAR 0x05
#define IP1000PHY_ANLPAR_10T 0x0020
#define IP1000PHY_ANLPAR_10T_FDX 0x0040
#define IP1000PHY_ANLPAR_100TX 0x0080
#define IP1000PHY_ANLPAR_100TX_FDX 0x0100
#define IP1000PHY_ANLPAR_100T4 0x0200
#define IP1000PHY_ANLPAR_PAUSE 0x0400
#define IP1000PHY_ANLPAR_APAUSE 0x0800
#define IP1000PHY_ANLPAR_RFAULT 0x2000
#define IP1000PHY_ANLPAR_ACK 0x4000
#define IP1000PHY_ANLPAR_NP 0x8000
/* Autonegotiation expansion register */
#define IP1000PHY_MII_ANER 0x06
#define IP1000PHY_ANER_LPNWAY 0x0001
#define IP1000PHY_ANER_PRCVD 0x0002
#define IP1000PHY_ANER_NEXTP 0x0004
#define IP1000PHY_ANER_LPNEXTP 0x0008
#define IP1000PHY_ANER_PDF 0x0100
/* Autonegotiation next page transmit register */
#define IP1000PHY_MII_NEXTP 0x07
#define IP1000PHY_NEXTP_MSGC 0x0001
#define IP1000PHY_NEXTP_TOGGLE 0x0800
#define IP1000PHY_NEXTP_ACK2 0x1000
#define IP1000PHY_NEXTP_MSGP 0x2000
#define IP1000PHY_NEXTP_NEXTP 0x8000
/* Autonegotiation link partner next page register */
#define IP1000PHY_MII_NEXTPLP 0x08
#define IP1000PHY_NEXTPLP_MSGC 0x0001
#define IP1000PHY_NEXTPLP_TOGGLE 0x0800
#define IP1000PHY_NEXTPLP_ACK2 0x1000
#define IP1000PHY_NEXTPLP_MSGP 0x2000
#define IP1000PHY_NEXTPLP_ACK 0x4000
#define IP1000PHY_NEXTPLP_NEXTP 0x8000
/* 1000baseT control register */
#define IP1000PHY_MII_1000CR 0x09
#define IP1000PHY_1000CR_1000T 0x0100
#define IP1000PHY_1000CR_1000T_FDX 0x0200
#define IP1000PHY_1000CR_MASTER 0x0400
#define IP1000PHY_1000CR_MMASTER 0x0800
#define IP1000PHY_1000CR_MANUAL 0x1000
#define IP1000PHY_1000CR_TMNORMAL 0x0000
#define IP1000PHY_1000CR_TM1 0x2000
#define IP1000PHY_1000CR_TM2 0x4000
#define IP1000PHY_1000CR_TM3 0x6000
#define IP1000PHY_1000CR_TM4 0x8000
/* 1000baseT status register */
#define IP1000PHY_MII_1000SR 0x0A
#define IP1000PHY_1000SR_LP 0x0400
#define IP1000PHY_1000SR_LP_FDX 0x0800
#define IP1000PHY_1000SR_RXSTAT 0x1000
#define IP1000PHY_1000SR_LRXSTAT 0x2000
#define IP1000PHY_1000SR_MASTER 0x4000
#define IP1000PHY_1000SR_MASTERF 0x8000
/* Extended status register */
#define IP1000PHY_MII_EXTSTS 0x0F
#define IP1000PHY_EXTSTS_1000T 0x1000
#define IP1000PHY_EXTSTS_1000T_FDX 0x2000
#define IP1000PHY_EXTSTS_1000X 0x4000
#define IP1000PHY_EXTSTS_1000X_FDX 0x8000
#endif /* _DEV_MII_IP1000PHYREG_H_ */

2698
sys/dev/stge/if_stge.c Normal file

File diff suppressed because it is too large Load Diff

697
sys/dev/stge/if_stgereg.h Normal file
View File

@ -0,0 +1,697 @@
/* $NetBSD: if_stgereg.h,v 1.3 2003/02/10 21:10:07 christos Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* $FreeBSD$ */
/*
* Sundance Technology PCI vendor ID
*/
#define VENDOR_SUNDANCETI 0x13f0
/*
* Tamarack Microelectronics PCI vendor ID
*/
#define VENDOR_TAMARACK 0x143d
/*
* D-Link Systems PCI vendor ID
*/
#define VENDOR_DLINK 0x1186
/*
* Antares Microsystems PCI vendor ID
*/
#define VENDOR_ANTARES 0x1754
/*
* Sundance Technology device ID
*/
#define DEVICEID_SUNDANCETI_ST1023 0x1023
#define DEVICEID_SUNDANCETI_ST2021 0x2021
#define DEVICEID_TAMARACK_TC9021 0x1021
#define DEVICEID_TAMARACK_TC9021_ALT 0x9021
/*
* D-Link Systems device ID
*/
#define DEVICEID_DLINK_DL4000 0x4000
/*
* Antares Microsystems device ID
*/
#define DEVICEID_ANTARES_TC9021 0x1021
/*
* Register description for the Sundance Tech. TC9021 10/100/1000
* Ethernet controller.
*
* Note that while DMA addresses are all in 64-bit fields, only
* the lower 40 bits of a DMA address are valid.
*/
#if (BUS_SPACE_MAXADDR < 0xFFFFFFFFFF)
#define STGE_DMA_MAXADDR BUS_SPACE_MAXADDR
#else
#define STGE_DMA_MAXADDR 0xFFFFFFFFFF
#endif
/*
* Register access macros
*/
#define CSR_WRITE_4(_sc, reg, val) \
bus_write_4((_sc)->sc_res[0], (reg), (val))
#define CSR_WRITE_2(_sc, reg, val) \
bus_write_2((_sc)->sc_res[0], (reg), (val))
#define CSR_WRITE_1(_sc, reg, val) \
bus_write_1((_sc)->sc_res[0], (reg), (val))
#define CSR_READ_4(_sc, reg) \
bus_read_4((_sc)->sc_res[0], (reg))
#define CSR_READ_2(_sc, reg) \
bus_read_2((_sc)->sc_res[0], (reg))
#define CSR_READ_1(_sc, reg) \
bus_read_1((_sc)->sc_res[0], (reg))
/*
* TC9021 buffer fragment descriptor.
*/
struct stge_frag {
uint64_t frag_word0; /* address, length */
};
#define FRAG_ADDR(x) (((uint64_t)(x)) << 0)
#define FRAG_ADDR_MASK FRAG_ADDR(0xfffffffffULL)
#define FRAG_LEN(x) (((uint64_t)(x)) << 48)
#define FRAG_LEN_MASK FRAG_LEN(0xffffULL)
/*
* TC9021 Transmit Frame Descriptor. Note the number of fragments
* here is arbitrary, but we can't have any more than 15.
*/
#define STGE_NTXFRAGS 15
struct stge_tfd {
uint64_t tfd_next; /* next TFD in list */
uint64_t tfd_control; /* control bits */
/* the buffer fragments */
struct stge_frag tfd_frags[STGE_NTXFRAGS];
};
#define TFD_FrameId(x) ((x) << 0)
#define TFD_FrameId_MAX 0xffff
#define TFD_WordAlign(x) ((x) << 16)
#define TFD_WordAlign_dword 0 /* align to dword in TxFIFO */
#define TFD_WordAlign_word 2 /* align to word in TxFIFO */
#define TFD_WordAlign_disable 1 /* disable alignment */
#define TFD_TCPChecksumEnable (1ULL << 18)
#define TFD_UDPChecksumEnable (1ULL << 19)
#define TFD_IPChecksumEnable (1ULL << 20)
#define TFD_FcsAppendDisable (1ULL << 21)
#define TFD_TxIndicate (1ULL << 22)
#define TFD_TxDMAIndicate (1ULL << 23)
#define TFD_FragCount(x) ((x) << 24)
#define TFD_VLANTagInsert (1ULL << 28)
#define TFD_TFDDone (1ULL << 31)
#define TFD_VID(x) (((uint64_t)(x)) << 32)
#define TFD_CFI (1ULL << 44)
#define TFD_UserPriority(x) (((uint64_t)(x)) << 45)
/*
* TC9021 Receive Frame Descriptor. Each RFD has a single fragment
* in it, and the chip tells us the beginning and end of the frame.
*/
struct stge_rfd {
uint64_t rfd_next; /* next RFD in list */
uint64_t rfd_status; /* status bits */
struct stge_frag rfd_frag; /* the buffer */
};
/* Low word of rfd_status */
#define RFD_RxStatus(x) ((x) & 0xffffffff)
#define RFD_RxDMAFrameLen(x) ((x) & 0xffff)
#define RFD_RxFIFOOverrun 0x00010000
#define RFD_RxRuntFrame 0x00020000
#define RFD_RxAlignmentError 0x00040000
#define RFD_RxFCSError 0x00080000
#define RFD_RxOversizedFrame 0x00100000
#define RFD_RxLengthError 0x00200000
#define RFD_VLANDetected 0x00400000
#define RFD_TCPDetected 0x00800000
#define RFD_TCPError 0x01000000
#define RFD_UDPDetected 0x02000000
#define RFD_UDPError 0x04000000
#define RFD_IPDetected 0x08000000
#define RFD_IPError 0x10000000
#define RFD_FrameStart 0x20000000
#define RFD_FrameEnd 0x40000000
#define RFD_RFDDone 0x80000000
/* High word of rfd_status */
#define RFD_TCI(x) ((((uint64_t)(x)) >> 32) & 0xffff)
/*
* EEPROM offsets.
*/
#define STGE_EEPROM_ConfigParam 0x00
#define STGE_EEPROM_AsicCtrl 0x01
#define STGE_EEPROM_SubSystemVendorId 0x02
#define STGE_EEPROM_SubSystemId 0x03
#define STGE_EEPROM_LEDMode 0x06
#define STGE_EEPROM_StationAddress0 0x10
#define STGE_EEPROM_StationAddress1 0x11
#define STGE_EEPROM_StationAddress2 0x12
/*
* The TC9021 register space.
*/
#define STGE_DMACtrl 0x00
#define DMAC_RxDMAComplete (1U << 3)
#define DMAC_RxDMAPollNow (1U << 4)
#define DMAC_TxDMAComplete (1U << 11)
#define DMAC_TxDMAPollNow (1U << 12)
#define DMAC_TxDMAInProg (1U << 15)
#define DMAC_RxEarlyDisable (1U << 16)
#define DMAC_MWIDisable (1U << 18)
#define DMAC_TxWriteBackDisable (1U << 19)
#define DMAC_TxBurstLimit(x) ((x) << 20)
#define DMAC_TargetAbort (1U << 30)
#define DMAC_MasterAbort (1U << 31)
#define STGE_RxDMAStatus 0x08
#define STGE_TFDListPtrLo 0x10
#define STGE_TFDListPtrHi 0x14
#define STGE_TxDMABurstThresh 0x18 /* 8-bit */
#define STGE_TxDMAUrgentThresh 0x19 /* 8-bit */
#define STGE_TxDMAPollPeriod 0x1a /* 8-bit, 320ns increments */
#define STGE_RFDListPtrLo 0x1c
#define STGE_RFDListPtrHi 0x20
#define STGE_RxDMABurstThresh 0x24 /* 8-bit */
#define STGE_RxDMAUrgentThresh 0x25 /* 8-bit */
#define STGE_RxDMAPollPeriod 0x26 /* 8-bit, 320ns increments */
#define STGE_RxDMAIntCtrl 0x28
#define RDIC_RxFrameCount(x) ((x) & 0xff)
#define RDIC_PriorityThresh(x) ((x) << 10)
#define RDIC_RxDMAWaitTime(x) ((x) << 16)
/*
* Number of receive frames transferred via DMA before a Rx interrupt is issued.
*/
#define STGE_RXINT_NFRAME_DEFAULT 8
#define STGE_RXINT_NFRAME_MIN 1
#define STGE_RXINT_NFRAME_MAX 255
/*
* Maximum amount of time (in 64ns increments) to wait before issuing a Rx
* interrupt if number of frames recevied is less than STGE_RXINT_NFRAME
* (STGE_RXINT_NFRAME_MIN <= STGE_RXINT_NFRAME <= STGE_RXINT_NFRAME_MAX)
*/
#define STGE_RXINT_DMAWAIT_DEFAULT 30 /* 30us */
#define STGE_RXINT_DMAWAIT_MIN 0
#define STGE_RXINT_DMAWAIT_MAX 4194
#define STGE_RXINT_USECS2TICK(x) (((x) * 1000)/64)
#define STGE_DebugCtrl 0x2c /* 16-bit */
#define DC_GPIO0Ctrl (1U << 0)
#define DC_GPIO1Ctrl (1U << 1)
#define DC_GPIO0 (1U << 2)
#define DC_GPIO1 (1U << 3)
#define STGE_AsicCtrl 0x30
#define AC_ExpRomDisable (1U << 0)
#define AC_ExpRomSize (1U << 1)
#define AC_PhySpeed10 (1U << 4)
#define AC_PhySpeed100 (1U << 5)
#define AC_PhySpeed1000 (1U << 6)
#define AC_PhyMedia (1U << 7)
#define AC_ForcedConfig(x) ((x) << 8)
#define AC_ForcedConfig_MASK AC_ForcedConfig(7)
#define AC_D3ResetDisable (1U << 11)
#define AC_SpeedupMode (1U << 13)
#define AC_LEDMode (1U << 14)
#define AC_RstOutPolarity (1U << 15)
#define AC_GlobalReset (1U << 16)
#define AC_RxReset (1U << 17)
#define AC_TxReset (1U << 18)
#define AC_DMA (1U << 19)
#define AC_FIFO (1U << 20)
#define AC_Network (1U << 21)
#define AC_Host (1U << 22)
#define AC_AutoInit (1U << 23)
#define AC_RstOut (1U << 24)
#define AC_InterruptRequest (1U << 25)
#define AC_ResetBusy (1U << 26)
#define AC_LEDSpeed (1U << 27)
#define AC_LEDModeBit1 (1U << 29)
#define STGE_FIFOCtrl 0x38 /* 16-bit */
#define FC_RAMTestMode (1U << 0)
#define FC_Transmitting (1U << 14)
#define FC_Receiving (1U << 15)
#define STGE_RxEarlyThresh 0x3a /* 16-bit */
#define STGE_FlowOffThresh 0x3c /* 16-bit */
#define STGE_FlowOnTresh 0x3e /* 16-bit */
#define STGE_TxStartThresh 0x44 /* 16-bit */
#define STGE_EepromData 0x48 /* 16-bit */
#define STGE_EepromCtrl 0x4a /* 16-bit */
#define EC_EepromAddress(x) ((x) & 0xff)
#define EC_EepromOpcode(x) ((x) << 8)
#define EC_OP_WE 0
#define EC_OP_WR 1
#define EC_OP_RR 2
#define EC_OP_ER 3
#define EC_EepromBusy (1U << 15)
#define STGE_ExpRomAddr 0x4c
#define STGE_ExpRomData 0x50 /* 8-bit */
#define STGE_WakeEvent 0x51 /* 8-bit */
#define STGE_Countdown 0x54
#define CD_Count(x) ((x) & 0xffff)
#define CD_CountdownSpeed (1U << 24)
#define CD_CountdownMode (1U << 25)
#define CD_CountdownIntEnabled (1U << 26)
#define STGE_IntStatusAck 0x5a /* 16-bit */
#define STGE_IntEnable 0x5c /* 16-bit */
#define STGE_IntStatus 0x5e /* 16-bit */
#define IS_InterruptStatus (1U << 0)
#define IS_HostError (1U << 1)
#define IS_TxComplete (1U << 2)
#define IS_MACControlFrame (1U << 3)
#define IS_RxComplete (1U << 4)
#define IS_RxEarly (1U << 5)
#define IS_InRequested (1U << 6)
#define IS_UpdateStats (1U << 7)
#define IS_LinkEvent (1U << 8)
#define IS_TxDMAComplete (1U << 9)
#define IS_RxDMAComplete (1U << 10)
#define IS_RFDListEnd (1U << 11)
#define IS_RxDMAPriority (1U << 12)
#define STGE_TxStatus 0x60
#define TS_TxError (1U << 0)
#define TS_LateCollision (1U << 2)
#define TS_MaxCollisions (1U << 3)
#define TS_TxUnderrun (1U << 4)
#define TS_TxIndicateReqd (1U << 6)
#define TS_TxComplete (1U << 7)
#define TS_TxFrameId_get(x) ((x) >> 16)
#define STGE_MACCtrl 0x6c
#define MC_IFSSelect(x) ((x) & 3)
#define MC_IFS96bit 0
#define MC_IFS1024bit 1
#define MC_IFS1792bit 2
#define MC_IFS4352bit 3
#define MC_DuplexSelect (1U << 5)
#define MC_RcvLargeFrames (1U << 6)
#define MC_TxFlowControlEnable (1U << 7)
#define MC_RxFlowControlEnable (1U << 8)
#define MC_RcvFCS (1U << 9)
#define MC_FIFOLoopback (1U << 10)
#define MC_MACLoopback (1U << 11)
#define MC_AutoVLANtagging (1U << 12)
#define MC_AutoVLANuntagging (1U << 13)
#define MC_CollisionDetect (1U << 16)
#define MC_CarrierSense (1U << 17)
#define MC_StatisticsEnable (1U << 21)
#define MC_StatisticsDisable (1U << 22)
#define MC_StatisticsEnabled (1U << 23)
#define MC_TxEnable (1U << 24)
#define MC_TxDisable (1U << 25)
#define MC_TxEnabled (1U << 26)
#define MC_RxEnable (1U << 27)
#define MC_RxDisable (1U << 28)
#define MC_RxEnabled (1U << 29)
#define MC_Paused (1U << 30)
#define MC_MASK 0x7fe33fa3
#define STGE_VLANTag 0x70
#define STGE_PhySet 0x75 /* 8-bit */
#define PS_MemLenb9b (1U << 0)
#define PS_MemLen (1U << 1)
#define PS_NonCompdet (1U << 2)
#define STGE_PhyCtrl 0x76 /* 8-bit */
#define PC_MgmtClk (1U << 0)
#define PC_MgmtData (1U << 1)
#define PC_MgmtDir (1U << 2) /* MAC->PHY */
#define PC_PhyDuplexPolarity (1U << 3)
#define PC_PhyDuplexStatus (1U << 4)
#define PC_PhyLnkPolarity (1U << 5)
#define PC_LinkSpeed(x) (((x) >> 6) & 3)
#define PC_LinkSpeed_Down 0
#define PC_LinkSpeed_10 1
#define PC_LinkSpeed_100 2
#define PC_LinkSpeed_1000 3
#define STGE_StationAddress0 0x78 /* 16-bit */
#define STGE_StationAddress1 0x7a /* 16-bit */
#define STGE_StationAddress2 0x7c /* 16-bit */
#define STGE_VLANHashTable 0x7e /* 16-bit */
#define STGE_VLANId 0x80
#define STGE_MaxFrameSize 0x86
#define STGE_ReceiveMode 0x88 /* 16-bit */
#define RM_ReceiveUnicast (1U << 0)
#define RM_ReceiveMulticast (1U << 1)
#define RM_ReceiveBroadcast (1U << 2)
#define RM_ReceiveAllFrames (1U << 3)
#define RM_ReceiveMulticastHash (1U << 4)
#define RM_ReceiveIPMulticast (1U << 5)
#define RM_ReceiveVLANMatch (1U << 8)
#define RM_ReceiveVLANHash (1U << 9)
#define STGE_HashTable0 0x8c
#define STGE_HashTable1 0x90
#define STGE_RMONStatisticsMask 0x98 /* set to disable */
#define STGE_StatisticsMask 0x9c /* set to disable */
#define STGE_RxJumboFrames 0xbc /* 16-bit */
#define STGE_TCPCheckSumErrors 0xc0 /* 16-bit */
#define STGE_IPCheckSumErrors 0xc2 /* 16-bit */
#define STGE_UDPCheckSumErrors 0xc4 /* 16-bit */
#define STGE_TxJumboFrames 0xf4 /* 16-bit */
/*
* TC9021 statistics. Available memory and I/O mapped.
*/
#define STGE_OctetRcvOk 0xa8
#define STGE_McstOctetRcvdOk 0xac
#define STGE_BcstOctetRcvdOk 0xb0
#define STGE_FramesRcvdOk 0xb4
#define STGE_McstFramesRcvdOk 0xb8
#define STGE_BcstFramesRcvdOk 0xbe /* 16-bit */
#define STGE_MacControlFramesRcvd 0xc6 /* 16-bit */
#define STGE_FrameTooLongErrors 0xc8 /* 16-bit */
#define STGE_InRangeLengthErrors 0xca /* 16-bit */
#define STGE_FramesCheckSeqErrors 0xcc /* 16-bit */
#define STGE_FramesLostRxErrors 0xce /* 16-bit */
#define STGE_OctetXmtdOk 0xd0
#define STGE_McstOctetXmtdOk 0xd4
#define STGE_BcstOctetXmtdOk 0xd8
#define STGE_FramesXmtdOk 0xdc
#define STGE_McstFramesXmtdOk 0xe0
#define STGE_FramesWDeferredXmt 0xe4
#define STGE_LateCollisions 0xe8
#define STGE_MultiColFrames 0xec
#define STGE_SingleColFrames 0xf0
#define STGE_BcstFramesXmtdOk 0xf6 /* 16-bit */
#define STGE_CarrierSenseErrors 0xf8 /* 16-bit */
#define STGE_MacControlFramesXmtd 0xfa /* 16-bit */
#define STGE_FramesAbortXSColls 0xfc /* 16-bit */
#define STGE_FramesWEXDeferal 0xfe /* 16-bit */
/*
* RMON-compatible statistics. Only accessible if memory-mapped.
*/
#define STGE_EtherStatsCollisions 0x100
#define STGE_EtherStatsOctetsTransmit 0x104
#define STGE_EtherStatsPktsTransmit 0x108
#define STGE_EtherStatsPkts64OctetsTransmit 0x10c
#define STGE_EtherStatsPkts64to127OctetsTransmit 0x110
#define STGE_EtherStatsPkts128to255OctetsTransmit 0x114
#define STGE_EtherStatsPkts256to511OctetsTransmit 0x118
#define STGE_EtherStatsPkts512to1023OctetsTransmit 0x11c
#define STGE_EtherStatsPkts1024to1518OctetsTransmit 0x120
#define STGE_EtherStatsCRCAlignErrors 0x124
#define STGE_EtherStatsUndersizePkts 0x128
#define STGE_EtherStatsFragments 0x12c
#define STGE_EtherStatsJabbers 0x130
#define STGE_EtherStatsOctets 0x134
#define STGE_EtherStatsPkts 0x138
#define STGE_EtherStatsPkts64Octets 0x13c
#define STGE_EtherStatsPkts65to127Octets 0x140
#define STGE_EtherStatsPkts128to255Octets 0x144
#define STGE_EtherStatsPkts256to511Octets 0x148
#define STGE_EtherStatsPkts512to1023Octets 0x14c
#define STGE_EtherStatsPkts1024to1518Octets 0x150
/*
* Transmit descriptor list size.
*/
#define STGE_TX_RING_CNT 256
#define STGE_TX_LOWAT (STGE_TX_RING_CNT/32)
#define STGE_TX_HIWAT (STGE_TX_RING_CNT - STGE_TX_LOWAT)
/*
* Receive descriptor list size.
*/
#define STGE_RX_RING_CNT 256
#define STGE_MAXTXSEGS STGE_NTXFRAGS
#define STGE_JUMBO_FRAMELEN 9022
#define STGE_JUMBO_MTU \
(STGE_JUMBO_FRAMELEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
struct stge_txdesc {
struct mbuf *tx_m; /* head of our mbuf chain */
bus_dmamap_t tx_dmamap; /* our DMA map */
STAILQ_ENTRY(stge_txdesc) tx_q;
};
STAILQ_HEAD(stge_txdq, stge_txdesc);
struct stge_rxdesc {
struct mbuf *rx_m;
bus_dmamap_t rx_dmamap;
};
#define STGE_ADDR_LO(x) ((u_int64_t) (x) & 0xffffffff)
#define STGE_ADDR_HI(x) ((u_int64_t) (x) >> 32)
#define STGE_RING_ALIGN 8
struct stge_chain_data{
bus_dma_tag_t stge_parent_tag;
bus_dma_tag_t stge_tx_tag;
struct stge_txdesc stge_txdesc[STGE_TX_RING_CNT];
struct stge_txdq stge_txfreeq;
struct stge_txdq stge_txbusyq;
bus_dma_tag_t stge_rx_tag;
struct stge_rxdesc stge_rxdesc[STGE_RX_RING_CNT];
bus_dma_tag_t stge_tx_ring_tag;
bus_dmamap_t stge_tx_ring_map;
bus_dma_tag_t stge_rx_ring_tag;
bus_dmamap_t stge_rx_ring_map;
bus_dmamap_t stge_rx_sparemap;
int stge_tx_prod;
int stge_tx_cons;
int stge_tx_cnt;
int stge_rx_cons;
#ifdef DEVICE_POLLING
int stge_rxcycles;
#endif
int stge_rxlen;
struct mbuf *stge_rxhead;
struct mbuf *stge_rxtail;
};
struct stge_ring_data {
struct stge_tfd *stge_tx_ring;
bus_addr_t stge_tx_ring_paddr;
struct stge_rfd *stge_rx_ring;
bus_addr_t stge_rx_ring_paddr;
};
#define STGE_TX_RING_ADDR(sc, i) \
((sc)->sc_rdata.stge_tx_ring_paddr + sizeof(struct stge_tfd) * (i))
#define STGE_RX_RING_ADDR(sc, i) \
((sc)->sc_rdata.stge_rx_ring_paddr + sizeof(struct stge_rfd) * (i))
#define STGE_TX_RING_SZ \
(sizeof(struct stge_tfd) * STGE_TX_RING_CNT)
#define STGE_RX_RING_SZ \
(sizeof(struct stge_rfd) * STGE_RX_RING_CNT)
/*
* Software state per device.
*/
struct stge_softc {
struct ifnet *sc_ifp; /* interface info */
device_t sc_dev;
device_t sc_miibus;
struct resource *sc_res[2];
struct resource_spec *sc_spec;
void *sc_ih; /* interrupt cookie */
int sc_rev; /* silicon revision */
struct callout sc_tick_ch; /* tick callout */
struct stge_chain_data sc_cdata;
struct stge_ring_data sc_rdata;
int sc_if_flags;
int sc_if_framesize;
int sc_txthresh; /* Tx threshold */
uint32_t sc_usefiber:1; /* if we're fiber */
uint32_t sc_stge1023:1; /* are we a 1023 */
uint32_t sc_DMACtrl; /* prototype DMACtrl reg. */
uint32_t sc_MACCtrl; /* prototype MacCtrl reg. */
uint16_t sc_IntEnable; /* prototype IntEnable reg. */
uint16_t sc_led; /* LED conf. from EEPROM */
uint8_t sc_PhyCtrl; /* prototype PhyCtrl reg. */
int sc_suspended;
int sc_detach;
int sc_rxint_nframe;
int sc_rxint_dmawait;
int sc_nerr;
struct task sc_link_task;
struct mtx sc_mii_mtx; /* MII mutex */
struct mtx sc_mtx;
};
#define STGE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define STGE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
#define STGE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
#define STGE_MII_LOCK(_sc) mtx_lock(&(_sc)->sc_mii_mtx)
#define STGE_MII_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mii_mtx)
#define STGE_MAXERR 5
#define STGE_RXCHAIN_RESET(_sc) \
do { \
(_sc)->sc_cdata.stge_rxhead = NULL; \
(_sc)->sc_cdata.stge_rxtail = NULL; \
(_sc)->sc_cdata.stge_rxlen = 0; \
} while (/*CONSTCOND*/0)
#define STGE_TIMEOUT 1000
struct stge_mii_frame {
uint8_t mii_stdelim;
uint8_t mii_opcode;
uint8_t mii_phyaddr;
uint8_t mii_regaddr;
uint8_t mii_turnaround;
uint16_t mii_data;
};
/*
* MII constants
*/
#define STGE_MII_STARTDELIM 0x01
#define STGE_MII_READOP 0x02
#define STGE_MII_WRITEOP 0x01
#define STGE_MII_TURNAROUND 0x02
#define STGE_RESET_NONE 0x00
#define STGE_RESET_TX 0x01
#define STGE_RESET_RX 0x02
#define STGE_RESET_FULL 0x04

View File

@ -0,0 +1,531 @@
/*-
* Copyright (c) 2005-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* 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 AUTHORS 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 AUTHORS 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/kernel.h>
#include <sys/linker.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/bio.h>
#include <sys/sysctl.h>
#include <sys/malloc.h>
#include <sys/kthread.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/smp.h>
#include <sys/uio.h>
#include <sys/vnode.h>
#include <vm/uma.h>
#include <geom/geom.h>
#include <geom/eli/g_eli.h>
#include <geom/eli/pkcs5v2.h>
/*
* The data layout description when integrity verification is configured.
*
* One of the most important assumption here is that authenticated data and its
* HMAC has to be stored in the same place (namely in the same sector) to make
* it work reliable.
* The problem is that file systems work only with sectors that are multiple of
* 512 bytes and a power of two number.
* My idea to implement it is as follows.
* Let's store HMAC in sector. This is a must. This leaves us 480 bytes for
* data. We can't use that directly (ie. we can't create provider with 480 bytes
* sector size). We need another sector from where we take only 32 bytes of data
* and we store HMAC of this data as well. This takes two sectors from the
* original provider at the input and leaves us one sector of authenticated data
* at the output. Not very efficient, but you got the idea.
* Now, let's assume, we want to create provider with 4096 bytes sector.
* To output 4096 bytes of authenticated data we need 8x480 plus 1x256, so we
* need nine 512-bytes sectors at the input to get one 4096-bytes sector at the
* output. That's better. With 4096 bytes sector we can use 89% of size of the
* original provider. I find it as an acceptable cost.
* The reliability comes from the fact, that every HMAC stored inside the sector
* is calculated only for the data in the same sector, so its impossible to
* write new data and leave old HMAC or vice versa.
*
* And here is the picture:
*
* da0: +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+-----+
* |32b |480b| |32b |480b| |32b |480b| |32b |480b| |32b |480b| |32b |480b| |32b |480b| |32b |480b| |32b |256b |
* |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data| |HMAC|Data |
* +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+----+ +----+-----+
* |512 bytes| |512 bytes| |512 bytes| |512 bytes| |512 bytes| |512 bytes| |512 bytes| |512 bytes| |288 bytes |
* +---------+ +---------+ +---------+ +---------+ +---------+ +---------+ +---------+ +---------+ |224 unused|
* +----------+
* da0.eli: +----+----+----+----+----+----+----+----+----+
* |480b|480b|480b|480b|480b|480b|480b|480b|256b|
* +----+----+----+----+----+----+----+----+----+
* | 4096 bytes |
* +--------------------------------------------+
*
* PS. You can use any sector size with geli(8). My example is using 4kB,
* because it's most efficient. For 8kB sectors you need 2 extra sectors,
* so the cost is the same as for 4kB sectors.
*/
/*
* Code paths:
* BIO_READ:
* g_eli_start -> g_eli_auth_read -> g_io_request -> g_eli_read_done -> g_eli_auth_run -> g_eli_auth_read_done -> g_io_deliver
* BIO_WRITE:
* g_eli_start -> g_eli_auth_run -> g_eli_auth_write_done -> g_io_request -> g_eli_write_done -> g_io_deliver
*/
MALLOC_DECLARE(M_ELI);
/*
* Here we generate key for HMAC. Every sector has its own HMAC key, so it is
* not possible to copy sectors.
* We cannot depend on fact, that every sector has its own IV, because different
* IV doesn't change HMAC, when we use encrypt-then-authenticate method.
*/
static void
g_eli_auth_keygen(struct g_eli_softc *sc, off_t offset, u_char *key)
{
SHA256_CTX ctx;
/* Copy precalculated SHA256 context. */
bcopy(&sc->sc_akeyctx, &ctx, sizeof(ctx));
SHA256_Update(&ctx, (uint8_t *)&offset, sizeof(offset));
SHA256_Final(key, &ctx);
}
/*
* The function is called after we read and decrypt data.
*
* g_eli_start -> g_eli_auth_read -> g_io_request -> g_eli_read_done -> g_eli_auth_run -> G_ELI_AUTH_READ_DONE -> g_io_deliver
*/
static int
g_eli_auth_read_done(struct cryptop *crp)
{
struct bio *bp;
if (crp->crp_etype == EAGAIN) {
if (g_eli_crypto_rerun(crp) == 0)
return (0);
}
bp = (struct bio *)crp->crp_opaque;
bp->bio_inbed++;
if (crp->crp_etype == 0) {
bp->bio_completed += crp->crp_olen;
G_ELI_DEBUG(3, "Crypto READ request done (%d/%d) (add=%jd completed=%jd).",
bp->bio_inbed, bp->bio_children, (intmax_t)crp->crp_olen, (intmax_t)bp->bio_completed);
} else {
G_ELI_DEBUG(1, "Crypto READ request failed (%d/%d) error=%d.",
bp->bio_inbed, bp->bio_children, crp->crp_etype);
if (bp->bio_error == 0)
bp->bio_error = crp->crp_etype;
}
/*
* Do we have all sectors already?
*/
if (bp->bio_inbed < bp->bio_children)
return (0);
if (bp->bio_error == 0) {
struct g_eli_softc *sc;
u_int i, lsec, nsec, data_secsize, decr_secsize, encr_secsize;
u_char *srcdata, *dstdata, *auth;
off_t coroff, corsize;
/*
* Verify data integrity based on calculated and read HMACs.
*/
sc = bp->bio_to->geom->softc;
/* Sectorsize of decrypted provider eg. 4096. */
decr_secsize = bp->bio_to->sectorsize;
/* The real sectorsize of encrypted provider, eg. 512. */
encr_secsize = LIST_FIRST(&sc->sc_geom->consumer)->provider->sectorsize;
/* Number of data bytes in one encrypted sector, eg. 480. */
data_secsize = sc->sc_data_per_sector;
/* Number of sectors from decrypted provider, eg. 2. */
nsec = bp->bio_length / decr_secsize;
/* Number of sectors from encrypted provider, eg. 18. */
nsec = (nsec * sc->sc_bytes_per_sector) / encr_secsize;
/* Last sector number in every big sector, eg. 9. */
lsec = sc->sc_bytes_per_sector / encr_secsize;
srcdata = bp->bio_driver2;
dstdata = bp->bio_data;
auth = srcdata + encr_secsize * nsec;
coroff = -1;
corsize = 0;
for (i = 1; i <= nsec; i++) {
data_secsize = sc->sc_data_per_sector;
if ((i % lsec) == 0)
data_secsize = decr_secsize % data_secsize;
if (bcmp(srcdata, auth, sc->sc_alen) != 0) {
/*
* Curruption detected, remember the offset if
* this is the first corrupted sector and
* increase size.
*/
if (bp->bio_error == 0)
bp->bio_error = -1;
if (coroff == -1) {
coroff = bp->bio_offset +
(dstdata - (u_char *)bp->bio_data);
}
corsize += data_secsize;
} else {
/*
* No curruption, good.
* Report previous corruption if there was one.
*/
if (coroff != -1) {
G_ELI_DEBUG(0, "%s: %jd bytes "
"corrupted at offset %jd.",
sc->sc_name, (intmax_t)corsize,
(intmax_t)coroff);
coroff = -1;
corsize = 0;
}
bcopy(srcdata + sc->sc_alen, dstdata,
data_secsize);
}
srcdata += encr_secsize;
dstdata += data_secsize;
auth += sc->sc_alen;
}
/* Report previous corruption if there was one. */
if (coroff != -1) {
G_ELI_DEBUG(0, "%s: %jd bytes corrupted at offset %jd.",
sc->sc_name, (intmax_t)corsize, (intmax_t)coroff);
}
}
free(bp->bio_driver2, M_ELI);
bp->bio_driver2 = NULL;
if (bp->bio_error != 0) {
if (bp->bio_error == -1)
bp->bio_error = EINVAL;
else {
G_ELI_LOGREQ(0, bp,
"Crypto READ request failed (error=%d).",
bp->bio_error);
}
bp->bio_completed = 0;
}
/*
* Read is finished, send it up.
*/
g_io_deliver(bp, bp->bio_error);
return (0);
}
/*
* The function is called after data encryption.
*
* g_eli_start -> g_eli_auth_run -> G_ELI_AUTH_WRITE_DONE -> g_io_request -> g_eli_write_done -> g_io_deliver
*/
static int
g_eli_auth_write_done(struct cryptop *crp)
{
struct g_eli_softc *sc;
struct g_consumer *cp;
struct bio *bp, *cbp, *cbp2;
u_int nsec;
if (crp->crp_etype == EAGAIN) {
if (g_eli_crypto_rerun(crp) == 0)
return (0);
}
bp = (struct bio *)crp->crp_opaque;
bp->bio_inbed++;
if (crp->crp_etype == 0) {
G_ELI_DEBUG(3, "Crypto WRITE request done (%d/%d).",
bp->bio_inbed, bp->bio_children);
} else {
G_ELI_DEBUG(1, "Crypto WRITE request failed (%d/%d) error=%d.",
bp->bio_inbed, bp->bio_children, crp->crp_etype);
if (bp->bio_error == 0)
bp->bio_error = crp->crp_etype;
}
/*
* All sectors are already encrypted?
*/
if (bp->bio_inbed < bp->bio_children)
return (0);
if (bp->bio_error != 0) {
G_ELI_LOGREQ(0, bp, "Crypto WRITE request failed (error=%d).",
bp->bio_error);
free(bp->bio_driver2, M_ELI);
bp->bio_driver2 = NULL;
cbp = bp->bio_driver1;
bp->bio_driver1 = NULL;
g_destroy_bio(cbp);
g_io_deliver(bp, bp->bio_error);
return (0);
}
sc = bp->bio_to->geom->softc;
cp = LIST_FIRST(&sc->sc_geom->consumer);
cbp = bp->bio_driver1;
bp->bio_driver1 = NULL;
cbp->bio_to = cp->provider;
cbp->bio_done = g_eli_write_done;
/* Number of sectors from decrypted provider, eg. 1. */
nsec = bp->bio_length / bp->bio_to->sectorsize;
/* Number of sectors from encrypted provider, eg. 9. */
nsec = (nsec * sc->sc_bytes_per_sector) / cp->provider->sectorsize;
cbp->bio_length = cp->provider->sectorsize * nsec;
cbp->bio_offset = (bp->bio_offset / bp->bio_to->sectorsize) * sc->sc_bytes_per_sector;
cbp->bio_data = bp->bio_driver2;
/*
* We write more than what is requested, so we have to be ready to write
* more than MAXPHYS.
*/
cbp2 = NULL;
if (cbp->bio_length > MAXPHYS) {
cbp2 = g_duplicate_bio(bp);
cbp2->bio_length = cbp->bio_length - MAXPHYS;
cbp2->bio_data = cbp->bio_data + MAXPHYS;
cbp2->bio_offset = cbp->bio_offset + MAXPHYS;
cbp2->bio_to = cp->provider;
cbp2->bio_done = g_eli_write_done;
cbp->bio_length = MAXPHYS;
}
/*
* Send encrypted data to the provider.
*/
G_ELI_LOGREQ(2, cbp, "Sending request.");
bp->bio_inbed = 0;
bp->bio_children = (cbp2 != NULL ? 2 : 1);
g_io_request(cbp, cp);
if (cbp2 != NULL) {
G_ELI_LOGREQ(2, cbp2, "Sending request.");
g_io_request(cbp2, cp);
}
return (0);
}
void
g_eli_auth_read(struct g_eli_softc *sc, struct bio *bp)
{
struct g_consumer *cp;
struct bio *cbp, *cbp2;
size_t size;
off_t nsec;
bp->bio_pflags = 0;
cp = LIST_FIRST(&sc->sc_geom->consumer);
cbp = bp->bio_driver1;
bp->bio_driver1 = NULL;
cbp->bio_to = cp->provider;
cbp->bio_done = g_eli_read_done;
/* Number of sectors from decrypted provider, eg. 1. */
nsec = bp->bio_length / bp->bio_to->sectorsize;
/* Number of sectors from encrypted provider, eg. 9. */
nsec = (nsec * sc->sc_bytes_per_sector) / cp->provider->sectorsize;
cbp->bio_length = cp->provider->sectorsize * nsec;
size = cbp->bio_length;
size += sc->sc_alen * nsec;
size += sizeof(struct cryptop) * nsec;
size += sizeof(struct cryptodesc) * nsec * 2;
size += G_ELI_AUTH_SECKEYLEN * nsec;
size += sizeof(struct uio) * nsec;
size += sizeof(struct iovec) * nsec;
cbp->bio_offset = (bp->bio_offset / bp->bio_to->sectorsize) * sc->sc_bytes_per_sector;
bp->bio_driver2 = malloc(size, M_ELI, M_WAITOK);
cbp->bio_data = bp->bio_driver2;
/*
* We read more than what is requested, so we have to be ready to read
* more than MAXPHYS.
*/
cbp2 = NULL;
if (cbp->bio_length > MAXPHYS) {
cbp2 = g_duplicate_bio(bp);
cbp2->bio_length = cbp->bio_length - MAXPHYS;
cbp2->bio_data = cbp->bio_data + MAXPHYS;
cbp2->bio_offset = cbp->bio_offset + MAXPHYS;
cbp2->bio_to = cp->provider;
cbp2->bio_done = g_eli_read_done;
cbp->bio_length = MAXPHYS;
}
/*
* Read encrypted data from provider.
*/
G_ELI_LOGREQ(2, cbp, "Sending request.");
g_io_request(cbp, cp);
if (cbp2 != NULL) {
G_ELI_LOGREQ(2, cbp2, "Sending request.");
g_io_request(cbp2, cp);
}
}
/*
* This is the main function responsible for cryptography (ie. communication
* with crypto(9) subsystem).
*/
void
g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp)
{
struct g_eli_softc *sc;
struct cryptop *crp;
struct cryptodesc *crde, *crda;
struct uio *uio;
struct iovec *iov;
u_int i, lsec, nsec, data_secsize, decr_secsize, encr_secsize;
off_t dstoff;
int err, error;
u_char *p, *data, *auth, *authkey, *plaindata;
G_ELI_LOGREQ(3, bp, "%s", __func__);
bp->bio_pflags = wr->w_number;
sc = wr->w_softc;
/* Sectorsize of decrypted provider eg. 4096. */
decr_secsize = bp->bio_to->sectorsize;
/* The real sectorsize of encrypted provider, eg. 512. */
encr_secsize = LIST_FIRST(&sc->sc_geom->consumer)->provider->sectorsize;
/* Number of data bytes in one encrypted sector, eg. 480. */
data_secsize = sc->sc_data_per_sector;
/* Number of sectors from decrypted provider, eg. 2. */
nsec = bp->bio_length / decr_secsize;
/* Number of sectors from encrypted provider, eg. 18. */
nsec = (nsec * sc->sc_bytes_per_sector) / encr_secsize;
/* Last sector number in every big sector, eg. 9. */
lsec = sc->sc_bytes_per_sector / encr_secsize;
/* Destination offset, used for IV generation. */
dstoff = (bp->bio_offset / bp->bio_to->sectorsize) * sc->sc_bytes_per_sector;
auth = NULL; /* Silence compiler warning. */
plaindata = bp->bio_data;
if (bp->bio_cmd == BIO_READ) {
data = bp->bio_driver2;
auth = data + encr_secsize * nsec;
p = auth + sc->sc_alen * nsec;
} else {
size_t size;
size = encr_secsize * nsec;
size += sizeof(*crp) * nsec;
size += sizeof(*crde) * nsec;
size += sizeof(*crda) * nsec;
size += G_ELI_AUTH_SECKEYLEN * nsec;
size += sizeof(*uio) * nsec;
size += sizeof(*iov) * nsec;
data = malloc(size, M_ELI, M_WAITOK);
bp->bio_driver2 = data;
p = data + encr_secsize * nsec;
}
bp->bio_inbed = 0;
bp->bio_children = nsec;
error = 0;
for (i = 1; i <= nsec; i++, dstoff += encr_secsize) {
crp = (struct cryptop *)p; p += sizeof(*crp);
crde = (struct cryptodesc *)p; p += sizeof(*crde);
crda = (struct cryptodesc *)p; p += sizeof(*crda);
authkey = (u_char *)p; p += G_ELI_AUTH_SECKEYLEN;
uio = (struct uio *)p; p += sizeof(*uio);
iov = (struct iovec *)p; p += sizeof(*iov);
data_secsize = sc->sc_data_per_sector;
if ((i % lsec) == 0)
data_secsize = decr_secsize % data_secsize;
if (bp->bio_cmd == BIO_READ) {
/* Remember read HMAC. */
bcopy(data, auth, sc->sc_alen);
auth += sc->sc_alen;
/* TODO: bzero(9) can be commented out later. */
bzero(data, sc->sc_alen);
} else {
bcopy(plaindata, data + sc->sc_alen, data_secsize);
plaindata += data_secsize;
}
iov->iov_len = sc->sc_alen + data_secsize;
iov->iov_base = data;
data += encr_secsize;
uio->uio_iov = iov;
uio->uio_iovcnt = 1;
uio->uio_segflg = UIO_SYSSPACE;
uio->uio_resid = iov->iov_len;
crp->crp_sid = wr->w_sid;
crp->crp_ilen = uio->uio_resid;
crp->crp_olen = data_secsize;
crp->crp_opaque = (void *)bp;
crp->crp_buf = (void *)uio;
crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
if (g_eli_batch)
crp->crp_flags |= CRYPTO_F_BATCH;
if (bp->bio_cmd == BIO_WRITE) {
crp->crp_callback = g_eli_auth_write_done;
crp->crp_desc = crde;
crde->crd_next = crda;
crda->crd_next = NULL;
} else {
crp->crp_callback = g_eli_auth_read_done;
crp->crp_desc = crda;
crda->crd_next = crde;
crde->crd_next = NULL;
}
crde->crd_skip = sc->sc_alen;
crde->crd_len = data_secsize;
crde->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
if (bp->bio_cmd == BIO_WRITE)
crde->crd_flags |= CRD_F_ENCRYPT;
crde->crd_alg = sc->sc_ealgo;
crde->crd_key = sc->sc_ekey;
crde->crd_klen = sc->sc_ekeylen;
g_eli_crypto_ivgen(sc, dstoff, crde->crd_iv,
sizeof(crde->crd_iv));
crda->crd_skip = sc->sc_alen;
crda->crd_len = data_secsize;
crda->crd_inject = 0;
crda->crd_flags = CRD_F_KEY_EXPLICIT;
crda->crd_alg = sc->sc_aalgo;
g_eli_auth_keygen(sc, dstoff, authkey);
crda->crd_key = authkey;
crda->crd_klen = G_ELI_AUTH_SECKEYLEN * 8;
crp->crp_etype = 0;
err = crypto_dispatch(crp);
if (err != 0 && error == 0)
error = err;
}
if (bp->bio_error == 0)
bp->bio_error = error;
}

View File

@ -0,0 +1,9 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../dev/stge
KMOD= if_stge
SRCS= if_stge.c device_if.h bus_if.h pci_if.h
SRCS+= miibus_if.h
.include <bsd.kmod.mk>

84
usr.sbin/sade/globals.c Normal file
View File

@ -0,0 +1,84 @@
/*
* $FreeBSD$
*
* Copyright (c) 1995
* Jordan Hubbard. 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,
* verbatim and that no modifications are made prior to this
* point in the file.
* 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 JORDAN HUBBARD ``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 JORDAN HUBBARD OR HIS PETS 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, LIFE 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 "sade.h"
/*
* Various global variables and an initialization hook to set them to
* whatever values we feel are appropriate.
*/
int DebugFD; /* Where diagnostic output goes */
Boolean Fake; /* Only pretend to be useful */
Boolean DialogActive; /* Is libdialog initialized? */
Boolean ColorDisplay; /* Are we on a color display? */
Boolean OnVTY; /* Are we on a VTY? */
Boolean Restarting; /* Are we restarting sysinstall? */
Variable *VarHead; /* The head of the variable chain */
int BootMgr; /* Which boot manager we're using */
int StatusLine; /* Where to stick our status messages */
jmp_buf BailOut; /* Beam me up, scotty! The natives are pissed! */
Chunk *HomeChunk;
Chunk *RootChunk;
Chunk *SwapChunk;
Chunk *TmpChunk;
Chunk *UsrChunk;
Chunk *VarChunk;
#ifdef __ia64__
Chunk *EfiChunk;
#endif
/*
* Yes, I know some of these are already automatically initialized as
* globals. I simply find it clearer to set everything explicitly.
*/
void
globalsInit(void)
{
DebugFD = -1;
ColorDisplay = FALSE;
Fake = FALSE;
Restarting = FALSE;
OnVTY = FALSE;
DialogActive = FALSE;
VarHead = NULL;
HomeChunk = NULL;
RootChunk = NULL;
SwapChunk = NULL;
TmpChunk = NULL;
UsrChunk = NULL;
VarChunk = NULL;
#ifdef __ia64__
EfiChunk = NULL;
#endif
}

55
usr.sbin/sade/list.h Normal file
View File

@ -0,0 +1,55 @@
/*
* $FreeBSD$
*
* Copyright (c) 1997 FreeBSD, Inc.
* 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,
* verbatim and that no modifications are made prior to this
* point in the file.
* 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 PAUL TRAINA ``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 PAUL TRAINA OR HIS KILLER RATS 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, LIFE 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.
*
*/
/* The structure */
typedef struct _qelement {
struct _qelement *q_forw;
struct _qelement *q_back;
} qelement;
#define INITQUE(Xhead) { \
(Xhead).q_forw = &(Xhead); \
(Xhead).q_back = &(Xhead); \
}
#define EMPTYQUE(Xhead) \
((Xhead).q_forw == &(Xhead))
#define INSQUEUE(elem, pred) { \
register qelement *Xe = (qelement *) (elem); \
register qelement *Xp = (qelement *) (pred); \
Xp->q_forw = (Xe->q_forw = (Xe->q_back = Xp)->q_forw)->q_back = Xe; \
}
#define REMQUE(elem) { \
register qelement *Xe = (qelement *) (elem); \
(Xe->q_back->q_forw = Xe->q_forw)->q_back = Xe->q_back; \
}

200
usr.sbin/sade/wizard.c Normal file
View File

@ -0,0 +1,200 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $FreeBSD$
*/
#include "sade.h"
#include <fcntl.h>
#include <err.h>
#include <libdisk.h>
static int
scan_block(int fd, daddr_t block)
{
u_char foo[512];
if (-1 == lseek(fd,block * 512,SEEK_SET))
err(1,"lseek");
if (512 != read(fd,foo, 512))
return 1;
return 0;
}
static void
Scan_Disk(Disk *d)
{
char device[64];
u_long l;
int i,j,fd;
strcpy(device,"/dev/");
strcat(device,d->name);
fd = open(device,O_RDWR);
if (fd < 0) {
msgWarn("open(%s) failed", device);
return;
}
for(i=-1,l=0;;l++) {
j = scan_block(fd,l);
if (j != i) {
if (i == -1) {
printf("%c: %lu.",j ? 'B' : 'G', l);
fflush(stdout);
} else if (i == 0) {
printf(".%lu\nB: %lu.",l-1,l);
fflush(stdout);
} else {
printf(".%lu\nG: %lu.",l-1,l);
fflush(stdout);
}
i = j;
}
}
close(fd);
}
void
slice_wizard(Disk *d)
{
Disk *db;
char myprompt[BUFSIZ];
char input[BUFSIZ];
char *p,*q=0;
char **cp,*cmds[200];
int ncmd,i;
systemSuspendDialog();
sprintf(myprompt,"%s> ", d->name);
while(1) {
printf("--==##==--\n");
Debug_Disk(d);
p = CheckRules(d);
if (p) {
printf("%s",p);
free(p);
}
printf("%s", myprompt);
fflush(stdout);
q = p = fgets(input,sizeof(input),stdin);
if(!p)
break;
for(cp = cmds; (*cp = strsep(&p, " \t\n")) != NULL;)
if (**cp != '\0')
cp++;
ncmd = cp - cmds;
if(!ncmd)
continue;
if (!strcasecmp(*cmds,"quit")) { break; }
if (!strcasecmp(*cmds,"exit")) { break; }
if (!strcasecmp(*cmds,"q")) { break; }
if (!strcasecmp(*cmds,"x")) { break; }
if (!strcasecmp(*cmds,"delete") && ncmd == 2) {
printf("delete = %d\n",
Delete_Chunk(d,
(struct chunk *)strtol(cmds[1],0,0)));
continue;
}
if (!strcasecmp(*cmds,"allfreebsd")) {
All_FreeBSD(d, 0);
continue;
}
if (!strcasecmp(*cmds,"dedicate")) {
All_FreeBSD(d, 1);
continue;
}
if (!strcasecmp(*cmds,"bios") && ncmd == 4) {
Set_Bios_Geom(d,
strtol(cmds[1],0,0),
strtol(cmds[2],0,0),
strtol(cmds[3],0,0));
continue;
}
if (!strcasecmp(*cmds,"list")) {
cp = Disk_Names();
printf("Disks:");
for(i=0;cp[i];i++) {
printf(" %s",cp[i]);
free(cp[i]);
}
free(cp);
continue;
}
#ifdef PC98
if (!strcasecmp(*cmds,"create") && ncmd == 7) {
printf("Create=%d\n",
Create_Chunk(d,
strtol(cmds[1],0,0),
strtol(cmds[2],0,0),
strtol(cmds[3],0,0),
strtol(cmds[4],0,0),
strtol(cmds[5],0,0),
cmds[6]));
continue;
}
#else
if (!strcasecmp(*cmds,"create") && ncmd == 6) {
printf("Create=%d\n",
Create_Chunk(d,
strtol(cmds[1],0,0),
strtol(cmds[2],0,0),
strtol(cmds[3],0,0),
strtol(cmds[4],0,0),
strtol(cmds[5],0,0), ""));
continue;
}
#endif
if (!strcasecmp(*cmds,"read")) {
db = d;
if (ncmd > 1)
d = Open_Disk(cmds[1]);
else
d = Open_Disk(d->name);
if (d)
Free_Disk(db);
else
d = db;
continue;
}
if (!strcasecmp(*cmds,"scan")) {
Scan_Disk(d);
continue;
}
if (!strcasecmp(*cmds,"write")) {
printf("Write=%d\n",
Fake ? 0 : Write_Disk(d));
q = strdup(d->name);
Free_Disk(d);
d = Open_Disk(q);
continue;
}
if (strcasecmp(*cmds,"help"))
printf("\007ERROR\n");
printf("CMDS:\n");
printf("allfreebsd\t\t");
printf("dedicate\t\t");
printf("bios cyl hd sect\n");
printf("collapse [pointer]\t\t");
#ifdef PC98
printf("create offset size enum subtype flags name\n");
#else
printf("create offset size enum subtype flags\n");
#endif
printf("subtype(part): swap=1, ffs=7\t\t");
printf("delete pointer\n");
printf("list\t\t");
printf("quit\n");
printf("read [disk]\t\t");
printf("scan\n");
printf("write\t\t");
printf("\n");
}
systemResumeDialog();
}