Merge ^/head r279163 through r279308.
This commit is contained in:
commit
0d56a8cba1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/clang360-import/; revision=279309
@ -1222,6 +1222,8 @@ legacy:
|
||||
#
|
||||
# bootstrap-tools: Build tools needed for compatibility
|
||||
#
|
||||
_bt= _bootstrap-tools
|
||||
|
||||
.if ${MK_GAMES} != "no"
|
||||
_strfile= games/fortune/strfile
|
||||
.endif
|
||||
@ -1245,6 +1247,8 @@ _sed= usr.bin/sed
|
||||
.if ${BOOTSTRAPPING} < 1000002
|
||||
_m4= lib/libohash \
|
||||
usr.bin/m4
|
||||
|
||||
${_bt}-usr.bin/m4: ${_bt}-lib/libohash
|
||||
.endif
|
||||
|
||||
.if ${BOOTSTRAPPING} < 1000014
|
||||
@ -1254,6 +1258,8 @@ _crunch= usr.sbin/crunch
|
||||
.if ${BOOTSTRAPPING} < 1000026
|
||||
_nmtree= lib/libnetbsd \
|
||||
usr.sbin/nmtree
|
||||
|
||||
${_bt}-usr.sbin/nmtree: ${_bt}-lib/libnetbsd
|
||||
.endif
|
||||
|
||||
.if ${BOOTSTRAPPING} < 1000027
|
||||
@ -1271,6 +1277,8 @@ _awk= usr.bin/awk
|
||||
.if ${BOOTSTRAPPING} < 1001506
|
||||
_yacc= lib/liby \
|
||||
usr.bin/yacc
|
||||
|
||||
${_bt}-usr.bin/yacc: ${_bt}-lib/liby
|
||||
.endif
|
||||
|
||||
.if ${MK_BSNMP} != "no"
|
||||
@ -1285,6 +1293,9 @@ _clang_tblgen= \
|
||||
lib/clang/libllvmtablegen \
|
||||
usr.bin/clang/tblgen \
|
||||
usr.bin/clang/clang-tblgen
|
||||
|
||||
${_bt}-usr.bin/clang/clang-tblgen: ${_bt}-lib/clang/libllvmtablegen ${_bt}-lib/clang/libllvmsupport
|
||||
${_bt}-usr.bin/clang/tblgen: ${_bt}-lib/clang/libllvmtablegen ${_bt}-lib/clang/libllvmsupport
|
||||
.endif
|
||||
|
||||
# ELF Tool Chain libraries are needed for ELF tools and dtrace tools.
|
||||
@ -1296,6 +1307,9 @@ _elftoolchain_libs= lib/libelf lib/libdwarf
|
||||
.if ${MK_CDDL} != "no"
|
||||
_dtrace_tools= cddl/usr.bin/sgsmsg cddl/lib/libctf cddl/usr.bin/ctfconvert \
|
||||
cddl/usr.bin/ctfmerge
|
||||
|
||||
${_bt}-cddl/usr.bin/ctfconvert: ${_bt}-lib/libelf ${_bt}-lib/libdwarf ${_bt}-cddl/lib/libctf
|
||||
${_bt}-cddl/usr.bin/ctfmerge: ${_bt}-lib/libelf ${_bt}-lib/libdwarf ${_bt}-cddl/lib/libctf
|
||||
.endif
|
||||
.endif
|
||||
|
||||
@ -1314,12 +1328,16 @@ _kerberos5_bootstrap_tools= \
|
||||
kerberos5/tools/asn1_compile \
|
||||
kerberos5/tools/slc \
|
||||
usr.bin/compile_et
|
||||
|
||||
${_bt}-kerberos5/tools/slc: ${_bt}-kerberos5/lib/libroken
|
||||
${_bt}-kerberos5/tools/asn1_compile: ${_bt}-kerberos5/lib/libroken
|
||||
.endif
|
||||
|
||||
bootstrap-tools: .PHONY
|
||||
|
||||
# Please document (add comment) why something is in 'bootstrap-tools'.
|
||||
# Try to bound the building of the bootstrap-tool to just the
|
||||
# FreeBSD versions that need the tool built at this stage of the build.
|
||||
bootstrap-tools: .MAKE
|
||||
.for _tool in \
|
||||
${_clang_tblgen} \
|
||||
${_kerberos5_bootstrap_tools} \
|
||||
@ -1345,12 +1363,15 @@ bootstrap-tools: .MAKE
|
||||
${_crunch} \
|
||||
${_nmtree} \
|
||||
${_vtfontcvt}
|
||||
${_bt}-${_tool}: .PHONY .MAKE
|
||||
${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \
|
||||
cd ${.CURDIR}/${_tool} && \
|
||||
${MAKE} DIRPRFX=${_tool}/ obj && \
|
||||
${MAKE} DIRPRFX=${_tool}/ depend && \
|
||||
${MAKE} DIRPRFX=${_tool}/ all && \
|
||||
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy install
|
||||
|
||||
bootstrap-tools: ${_bt}-${_tool}
|
||||
.endfor
|
||||
|
||||
#
|
||||
|
21
bin/sh/sh.1
21
bin/sh/sh.1
@ -32,7 +32,7 @@
|
||||
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 14, 2014
|
||||
.Dd February 22, 2015
|
||||
.Dt SH 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -1196,17 +1196,18 @@ command is implemented as a special built-in command.
|
||||
.Ss Variables and Parameters
|
||||
The shell maintains a set of parameters.
|
||||
A parameter
|
||||
denoted by a name is called a variable.
|
||||
denoted by a name
|
||||
(consisting solely
|
||||
of alphabetics, numerics, and underscores,
|
||||
and starting with an alphabetic or an underscore)
|
||||
is called a variable.
|
||||
When starting up,
|
||||
the shell turns all the environment variables into shell
|
||||
the shell turns all environment variables with valid names into shell
|
||||
variables.
|
||||
New variables can be set using the form
|
||||
.Pp
|
||||
.D1 Ar name Ns = Ns Ar value
|
||||
.Pp
|
||||
Variables set by the user must have a name consisting solely
|
||||
of alphabetics, numerics, and underscores.
|
||||
The first letter of a variable name must not be numeric.
|
||||
A parameter can also be denoted by a number
|
||||
or a special character as explained below.
|
||||
.Pp
|
||||
@ -1369,6 +1370,10 @@ This variable overrides the
|
||||
.Va MAIL
|
||||
setting.
|
||||
There is a maximum of 10 mailboxes that can be monitored at once.
|
||||
.It Va OPTIND
|
||||
The index of the next argument to be processed by
|
||||
.Ic getopts .
|
||||
This is initialized to 1 at startup.
|
||||
.It Va PATH
|
||||
The default search path for executables.
|
||||
See the
|
||||
@ -2297,6 +2302,8 @@ If an invalid option is encountered,
|
||||
is set to
|
||||
.Ql \&? .
|
||||
It returns a false value (1) when it encounters the end of the options.
|
||||
A new set of arguments may be parsed by assigning
|
||||
.Li OPTIND=1 .
|
||||
.It Ic hash Oo Fl rv Oc Op Ar command ...
|
||||
The shell maintains a hash table which remembers the locations of commands.
|
||||
With no arguments whatsoever, the
|
||||
@ -2771,7 +2778,7 @@ This is inherited by children of the shell, and is used in the history
|
||||
editing modes.
|
||||
.El
|
||||
.Pp
|
||||
Additionally, all environment variables are turned into shell variables
|
||||
Additionally, environment variables are turned into shell variables
|
||||
at startup,
|
||||
which may affect the shell as described under
|
||||
.Sx Special Variables .
|
||||
|
@ -2382,7 +2382,8 @@ find_line (bfd *abfd,
|
||||
else
|
||||
addr += section->vma;
|
||||
*filename_ptr = NULL;
|
||||
*functionname_ptr = NULL;
|
||||
if (!do_line)
|
||||
*functionname_ptr = NULL;
|
||||
*linenumber_ptr = 0;
|
||||
|
||||
if (! *pinfo)
|
||||
|
@ -4268,6 +4268,11 @@ const struct powerpc_opcode powerpc_opcodes[] = {
|
||||
{ "stvx", X(31, 231), X_MASK, PPCVEC, { VS, RA, RB } },
|
||||
{ "stvxl", X(31, 487), X_MASK, PPCVEC, { VS, RA, RB } },
|
||||
|
||||
/* New VSX opcodes in POWER ISA 2.06 */
|
||||
/* XXX: only enough opcodes for FreeBSD kernel, remove and replace with real info */
|
||||
{ "stxvw4x", X(31, 908), X_MASK, PPCVEC, { FRS, RA0, RB } },
|
||||
{ "lxvw4x", X(31, 780), X_MASK, PPCVEC, { FRT, RA0, RB } },
|
||||
|
||||
/* New load/store left/right index vector instructions that are in the Cell only. */
|
||||
{ "lvlx", X(31, 519), X_MASK, CELL, { VD, RA0, RB } },
|
||||
{ "lvlxl", X(31, 775), X_MASK, CELL, { VD, RA0, RB } },
|
||||
|
@ -1525,7 +1525,8 @@ print_lineno(struct sym_entry *ep, struct func_info_head *func_info,
|
||||
/* For function symbol, search the function line information list. */
|
||||
if ((ep->sym->st_info & 0xf) == STT_FUNC && func_info != NULL) {
|
||||
SLIST_FOREACH(func, func_info, entries) {
|
||||
if (!strcmp(ep->name, func->name) &&
|
||||
if (func->name != NULL &&
|
||||
!strcmp(ep->name, func->name) &&
|
||||
ep->sym->st_value >= func->lowpc &&
|
||||
ep->sym->st_value < func->highpc) {
|
||||
printf("\t%s:%" PRIu64, func->file, func->line);
|
||||
|
@ -796,6 +796,7 @@
|
||||
.ds doc-str-Lb-libmd Message Digest (MD4, MD5, etc.) Support Library (libmd, \-lmd)
|
||||
.ds doc-str-Lb-libmemstat Kernel Memory Allocator Statistics Library (libmemstat, \-lmemstat)
|
||||
.ds doc-str-Lb-libmenu Curses Menu Library (libmenu, \-lmenu)
|
||||
.ds doc-str-Lb-libmt Magnetic Tape Library (libmt, \-lmt)
|
||||
.ds doc-str-Lb-libnetgraph Netgraph User Library (libnetgraph, \-lnetgraph)
|
||||
.ds doc-str-Lb-libnetpgp Netpgp signing, verification, encryption and decryption (libnetpgp, \-lnetpgp)
|
||||
.ds doc-str-Lb-libossaudio OSS Audio Emulation Library (libossaudio, \-lossaudio)
|
||||
|
@ -218,15 +218,17 @@ static int64_t read_sleb128(dw_eh_ptr_t *data)
|
||||
static uint64_t read_value(char encoding, dw_eh_ptr_t *data)
|
||||
{
|
||||
enum dwarf_data_encoding type = get_encoding(encoding);
|
||||
uint64_t v;
|
||||
switch (type)
|
||||
{
|
||||
// Read fixed-length types
|
||||
#define READ(dwarf, type) \
|
||||
case dwarf:\
|
||||
v = static_cast<uint64_t>(*reinterpret_cast<type*>(*data));\
|
||||
*data += sizeof(type);\
|
||||
break;
|
||||
{\
|
||||
type t;\
|
||||
memcpy(&t, *data, sizeof t);\
|
||||
*data += sizeof t;\
|
||||
return static_cast<uint64_t>(t);\
|
||||
}
|
||||
READ(DW_EH_PE_udata2, uint16_t)
|
||||
READ(DW_EH_PE_udata4, uint32_t)
|
||||
READ(DW_EH_PE_udata8, uint64_t)
|
||||
@ -237,15 +239,11 @@ static uint64_t read_value(char encoding, dw_eh_ptr_t *data)
|
||||
#undef READ
|
||||
// Read variable-length types
|
||||
case DW_EH_PE_sleb128:
|
||||
v = read_sleb128(data);
|
||||
break;
|
||||
return read_sleb128(data);
|
||||
case DW_EH_PE_uleb128:
|
||||
v = read_uleb128(data);
|
||||
break;
|
||||
return read_uleb128(data);
|
||||
default: abort();
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
|
11
etc/Makefile
11
etc/Makefile
@ -158,16 +158,13 @@ BIN1+= regdomain.xml
|
||||
# -rwxr-xr-x root:wheel, for the new cron root:wheel
|
||||
BIN2= netstart pccard_ether rc.suspend rc.resume
|
||||
|
||||
MTREE= BSD.include.dist BSD.root.dist BSD.usr.dist BSD.var.dist
|
||||
MTREE= BSD.debug.dist BSD.include.dist BSD.root.dist BSD.usr.dist BSD.var.dist
|
||||
.if ${MK_TESTS} != "no"
|
||||
MTREE+= BSD.tests.dist
|
||||
.endif
|
||||
.if ${MK_SENDMAIL} != "no"
|
||||
MTREE+= BSD.sendmail.dist
|
||||
.endif
|
||||
.if ${MK_DEBUG_FILES} != "no"
|
||||
MTREE+= BSD.debug.dist
|
||||
.endif
|
||||
|
||||
PPPCNF= ppp.conf
|
||||
|
||||
@ -346,10 +343,8 @@ MTREE_CMD?= mtree
|
||||
MTREES= mtree/BSD.root.dist / \
|
||||
mtree/BSD.var.dist /var \
|
||||
mtree/BSD.usr.dist /usr \
|
||||
mtree/BSD.include.dist /usr/include
|
||||
.if ${MK_DEBUG_FILES} != "no"
|
||||
MTREES+= mtree/BSD.debug.dist /usr/lib
|
||||
.endif
|
||||
mtree/BSD.include.dist /usr/include \
|
||||
mtree/BSD.debug.dist /usr/lib
|
||||
.if ${MK_GROFF} != "no"
|
||||
MTREES+= mtree/BSD.groff.dist /usr
|
||||
.endif
|
||||
|
@ -70,6 +70,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
|
||||
libmd \
|
||||
${_libmilter} \
|
||||
${_libmp} \
|
||||
libmt \
|
||||
${_libnandfs} \
|
||||
libnetbsd \
|
||||
${_libnetgraph} \
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\" @(#)setmode.3 8.2 (Berkeley) 4/28/95
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 28, 1995
|
||||
.Dd February 22, 2015
|
||||
.Dt SETMODE 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -99,7 +99,20 @@ The
|
||||
function
|
||||
may fail and set errno for any of the errors specified for the library
|
||||
routine
|
||||
.Xr malloc 3 .
|
||||
.Xr malloc 3
|
||||
or
|
||||
.Xr strtol 3 .
|
||||
In addition,
|
||||
.Fn setmode
|
||||
will fail and set
|
||||
.Va errno
|
||||
to:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
The
|
||||
.Fa mode
|
||||
argument does not represent a valid mode.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr chmod 1 ,
|
||||
.Xr stat 2 ,
|
||||
|
@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@ -66,7 +68,7 @@ typedef struct bitcmd {
|
||||
#define CMD2_OBITS 0x08
|
||||
#define CMD2_UBITS 0x10
|
||||
|
||||
static BITCMD *addcmd(BITCMD *, int, int, int, u_int);
|
||||
static BITCMD *addcmd(BITCMD *, mode_t, mode_t, mode_t, mode_t);
|
||||
static void compress_mode(BITCMD *);
|
||||
#ifdef SETMODE_DEBUG
|
||||
static void dumpmode(BITCMD *);
|
||||
@ -151,33 +153,32 @@ common: if (set->cmd2 & CMD2_CLR) {
|
||||
BITCMD *newset; \
|
||||
setlen += SET_LEN_INCR; \
|
||||
newset = realloc(saveset, sizeof(BITCMD) * setlen); \
|
||||
if (!newset) { \
|
||||
if (saveset) \
|
||||
free(saveset); \
|
||||
saveset = NULL; \
|
||||
return (NULL); \
|
||||
} \
|
||||
if (newset == NULL) \
|
||||
goto out; \
|
||||
set = newset + (set - saveset); \
|
||||
saveset = newset; \
|
||||
endset = newset + (setlen - 2); \
|
||||
} \
|
||||
set = addcmd(set, (a), (b), (c), (d))
|
||||
set = addcmd(set, (mode_t)(a), (mode_t)(b), (mode_t)(c), (d))
|
||||
|
||||
#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
|
||||
void *
|
||||
setmode(const char *p)
|
||||
{
|
||||
int perm, who;
|
||||
int serrno;
|
||||
char op, *ep;
|
||||
BITCMD *set, *saveset, *endset;
|
||||
sigset_t sigset, sigoset;
|
||||
mode_t mask;
|
||||
int equalopdone=0, permXbits, setlen;
|
||||
mode_t mask, perm, permXbits, who;
|
||||
long perml;
|
||||
int equalopdone;
|
||||
int setlen;
|
||||
|
||||
if (!*p)
|
||||
if (!*p) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a copy of the mask for the permissions that are mask relative.
|
||||
@ -203,10 +204,17 @@ setmode(const char *p)
|
||||
* or illegal bits.
|
||||
*/
|
||||
if (isdigit((unsigned char)*p)) {
|
||||
errno = 0;
|
||||
perml = strtol(p, &ep, 8);
|
||||
if (*ep || perml < 0 || perml & ~(STANDARD_BITS|S_ISTXT)) {
|
||||
free(saveset);
|
||||
return (NULL);
|
||||
if (*ep) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (errno == ERANGE && (perml == LONG_MAX || perml == LONG_MIN))
|
||||
goto out;
|
||||
if (perml & ~(STANDARD_BITS|S_ISTXT)) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
perm = (mode_t)perml;
|
||||
ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
|
||||
@ -218,6 +226,7 @@ setmode(const char *p)
|
||||
* Build list of structures to set/clear/copy bits as described by
|
||||
* each clause of the symbolic mode.
|
||||
*/
|
||||
equalopdone = 0;
|
||||
for (;;) {
|
||||
/* First, find out which bits might be modified. */
|
||||
for (who = 0;; ++p) {
|
||||
@ -240,8 +249,8 @@ setmode(const char *p)
|
||||
}
|
||||
|
||||
getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
|
||||
free(saveset);
|
||||
return (NULL);
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (op == '=')
|
||||
equalopdone = 0;
|
||||
@ -330,10 +339,15 @@ apply: if (!*p)
|
||||
dumpmode(saveset);
|
||||
#endif
|
||||
return (saveset);
|
||||
out:
|
||||
serrno = errno;
|
||||
free(saveset);
|
||||
errno = serrno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BITCMD *
|
||||
addcmd(BITCMD *set, int op, int who, int oparg, u_int mask)
|
||||
addcmd(BITCMD *set, mode_t op, mode_t who, mode_t oparg, mode_t mask)
|
||||
{
|
||||
switch (op) {
|
||||
case '=':
|
||||
|
@ -54,9 +54,8 @@
|
||||
.Fn setstate "char *state"
|
||||
.Sh DESCRIPTION
|
||||
.Bf -symbolic
|
||||
The functions described in this manual page are not cryptographically
|
||||
secure.
|
||||
Cryptographic applications should use
|
||||
The functions described in this manual page are not secure.
|
||||
Applications which require unpredictable random numbers should use
|
||||
.Xr arc4random 3
|
||||
instead.
|
||||
.Ef
|
||||
|
13
lib/libmt/Makefile
Normal file
13
lib/libmt/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
# $FreeBSD$
|
||||
|
||||
LIB= mt
|
||||
SHLIBDIR?= /lib
|
||||
SRCS= mtlib.c
|
||||
INCS= mtlib.h
|
||||
|
||||
DPADD= ${LIBSBUF}
|
||||
LDADD= -lsbuf
|
||||
|
||||
MAN= mt.3
|
||||
|
||||
.include <bsd.lib.mk>
|
455
lib/libmt/mt.3
Normal file
455
lib/libmt/mt.3
Normal file
@ -0,0 +1,455 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2013, 2015 Spectra Logic Corporation
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions, and the following disclaimer,
|
||||
.\" without modification.
|
||||
.\" 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
.\" substantially similar to the "NO WARRANTY" disclaimer below
|
||||
.\" ("Disclaimer") and any redistribution must be conditioned upon
|
||||
.\" including a substantially similar Disclaimer requirement for further
|
||||
.\" binary redistribution.
|
||||
.\"
|
||||
.\" NO WARRANTY
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
.\"
|
||||
.\" Authors: Ken Merry (Spectra Logic Corporation)
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 13, 2015
|
||||
.Dt MT 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm
|
||||
.Nm mt_start_element ,
|
||||
.Nm mt_end_element ,
|
||||
.Nm mt_char_handler ,
|
||||
.Nm mt_status_tree_sbuf ,
|
||||
.Nm mt_status_tree_print ,
|
||||
.Nm mt_status_entry_free ,
|
||||
.Nm mt_status_free ,
|
||||
.Nm mt_entry_sbuf ,
|
||||
.Nm mt_param_parent_print ,
|
||||
.Nm mt_param_entry_print ,
|
||||
.Nm mt_protect_print ,
|
||||
.Nm mt_param_list ,
|
||||
.Nm mt_density_name ,
|
||||
.Nm mt_density_bp ,
|
||||
.Nm mt_density_num ,
|
||||
.Nm mt_get_xml_str ,
|
||||
.Nm mt_get_status
|
||||
.Nd Magnetic Tape library
|
||||
.Sh LIBRARY
|
||||
.Lb libmt
|
||||
.Sh SYNOPSIS
|
||||
.In sys/sbuf.h
|
||||
.In bsdxml.h
|
||||
.In mtlib.h
|
||||
.Ft void
|
||||
.Fo mt_start_element
|
||||
.Fa "void *user_data"
|
||||
.Fa "const char *name"
|
||||
.Fa "const char **attr"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mt_end_element
|
||||
.Fa "void *user_data"
|
||||
.Fa "const char *name"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mt_char_handler
|
||||
.Fa "void *user_data"
|
||||
.Fa "const XML_Char *str"
|
||||
.Fa "int len"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mt_status_tree_sbuf
|
||||
.Fa "struct sbuf *sb"
|
||||
.Fa "struct mt_status_entry *entry"
|
||||
.Fa "int indent"
|
||||
.Fa "void (*sbuf_func)(struct sbuf *sb, struct mt_status_entry *entry, void *arg)"
|
||||
.Fa "void *arg"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mt_status_tree_print
|
||||
.Fa "struct mt_status_entry *entry"
|
||||
.Fa "int indent"
|
||||
.Fa "void (*print_func)(struct mt_status_entry *entry, void *arg)"
|
||||
.Fa "void *arg"
|
||||
.Fc
|
||||
.Ft "struct mt_status_entry *"
|
||||
.Fo mt_entry_find
|
||||
.Fa "struct mt_status_entry *entry"
|
||||
.Fa "char *name"
|
||||
.Fc
|
||||
.Ft "struct mt_status_entry *"
|
||||
.Fo mt_status_entry_find
|
||||
.Fa "struct mt_status_data *status_data"
|
||||
.Fa "char *name"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mt_status_entry_free
|
||||
.Fa "struct mt_status_entry *entry)"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mt_status_free
|
||||
.Fa "struct mt_status_data *status_data"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mt_entry_sbuf
|
||||
.Fa "struct sbuf *sb"
|
||||
.Fa "struct mt_status_entry *entry"
|
||||
.Fa "char *fmt"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mt_param_parent_sbuf
|
||||
.Fa "struct sbuf *sb"
|
||||
.Fa "struct mt_status_entry *entry"
|
||||
.Fa "struct mt_print_params *print_params"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mt_param_parent_print
|
||||
.Fa "struct mt_status_entry *entry"
|
||||
.Fa "struct mt_print_params *print_params"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mt_param_entry_sbuf
|
||||
.Fa "struct sbuf *sb"
|
||||
.Fa "struct mt_status_entry *entry"
|
||||
.Fa "void *arg"
|
||||
.Fc
|
||||
.Ft void
|
||||
.Fo mt_param_entry_print
|
||||
.Fa "struct mt_status_entry *entry"
|
||||
.Fa "void *arg"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo mt_protect_print
|
||||
.Fa "struct mt_status_data *status_data"
|
||||
.Fa "int verbose"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo mt_param_list
|
||||
.Fa "struct mt_status_data *status_data"
|
||||
.Fa "char *param_name"
|
||||
.Fa "int quiet"
|
||||
.Fc
|
||||
.Ft "const char *"
|
||||
.Fo mt_density_name
|
||||
.Fa "int density_num"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo mt_density_bp
|
||||
.Fa "int density_num"
|
||||
.Fa "int bpi"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo mt_density_num
|
||||
.Fa "const char *density_name"
|
||||
.Fc
|
||||
.Ft int
|
||||
.Fo mt_get_status
|
||||
.Fa "char *xml_str"
|
||||
.Fa "struct mt_status_data *status_data"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
The MT library consists of a number of functions designed to aid in
|
||||
interacting with the
|
||||
.Xr sa 4
|
||||
driver.
|
||||
The
|
||||
.Xr sa 4
|
||||
driver returns some status data as XML-formatted strings, and
|
||||
the primary purpose of this library is to make it easier for the
|
||||
software developer to parse those strings and extract the status values.
|
||||
.Pp
|
||||
The
|
||||
.Fn mt_start_element ,
|
||||
.Fn mt_end_element ,
|
||||
and
|
||||
.Fn mt_char_handler
|
||||
functions are designed to work with the
|
||||
.Xr libbbsdxml 3
|
||||
library, which is an XML parsing library.
|
||||
The user data for the XML parser should be set with
|
||||
.Fn XML_SetUserData
|
||||
to a zeroed struct
|
||||
mt_status_data with the entries list initialized.
|
||||
The element handlers for the XML parser should be set to
|
||||
.Fn mt_start_element
|
||||
and
|
||||
.Fn mt_end_element
|
||||
with
|
||||
.Fn XML_SetElementHandler .
|
||||
The character data handler should be set to
|
||||
.Fn mt_char_handler
|
||||
with the
|
||||
.Fn XML_SetCharacterDataHandler
|
||||
function.
|
||||
The error member of the status_data structure will be set to 0 if parsing
|
||||
is successful, and non-zero if parsing failed.
|
||||
In the event of a failure, the error_str member will contain an error
|
||||
message describing the failure.
|
||||
These functions will build a tree of tape driver status data that can be
|
||||
searched and printed using the other functions in this library.
|
||||
.Pp
|
||||
.Fn mt_status_tree_sbuf
|
||||
takes the root node of a tree of
|
||||
.Xr sa 4
|
||||
driver status information, and displays it in an
|
||||
.Xr sbuf 9 .
|
||||
The
|
||||
.Ar sb
|
||||
argument is the destination sbuf.
|
||||
The
|
||||
.Ar entry
|
||||
argument is the root of the tree.
|
||||
The
|
||||
.Ar indent
|
||||
argument is the number of characters to indent the output.
|
||||
Each recursive call to
|
||||
.Fn mt_status_tree_sbuf
|
||||
will have the indent level incremented by 2.
|
||||
The
|
||||
.Ar sbuf_func
|
||||
argument is for a user-supplied alternate printing function.
|
||||
If it is non-NULL, it will be called instead of the default output printing
|
||||
code.
|
||||
The
|
||||
.Ar arg
|
||||
argument is an argument for the
|
||||
.Ar sbuf_func
|
||||
function.
|
||||
.Pp
|
||||
The
|
||||
.Fn mt_status_tree_print
|
||||
function is the same as the
|
||||
.Fn mt_status_tree_sbuf
|
||||
function, except that the tree is printed to standard out instead of to a
|
||||
sbuf.
|
||||
.Pp
|
||||
The
|
||||
.Fn mt_entry_find
|
||||
function returns the first entry in the tree starting at
|
||||
.Ar entry
|
||||
that matches
|
||||
.Ar name .
|
||||
The supplied node name can be a single level name like "foo", or it can
|
||||
specify mulitple node names that must be matched, for instance "foo.bar.baz".
|
||||
In the case of a single level name, it will match any node beneath
|
||||
.Ar entry
|
||||
that matches
|
||||
.Ar name .
|
||||
In the case of a multi-level name like "foo.bar.baz", it will return the
|
||||
first entry named "baz" whose immediate parent is "bar" and where the
|
||||
parent of "bar" is named "foo".
|
||||
.Pp
|
||||
The
|
||||
.Fn mt_status_entry_find
|
||||
is the same as
|
||||
.Fn mt_entry_find ,
|
||||
except that it operates on the top level mt_status_data and all
|
||||
mt_status_entry nodes below it instead of just an mt_status_entry
|
||||
structure.
|
||||
.Pp
|
||||
The
|
||||
.Fn mt_status_entry_free
|
||||
function frees the tree of status data underneath
|
||||
.Ar entry .
|
||||
.Pp
|
||||
The
|
||||
.Fn mt_status_free
|
||||
function frees the tree of status data underneath
|
||||
.Ar status_data .
|
||||
.Pp
|
||||
The
|
||||
.Fn mt_entry_sbuf
|
||||
function prints
|
||||
.Ar entry
|
||||
to the supplied sbuf
|
||||
.Ar sb ,
|
||||
optionally using the
|
||||
.Xr printf 3
|
||||
format
|
||||
.Ar fmt .
|
||||
If
|
||||
.Ar fmt
|
||||
is NULL, then
|
||||
.Fn mt_entry_sbuf
|
||||
will render integer types in base 10 without special formatting and all
|
||||
other types as they were rendered in the XML.
|
||||
.Pp
|
||||
.Fn mt_param_parent_sbuf
|
||||
prints the parents of the given
|
||||
.Ar entry
|
||||
to the supplied sbuf
|
||||
.Ar sb
|
||||
subject to the print parameters
|
||||
.Ar print_params .
|
||||
The result will be formatted with a period between each level, like
|
||||
"foo.bar.baz".
|
||||
.Pp
|
||||
.Fn mt_param_parent_print
|
||||
is like
|
||||
.Fn mt_param_parent_sbuf
|
||||
except that it prints the results to standard output instead of an sbuf.
|
||||
.Pp
|
||||
.Fn mt_param_entry_sbuf
|
||||
prints the
|
||||
.Ar entry
|
||||
to the given sbuf
|
||||
.Ar sb .
|
||||
The argument
|
||||
.Ar arg
|
||||
is a pointer to struct mt_print_params, which allows the caller to control
|
||||
the printing output.
|
||||
This function is intended to be supplied as an argument to
|
||||
.Fn mt_status_tree_sbuf .
|
||||
.Pp
|
||||
.Fn mt_param_entry_print
|
||||
is like
|
||||
.Fn mt_param_entry_sbuf
|
||||
except that it prints to standard output instead of an sbuf.
|
||||
It is intended to be used as an argument to
|
||||
.Fn mt_status_tree_print .
|
||||
.Pp
|
||||
.Fn mt_protect_print
|
||||
prints tape drive protection information from the supplied
|
||||
.Ar status_data
|
||||
beginning at the node name defined as the root node for protection data.
|
||||
If the
|
||||
.Ar verbose
|
||||
argument is non-zero, protection entry descriptions will be printed.
|
||||
If it is zero, protection entry descriptions will not be printed.
|
||||
.Pp
|
||||
.Fn mt_param_list
|
||||
prints tape driver parameters information from the supplied
|
||||
.Ar status_data .
|
||||
If the
|
||||
.Ar param_name
|
||||
is non-NULL, only the named parameter will be printed.
|
||||
If
|
||||
.Ar quiet
|
||||
is non-zero, parameter descriptions will be omitted in the output.
|
||||
.Pp
|
||||
.Fn mt_density_name
|
||||
Returns a text identifier for the supplied numeric
|
||||
.Ar density_num .
|
||||
The
|
||||
.Ar density_num
|
||||
should currently be a value between 0 and 255 inclusive, since that is the
|
||||
valid range for
|
||||
.Tn SCSI
|
||||
density code values.
|
||||
See below for notes on the return values.
|
||||
.Pp
|
||||
.Fn mt_density_bp
|
||||
Returns the bits per inch or bits per mm values for a given density entry
|
||||
specified by the
|
||||
.Ar density_num .
|
||||
If the
|
||||
.Ar bpi
|
||||
argument is non-zero, the bits per inch value is returned.
|
||||
Otherwise, the bits per mm value is returned.
|
||||
.Pp
|
||||
.Fn mt_density_num
|
||||
returns a numeric value for a text density description.
|
||||
It does a case-insensitive comparison of density names in the density table
|
||||
to the supplied density name.
|
||||
.Pp
|
||||
.Fn mt_get_xml_str
|
||||
gets the current XML status / parameter string from the sa(4) driver
|
||||
instance referenced by the open file descriptor
|
||||
.Ar mtfd .
|
||||
The
|
||||
.Xr mtio 4
|
||||
.Xr ioctl 2
|
||||
to be used is supplied as the
|
||||
.Ar cmd
|
||||
argument.
|
||||
Currently the
|
||||
.Fn mt_get_xml_str
|
||||
function will work with the
|
||||
.Dv MTIOCEXTGET
|
||||
and
|
||||
.Dv MTIOCPARAMGET
|
||||
ioctls.
|
||||
The supplied
|
||||
.Ar xml_str
|
||||
will be filled in with a pointer to the complete XML status string.
|
||||
Multiple calls to the given
|
||||
.Xr ioctl 2
|
||||
are made and more space is malloced until all of the XML string is fetched.
|
||||
The string returned in the
|
||||
.Ar xml_str
|
||||
argument should be freed when it is no longer in use.
|
||||
.Sh RETURN VALUES
|
||||
.Fn mt_entry_find
|
||||
returns the first matching entry, or NULL if it fails to find a match.
|
||||
.Pp
|
||||
.Fn mt_status_entry_find
|
||||
returns the first matching entry, or NULL if it fails to find a match.
|
||||
.Pp
|
||||
.Fn mt_protect_print
|
||||
Returns 0 for success, and non-zero for failure.
|
||||
.Fn mt_protect_print
|
||||
can only fail if it cannot find protection information in the supplied
|
||||
status data.
|
||||
.Pp
|
||||
.Fn mt_param_list
|
||||
Returns 0 for success and non-zero for failure.
|
||||
.Fn mt_param_list
|
||||
can only fail if it cannot find parameter information in the supplied
|
||||
status data.
|
||||
.Pp
|
||||
.Fn mt_density_name
|
||||
returns a text description of a numeric density.
|
||||
The special density value 0 is decoded as "default".
|
||||
The special density value 0x7f is decoded as "same".
|
||||
If the density is not known,
|
||||
.Fn mt_density_name
|
||||
will return "UNKNOWN".
|
||||
.Pp
|
||||
.Fn mt_density_bp
|
||||
returns the bits per inch value for the given density (if the
|
||||
.Ar bpi
|
||||
field is non-zero), the bits per mm value otherwise, or 0 if the supplied
|
||||
.Ar density_num
|
||||
is not in the density table or the table entry does not include bpi / bpmm
|
||||
values.
|
||||
.Pp
|
||||
.Fn mt_density_num
|
||||
returns a numeric density value between 0 and 255 for the supplied density
|
||||
name.
|
||||
It returns 0 if the density name is not recognized.
|
||||
.Pp
|
||||
.Fn mt_get_xml_str
|
||||
returns 0 for success, and -1 for failure.
|
||||
.Sh SEE ALSO
|
||||
.Xr mt 1 ,
|
||||
.Xr mtio 4 ,
|
||||
.Xr sa 4
|
||||
.Sh HISTORY
|
||||
The MT library first appeared in
|
||||
.Fx 10.1 .
|
||||
.Sh AUTHORS
|
||||
.An Ken Merry Aq ken@FreeBSD.org
|
||||
.Sh BUGS
|
||||
The library interface is not complete, and may change in the future.
|
||||
Application authors should not rely on the library interface to be
|
||||
consistent in the immediate future.
|
756
lib/libmt/mtlib.c
Normal file
756
lib/libmt/mtlib.c
Normal file
@ -0,0 +1,756 @@
|
||||
/*-
|
||||
* Copyright (c) 2013, 2014, 2015 Spectra Logic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*
|
||||
* Authors: Ken Merry (Spectra Logic Corporation)
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mtio.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/sbuf.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <bsdxml.h>
|
||||
#include <mtlib.h>
|
||||
|
||||
/*
|
||||
* Called at the start of each XML element, and includes the list of
|
||||
* attributes for the element.
|
||||
*/
|
||||
void
|
||||
mt_start_element(void *user_data, const char *name, const char **attr)
|
||||
{
|
||||
int i;
|
||||
struct mt_status_data *mtinfo;
|
||||
struct mt_status_entry *entry;
|
||||
|
||||
mtinfo = (struct mt_status_data *)user_data;
|
||||
|
||||
if (mtinfo->error != 0)
|
||||
return;
|
||||
|
||||
mtinfo->level++;
|
||||
if ((u_int)mtinfo->level >= (sizeof(mtinfo->cur_sb) /
|
||||
sizeof(mtinfo->cur_sb[0]))) {
|
||||
mtinfo->error = 1;
|
||||
snprintf(mtinfo->error_str, sizeof(mtinfo->error_str),
|
||||
"%s: too many nesting levels, %zd max", __func__,
|
||||
sizeof(mtinfo->cur_sb) / sizeof(mtinfo->cur_sb[0]));
|
||||
return;
|
||||
}
|
||||
|
||||
mtinfo->cur_sb[mtinfo->level] = sbuf_new_auto();
|
||||
if (mtinfo->cur_sb[mtinfo->level] == NULL) {
|
||||
mtinfo->error = 1;
|
||||
snprintf(mtinfo->error_str, sizeof(mtinfo->error_str),
|
||||
"%s: Unable to allocate sbuf", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
entry = malloc(sizeof(*entry));
|
||||
if (entry == NULL) {
|
||||
mtinfo->error = 1;
|
||||
snprintf(mtinfo->error_str, sizeof(mtinfo->error_str),
|
||||
"%s: unable to allocate %zd bytes", __func__,
|
||||
sizeof(*entry));
|
||||
return;
|
||||
}
|
||||
bzero(entry, sizeof(*entry));
|
||||
STAILQ_INIT(&entry->nv_list);
|
||||
STAILQ_INIT(&entry->child_entries);
|
||||
entry->entry_name = strdup(name);
|
||||
mtinfo->cur_entry[mtinfo->level] = entry;
|
||||
if (mtinfo->cur_entry[mtinfo->level - 1] == NULL) {
|
||||
STAILQ_INSERT_TAIL(&mtinfo->entries, entry, links);
|
||||
} else {
|
||||
STAILQ_INSERT_TAIL(
|
||||
&mtinfo->cur_entry[mtinfo->level - 1]->child_entries,
|
||||
entry, links);
|
||||
entry->parent = mtinfo->cur_entry[mtinfo->level - 1];
|
||||
}
|
||||
for (i = 0; attr[i] != NULL; i+=2) {
|
||||
struct mt_status_nv *nv;
|
||||
int need_nv;
|
||||
|
||||
need_nv = 0;
|
||||
|
||||
if (strcmp(attr[i], "size") == 0) {
|
||||
entry->size = strtoull(attr[i+1], NULL, 0);
|
||||
} else if (strcmp(attr[i], "type") == 0) {
|
||||
if (strcmp(attr[i+1], "int") == 0) {
|
||||
entry->var_type = MT_TYPE_INT;
|
||||
} else if (strcmp(attr[i+1], "uint") == 0) {
|
||||
entry->var_type = MT_TYPE_UINT;
|
||||
} else if (strcmp(attr[i+1], "str") == 0) {
|
||||
entry->var_type = MT_TYPE_STRING;
|
||||
} else if (strcmp(attr[i+1], "node") == 0) {
|
||||
entry->var_type = MT_TYPE_NODE;
|
||||
} else {
|
||||
need_nv = 1;
|
||||
}
|
||||
} else if (strcmp(attr[i], "fmt") == 0) {
|
||||
entry->fmt = strdup(attr[i+1]);
|
||||
} else if (strcmp(attr[i], "desc") == 0) {
|
||||
entry->desc = strdup(attr[i+1]);
|
||||
} else {
|
||||
need_nv = 1;
|
||||
}
|
||||
if (need_nv != 0) {
|
||||
nv = malloc(sizeof(*nv));
|
||||
if (nv == NULL) {
|
||||
mtinfo->error = 1;
|
||||
snprintf(mtinfo->error_str,
|
||||
sizeof(mtinfo->error_str),
|
||||
"%s: error allocating %zd bytes",
|
||||
__func__, sizeof(*nv));
|
||||
}
|
||||
bzero(nv, sizeof(*nv));
|
||||
nv->name = strdup(attr[i]);
|
||||
nv->value = strdup(attr[i+1]);
|
||||
STAILQ_INSERT_TAIL(&entry->nv_list, nv, links);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called on XML element close.
|
||||
*/
|
||||
void
|
||||
mt_end_element(void *user_data, const char *name)
|
||||
{
|
||||
struct mt_status_data *mtinfo;
|
||||
char *str;
|
||||
|
||||
mtinfo = (struct mt_status_data *)user_data;
|
||||
|
||||
if (mtinfo->error != 0)
|
||||
return;
|
||||
|
||||
if (mtinfo->cur_sb[mtinfo->level] == NULL) {
|
||||
mtinfo->error = 1;
|
||||
snprintf(mtinfo->error_str, sizeof(mtinfo->error_str),
|
||||
"%s: no valid sbuf at level %d (name %s)", __func__,
|
||||
mtinfo->level, name);
|
||||
return;
|
||||
}
|
||||
sbuf_finish(mtinfo->cur_sb[mtinfo->level]);
|
||||
str = strdup(sbuf_data(mtinfo->cur_sb[mtinfo->level]));
|
||||
if (str == NULL) {
|
||||
mtinfo->error = 1;
|
||||
snprintf(mtinfo->error_str, sizeof(mtinfo->error_str),
|
||||
"%s can't allocate %zd bytes for string", __func__,
|
||||
sbuf_len(mtinfo->cur_sb[mtinfo->level]));
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(str) == 0) {
|
||||
free(str);
|
||||
str = NULL;
|
||||
}
|
||||
if (str != NULL) {
|
||||
struct mt_status_entry *entry;
|
||||
|
||||
entry = mtinfo->cur_entry[mtinfo->level];
|
||||
switch(entry->var_type) {
|
||||
case MT_TYPE_INT:
|
||||
entry->value_signed = strtoll(str, NULL, 0);
|
||||
break;
|
||||
case MT_TYPE_UINT:
|
||||
entry->value_unsigned = strtoull(str, NULL, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mtinfo->cur_entry[mtinfo->level]->value = str;
|
||||
|
||||
sbuf_delete(mtinfo->cur_sb[mtinfo->level]);
|
||||
mtinfo->cur_sb[mtinfo->level] = NULL;
|
||||
mtinfo->cur_entry[mtinfo->level] = NULL;
|
||||
mtinfo->level--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to handle character strings in the current element.
|
||||
*/
|
||||
void
|
||||
mt_char_handler(void *user_data, const XML_Char *str, int len)
|
||||
{
|
||||
struct mt_status_data *mtinfo;
|
||||
|
||||
mtinfo = (struct mt_status_data *)user_data;
|
||||
if (mtinfo->error != 0)
|
||||
return;
|
||||
|
||||
sbuf_bcat(mtinfo->cur_sb[mtinfo->level], str, len);
|
||||
}
|
||||
|
||||
void
|
||||
mt_status_tree_sbuf(struct sbuf *sb, struct mt_status_entry *entry, int indent,
|
||||
void (*sbuf_func)(struct sbuf *sb, struct mt_status_entry *entry,
|
||||
void *arg), void *arg)
|
||||
{
|
||||
struct mt_status_nv *nv;
|
||||
struct mt_status_entry *entry2;
|
||||
|
||||
if (sbuf_func != NULL) {
|
||||
sbuf_func(sb, entry, arg);
|
||||
} else {
|
||||
sbuf_printf(sb, "%*sname: %s, value: %s, fmt: %s, size: %zd, "
|
||||
"type: %d, desc: %s\n", indent, "", entry->entry_name,
|
||||
entry->value, entry->fmt, entry->size, entry->var_type,
|
||||
entry->desc);
|
||||
STAILQ_FOREACH(nv, &entry->nv_list, links) {
|
||||
sbuf_printf(sb, "%*snv: name: %s, value: %s\n",
|
||||
indent + 1, "", nv->name, nv->value);
|
||||
}
|
||||
}
|
||||
|
||||
STAILQ_FOREACH(entry2, &entry->child_entries, links)
|
||||
mt_status_tree_sbuf(sb, entry2, indent + 2, sbuf_func, arg);
|
||||
}
|
||||
|
||||
void
|
||||
mt_status_tree_print(struct mt_status_entry *entry, int indent,
|
||||
void (*print_func)(struct mt_status_entry *entry, void *arg), void *arg)
|
||||
{
|
||||
|
||||
if (print_func != NULL) {
|
||||
struct mt_status_entry *entry2;
|
||||
|
||||
print_func(entry, arg);
|
||||
STAILQ_FOREACH(entry2, &entry->child_entries, links)
|
||||
mt_status_tree_print(entry2, indent + 2, print_func,
|
||||
arg);
|
||||
} else {
|
||||
struct sbuf *sb;
|
||||
|
||||
sb = sbuf_new_auto();
|
||||
if (sb == NULL)
|
||||
return;
|
||||
mt_status_tree_sbuf(sb, entry, indent, NULL, NULL);
|
||||
sbuf_finish(sb);
|
||||
|
||||
printf("%s", sbuf_data(sb));
|
||||
sbuf_delete(sb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a parameter name in the form "foo" or "foo.bar.baz", traverse the
|
||||
* tree looking for the parameter (the first case) or series of parameters
|
||||
* (second case).
|
||||
*/
|
||||
struct mt_status_entry *
|
||||
mt_entry_find(struct mt_status_entry *entry, char *name)
|
||||
{
|
||||
struct mt_status_entry *entry2;
|
||||
char *tmpname = NULL, *tmpname2 = NULL, *tmpstr = NULL;
|
||||
|
||||
tmpname = strdup(name);
|
||||
if (tmpname == NULL)
|
||||
goto bailout;
|
||||
|
||||
/* Save a pointer so we can free this later */
|
||||
tmpname2 = tmpname;
|
||||
|
||||
tmpstr = strsep(&tmpname, ".");
|
||||
|
||||
/*
|
||||
* Is this the entry we're looking for? Or do we have further
|
||||
* child entries that we need to grab?
|
||||
*/
|
||||
if (strcmp(entry->entry_name, tmpstr) == 0) {
|
||||
if (tmpname == NULL) {
|
||||
/*
|
||||
* There are no further child entries to find. We
|
||||
* have a complete match.
|
||||
*/
|
||||
free(tmpname2);
|
||||
return (entry);
|
||||
} else {
|
||||
/*
|
||||
* There are more child entries that we need to find.
|
||||
* Fall through to the recursive search off of this
|
||||
* entry, below. Use tmpname, which will contain
|
||||
* everything after the first period.
|
||||
*/
|
||||
name = tmpname;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Recursively look for further entries.
|
||||
*/
|
||||
STAILQ_FOREACH(entry2, &entry->child_entries, links) {
|
||||
struct mt_status_entry *entry3;
|
||||
|
||||
entry3 = mt_entry_find(entry2, name);
|
||||
if (entry3 != NULL) {
|
||||
free(tmpname2);
|
||||
return (entry3);
|
||||
}
|
||||
}
|
||||
|
||||
bailout:
|
||||
free(tmpname2);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct mt_status_entry *
|
||||
mt_status_entry_find(struct mt_status_data *status_data, char *name)
|
||||
{
|
||||
struct mt_status_entry *entry, *entry2;
|
||||
|
||||
STAILQ_FOREACH(entry, &status_data->entries, links) {
|
||||
entry2 = mt_entry_find(entry, name);
|
||||
if (entry2 != NULL)
|
||||
return (entry2);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
mt_status_entry_free(struct mt_status_entry *entry)
|
||||
{
|
||||
struct mt_status_entry *entry2, *entry3;
|
||||
struct mt_status_nv *nv, *nv2;
|
||||
|
||||
STAILQ_FOREACH_SAFE(entry2, &entry->child_entries, links, entry3) {
|
||||
STAILQ_REMOVE(&entry->child_entries, entry2, mt_status_entry,
|
||||
links);
|
||||
mt_status_entry_free(entry2);
|
||||
}
|
||||
|
||||
free(entry->entry_name);
|
||||
free(entry->value);
|
||||
free(entry->fmt);
|
||||
free(entry->desc);
|
||||
|
||||
STAILQ_FOREACH_SAFE(nv, &entry->nv_list, links, nv2) {
|
||||
STAILQ_REMOVE(&entry->nv_list, nv, mt_status_nv, links);
|
||||
free(nv->name);
|
||||
free(nv->value);
|
||||
free(nv);
|
||||
}
|
||||
free(entry);
|
||||
}
|
||||
|
||||
void
|
||||
mt_status_free(struct mt_status_data *status_data)
|
||||
{
|
||||
struct mt_status_entry *entry, *entry2;
|
||||
|
||||
STAILQ_FOREACH_SAFE(entry, &status_data->entries, links, entry2) {
|
||||
STAILQ_REMOVE(&status_data->entries, entry, mt_status_entry,
|
||||
links);
|
||||
mt_status_entry_free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mt_entry_sbuf(struct sbuf *sb, struct mt_status_entry *entry, char *fmt)
|
||||
{
|
||||
switch(entry->var_type) {
|
||||
case MT_TYPE_INT:
|
||||
if (fmt != NULL)
|
||||
sbuf_printf(sb, fmt, (intmax_t)entry->value_signed);
|
||||
else
|
||||
sbuf_printf(sb, "%jd",
|
||||
(intmax_t)entry->value_signed);
|
||||
break;
|
||||
case MT_TYPE_UINT:
|
||||
if (fmt != NULL)
|
||||
sbuf_printf(sb, fmt, (uintmax_t)entry->value_unsigned);
|
||||
else
|
||||
sbuf_printf(sb, "%ju",
|
||||
(uintmax_t)entry->value_unsigned);
|
||||
break;
|
||||
default:
|
||||
if (fmt != NULL)
|
||||
sbuf_printf(sb, fmt, entry->value);
|
||||
else
|
||||
sbuf_printf(sb, "%s", entry->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mt_param_parent_print(struct mt_status_entry *entry,
|
||||
struct mt_print_params *print_params)
|
||||
{
|
||||
if (entry->parent != NULL)
|
||||
mt_param_parent_print(entry->parent, print_params);
|
||||
|
||||
if (((print_params->flags & MT_PF_INCLUDE_ROOT) == 0)
|
||||
&& (strcmp(entry->entry_name, print_params->root_name) == 0))
|
||||
return;
|
||||
|
||||
printf("%s.", entry->entry_name);
|
||||
}
|
||||
|
||||
void
|
||||
mt_param_parent_sbuf(struct sbuf *sb, struct mt_status_entry *entry,
|
||||
struct mt_print_params *print_params)
|
||||
{
|
||||
if (entry->parent != NULL)
|
||||
mt_param_parent_sbuf(sb, entry->parent, print_params);
|
||||
|
||||
if (((print_params->flags & MT_PF_INCLUDE_ROOT) == 0)
|
||||
&& (strcmp(entry->entry_name, print_params->root_name) == 0))
|
||||
return;
|
||||
|
||||
sbuf_printf(sb, "%s.", entry->entry_name);
|
||||
}
|
||||
|
||||
void
|
||||
mt_param_entry_sbuf(struct sbuf *sb, struct mt_status_entry *entry, void *arg)
|
||||
{
|
||||
struct mt_print_params *print_params;
|
||||
|
||||
print_params = (struct mt_print_params *)arg;
|
||||
|
||||
/*
|
||||
* We don't want to print nodes.
|
||||
*/
|
||||
if (entry->var_type == MT_TYPE_NODE)
|
||||
return;
|
||||
|
||||
if ((print_params->flags & MT_PF_FULL_PATH)
|
||||
&& (entry->parent != NULL))
|
||||
mt_param_parent_sbuf(sb, entry->parent, print_params);
|
||||
|
||||
sbuf_printf(sb, "%s: %s", entry->entry_name, entry->value);
|
||||
if ((print_params->flags & MT_PF_VERBOSE)
|
||||
&& (entry->desc != NULL)
|
||||
&& (strlen(entry->desc) > 0))
|
||||
sbuf_printf(sb, " (%s)", entry->desc);
|
||||
sbuf_printf(sb, "\n");
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
mt_param_entry_print(struct mt_status_entry *entry, void *arg)
|
||||
{
|
||||
struct mt_print_params *print_params;
|
||||
|
||||
print_params = (struct mt_print_params *)arg;
|
||||
|
||||
/*
|
||||
* We don't want to print nodes.
|
||||
*/
|
||||
if (entry->var_type == MT_TYPE_NODE)
|
||||
return;
|
||||
|
||||
if ((print_params->flags & MT_PF_FULL_PATH)
|
||||
&& (entry->parent != NULL))
|
||||
mt_param_parent_print(entry->parent, print_params);
|
||||
|
||||
printf("%s: %s", entry->entry_name, entry->value);
|
||||
if ((print_params->flags & MT_PF_VERBOSE)
|
||||
&& (entry->desc != NULL)
|
||||
&& (strlen(entry->desc) > 0))
|
||||
printf(" (%s)", entry->desc);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int
|
||||
mt_protect_print(struct mt_status_data *status_data, int verbose)
|
||||
{
|
||||
struct mt_status_entry *entry;
|
||||
const char *prot_name = MT_PROTECTION_NAME;
|
||||
struct mt_print_params print_params;
|
||||
|
||||
snprintf(print_params.root_name, sizeof(print_params.root_name),
|
||||
MT_PARAM_ROOT_NAME);
|
||||
print_params.flags = MT_PF_FULL_PATH;
|
||||
if (verbose != 0)
|
||||
print_params.flags |= MT_PF_VERBOSE;
|
||||
|
||||
entry = mt_status_entry_find(status_data, __DECONST(char *,prot_name));
|
||||
if (entry == NULL)
|
||||
return (1);
|
||||
mt_status_tree_print(entry, 0, mt_param_entry_print, &print_params);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
mt_param_list(struct mt_status_data *status_data, char *param_name, int quiet)
|
||||
{
|
||||
struct mt_status_entry *entry;
|
||||
struct mt_print_params print_params;
|
||||
char root_name[20];
|
||||
|
||||
snprintf(root_name, sizeof(root_name), "mtparamget");
|
||||
strlcpy(print_params.root_name, root_name,
|
||||
sizeof(print_params.root_name));
|
||||
|
||||
print_params.flags = MT_PF_FULL_PATH;
|
||||
if (quiet == 0)
|
||||
print_params.flags |= MT_PF_VERBOSE;
|
||||
|
||||
if (param_name != NULL) {
|
||||
entry = mt_status_entry_find(status_data, param_name);
|
||||
if (entry == NULL)
|
||||
return (1);
|
||||
|
||||
mt_param_entry_print(entry, &print_params);
|
||||
|
||||
return (0);
|
||||
} else {
|
||||
entry = mt_status_entry_find(status_data, root_name);
|
||||
|
||||
STAILQ_FOREACH(entry, &status_data->entries, links)
|
||||
mt_status_tree_print(entry, 0, mt_param_entry_print,
|
||||
&print_params);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct densities {
|
||||
int dens;
|
||||
int bpmm;
|
||||
int bpi;
|
||||
const char *name;
|
||||
} dens[] = {
|
||||
/*
|
||||
* Taken from T10 Project 997D
|
||||
* SCSI-3 Stream Device Commands (SSC)
|
||||
* Revision 11, 4-Nov-97
|
||||
*
|
||||
* LTO 1-6 definitions obtained from the eighth edition of the
|
||||
* IBM TotalStorage LTO Ultrium Tape Drive SCSI Reference
|
||||
* (July 2007) and the second edition of the IBM System Storage LTO
|
||||
* Tape Drive SCSI Reference (February 13, 2013).
|
||||
*
|
||||
* IBM 3592 definitions obtained from second edition of the IBM
|
||||
* System Storage Tape Drive 3592 SCSI Reference (May 25, 2012).
|
||||
*/
|
||||
/*Num. bpmm bpi Reference */
|
||||
{ 0x1, 32, 800, "X3.22-1983" },
|
||||
{ 0x2, 63, 1600, "X3.39-1986" },
|
||||
{ 0x3, 246, 6250, "X3.54-1986" },
|
||||
{ 0x5, 315, 8000, "X3.136-1986" },
|
||||
{ 0x6, 126, 3200, "X3.157-1987" },
|
||||
{ 0x7, 252, 6400, "X3.116-1986" },
|
||||
{ 0x8, 315, 8000, "X3.158-1987" },
|
||||
{ 0x9, 491, 37871, "X3.180" },
|
||||
{ 0xA, 262, 6667, "X3B5/86-199" },
|
||||
{ 0xB, 63, 1600, "X3.56-1986" },
|
||||
{ 0xC, 500, 12690, "HI-TC1" },
|
||||
{ 0xD, 999, 25380, "HI-TC2" },
|
||||
{ 0xF, 394, 10000, "QIC-120" },
|
||||
{ 0x10, 394, 10000, "QIC-150" },
|
||||
{ 0x11, 630, 16000, "QIC-320" },
|
||||
{ 0x12, 2034, 51667, "QIC-1350" },
|
||||
{ 0x13, 2400, 61000, "X3B5/88-185A" },
|
||||
{ 0x14, 1703, 43245, "X3.202-1991" },
|
||||
{ 0x15, 1789, 45434, "ECMA TC17" },
|
||||
{ 0x16, 394, 10000, "X3.193-1990" },
|
||||
{ 0x17, 1673, 42500, "X3B5/91-174" },
|
||||
{ 0x18, 1673, 42500, "X3B5/92-50" },
|
||||
{ 0x19, 2460, 62500, "DLTapeIII" },
|
||||
{ 0x1A, 3214, 81633, "DLTapeIV(20GB)" },
|
||||
{ 0x1B, 3383, 85937, "DLTapeIV(35GB)" },
|
||||
{ 0x1C, 1654, 42000, "QIC-385M" },
|
||||
{ 0x1D, 1512, 38400, "QIC-410M" },
|
||||
{ 0x1E, 1385, 36000, "QIC-1000C" },
|
||||
{ 0x1F, 2666, 67733, "QIC-2100C" },
|
||||
{ 0x20, 2666, 67733, "QIC-6GB(M)" },
|
||||
{ 0x21, 2666, 67733, "QIC-20GB(C)" },
|
||||
{ 0x22, 1600, 40640, "QIC-2GB(C)" },
|
||||
{ 0x23, 2666, 67733, "QIC-875M" },
|
||||
{ 0x24, 2400, 61000, "DDS-2" },
|
||||
{ 0x25, 3816, 97000, "DDS-3" },
|
||||
{ 0x26, 3816, 97000, "DDS-4" },
|
||||
{ 0x27, 3056, 77611, "Mammoth" },
|
||||
{ 0x28, 1491, 37871, "X3.224" },
|
||||
{ 0x40, 4880, 123952, "LTO-1" },
|
||||
{ 0x41, 3868, 98250, "DLTapeIV(40GB)" },
|
||||
{ 0x42, 7398, 187909, "LTO-2" },
|
||||
{ 0x44, 9638, 244805, "LTO-3" },
|
||||
{ 0x46, 12725, 323215, "LTO-4" },
|
||||
{ 0x48, 5236, 133000, "SDLTapeI(110)" },
|
||||
{ 0x49, 7598, 193000, "SDLTapeI(160)" },
|
||||
{ 0x4a, 0, 0, "T10000A" },
|
||||
{ 0x4b, 0, 0, "T10000B" },
|
||||
{ 0x4c, 0, 0, "T10000C" },
|
||||
{ 0x4d, 0, 0, "T10000D" },
|
||||
{ 0x51, 11800, 299720, "3592A1 (unencrypted)" },
|
||||
{ 0x52, 11800, 299720, "3592A2 (unencrypted)" },
|
||||
{ 0x53, 13452, 341681, "3592A3 (unencrypted)" },
|
||||
{ 0x54, 19686, 500024, "3592A4 (unencrypted)" },
|
||||
{ 0x55, 20670, 525018, "3592A5 (unencrypted)" },
|
||||
{ 0x58, 15142, 384607, "LTO-5" },
|
||||
{ 0x5A, 15142, 384607, "LTO-6" },
|
||||
{ 0x71, 11800, 299720, "3592A1 (encrypted)" },
|
||||
{ 0x72, 11800, 299720, "3592A2 (encrypted)" },
|
||||
{ 0x73, 13452, 341681, "3592A3 (encrypted)" },
|
||||
{ 0x74, 19686, 500024, "3592A4 (encrypted)" },
|
||||
{ 0x75, 20670, 525018, "3592A5 (encrypted)" },
|
||||
{ 0x8c, 1789, 45434, "EXB-8500c" },
|
||||
{ 0x90, 1703, 43245, "EXB-8200c" },
|
||||
{ 0, 0, 0, NULL }
|
||||
};
|
||||
|
||||
const char *
|
||||
mt_density_name(int density_num)
|
||||
{
|
||||
struct densities *sd;
|
||||
|
||||
/* densities 0 and 0x7f are handled as special cases */
|
||||
if (density_num == 0)
|
||||
return ("default");
|
||||
if (density_num == 0x7f)
|
||||
return ("same");
|
||||
|
||||
for (sd = dens; sd->dens != 0; sd++)
|
||||
if (sd->dens == density_num)
|
||||
break;
|
||||
if (sd->dens == 0)
|
||||
return ("UNKNOWN");
|
||||
return (sd->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a specific density number, return either the bits per inch or bits
|
||||
* per millimeter for the given density.
|
||||
*/
|
||||
int
|
||||
mt_density_bp(int density_num, int bpi)
|
||||
{
|
||||
struct densities *sd;
|
||||
|
||||
for (sd = dens; sd->dens; sd++)
|
||||
if (sd->dens == density_num)
|
||||
break;
|
||||
if (sd->dens == 0)
|
||||
return (0);
|
||||
if (bpi)
|
||||
return (sd->bpi);
|
||||
else
|
||||
return (sd->bpmm);
|
||||
}
|
||||
|
||||
int
|
||||
mt_density_num(const char *density_name)
|
||||
{
|
||||
struct densities *sd;
|
||||
size_t l = strlen(density_name);
|
||||
|
||||
for (sd = dens; sd->dens; sd++)
|
||||
if (strncasecmp(sd->name, density_name, l) == 0)
|
||||
break;
|
||||
return (sd->dens);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current status XML string.
|
||||
* Returns 0 on success, -1 on failure (with errno set, and *xml_str == NULL).
|
||||
*/
|
||||
int
|
||||
mt_get_xml_str(int mtfd, unsigned long cmd, char **xml_str)
|
||||
{
|
||||
size_t alloc_len = 32768;
|
||||
struct mtextget extget;
|
||||
int error;
|
||||
|
||||
*xml_str = NULL;
|
||||
|
||||
for (;;) {
|
||||
bzero(&extget, sizeof(extget));
|
||||
*xml_str = malloc(alloc_len);
|
||||
if (*xml_str == NULL)
|
||||
return (-1);
|
||||
extget.status_xml = *xml_str;
|
||||
extget.alloc_len = alloc_len;
|
||||
|
||||
error = ioctl(mtfd, cmd, (caddr_t)&extget);
|
||||
if (error == 0 && extget.status == MT_EXT_GET_OK)
|
||||
break;
|
||||
|
||||
free(*xml_str);
|
||||
*xml_str = NULL;
|
||||
|
||||
if (error != 0 || extget.status != MT_EXT_GET_NEED_MORE_SPACE)
|
||||
return (-1);
|
||||
|
||||
/* The driver needs more space, so double and try again. */
|
||||
alloc_len *= 2;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Populate a struct mt_status_data from the XML string via mt_get_xml_str().
|
||||
*
|
||||
* Returns XML_STATUS_OK on success.
|
||||
* If XML_STATUS_ERROR is returned, errno may be set to indicate the reason.
|
||||
* The caller must check status_data->error.
|
||||
*/
|
||||
int
|
||||
mt_get_status(char *xml_str, struct mt_status_data *status_data)
|
||||
{
|
||||
XML_Parser parser;
|
||||
int retval;
|
||||
|
||||
bzero(status_data, sizeof(*status_data));
|
||||
STAILQ_INIT(&status_data->entries);
|
||||
|
||||
parser = XML_ParserCreate(NULL);
|
||||
if (parser == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (XML_STATUS_ERROR);
|
||||
}
|
||||
|
||||
XML_SetUserData(parser, status_data);
|
||||
XML_SetElementHandler(parser, mt_start_element, mt_end_element);
|
||||
XML_SetCharacterDataHandler(parser, mt_char_handler);
|
||||
|
||||
retval = XML_Parse(parser, xml_str, strlen(xml_str), 1);
|
||||
XML_ParserFree(parser);
|
||||
return (retval);
|
||||
}
|
122
lib/libmt/mtlib.h
Normal file
122
lib/libmt/mtlib.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*-
|
||||
* Copyright (c) 2013, 2014 Spectra Logic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* substantially similar to the "NO WARRANTY" disclaimer below
|
||||
* ("Disclaimer") and any redistribution must be conditioned upon
|
||||
* including a substantially similar Disclaimer requirement for further
|
||||
* binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*
|
||||
* Authors: Ken Merry (Spectra Logic Corporation)
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MTLIB_H
|
||||
#define _MTLIB_H
|
||||
|
||||
typedef enum {
|
||||
MT_TYPE_NONE,
|
||||
MT_TYPE_STRING,
|
||||
MT_TYPE_INT,
|
||||
MT_TYPE_UINT,
|
||||
MT_TYPE_NODE
|
||||
} mt_variable_type;
|
||||
|
||||
struct mt_status_nv {
|
||||
char *name;
|
||||
char *value;
|
||||
STAILQ_ENTRY(mt_status_nv) links;
|
||||
};
|
||||
|
||||
struct mt_status_entry {
|
||||
char *entry_name;
|
||||
char *value;
|
||||
uint64_t value_unsigned;
|
||||
int64_t value_signed;
|
||||
char *fmt;
|
||||
char *desc;
|
||||
size_t size;
|
||||
mt_variable_type var_type;
|
||||
struct mt_status_entry *parent;
|
||||
STAILQ_HEAD(, mt_status_nv) nv_list;
|
||||
STAILQ_HEAD(, mt_status_entry) child_entries;
|
||||
STAILQ_ENTRY(mt_status_entry) links;
|
||||
};
|
||||
|
||||
struct mt_status_data {
|
||||
int level;
|
||||
struct sbuf *cur_sb[32];
|
||||
struct mt_status_entry *cur_entry[32];
|
||||
int error;
|
||||
char error_str[128];
|
||||
STAILQ_HEAD(, mt_status_entry) entries;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
MT_PF_NONE = 0x00,
|
||||
MT_PF_VERBOSE = 0x01,
|
||||
MT_PF_FULL_PATH = 0x02,
|
||||
MT_PF_INCLUDE_ROOT = 0x04
|
||||
} mt_print_flags;
|
||||
|
||||
struct mt_print_params {
|
||||
mt_print_flags flags;
|
||||
char root_name[64];
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
void mt_start_element(void *user_data, const char *name, const char **attr);
|
||||
void mt_end_element(void *user_data, const char *name);
|
||||
void mt_char_handler(void *user_data, const XML_Char *str, int len);
|
||||
void mt_status_tree_sbuf(struct sbuf *sb, struct mt_status_entry *entry,
|
||||
int indent, void (*sbuf_func)(struct sbuf *sb,
|
||||
struct mt_status_entry *entry, void *arg), void *arg);
|
||||
void mt_status_tree_print(struct mt_status_entry *entry, int indent,
|
||||
void (*print_func)(struct mt_status_entry *entry,
|
||||
void *arg), void *arg);
|
||||
struct mt_status_entry *mt_entry_find(struct mt_status_entry *entry,
|
||||
char *name);
|
||||
struct mt_status_entry *mt_status_entry_find(struct mt_status_data *status_data,
|
||||
char *name);
|
||||
void mt_status_entry_free(struct mt_status_entry *entry);
|
||||
void mt_status_free(struct mt_status_data *status_data);
|
||||
void mt_entry_sbuf(struct sbuf *sb, struct mt_status_entry *entry, char *fmt);
|
||||
void mt_param_parent_print(struct mt_status_entry *entry,
|
||||
struct mt_print_params *print_params);
|
||||
void mt_param_parent_sbuf(struct sbuf *sb, struct mt_status_entry *entry,
|
||||
struct mt_print_params *print_params);
|
||||
void mt_param_entry_sbuf(struct sbuf *sb, struct mt_status_entry *entry,
|
||||
void *arg);
|
||||
void mt_param_entry_print(struct mt_status_entry *entry, void *arg);
|
||||
int mt_protect_print(struct mt_status_data *status_data, int verbose);
|
||||
int mt_param_list(struct mt_status_data *status_data, char *param_name,
|
||||
int quiet);
|
||||
const char *mt_density_name(int density_num);
|
||||
int mt_density_bp(int density_num, int bpi);
|
||||
int mt_density_num(const char *density_name);
|
||||
int mt_get_xml_str(int mtfd, unsigned long cmd, char **xml_str);
|
||||
int mt_get_status(char *xml_str, struct mt_status_data *status_data);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _MTLIB_H */
|
@ -633,7 +633,7 @@ mutex_unlock_common(struct pthread_mutex *m, int cv, int *mtx_defer)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
uint32_t id;
|
||||
int defered;
|
||||
int defered, error;
|
||||
|
||||
if (__predict_false(m <= THR_MUTEX_DESTROYED)) {
|
||||
if (m == THR_MUTEX_DESTROYED)
|
||||
@ -647,6 +647,7 @@ mutex_unlock_common(struct pthread_mutex *m, int cv, int *mtx_defer)
|
||||
if (__predict_false(m->m_owner != curthread))
|
||||
return (EPERM);
|
||||
|
||||
error = 0;
|
||||
id = TID(curthread);
|
||||
if (__predict_false(
|
||||
PMUTEX_TYPE(m->m_flags) == PTHREAD_MUTEX_RECURSIVE &&
|
||||
@ -660,7 +661,7 @@ mutex_unlock_common(struct pthread_mutex *m, int cv, int *mtx_defer)
|
||||
defered = 0;
|
||||
|
||||
DEQUEUE_MUTEX(curthread, m);
|
||||
_thr_umutex_unlock2(&m->m_lock, id, mtx_defer);
|
||||
error = _thr_umutex_unlock2(&m->m_lock, id, mtx_defer);
|
||||
|
||||
if (mtx_defer == NULL && defered) {
|
||||
_thr_wake_all(curthread->defer_waiters,
|
||||
@ -670,7 +671,7 @@ mutex_unlock_common(struct pthread_mutex *m, int cv, int *mtx_defer)
|
||||
}
|
||||
if (!cv && m->m_flags & PMUTEX_FLAG_PRIVATE)
|
||||
THR_CRITICAL_LEAVE(curthread);
|
||||
return (0);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -373,7 +373,7 @@ static const double qS2[6] = {
|
||||
if(ix>=0x40200000) {p = qR8; q= qS8;}
|
||||
else if(ix>=0x40122E8B){p = qR5; q= qS5;}
|
||||
else if(ix>=0x4006DB6D){p = qR3; q= qS3;}
|
||||
else if(ix>=0x40000000){p = qR2; q= qS2;}
|
||||
else {p = qR2; q= qS2;} /* ix>=0x40000000 */
|
||||
z = one/(x*x);
|
||||
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
|
||||
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
|
||||
|
@ -329,7 +329,7 @@ static const float qS2[6] = {
|
||||
if(ix>=0x41000000) {p = qR8; q= qS8;}
|
||||
else if(ix>=0x40f71c58){p = qR5; q= qS5;}
|
||||
else if(ix>=0x4036db68){p = qR3; q= qS3;}
|
||||
else if(ix>=0x40000000){p = qR2; q= qS2;}
|
||||
else {p = qR2; q= qS2;} /* ix>=0x40000000 */
|
||||
z = one/(x*x);
|
||||
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
|
||||
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
|
||||
|
@ -368,7 +368,7 @@ static const double qs2[6] = {
|
||||
if(ix>=0x40200000) {p = qr8; q= qs8;}
|
||||
else if(ix>=0x40122E8B){p = qr5; q= qs5;}
|
||||
else if(ix>=0x4006DB6D){p = qr3; q= qs3;}
|
||||
else if(ix>=0x40000000){p = qr2; q= qs2;}
|
||||
else {p = qr2; q= qs2;} /* ix>=0x40000000 */
|
||||
z = one/(x*x);
|
||||
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
|
||||
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
|
||||
|
@ -325,7 +325,7 @@ static const float qs2[6] = {
|
||||
if(ix>=0x40200000) {p = qr8; q= qs8;}
|
||||
else if(ix>=0x40f71c58){p = qr5; q= qs5;}
|
||||
else if(ix>=0x4036db68){p = qr3; q= qs3;}
|
||||
else if(ix>=0x40000000){p = qr2; q= qs2;}
|
||||
else {p = qr2; q= qs2;} /* ix>=0x40000000 */
|
||||
z = one/(x*x);
|
||||
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
|
||||
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
|
||||
|
@ -286,7 +286,7 @@ real-release:
|
||||
${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} obj
|
||||
${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} ${RELEASE_TARGETS}
|
||||
|
||||
install: release-install vm-install
|
||||
install: release-install vm-install cloudware-install
|
||||
|
||||
release-install:
|
||||
.if defined(DESTDIR) && !empty(DESTDIR)
|
||||
|
@ -20,24 +20,30 @@ CLOUDWARE?= AZURE \
|
||||
OPENSTACK
|
||||
AZURE_FORMAT= vhdf
|
||||
AZURE_DESC= Microsoft Azure platform image
|
||||
AZURE_DISK= ${OSRELEASE}.${AZURE_FORMAT}
|
||||
GCE_FORMAT= raw
|
||||
GCE_DESC= Google Compute Engine image
|
||||
GCE_DISK= disk.${GCE_FORMAT}
|
||||
OPENSTACK_FORMAT=qcow2
|
||||
OPENSTACK_DESC= OpenStack platform image
|
||||
OPENSTACK_DISK= ${OSRELEASE}.${OPENSTACK_FORMAT}
|
||||
|
||||
.if defined(WITH_CLOUDWARE) && !empty(WITH_CLOUDWARE) && !empty(CLOUDWARE)
|
||||
. for _CW in ${CLOUDWARE}
|
||||
CLOUDTARGETS+= vm-${_CW:tl}
|
||||
CLEANDIRS+= vm-${_CW:tl}
|
||||
CLOUDTARGETS+= cw-${_CW:tl}
|
||||
CLEANDIRS+= cw-${_CW:tl}
|
||||
CLEANFILES+= ${_CW:tl}.img \
|
||||
${_CW:tl}.${${_CW:tu}_FORMAT} \
|
||||
${_CW:tl}.${${_CW:tu}_FORMAT}.raw
|
||||
${_CW:tl}.${${_CW:tu}_FORMAT}.raw \
|
||||
cw${_CW:tl}-package
|
||||
CLOUDINSTALL+= cw${_CW:tl}-install
|
||||
CLOUDPACKAGE+= cw${_CW:tl}-package
|
||||
${_CW:tu}IMAGE= ${_CW:tl}.${${_CW:tu}_FORMAT}
|
||||
. if exists(${.CURDIR}/tools/${_CW:tl}.conf) && !defined(${_CW:tu}CONF)
|
||||
${_CW:tu}CONF?= ${.CURDIR}/tools/${_CW:tl}.conf
|
||||
. endif
|
||||
|
||||
vm-${_CW:tl}:
|
||||
cw-${_CW:tl}:
|
||||
mkdir -p ${.OBJDIR}/${.TARGET}
|
||||
env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \
|
||||
${.CURDIR}/scripts/mk-vmimage.sh \
|
||||
@ -45,6 +51,26 @@ vm-${_CW:tl}:
|
||||
-i ${.OBJDIR}/${_CW:tl}.img -s ${VMSIZE} -f ${${_CW}_FORMAT} \
|
||||
-S ${WORLDDIR} -o ${.OBJDIR}/${${_CW}IMAGE} -c ${${_CW}CONF}
|
||||
touch ${.TARGET}
|
||||
|
||||
cw${_CW:tl}-install:
|
||||
mkdir -p ${DESTDIR}/${_CW:tl}
|
||||
cp -p ${${_CW}IMAGE} \
|
||||
${DESTDIR}/${_CW:tl}/${${_CW}_DISK}
|
||||
cd ${DESTDIR}/${_CW:tl} && sha256 ${${_CW}_DISK}* > \
|
||||
${DESTDIR}/${_CW:tl}/CHECKSUM.SHA256
|
||||
cd ${DESTDIR}/${_CW:tl} && md5 ${${_CW}_DISK}* > \
|
||||
${DESTDIR}/${_CW:tl}/CHECKSUM.MD5
|
||||
|
||||
cw${_CW:tl}-package:
|
||||
@# Special target to handle packaging cloud images in the formats
|
||||
@# specific to each hosting provider.
|
||||
.if exists(${.CURDIR}/tools/${_CW:tl}-package.sh)
|
||||
env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \
|
||||
${.CURDIR}/tools/${_CW:tl}-package.sh \
|
||||
-D ${DESTDIR} -I ${${_CW}_DISK} -S ${WORLDDIR}
|
||||
.endif
|
||||
touch ${.TARGET}
|
||||
|
||||
. endfor
|
||||
.endif
|
||||
|
||||
@ -97,8 +123,6 @@ vm-install:
|
||||
${DESTDIR}/vmimages/${OSRELEASE}.${FORMAT}
|
||||
. endfor
|
||||
. if defined(WITH_COMPRESSED_VMIMAGES) && !empty(WITH_COMPRESSED_VMIMAGES)
|
||||
# This is very time consuming, so defer it after the images are moved to
|
||||
# the DESTDIR.
|
||||
. for FORMAT in ${VMFORMATS}
|
||||
# Don't keep the originals. There is a copy in ${.OBJDIR} if needed.
|
||||
${XZ_CMD} ${DESTDIR}/vmimages/${OSRELEASE}.${FORMAT}
|
||||
@ -119,3 +143,8 @@ cloudware-release:
|
||||
.if defined(WITH_CLOUDWARE) && !empty(WITH_CLOUDWARE) && !empty(CLOUDWARE)
|
||||
${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} ${CLOUDTARGETS}
|
||||
.endif
|
||||
|
||||
cloudware-install:
|
||||
.if defined(WITH_CLOUDWARE) && !empty(WITH_CLOUDWARE) && !empty(CLOUDWARE)
|
||||
${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} ${CLOUDINSTALL}
|
||||
.endif
|
||||
|
47
release/tools/gce-package.sh
Executable file
47
release/tools/gce-package.sh
Executable file
@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
# Script to handle packaging cloud images for GCE.
|
||||
#
|
||||
# XXX:
|
||||
# This script only exists to help in automating image creation,
|
||||
# and reimplementing this is intended (in other words, this is
|
||||
# temporary).
|
||||
|
||||
usage() {
|
||||
echo "Usage:"
|
||||
echo "$(basename ${0}) -D <destdir> -I <input_file> -S <src_tree>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
main() {
|
||||
while getopts "D:I:W:" opt; do
|
||||
case ${opt} in
|
||||
D)
|
||||
DESTDIR="${OPTARG}"
|
||||
;;
|
||||
I)
|
||||
INFILE="${OPTARG}"
|
||||
;;
|
||||
S)
|
||||
WORLDDIR="${OPTARG}"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $(( ${OPTIND} - 1 ))
|
||||
|
||||
if [ -z "${DESTDIR}" -o -z "${INFILE}" -o -z "${WORLDDIR}" ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
OUTFILE="$(make -C ${WORLDDIR}/release -V OSRELEASE).tar.gz"
|
||||
|
||||
cd ${DESTDIR} && tar --format=gnutar -zcf ${OUTFILE} ${INFILE}
|
||||
}
|
||||
|
||||
main "$@"
|
@ -131,7 +131,7 @@ CRUNCH_LIBS+= -lgeom -lbsdxml -lkiconv
|
||||
.if ${MK_OPENSSL} == "no"
|
||||
CRUNCH_LIBS+= -lmd
|
||||
.endif
|
||||
CRUNCH_LIBS+= -lsbuf -lufs -lz
|
||||
CRUNCH_LIBS+= -lmt -lsbuf -lufs -lz
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "i386"
|
||||
CRUNCH_PROGS_sbin+= bsdlabel sconfig fdisk
|
||||
|
@ -31,7 +31,7 @@
|
||||
.\" @(#)mtio.4 8.1 (Berkeley) 6/5/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 11, 2011
|
||||
.Dd February 12, 2015
|
||||
.Dt MTIO 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -40,10 +40,10 @@
|
||||
.Sh DESCRIPTION
|
||||
The special files
|
||||
named
|
||||
.Pa /dev/[n]sa*
|
||||
.Pa /dev/[en]sa*
|
||||
refer to SCSI tape drives,
|
||||
which may be attached to the system.
|
||||
.Pa /dev/[n]sa*.ctl
|
||||
.Pa /dev/sa*.ctl
|
||||
are control devices that can be used to issue ioctls to the SCSI
|
||||
tape driver to set parameters that are required to last beyond the
|
||||
unmounting of a tape.
|
||||
@ -53,16 +53,19 @@ when the last requested read, write or seek has finished, or the end of the tape
|
||||
has been reached.
|
||||
The letter
|
||||
.Ql n
|
||||
is usually prepended to
|
||||
is prepended to
|
||||
the name of the no-rewind devices.
|
||||
The letter
|
||||
.Ql e
|
||||
is prepended to the name of the eject devices.
|
||||
.Pp
|
||||
Tapes can be written with either fixed length records or variable length
|
||||
records.
|
||||
See
|
||||
.Xr sa 4
|
||||
for more information.
|
||||
Two end-of-file markers mark the end of a tape, and
|
||||
one end-of-file marker marks the end of a tape file.
|
||||
Two filemarks mark the end of a tape, and
|
||||
one filemark marks the end of a tape file.
|
||||
If the tape is not to be rewound it is positioned with the
|
||||
head in between the two tape marks, where the next write
|
||||
will over write the second end-of-file marker.
|
||||
@ -128,6 +131,8 @@ struct mtop {
|
||||
#define MTWSS 16 /* write setmark(s) */
|
||||
#define MTFSS 17 /* forward space setmark */
|
||||
#define MTBSS 18 /* backward space setmark */
|
||||
#define MTLOAD 19 /* load tape in drive */
|
||||
#define MTWEOFI 20 /* write an end-of-file record without waiting*/
|
||||
|
||||
#define MT_COMP_ENABLE 0xffffffff
|
||||
#define MT_COMP_DISABLED 0xfffffffe
|
||||
@ -224,6 +229,112 @@ union mterrstat {
|
||||
char _reserved_padding[256];
|
||||
};
|
||||
|
||||
struct mtrblim {
|
||||
uint32_t granularity;
|
||||
uint32_t min_block_length;
|
||||
uint32_t max_block_length;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
MT_LOCATE_DEST_OBJECT = 0x00,
|
||||
MT_LOCATE_DEST_FILE = 0x01,
|
||||
MT_LOCATE_DEST_SET = 0x02,
|
||||
MT_LOCATE_DEST_EOD = 0x03
|
||||
} mt_locate_dest_type;
|
||||
|
||||
typedef enum {
|
||||
MT_LOCATE_BAM_IMPLICIT = 0x00,
|
||||
MT_LOCATE_BAM_EXPLICIT = 0x01
|
||||
} mt_locate_bam;
|
||||
|
||||
typedef enum {
|
||||
MT_LOCATE_FLAG_IMMED = 0x01,
|
||||
MT_LOCATE_FLAG_CHANGE_PART = 0x02
|
||||
} mt_locate_flags;
|
||||
|
||||
struct mtlocate {
|
||||
mt_locate_flags flags;
|
||||
mt_locate_dest_type dest_type;
|
||||
mt_locate_bam block_address_mode;
|
||||
int64_t partition;
|
||||
uint64_t logical_id;
|
||||
uint8_t reserved[64];
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
MT_EXT_GET_NONE,
|
||||
MT_EXT_GET_OK,
|
||||
MT_EXT_GET_NEED_MORE_SPACE,
|
||||
MT_EXT_GET_ERROR
|
||||
} mt_ext_get_status;
|
||||
|
||||
struct mtextget {
|
||||
uint32_t alloc_len;
|
||||
char *status_xml;
|
||||
uint32_t fill_len;
|
||||
mt_ext_get_status status;
|
||||
char error_str[128];
|
||||
uint8_t reserved[64];
|
||||
};
|
||||
|
||||
#define MT_EXT_GET_ROOT_NAME "mtextget"
|
||||
#define MT_DENSITY_ROOT_NAME "mtdensity"
|
||||
#define MT_MEDIA_DENSITY_NAME "media_density"
|
||||
#define MT_DENSITY_REPORT_NAME "density_report"
|
||||
#define MT_MEDIUM_TYPE_REPORT_NAME "medium_type_report"
|
||||
#define MT_MEDIA_REPORT_NAME "media_report"
|
||||
#define MT_DENSITY_ENTRY_NAME "density_entry"
|
||||
|
||||
#define MT_DENS_WRITE_OK 0x80
|
||||
#define MT_DENS_DUP 0x40
|
||||
#define MT_DENS_DEFLT 0x20
|
||||
|
||||
|
||||
#define MT_PARAM_FIXED_STR_LEN 32
|
||||
union mt_param_value {
|
||||
int64_t value_signed;
|
||||
uint64_t value_unsigned;
|
||||
char *value_var_str;
|
||||
char value_fixed_str[MT_PARAM_FIXED_STR_LEN];
|
||||
uint8_t reserved[64];
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
MT_PARAM_SET_NONE,
|
||||
MT_PARAM_SET_SIGNED,
|
||||
MT_PARAM_SET_UNSIGNED,
|
||||
MT_PARAM_SET_VAR_STR,
|
||||
MT_PARAM_SET_FIXED_STR
|
||||
} mt_param_set_type;
|
||||
|
||||
typedef enum {
|
||||
MT_PARAM_STATUS_NONE,
|
||||
MT_PARAM_STATUS_OK,
|
||||
MT_PARAM_STATUS_ERROR
|
||||
} mt_param_set_status;
|
||||
|
||||
#define MT_PARAM_VALUE_NAME_LEN 64
|
||||
struct mtparamset {
|
||||
char value_name[MT_PARAM_VALUE_NAME_LEN];
|
||||
mt_param_set_type value_type;
|
||||
int value_len;
|
||||
union mt_param_value value;
|
||||
mt_param_set_status status;
|
||||
char error_str[128];
|
||||
};
|
||||
|
||||
#define MT_PARAM_ROOT_NAME "mtparamget"
|
||||
#define MT_PROTECTION_NAME "protection"
|
||||
|
||||
/*
|
||||
* Set a list of parameters.
|
||||
*/
|
||||
struct mtsetlist {
|
||||
int num_params;
|
||||
int param_len;
|
||||
struct mtparamset *params;
|
||||
};
|
||||
|
||||
/*
|
||||
* Constants for mt_type byte. These are the same
|
||||
* for controllers compatible with the types listed.
|
||||
@ -273,6 +384,12 @@ union mterrstat {
|
||||
#define MTIOCSETEOTMODEL _IOW('m', 8, uint32_t)
|
||||
/* Get current EOT model */
|
||||
#define MTIOCGETEOTMODEL _IOR('m', 8, uint32_t)
|
||||
#define MTIOCRBLIM _IOR('m', 9, struct mtrblim) /* get block limits */
|
||||
#define MTIOCEXTLOCATE _IOW('m', 10, struct mtlocate) /* seek to position */
|
||||
#define MTIOCEXTGET _IOWR('m', 11, struct mtextget) /* get tape status */
|
||||
#define MTIOCPARAMGET _IOWR('m', 12, struct mtextget) /* get tape params */
|
||||
#define MTIOCPARAMSET _IOWR('m', 13, struct mtparamset) /* set tape params */
|
||||
#define MTIOCSETLIST _IOWR('m', 14, struct mtsetlist) /* set N params */
|
||||
|
||||
#ifndef _KERNEL
|
||||
#define DEFTAPE "/dev/nsa0"
|
||||
@ -281,13 +398,12 @@ union mterrstat {
|
||||
#endif /* !_SYS_MTIO_H_ */
|
||||
.Ed
|
||||
.Sh FILES
|
||||
.Bl -tag -width /dev/[n]sa* -compact
|
||||
.It Pa /dev/[n]sa*
|
||||
.Bl -tag -width /dev/[en]sa* -compact
|
||||
.It Pa /dev/[en]sa*
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mt 1 ,
|
||||
.Xr tar 1 ,
|
||||
.Xr ast 4 ,
|
||||
.Xr sa 4
|
||||
.Sh HISTORY
|
||||
The
|
||||
@ -296,8 +412,3 @@ manual appeared in
|
||||
.Bx 4.2 .
|
||||
An i386 version first appeared in
|
||||
.Fx 2.2 .
|
||||
.Sh BUGS
|
||||
The status should be returned in a device independent format.
|
||||
.Pp
|
||||
The special file naming should be redone in a more consistent and
|
||||
understandable manner.
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 23, 2013
|
||||
.Dd February 12, 2015
|
||||
.Dt SA 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -285,10 +285,10 @@ device driver written and ported from
|
||||
by
|
||||
.An Julian Elischer .
|
||||
.Pp
|
||||
The current owner of record is
|
||||
.An Matthew Jacob
|
||||
who has suffered too many
|
||||
years of breaking tape drivers.
|
||||
The owner of record for many years was
|
||||
.An Matthew Jacob .
|
||||
The current maintainer is
|
||||
.An Kenneth Merry
|
||||
.Sh BUGS
|
||||
This driver lacks many of the hacks required to deal with older devices.
|
||||
Many older
|
||||
@ -305,7 +305,5 @@ for your device in order to read tapes written under
|
||||
.Fx
|
||||
2.X.
|
||||
.Pp
|
||||
Fine grained density and compression mode support that is bound to specific
|
||||
device names needs to be added.
|
||||
.Pp
|
||||
Support for fast indexing by use of partitions is missing.
|
||||
Partitions are only supported for status information and location.
|
||||
It would be nice to add support for creating and editing tape partitions.
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 30, 2014
|
||||
.Dd February 22, 2015
|
||||
.Dt SFXGE 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -103,7 +103,7 @@ The value must be greater than 0.
|
||||
The maximum number of non-TCP packets in the deferred packet
|
||||
.Dq get-list
|
||||
, used only if the transmit queue lock can be acquired.
|
||||
If packet is dropped, the
|
||||
If a packet is dropped, the
|
||||
.Va tx_get_non_tcp_overflow
|
||||
counter is incremented and the local sender receives ENOBUFS.
|
||||
The value must be greater than 0.
|
||||
|
@ -591,15 +591,15 @@ This would usually be set to
|
||||
.It Va weekly_status_security_enable
|
||||
.Pq Vt bool
|
||||
Weekly counterpart of
|
||||
.Va daily_status_securiy_enable .
|
||||
.Va daily_status_security_enable .
|
||||
.It Va weekly_status_security_inline
|
||||
.Pq Vt bool
|
||||
Weekly counterpart of
|
||||
.Va daily_status_securiy_inline .
|
||||
.Va daily_status_security_inline .
|
||||
.It Va weekly_status_security_output
|
||||
.Pq Vt str
|
||||
Weekly counterpart of
|
||||
.Va daily_status_securiy_output .
|
||||
.Va daily_status_security_output .
|
||||
.It Va weekly_status_pkg_enable
|
||||
.Pq Vt bool
|
||||
Set to
|
||||
@ -670,15 +670,15 @@ command.
|
||||
.It Va monthly_status_security_enable
|
||||
.Pq Vt bool
|
||||
Monthly counterpart of
|
||||
.Va daily_status_securiy_enable .
|
||||
.Va daily_status_security_enable .
|
||||
.It Va monthly_status_security_inline
|
||||
.Pq Vt bool
|
||||
Monthly counterpart of
|
||||
.Va daily_status_securiy_inline .
|
||||
.Va daily_status_security_inline .
|
||||
.It Va monthly_status_security_output
|
||||
.Pq Vt str
|
||||
Monthly counterpart of
|
||||
.Va daily_status_securiy_output .
|
||||
.Va daily_status_security_output .
|
||||
.It Va monthly_local
|
||||
.Pq Vt str
|
||||
Set to a list of extra scripts that should be run after all other
|
||||
|
@ -85,6 +85,7 @@ LIBMEMSTAT?= ${DESTDIR}${LIBDIR}/libmemstat.a
|
||||
LIBMENU?= ${DESTDIR}${LIBDIR}/libmenu.a
|
||||
LIBMILTER?= ${DESTDIR}${LIBDIR}/libmilter.a
|
||||
LIBMP?= ${DESTDIR}${LIBDIR}/libmp.a
|
||||
LIBMT?= ${DESTDIR}${LIBDIR}/libmt.a
|
||||
LIBNCURSES?= ${DESTDIR}${LIBDIR}/libncurses.a
|
||||
LIBNCURSESW?= ${DESTDIR}${LIBDIR}/libncursesw.a
|
||||
LIBNETGRAPH?= ${DESTDIR}${LIBDIR}/libnetgraph.a
|
||||
|
@ -11,3 +11,13 @@ SRCCONF?= /etc/src.conf
|
||||
.include "${SRCCONF}"
|
||||
_srcconf_included_: .NOTMAIN
|
||||
.endif
|
||||
# If we were found via .../share/mk we need to replace that in
|
||||
# with ${.PARSEDIR:tA} so that we can be found by
|
||||
# sub-makes launched from objdir.
|
||||
.if ${.MAKEFLAGS:M.../share/mk} != ""
|
||||
.MAKEFLAGS:= ${.MAKEFLAGS:S,.../share/mk,${.PARSEDIR:tA},}
|
||||
.endif
|
||||
.if ${MAKESYSPATH:Uno:M*.../*} != ""
|
||||
MAKESYSPATH:= ${MAKESYSPATH:S,.../share/mk,${.PARSEDIR:tA},}
|
||||
.export MAKESYSPATH
|
||||
.endif
|
||||
|
@ -342,18 +342,6 @@ vmcs_init(struct vmcs *vmcs)
|
||||
*/
|
||||
VMPTRLD(vmcs);
|
||||
|
||||
/* Initialize guest IA32_PAT MSR with the default value */
|
||||
pat = PAT_VALUE(0, PAT_WRITE_BACK) |
|
||||
PAT_VALUE(1, PAT_WRITE_THROUGH) |
|
||||
PAT_VALUE(2, PAT_UNCACHED) |
|
||||
PAT_VALUE(3, PAT_UNCACHEABLE) |
|
||||
PAT_VALUE(4, PAT_WRITE_BACK) |
|
||||
PAT_VALUE(5, PAT_WRITE_THROUGH) |
|
||||
PAT_VALUE(6, PAT_UNCACHED) |
|
||||
PAT_VALUE(7, PAT_UNCACHEABLE);
|
||||
if ((error = vmwrite(VMCS_GUEST_IA32_PAT, pat)) != 0)
|
||||
goto done;
|
||||
|
||||
/* Host state */
|
||||
|
||||
/* Initialize host IA32_PAT MSR */
|
||||
|
@ -100,13 +100,11 @@ __FBSDID("$FreeBSD$");
|
||||
(VM_EXIT_HOST_LMA | \
|
||||
VM_EXIT_SAVE_EFER | \
|
||||
VM_EXIT_LOAD_EFER | \
|
||||
VM_EXIT_ACKNOWLEDGE_INTERRUPT | \
|
||||
VM_EXIT_SAVE_PAT | \
|
||||
VM_EXIT_LOAD_PAT)
|
||||
VM_EXIT_ACKNOWLEDGE_INTERRUPT)
|
||||
|
||||
#define VM_EXIT_CTLS_ZERO_SETTING VM_EXIT_SAVE_DEBUG_CONTROLS
|
||||
|
||||
#define VM_ENTRY_CTLS_ONE_SETTING (VM_ENTRY_LOAD_EFER | VM_ENTRY_LOAD_PAT)
|
||||
#define VM_ENTRY_CTLS_ONE_SETTING (VM_ENTRY_LOAD_EFER)
|
||||
|
||||
#define VM_ENTRY_CTLS_ZERO_SETTING \
|
||||
(VM_ENTRY_LOAD_DEBUG_CONTROLS | \
|
||||
@ -859,10 +857,6 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
|
||||
* VM exit and entry respectively. It is also restored from the
|
||||
* host VMCS area on a VM exit.
|
||||
*
|
||||
* MSR_PAT is saved and restored in the guest VMCS are on a VM exit
|
||||
* and entry respectively. It is also restored from the host VMCS
|
||||
* area on a VM exit.
|
||||
*
|
||||
* The TSC MSR is exposed read-only. Writes are disallowed as that
|
||||
* will impact the host TSC.
|
||||
* XXX Writes would be implemented with a wrmsr trap, and
|
||||
@ -874,7 +868,6 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
|
||||
guest_msr_rw(vmx, MSR_SYSENTER_ESP_MSR) ||
|
||||
guest_msr_rw(vmx, MSR_SYSENTER_EIP_MSR) ||
|
||||
guest_msr_rw(vmx, MSR_EFER) ||
|
||||
guest_msr_rw(vmx, MSR_PAT) ||
|
||||
guest_msr_ro(vmx, MSR_TSC))
|
||||
panic("vmx_vminit: error setting guest msr access");
|
||||
|
||||
|
@ -103,6 +103,7 @@ enum {
|
||||
IDX_MSR_STAR,
|
||||
IDX_MSR_SF_MASK,
|
||||
IDX_MSR_KGSBASE,
|
||||
IDX_MSR_PAT,
|
||||
GUEST_MSR_NUM /* must be the last enumeration */
|
||||
};
|
||||
|
||||
|
@ -230,6 +230,25 @@ westmere_cpu(void)
|
||||
return (false);
|
||||
}
|
||||
|
||||
static bool
|
||||
pat_valid(uint64_t val)
|
||||
{
|
||||
int i, pa;
|
||||
|
||||
/*
|
||||
* From Intel SDM: Table "Memory Types That Can Be Encoded With PAT"
|
||||
*
|
||||
* Extract PA0 through PA7 and validate that each one encodes a
|
||||
* valid memory type.
|
||||
*/
|
||||
for (i = 0; i < 8; i++) {
|
||||
pa = (val >> (i * 8)) & 0xff;
|
||||
if (pa == 2 || pa == 3 || pa >= 8)
|
||||
return (false);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
void
|
||||
vmx_msr_init(void)
|
||||
{
|
||||
@ -302,6 +321,10 @@ vmx_msr_init(void)
|
||||
void
|
||||
vmx_msr_guest_init(struct vmx *vmx, int vcpuid)
|
||||
{
|
||||
uint64_t *guest_msrs;
|
||||
|
||||
guest_msrs = vmx->guest_msrs[vcpuid];
|
||||
|
||||
/*
|
||||
* The permissions bitmap is shared between all vcpus so initialize it
|
||||
* once when initializing the vBSP.
|
||||
@ -313,6 +336,19 @@ vmx_msr_guest_init(struct vmx *vmx, int vcpuid)
|
||||
guest_msr_rw(vmx, MSR_SF_MASK);
|
||||
guest_msr_rw(vmx, MSR_KGSBASE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize guest IA32_PAT MSR with default value after reset.
|
||||
*/
|
||||
guest_msrs[IDX_MSR_PAT] = PAT_VALUE(0, PAT_WRITE_BACK) |
|
||||
PAT_VALUE(1, PAT_WRITE_THROUGH) |
|
||||
PAT_VALUE(2, PAT_UNCACHED) |
|
||||
PAT_VALUE(3, PAT_UNCACHEABLE) |
|
||||
PAT_VALUE(4, PAT_WRITE_BACK) |
|
||||
PAT_VALUE(5, PAT_WRITE_THROUGH) |
|
||||
PAT_VALUE(6, PAT_UNCACHED) |
|
||||
PAT_VALUE(7, PAT_UNCACHEABLE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -353,7 +389,11 @@ vmx_msr_guest_exit(struct vmx *vmx, int vcpuid)
|
||||
int
|
||||
vmx_rdmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t *val, bool *retu)
|
||||
{
|
||||
int error = 0;
|
||||
const uint64_t *guest_msrs;
|
||||
int error;
|
||||
|
||||
guest_msrs = vmx->guest_msrs[vcpuid];
|
||||
error = 0;
|
||||
|
||||
switch (num) {
|
||||
case MSR_IA32_MISC_ENABLE:
|
||||
@ -366,6 +406,9 @@ vmx_rdmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t *val, bool *retu)
|
||||
case MSR_TURBO_RATIO_LIMIT1:
|
||||
*val = turbo_ratio_limit;
|
||||
break;
|
||||
case MSR_PAT:
|
||||
*val = guest_msrs[IDX_MSR_PAT];
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
@ -376,10 +419,13 @@ vmx_rdmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t *val, bool *retu)
|
||||
int
|
||||
vmx_wrmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t val, bool *retu)
|
||||
{
|
||||
uint64_t *guest_msrs;
|
||||
uint64_t changed;
|
||||
int error;
|
||||
|
||||
guest_msrs = vmx->guest_msrs[vcpuid];
|
||||
error = 0;
|
||||
|
||||
switch (num) {
|
||||
case MSR_IA32_MISC_ENABLE:
|
||||
changed = val ^ misc_enable;
|
||||
@ -401,6 +447,12 @@ vmx_wrmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t val, bool *retu)
|
||||
error = EINVAL;
|
||||
|
||||
break;
|
||||
case MSR_PAT:
|
||||
if (pat_valid(val))
|
||||
guest_msrs[IDX_MSR_PAT] = val;
|
||||
else
|
||||
vm_inject_gp(vmx->vm, vcpuid);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
|
@ -72,11 +72,7 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
ENTRY(armv7_setttb)
|
||||
stmdb sp!, {r0, lr}
|
||||
bl _C_LABEL(armv7_idcache_wbinv_all) /* clean the D cache */
|
||||
ldmia sp!, {r0, lr}
|
||||
dsb
|
||||
|
||||
orr r0, r0, #PT_ATTR
|
||||
mcr CP15_TTBR0(r0)
|
||||
isb
|
||||
|
@ -205,7 +205,7 @@ gic_decode_fdt(uint32_t iparent, uint32_t *intr, int *interrupt,
|
||||
*trig = INTR_TRIGGER_CONFORM;
|
||||
*pol = INTR_POLARITY_CONFORM;
|
||||
} else {
|
||||
if (intr[0] == 0)
|
||||
if (fdt32_to_cpu(intr[0]) == 0)
|
||||
*interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_SPI;
|
||||
else
|
||||
*interrupt = fdt32_to_cpu(intr[1]) + GIC_FIRST_PPI;
|
||||
@ -217,13 +217,13 @@ gic_decode_fdt(uint32_t iparent, uint32_t *intr, int *interrupt,
|
||||
* 8 = active low level-sensitive
|
||||
* The hardware only supports active-high-level or rising-edge.
|
||||
*/
|
||||
if (intr[2] & 0x0a) {
|
||||
if (fdt32_to_cpu(intr[2]) & 0x0a) {
|
||||
printf("unsupported trigger/polarity configuration "
|
||||
"0x%2x\n", intr[2] & 0x0f);
|
||||
"0x%2x\n", fdt32_to_cpu(intr[2]) & 0x0f);
|
||||
return (ENOTSUP);
|
||||
}
|
||||
*pol = INTR_POLARITY_CONFORM;
|
||||
if (intr[2] & 0x01)
|
||||
if (fdt32_to_cpu(intr[2]) & 0x01)
|
||||
*trig = INTR_TRIGGER_EDGE;
|
||||
else
|
||||
*trig = INTR_TRIGGER_LEVEL;
|
||||
|
@ -47,13 +47,22 @@
|
||||
ranges = <0x0 0x18000000 0x04000000>;
|
||||
bus-frequency = <0>;
|
||||
|
||||
pic: pic@4000 {
|
||||
compatible = "netlogic,xlp-pic";
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
reg = <0x4000 0x200>;
|
||||
};
|
||||
|
||||
serial0: serial@30100 {
|
||||
compatible = "ns16550";
|
||||
reg = <0x30100 0x200>;
|
||||
reg-shift = <2>;
|
||||
current-speed = <115200>;
|
||||
clock-frequency = <133000000>;
|
||||
interrupts = <9>;
|
||||
interrupt-parent = <&pic>;
|
||||
interrupts = <17>;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -1299,13 +1299,12 @@ fdt_merge_strings(int argc, char *argv[], int start, char **buffer)
|
||||
sz += argc - start;
|
||||
|
||||
buf = (char *)malloc(sizeof(char) * sz);
|
||||
bzero(buf, sizeof(char) * sz);
|
||||
|
||||
if (buf == NULL) {
|
||||
sprintf(command_errbuf, "could not allocate space "
|
||||
"for string");
|
||||
return (1);
|
||||
}
|
||||
bzero(buf, sizeof(char) * sz);
|
||||
|
||||
idx = 0;
|
||||
for (i = start, idx = 0; i < argc; i++) {
|
||||
|
@ -32,19 +32,63 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
#include <stand.h>
|
||||
#include <machine/pc/bios.h>
|
||||
#include "bootstrap.h"
|
||||
#include "libi386.h"
|
||||
#include "btxv86.h"
|
||||
|
||||
vm_offset_t memtop, memtop_copyin, high_heap_base;
|
||||
uint32_t bios_basemem, bios_extmem, high_heap_size;
|
||||
|
||||
static struct bios_smap smap;
|
||||
static struct bios_smap_xattr smap;
|
||||
|
||||
/*
|
||||
* Used to track which method was used to set BIOS memory
|
||||
* regions.
|
||||
*/
|
||||
static uint8_t b_bios_probed;
|
||||
#define B_BASEMEM_E820 0x1
|
||||
#define B_BASEMEM_12 0x2
|
||||
#define B_EXTMEM_E820 0x4
|
||||
#define B_EXTMEM_E801 0x8
|
||||
#define B_EXTMEM_8800 0x10
|
||||
|
||||
/*
|
||||
* The minimum amount of memory to reserve in bios_extmem for the heap.
|
||||
*/
|
||||
#define HEAP_MIN (3 * 1024 * 1024)
|
||||
|
||||
/*
|
||||
* Products in this list need quirks to detect
|
||||
* memory correctly. You need both maker and product as
|
||||
* reported by smbios.
|
||||
*/
|
||||
#define BQ_DISTRUST_E820_EXTMEM 0x1 /* e820 might not return useful
|
||||
extended memory */
|
||||
struct bios_getmem_quirks {
|
||||
const char* bios_vendor;
|
||||
const char* maker;
|
||||
const char* product;
|
||||
int quirk;
|
||||
};
|
||||
|
||||
static struct bios_getmem_quirks quirks[] = {
|
||||
{"coreboot", "Acer", "Peppy", BQ_DISTRUST_E820_EXTMEM},
|
||||
{NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
static int
|
||||
bios_getquirks(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; quirks[i].quirk != 0; ++i)
|
||||
if (smbios_match(quirks[i].bios_vendor, quirks[i].maker,
|
||||
quirks[i].product))
|
||||
return (quirks[i].quirk);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
bios_getmem(void)
|
||||
{
|
||||
@ -56,7 +100,7 @@ bios_getmem(void)
|
||||
v86.ctl = V86_FLAGS;
|
||||
v86.addr = 0x15; /* int 0x15 function 0xe820*/
|
||||
v86.eax = 0xe820;
|
||||
v86.ecx = sizeof(struct bios_smap);
|
||||
v86.ecx = sizeof(struct bios_smap_xattr);
|
||||
v86.edx = SMAP_SIG;
|
||||
v86.es = VTOPSEG(&smap);
|
||||
v86.edi = VTOPOFF(&smap);
|
||||
@ -65,11 +109,16 @@ bios_getmem(void)
|
||||
break;
|
||||
/* look for a low-memory segment that's large enough */
|
||||
if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) &&
|
||||
(smap.length >= (512 * 1024)))
|
||||
(smap.length >= (512 * 1024))) {
|
||||
bios_basemem = smap.length;
|
||||
b_bios_probed |= B_BASEMEM_E820;
|
||||
}
|
||||
|
||||
/* look for the first segment in 'extended' memory */
|
||||
if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000)) {
|
||||
if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000) &&
|
||||
!(bios_getquirks() & BQ_DISTRUST_E820_EXTMEM)) {
|
||||
bios_extmem = smap.length;
|
||||
b_bios_probed |= B_EXTMEM_E820;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -100,6 +149,7 @@ bios_getmem(void)
|
||||
v86int();
|
||||
|
||||
bios_basemem = (v86.eax & 0xffff) * 1024;
|
||||
b_bios_probed |= B_BASEMEM_12;
|
||||
}
|
||||
|
||||
/* Fall back through several compatibility functions for extended memory */
|
||||
@ -109,7 +159,30 @@ bios_getmem(void)
|
||||
v86.eax = 0xe801;
|
||||
v86int();
|
||||
if (!(V86_CY(v86.efl))) {
|
||||
bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024;
|
||||
/*
|
||||
* Clear high_heap; it may end up overlapping
|
||||
* with the segment we're determining here.
|
||||
* Let the default "steal stuff from top of
|
||||
* bios_extmem" code below pick up on it.
|
||||
*/
|
||||
high_heap_size = 0;
|
||||
high_heap_base = 0;
|
||||
|
||||
/*
|
||||
* %cx is the number of 1KiB blocks between 1..16MiB.
|
||||
* It can only be up to 0x3c00; if it's smaller then
|
||||
* there's a PC AT memory hole so we can't treat
|
||||
* it as contiguous.
|
||||
*/
|
||||
bios_extmem = (v86.ecx & 0xffff) * 1024;
|
||||
if (bios_extmem == (1024 * 0x3c00))
|
||||
bios_extmem += (v86.edx & 0xffff) * 64 * 1024;
|
||||
|
||||
/* truncate bios_extmem */
|
||||
if (bios_extmem > 0x3ff00000)
|
||||
bios_extmem = 0x3ff00000;
|
||||
|
||||
b_bios_probed |= B_EXTMEM_E801;
|
||||
}
|
||||
}
|
||||
if (bios_extmem == 0) {
|
||||
@ -118,6 +191,7 @@ bios_getmem(void)
|
||||
v86.eax = 0x8800;
|
||||
v86int();
|
||||
bios_extmem = (v86.eax & 0xffff) * 1024;
|
||||
b_bios_probed |= B_EXTMEM_8800;
|
||||
}
|
||||
|
||||
/* Set memtop to actual top of memory */
|
||||
@ -132,4 +206,36 @@ bios_getmem(void)
|
||||
high_heap_size = HEAP_MIN;
|
||||
high_heap_base = memtop - HEAP_MIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
command_biosmem(int argc, char *argv[])
|
||||
{
|
||||
int bq = bios_getquirks();
|
||||
|
||||
printf("bios_basemem: 0x%llx\n", (unsigned long long) bios_basemem);
|
||||
printf("bios_extmem: 0x%llx\n", (unsigned long long) bios_extmem);
|
||||
printf("memtop: 0x%llx\n", (unsigned long long) memtop);
|
||||
printf("high_heap_base: 0x%llx\n", (unsigned long long) high_heap_base);
|
||||
printf("high_heap_size: 0x%llx\n", (unsigned long long) high_heap_size);
|
||||
printf("bios_quirks: 0x%02x", bq);
|
||||
if (bq & BQ_DISTRUST_E820_EXTMEM)
|
||||
printf(" BQ_DISTRUST_E820_EXTMEM");
|
||||
printf("\n");
|
||||
printf("b_bios_probed: 0x%02x", (int) b_bios_probed);
|
||||
if (b_bios_probed & B_BASEMEM_E820)
|
||||
printf(" B_BASEMEM_E820");
|
||||
if (b_bios_probed & B_BASEMEM_12)
|
||||
printf(" B_BASEMEM_12");
|
||||
if (b_bios_probed & B_EXTMEM_E820)
|
||||
printf(" B_EXTMEM_E820");
|
||||
if (b_bios_probed & B_EXTMEM_E801)
|
||||
printf(" B_EXTMEM_E801");
|
||||
if (b_bios_probed & B_EXTMEM_8800)
|
||||
printf(" B_EXTMEM_8800");
|
||||
printf("\n");
|
||||
|
||||
return (CMD_OK);
|
||||
}
|
||||
|
||||
COMMAND_SET(biosmem, "biosmem", "show BIOS memory setup", command_biosmem);
|
||||
|
@ -7442,6 +7442,71 @@ scsi_persistent_reserve_out(struct ccb_scsiio *csio, uint32_t retries,
|
||||
scsi_cmd->opcode = PERSISTENT_RES_OUT;
|
||||
scsi_cmd->action = service_action;
|
||||
scsi_cmd->scope_type = scope | res_type;
|
||||
|
||||
cam_fill_csio(csio,
|
||||
retries,
|
||||
cbfcnp,
|
||||
/*flags*/CAM_DIR_OUT,
|
||||
tag_action,
|
||||
/*data_ptr*/data_ptr,
|
||||
/*dxfer_len*/dxfer_len,
|
||||
sense_len,
|
||||
sizeof(*scsi_cmd),
|
||||
timeout);
|
||||
}
|
||||
|
||||
void
|
||||
scsi_security_protocol_in(struct ccb_scsiio *csio, uint32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
uint8_t tag_action, uint32_t security_protocol,
|
||||
uint32_t security_protocol_specific, int byte4,
|
||||
uint8_t *data_ptr, uint32_t dxfer_len, int sense_len,
|
||||
int timeout)
|
||||
{
|
||||
struct scsi_security_protocol_in *scsi_cmd;
|
||||
|
||||
scsi_cmd = (struct scsi_security_protocol_in *)&csio->cdb_io.cdb_bytes;
|
||||
bzero(scsi_cmd, sizeof(*scsi_cmd));
|
||||
|
||||
scsi_cmd->opcode = SECURITY_PROTOCOL_IN;
|
||||
|
||||
scsi_cmd->security_protocol = security_protocol;
|
||||
scsi_ulto2b(security_protocol_specific,
|
||||
scsi_cmd->security_protocol_specific);
|
||||
scsi_cmd->byte4 = byte4;
|
||||
scsi_ulto4b(dxfer_len, scsi_cmd->length);
|
||||
|
||||
cam_fill_csio(csio,
|
||||
retries,
|
||||
cbfcnp,
|
||||
/*flags*/CAM_DIR_IN,
|
||||
tag_action,
|
||||
data_ptr,
|
||||
dxfer_len,
|
||||
sense_len,
|
||||
sizeof(*scsi_cmd),
|
||||
timeout);
|
||||
}
|
||||
|
||||
void
|
||||
scsi_security_protocol_out(struct ccb_scsiio *csio, uint32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
uint8_t tag_action, uint32_t security_protocol,
|
||||
uint32_t security_protocol_specific, int byte4,
|
||||
uint8_t *data_ptr, uint32_t dxfer_len, int sense_len,
|
||||
int timeout)
|
||||
{
|
||||
struct scsi_security_protocol_out *scsi_cmd;
|
||||
|
||||
scsi_cmd = (struct scsi_security_protocol_out *)&csio->cdb_io.cdb_bytes;
|
||||
bzero(scsi_cmd, sizeof(*scsi_cmd));
|
||||
|
||||
scsi_cmd->opcode = SECURITY_PROTOCOL_OUT;
|
||||
|
||||
scsi_cmd->security_protocol = security_protocol;
|
||||
scsi_ulto2b(security_protocol_specific,
|
||||
scsi_cmd->security_protocol_specific);
|
||||
scsi_cmd->byte4 = byte4;
|
||||
scsi_ulto4b(dxfer_len, scsi_cmd->length);
|
||||
|
||||
cam_fill_csio(csio,
|
||||
|
@ -1758,6 +1758,7 @@ struct ata_pass_16 {
|
||||
#define SERVICE_ACTION_IN 0x9E
|
||||
#define REPORT_LUNS 0xA0
|
||||
#define ATA_PASS_12 0xA1
|
||||
#define SECURITY_PROTOCOL_IN 0xA2
|
||||
#define MAINTENANCE_IN 0xA3
|
||||
#define MAINTENANCE_OUT 0xA4
|
||||
#define MOVE_MEDIUM 0xA5
|
||||
@ -1765,6 +1766,7 @@ struct ata_pass_16 {
|
||||
#define WRITE_12 0xAA
|
||||
#define WRITE_VERIFY_12 0xAE
|
||||
#define VERIFY_12 0xAF
|
||||
#define SECURITY_PROTOCOL_OUT 0xB5
|
||||
#define READ_ELEMENT_STATUS 0xB8
|
||||
#define READ_CD 0xBE
|
||||
|
||||
@ -2702,6 +2704,41 @@ struct scsi_target_group_data_extended {
|
||||
struct scsi_target_port_group_descriptor groups[];
|
||||
};
|
||||
|
||||
struct scsi_security_protocol_in
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t security_protocol;
|
||||
#define SPI_PROT_INFORMATION 0x00
|
||||
#define SPI_PROT_CBCS 0x07
|
||||
#define SPI_PROT_TAPE_DATA_ENC 0x20
|
||||
#define SPI_PROT_DATA_ENC_CONFIG 0x21
|
||||
#define SPI_PROT_SA_CREATE_CAP 0x40
|
||||
#define SPI_PROT_IKEV2_SCSI 0x41
|
||||
#define SPI_PROT_JEDEC_UFS 0xEC
|
||||
#define SPI_PROT_SDCARD_TFSSS 0xED
|
||||
#define SPI_PROT_AUTH_HOST_TRANSIENT 0xEE
|
||||
#define SPI_PROT_ATA_DEVICE_PASSWORD 0xEF
|
||||
uint8_t security_protocol_specific[2];
|
||||
uint8_t byte4;
|
||||
#define SPI_INC_512 0x80
|
||||
uint8_t reserved1;
|
||||
uint8_t length[4];
|
||||
uint8_t reserved2;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
struct scsi_security_protocol_out
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint8_t security_protocol;
|
||||
uint8_t security_protocol_specific[2];
|
||||
uint8_t byte4;
|
||||
#define SPO_INC_512 0x80
|
||||
uint8_t reserved1;
|
||||
uint8_t length[4];
|
||||
uint8_t reserved2;
|
||||
uint8_t control;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SSD_TYPE_NONE,
|
||||
@ -3623,6 +3660,20 @@ void scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
u_int8_t tag_action, int start, int load_eject,
|
||||
int immediate, u_int8_t sense_len, u_int32_t timeout);
|
||||
|
||||
void scsi_security_protocol_in(struct ccb_scsiio *csio, uint32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
uint8_t tag_action, uint32_t security_protocol,
|
||||
uint32_t security_protocol_specific, int byte4,
|
||||
uint8_t *data_ptr, uint32_t dxfer_len,
|
||||
int sense_len, int timeout);
|
||||
|
||||
void scsi_security_protocol_out(struct ccb_scsiio *csio, uint32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *,union ccb *),
|
||||
uint8_t tag_action, uint32_t security_protocol,
|
||||
uint32_t security_protocol_specific, int byte4,
|
||||
uint8_t *data_ptr, uint32_t dxfer_len,
|
||||
int sense_len, int timeout);
|
||||
|
||||
void scsi_persistent_reserve_in(struct ccb_scsiio *csio, uint32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *,union ccb *),
|
||||
uint8_t tag_action, int service_action,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@
|
||||
* SCSI Sequential Access Peripheral driver for CAM.
|
||||
*
|
||||
* Copyright (c) 1999, 2000 Matthew Jacob
|
||||
* Copyright (c) 2013, 2014, 2015 Spectra Logic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -141,6 +142,53 @@ struct scsi_erase
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
/*
|
||||
* Set tape capacity.
|
||||
*/
|
||||
struct scsi_set_capacity
|
||||
{
|
||||
u_int8_t opcode;
|
||||
u_int8_t byte1;
|
||||
#define SA_SSC_IMMED 0x01
|
||||
u_int8_t reserved;
|
||||
u_int8_t cap_proportion[2];
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
/*
|
||||
* Format tape media. The CDB opcode is the same as the disk-specific
|
||||
* FORMAT UNIT command, but the fields are different inside the CDB. Thus
|
||||
* the reason for a separate definition here.
|
||||
*/
|
||||
struct scsi_format_medium
|
||||
{
|
||||
u_int8_t opcode;
|
||||
u_int8_t byte1;
|
||||
#define SFM_IMMED 0x01
|
||||
#define SFM_VERIFY 0x02
|
||||
u_int8_t byte2;
|
||||
#define SFM_FORMAT_DEFAULT 0x00
|
||||
#define SFM_FORMAT_PARTITION 0x01
|
||||
#define SFM_FORMAT_DEF_PART 0x02
|
||||
#define SFM_FORMAT_MASK 0x0f
|
||||
u_int8_t length[2];
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
struct scsi_allow_overwrite
|
||||
{
|
||||
u_int8_t opcode;
|
||||
u_int8_t reserved1;
|
||||
u_int8_t allow_overwrite;
|
||||
#define SAO_ALLOW_OVERWRITE_DISABLED 0x00
|
||||
#define SAO_ALLOW_OVERWRITE_CUR_POS 0x01
|
||||
#define SAO_ALLOW_OVERWRITE_FORMAT 0x02
|
||||
u_int8_t partition;
|
||||
u_int8_t logical_id[8];
|
||||
u_int8_t reserved2[3];
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
/*
|
||||
* Dev specific mode page masks.
|
||||
*/
|
||||
@ -180,11 +228,18 @@ struct scsi_dev_conf_page {
|
||||
#define SA_BIS 0x40 /* block identifiers supported */
|
||||
#define SA_RSMK 0x20 /* report setmarks */
|
||||
#define SA_AVC 0x10 /* automatic velocity control */
|
||||
#define SA_SOCF_MASK 0xc0 /* stop on consecutive formats */
|
||||
#define SA_RBO 0x20 /* recover buffer order */
|
||||
#define SA_REW 0x10 /* report early warning */
|
||||
#define SA_SOCF_MASK 0x0c /* stop on consecutive formats */
|
||||
#define SA_RBO 0x02 /* recover buffer order */
|
||||
#define SA_REW 0x01 /* report early warning */
|
||||
u_int8_t gap_size;
|
||||
u_int8_t byte10;
|
||||
/* from SCSI-3: SSC-4 Working draft (2/14) 8.3.3 */
|
||||
#define SA_EOD_DEF_MASK 0xe0 /* EOD defined */
|
||||
#define SA_EEG 0x10 /* Enable EOD Generation */
|
||||
#define SA_SEW 0x08 /* Synchronize at Early Warning */
|
||||
#define SA_SOFT_WP 0x04 /* Software Write Protect */
|
||||
#define SA_BAML 0x02 /* Block Address Mode Lock */
|
||||
#define SA_BAM 0x01 /* Block Address Mode */
|
||||
u_int8_t ew_bufsize[3];
|
||||
u_int8_t sel_comp_alg;
|
||||
#define SA_COMP_NONE 0x00
|
||||
@ -221,10 +276,78 @@ typedef union {
|
||||
struct scsi_data_compression_page dcomp;
|
||||
} sa_comp_t;
|
||||
|
||||
/*
|
||||
* Control Data Protection subpage. This is as defined in SSC3r03.
|
||||
*/
|
||||
struct scsi_control_data_prot_subpage {
|
||||
uint8_t page_code;
|
||||
#define SA_CTRL_DP_PAGE_CODE 0x0a
|
||||
uint8_t subpage_code;
|
||||
#define SA_CTRL_DP_SUBPAGE_CODE 0xf0
|
||||
uint8_t length[2];
|
||||
uint8_t prot_method;
|
||||
#define SA_CTRL_DP_NO_LBP 0x00
|
||||
#define SA_CTRL_DP_REED_SOLOMON 0x01
|
||||
#define SA_CTRL_DP_METHOD_MAX 0xff
|
||||
uint8_t pi_length;
|
||||
#define SA_CTRL_DP_PI_LENGTH_MASK 0x3f
|
||||
#define SA_CTRL_DP_RS_LENGTH 4
|
||||
uint8_t prot_bits;
|
||||
#define SA_CTRL_DP_LBP_W 0x80
|
||||
#define SA_CTRL_DP_LBP_R 0x40
|
||||
#define SA_CTRL_DP_RBDP 0x20
|
||||
uint8_t reserved[];
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the Read/Write Control mode page used on IBM Enterprise Tape
|
||||
* Drives. They are known as 3592, TS, or Jaguar drives. The SCSI inquiry
|
||||
* data will show a Product ID "03592XXX", where XXX is 'J1A', 'E05' (TS1120),
|
||||
* 'E06' (TS1130), 'E07' (TS1140) or 'E08' (TS1150).
|
||||
*
|
||||
* This page definition is current as of the 3592 SCSI Reference v6,
|
||||
* released on December 16th, 2014.
|
||||
*/
|
||||
struct scsi_tape_ibm_rw_control {
|
||||
uint8_t page_code;
|
||||
#define SA_IBM_RW_CTRL_PAGE_CODE 0x25
|
||||
uint8_t page_length;
|
||||
uint8_t ignore_seq_checks;
|
||||
#define SA_IBM_RW_CTRL_LOC_IGNORE_SEQ 0x04
|
||||
#define SA_IBM_RW_CTRL_SPC_BLK_IGNORE_SEQ 0x02
|
||||
#define SA_IBM_RW_CTRL_SPC_FM_IGNORE_SEQ 0x01
|
||||
uint8_t ignore_data_checks;
|
||||
#define SA_IBM_RW_CTRL_LOC_IGNORE_DATA 0x04
|
||||
#define SA_IBM_RW_CTRL_SPC_BLK_IGNORE_DATA 0x02
|
||||
#define SA_IBM_RW_CTRL_SPC_FM_IGNORE_DATA 0x01
|
||||
uint8_t reserved1;
|
||||
uint8_t leop_method;
|
||||
#define SA_IBM_RW_CTRL_LEOP_DEFAULT 0x00
|
||||
#define SA_IBM_RW_CTRL_LEOP_MAX_CAP 0x01
|
||||
#define SA_IBM_RW_CTRL_LEOP_CONST_CAP 0x02
|
||||
uint8_t leop_ew[2];
|
||||
uint8_t byte8;
|
||||
#define SA_IBM_RW_CTRL_DISABLE_FASTSYNC 0x80
|
||||
#define SA_IBM_RW_CTRL_DISABLE_SKIPSYNC 0x40
|
||||
#define SA_IBM_RW_CTRL_DISABLE_CROSS_EOD 0x08
|
||||
#define SA_IBM_RW_CTRL_DISABLE_CROSS_PERM_ERR 0x04
|
||||
#define SA_IBM_RW_CTRL_REPORT_SEG_EW 0x02
|
||||
#define SA_IBM_RW_CTRL_REPORT_HOUSEKEEPING_ERR 0x01
|
||||
uint8_t default_write_dens_bop_0;
|
||||
uint8_t pending_write_dens_bop_0;
|
||||
uint8_t reserved2[21];
|
||||
};
|
||||
|
||||
struct scsi_tape_read_position {
|
||||
u_int8_t opcode; /* READ_POSITION */
|
||||
u_int8_t byte1; /* set LSB to read hardware block pos */
|
||||
u_int8_t reserved[8];
|
||||
#define SA_RPOS_SHORT_FORM 0x00
|
||||
#define SA_RPOS_SHORT_VENDOR 0x01
|
||||
#define SA_RPOS_LONG_FORM 0x06
|
||||
#define SA_RPOS_EXTENDED_FORM 0x08
|
||||
u_int8_t reserved[5];
|
||||
u_int8_t length[2];
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
struct scsi_tape_position_data { /* Short Form */
|
||||
@ -235,6 +358,7 @@ struct scsi_tape_position_data { /* Short Form */
|
||||
#define SA_RPOS_BYCU 0x10 /* Byte Count Unknown (SCSI3) */
|
||||
#define SA_RPOS_BPU 0x04 /* Block Position Unknown */
|
||||
#define SA_RPOS_PERR 0x02 /* Position Error (SCSI3) */
|
||||
#define SA_RPOS_BPEW 0x01 /* Beyond Programmable Early Warning */
|
||||
#define SA_RPOS_UNCERTAIN SA_RPOS_BPU
|
||||
u_int8_t partition;
|
||||
u_int8_t reserved[2];
|
||||
@ -245,6 +369,38 @@ struct scsi_tape_position_data { /* Short Form */
|
||||
u_int8_t nbufbyte[4];
|
||||
};
|
||||
|
||||
struct scsi_tape_position_long_data {
|
||||
u_int8_t flags;
|
||||
#define SA_RPOS_LONG_BOP 0x80 /* Beginning of Partition */
|
||||
#define SA_RPOS_LONG_EOP 0x40 /* End of Partition */
|
||||
#define SA_RPOS_LONG_MPU 0x08 /* Mark Position Unknown */
|
||||
#define SA_RPOS_LONG_LONU 0x04 /* Logical Object Number Unknown */
|
||||
#define SA_RPOS_LONG_BPEW 0x01 /* Beyond Programmable Early Warning */
|
||||
u_int8_t reserved[3];
|
||||
u_int8_t partition[4];
|
||||
u_int8_t logical_object_num[8];
|
||||
u_int8_t logical_file_num[8];
|
||||
u_int8_t set_id[8];
|
||||
};
|
||||
|
||||
struct scsi_tape_position_ext_data {
|
||||
u_int8_t flags;
|
||||
#define SA_RPOS_EXT_BOP 0x80 /* Beginning of Partition */
|
||||
#define SA_RPOS_EXT_EOP 0x40 /* End of Partition */
|
||||
#define SA_RPOS_EXT_LOCU 0x20 /* Logical Object Count Unknown */
|
||||
#define SA_RPOS_EXT_BYCU 0x10 /* Byte Count Unknown */
|
||||
#define SA_RPOS_EXT_LOLU 0x04 /* Logical Object Location Unknown */
|
||||
#define SA_RPOS_EXT_PERR 0x02 /* Position Error */
|
||||
#define SA_RPOS_EXT_BPEW 0x01 /* Beyond Programmable Early Warning */
|
||||
u_int8_t partition;
|
||||
u_int8_t length[2];
|
||||
u_int8_t reserved;
|
||||
u_int8_t num_objects[3];
|
||||
u_int8_t first_object[8];
|
||||
u_int8_t last_object[8];
|
||||
u_int8_t bytes_in_buffer[8];
|
||||
};
|
||||
|
||||
struct scsi_tape_locate {
|
||||
u_int8_t opcode;
|
||||
u_int8_t byte1;
|
||||
@ -253,18 +409,521 @@ struct scsi_tape_locate {
|
||||
#define SA_SPOS_BT 0x04
|
||||
u_int8_t reserved1;
|
||||
u_int8_t blkaddr[4];
|
||||
#define SA_SPOS_MAX_BLK 0xffffffff
|
||||
u_int8_t reserved2;
|
||||
u_int8_t partition;
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
struct scsi_locate_16 {
|
||||
u_int8_t opcode;
|
||||
u_int8_t byte1;
|
||||
#define SA_LC_IMMEDIATE 0x01
|
||||
#define SA_LC_CP 0x02
|
||||
#define SA_LC_DEST_TYPE_MASK 0x38
|
||||
#define SA_LC_DEST_TYPE_SHIFT 3
|
||||
#define SA_LC_DEST_OBJECT 0x00
|
||||
#define SA_LC_DEST_FILE 0x01
|
||||
#define SA_LC_DEST_SET 0x02
|
||||
#define SA_LC_DEST_EOD 0x03
|
||||
u_int8_t byte2;
|
||||
#define SA_LC_BAM_IMPLICIT 0x00
|
||||
#define SA_LC_BAM_EXPLICIT 0x01
|
||||
u_int8_t partition;
|
||||
u_int8_t logical_id[8];
|
||||
u_int8_t reserved[3];
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
struct scsi_report_density_support {
|
||||
u_int8_t opcode;
|
||||
u_int8_t byte1;
|
||||
#define SRDS_MEDIA 0x01
|
||||
#define SRDS_MEDIUM_TYPE 0x02
|
||||
u_int8_t reserved[5];
|
||||
u_int8_t length[2];
|
||||
#define SRDS_MAX_LENGTH 0xffff
|
||||
u_int8_t control;
|
||||
};
|
||||
|
||||
struct scsi_density_hdr {
|
||||
u_int8_t length[2];
|
||||
u_int8_t reserved[2];
|
||||
u_int8_t descriptor[];
|
||||
};
|
||||
|
||||
struct scsi_density_data {
|
||||
u_int8_t primary_density_code;
|
||||
u_int8_t secondary_density_code;
|
||||
u_int8_t byte2;
|
||||
#define SDD_DLV 0x01
|
||||
#define SDD_DEFLT 0x20
|
||||
#define SDD_DUP 0x40
|
||||
#define SDD_WRTOK 0x80
|
||||
u_int8_t length[2];
|
||||
#define SDD_DEFAULT_LENGTH 52
|
||||
u_int8_t bits_per_mm[3];
|
||||
u_int8_t media_width[2];
|
||||
u_int8_t tracks[2];
|
||||
u_int8_t capacity[4];
|
||||
u_int8_t assigning_org[8];
|
||||
u_int8_t density_name[8];
|
||||
u_int8_t description[20];
|
||||
};
|
||||
|
||||
struct scsi_medium_type_data {
|
||||
u_int8_t medium_type;
|
||||
u_int8_t reserved1;
|
||||
u_int8_t length[2];
|
||||
#define SMTD_DEFAULT_LENGTH 52
|
||||
u_int8_t num_density_codes;
|
||||
u_int8_t primary_density_codes[8];
|
||||
u_int8_t media_width[2];
|
||||
u_int8_t medium_length[2];
|
||||
u_int8_t reserved2[2];
|
||||
u_int8_t assigning_org[8];
|
||||
u_int8_t medium_type_name[8];
|
||||
u_int8_t description[20];
|
||||
};
|
||||
|
||||
/*
|
||||
* Security Protocol Specific values for the Tape Data Encryption protocol
|
||||
* (0x20) used with SECURITY PROTOCOL IN. See below for values used with
|
||||
* SECURITY PROTOCOL OUT. Current as of SSC4r03.
|
||||
*/
|
||||
#define TDE_IN_SUPPORT_PAGE 0x0000
|
||||
#define TDE_OUT_SUPPORT_PAGE 0x0001
|
||||
#define TDE_DATA_ENC_CAP_PAGE 0x0010
|
||||
#define TDE_SUPPORTED_KEY_FORMATS_PAGE 0x0011
|
||||
#define TDE_DATA_ENC_MAN_CAP_PAGE 0x0012
|
||||
#define TDE_DATA_ENC_STATUS_PAGE 0x0020
|
||||
#define TDE_NEXT_BLOCK_ENC_STATUS_PAGE 0x0021
|
||||
#define TDE_GET_ENC_MAN_ATTR_PAGE 0x0022
|
||||
#define TDE_RANDOM_NUM_PAGE 0x0030
|
||||
#define TDE_KEY_WRAP_PK_PAGE 0x0031
|
||||
|
||||
/*
|
||||
* Tape Data Encryption protocol pages used with SECURITY PROTOCOL IN and
|
||||
* SECURITY PROTOCOL OUT.
|
||||
*/
|
||||
/*
|
||||
* Tape Data Encryption In Support page (0x0000).
|
||||
*/
|
||||
struct tde_in_support_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t page_length[2];
|
||||
uint8_t page_codes[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tape Data Encryption Out Support page (0x0001).
|
||||
*/
|
||||
struct tde_out_support_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t page_length[2];
|
||||
uint8_t page_codes[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Logical block encryption algorithm descriptor. This is reported in the
|
||||
* Data Encryption Capabilities page.
|
||||
*/
|
||||
struct tde_block_enc_alg_desc {
|
||||
uint8_t alg_index;
|
||||
uint8_t reserved1;
|
||||
uint8_t desc_length[2];
|
||||
uint8_t byte4;
|
||||
#define TDE_BEA_AVFMV 0x80
|
||||
#define TDE_BEA_SDK_C 0x40
|
||||
#define TDE_BEA_MAC_C 0x20
|
||||
#define TDE_BEA_DELB_C 0x10
|
||||
#define TDE_BEA_DECRYPT_C_MASK 0x0c
|
||||
#define TDE_BEA_DECRYPT_C_EXT 0x0c
|
||||
#define TDE_BEA_DECRYPT_C_HARD 0x08
|
||||
#define TDE_BEA_DECRYPT_C_SOFT 0x04
|
||||
#define TDE_BEA_DECRYPT_C_NO_CAP 0x00
|
||||
#define TDE_BEA_ENCRYPT_C_MASK 0x03
|
||||
#define TDE_BEA_ENCRYPT_C_EXT 0x03
|
||||
#define TDE_BEA_ENCRYPT_C_HARD 0x02
|
||||
#define TDE_BEA_ENCRYPT_C_SOFT 0x01
|
||||
#define TDE_BEA_ENCRYPT_C_NO_CAP 0x00
|
||||
uint8_t byte5;
|
||||
#define TDE_BEA_AVFCLP_MASK 0xc0
|
||||
#define TDE_BEA_AVFCLP_VALID 0x80
|
||||
#define TDE_BEA_AVFCLP_NOT_VALID 0x40
|
||||
#define TDE_BEA_AVFCLP_NOT_APP 0x00
|
||||
#define TDE_BEA_NONCE_C_MASK 0x30
|
||||
#define TDE_BEA_NONCE_C_SUPPORTED 0x30
|
||||
#define TDE_BEA_NONCE_C_PROVIDED 0x20
|
||||
#define TDE_BEA_NONCE_C_GENERATED 0x10
|
||||
#define TDE_BEA_NONCE_C_NOT_REQUIRED 0x00
|
||||
#define TDE_BEA_KADF_C 0x08
|
||||
#define TDE_BEA_VCELB_C 0x04
|
||||
#define TDE_BEA_UKADF 0x02
|
||||
#define TDE_BEA_AKADF 0x01
|
||||
uint8_t max_unauth_key_bytes[2];
|
||||
uint8_t max_auth_key_bytes[2];
|
||||
uint8_t lbe_key_size[2];
|
||||
uint8_t byte12;
|
||||
#define TDE_BEA_DKAD_C_MASK 0xc0
|
||||
#define TDE_BEA_DKAD_C_CAPABLE 0xc0
|
||||
#define TDE_BEA_DKAD_C_NOT_ALLOWED 0x80
|
||||
#define TDE_BEA_DKAD_C_REQUIRED 0x40
|
||||
#define TDE_BEA_EEMC_C_MASK 0x30
|
||||
#define TDE_BEA_EEMC_C_ALLOWED 0x20
|
||||
#define TDE_BEA_EEMC_C_NOT_ALLOWED 0x10
|
||||
#define TDE_BEA_EEMC_C_NOT_SPECIFIED 0x00
|
||||
/*
|
||||
* Raw Decryption Mode Control Capabilities (RDMC_C) field. The
|
||||
* descriptions are too complex to represent as a simple name.
|
||||
*/
|
||||
#define TDE_BEA_RDMC_C_MASK 0x0e
|
||||
#define TDE_BEA_RDMC_C_MODE_7 0x0e
|
||||
#define TDE_BEA_RDMC_C_MODE_6 0x0c
|
||||
#define TDE_BEA_RDMC_C_MODE_5 0x0a
|
||||
#define TDE_BEA_RDMC_C_MODE_4 0x08
|
||||
#define TDE_BEA_RDMC_C_MODE_1 0x02
|
||||
#define TDE_BEA_EAREM 0x01
|
||||
uint8_t byte13;
|
||||
#define TDE_BEA_MAX_EEDKS_MASK 0x0f
|
||||
uint8_t msdk_count[2];
|
||||
uint8_t max_eedk_size[2];
|
||||
uint8_t reserved2[2];
|
||||
uint8_t security_algo_code[4];
|
||||
};
|
||||
|
||||
/*
|
||||
* Data Encryption Capabilities page (0x0010).
|
||||
*/
|
||||
struct tde_data_enc_cap_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t page_length;
|
||||
uint8_t byte4;
|
||||
#define DATA_ENC_CAP_EXTDECC_MASK 0x0c
|
||||
#define DATA_ENC_CAP_EXTDECC_NOT_REPORTED 0x00
|
||||
#define DATA_ENC_CAP_EXTDECC_NOT_CAPABLE 0x04
|
||||
#define DATA_ENC_CAP_EXTDECC_CAPABLE 0x08
|
||||
#define DATA_ENC_CAP_CFG_P_MASK 0x03
|
||||
#define DATA_ENC_CAP_CFG_P_NOT_REPORTED 0x00
|
||||
#define DATA_ENC_CAP_CFG_P_ALLOWED 0x01
|
||||
#define DATA_ENC_CAP_CFG_P_NOT_ALLOWED 0x02
|
||||
uint8_t reserved[15];
|
||||
struct tde_block_enc_alg_desc alg_descs[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tape Data Encryption Supported Key Formats page (0x0011).
|
||||
*/
|
||||
struct tde_supported_key_formats_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t page_length[2];
|
||||
uint8_t key_formats_list[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tape Data Encryption Management Capabilities page (0x0012).
|
||||
*/
|
||||
struct tde_data_enc_man_cap_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t page_length[2];
|
||||
uint8_t byte4;
|
||||
#define TDE_DEMC_LOCK_C 0x01
|
||||
uint8_t byte5;
|
||||
#define TDE_DEMC_CKOD_C 0x04
|
||||
#define TDE_DEMC_CKORP_C 0x02
|
||||
#define TDE_DEMC_CKORL_C 0x01
|
||||
uint8_t reserved1;
|
||||
uint8_t byte7;
|
||||
#define TDE_DEMC_AITN_C 0x04
|
||||
#define TDE_DEMC_LOCAL_C 0x02
|
||||
#define TDE_DEMC_PUBLIC_C 0x01
|
||||
uint8_t reserved2[8];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tape Data Encryption Status Page (0x0020).
|
||||
*/
|
||||
struct tde_data_enc_status_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t page_length[2];
|
||||
uint8_t scope;
|
||||
#define TDE_DES_IT_NEXUS_SCOPE_MASK 0xe0
|
||||
#define TDE_DES_LBE_SCOPE_MASK 0x07
|
||||
uint8_t encryption_mode;
|
||||
uint8_t decryption_mode;
|
||||
uint8_t algo_index;
|
||||
uint8_t key_instance_counter[4];
|
||||
uint8_t byte12;
|
||||
#define TDE_DES_PARAM_CTRL_MASK 0x70
|
||||
#define TDE_DES_PARAM_CTRL_MGMT 0x40
|
||||
#define TDE_DES_PARAM_CTRL_CHANGER 0x30
|
||||
#define TDE_DES_PARAM_CTRL_DRIVE 0x20
|
||||
#define TDE_DES_PARAM_CTRL_EXT 0x10
|
||||
#define TDE_DES_PARAM_CTRL_NOT_REPORTED 0x00
|
||||
#define TDE_DES_VCELB 0x08
|
||||
#define TDE_DES_CEEMS_MASK 0x06
|
||||
#define TDE_DES_RDMD 0x01
|
||||
uint8_t enc_params_kad_format;
|
||||
uint8_t asdk_count[2];
|
||||
uint8_t reserved[8];
|
||||
uint8_t key_assoc_data_desc[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tape Data Encryption Next Block Encryption Status page (0x0021).
|
||||
*/
|
||||
struct tde_next_block_enc_status_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t page_length[2];
|
||||
uint8_t logical_obj_number[8];
|
||||
uint8_t status;
|
||||
#define TDE_NBES_COMP_STATUS_MASK 0xf0
|
||||
#define TDE_NBES_COMP_INCAPABLE 0x00
|
||||
#define TDE_NBES_COMP_NOT_YET 0x10
|
||||
#define TDE_NBES_COMP_NOT_A_BLOCK 0x20
|
||||
#define TDE_NBES_COMP_NOT_COMPRESSED 0x30
|
||||
#define TDE_NBES_COMP_COMPRESSED 0x40
|
||||
#define TDE_NBES_ENC_STATUS_MASK 0x0f
|
||||
#define TDE_NBES_ENC_INCAPABLE 0x00
|
||||
#define TDE_NBES_ENC_NOT_YET 0x01
|
||||
#define TDE_NBES_ENC_NOT_A_BLOCK 0x02
|
||||
#define TDE_NBES_ENC_NOT_ENCRYPTED 0x03
|
||||
#define TDE_NBES_ENC_ALG_NOT_SUPPORTED 0x04
|
||||
#define TDE_NBES_ENC_SUPPORTED_ALG 0x05
|
||||
#define TDE_NBES_ENC_NO_KEY 0x06
|
||||
uint8_t algo_index;
|
||||
uint8_t byte14;
|
||||
#define TDE_NBES_EMES 0x02
|
||||
#define TDE_NBES_RDMDS 0x01
|
||||
uint8_t next_block_kad_format;
|
||||
uint8_t key_assoc_data_desc[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tape Data Encryption Get Encryption Management Attributes page (0x0022).
|
||||
*/
|
||||
struct tde_get_enc_man_attr_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t reserved[3];
|
||||
uint8_t byte5;
|
||||
#define TDE_GEMA_CAOD 0x01
|
||||
uint8_t page_length[2];
|
||||
uint8_t enc_mgmt_attr_desc[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tape Data Encryption Random Number page (0x0030).
|
||||
*/
|
||||
struct tde_random_num_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t page_length[2];
|
||||
uint8_t random_number[32];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tape Data Encryption Device Server Key Wrapping Public Key page (0x0031).
|
||||
*/
|
||||
struct tde_key_wrap_pk_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t page_length[2];
|
||||
uint8_t public_key_type[4];
|
||||
uint8_t public_key_format[4];
|
||||
uint8_t public_key_length[2];
|
||||
uint8_t public_key[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Security Protocol Specific values for the Tape Data Encryption protocol
|
||||
* (0x20) used with SECURITY PROTOCOL OUT. See above for values used with
|
||||
* SECURITY PROTOCOL IN. Current as of SSCr03.
|
||||
*/
|
||||
#define TDE_SET_DATA_ENC_PAGE 0x0010
|
||||
#define TDE_SA_ENCAP_PAGE 0x0011
|
||||
#define TDE_SET_ENC_MGMT_ATTR_PAGE 0x0022
|
||||
|
||||
/*
|
||||
* Tape Data Encryption Set Data Encryption page (0x0010).
|
||||
*/
|
||||
struct tde_set_data_enc_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t page_length[2];
|
||||
uint8_t byte4;
|
||||
#define TDE_SDE_SCOPE_MASK 0xe0
|
||||
#define TDE_SDE_SCOPE_ALL_IT_NEXUS 0x80
|
||||
#define TDE_SDE_SCOPE_LOCAL 0x40
|
||||
#define TDE_SDE_SCOPE_PUBLIC 0x00
|
||||
#define TDE_SDE_LOCK 0x01
|
||||
uint8_t byte5;
|
||||
#define TDE_SDE_CEEM_MASK 0xc0
|
||||
#define TDE_SDE_CEEM_ENCRYPT 0xc0
|
||||
#define TDE_SDE_CEEM_EXTERNAL 0x80
|
||||
#define TDE_SDE_CEEM_NO_CHECK 0x40
|
||||
#define TDE_SDE_RDMC_MASK 0x30
|
||||
#define TDE_SDE_RDMC_DISABLED 0x30
|
||||
#define TDE_SDE_RDMC_ENABLED 0x20
|
||||
#define TDE_SDE_RDMC_DEFAULT 0x00
|
||||
#define TDE_SDE_SDK 0x08
|
||||
#define TDE_SDE_CKOD 0x04
|
||||
#define TDE_SDE_CKORP 0x02
|
||||
#define TDE_SDE_CKORL 0x01
|
||||
uint8_t encryption_mode;
|
||||
#define TDE_SDE_ENC_MODE_DISABLE 0x00
|
||||
#define TDE_SDE_ENC_MODE_EXTERNAL 0x01
|
||||
#define TDE_SDE_ENC_MODE_ENCRYPT 0x02
|
||||
uint8_t decryption_mode;
|
||||
#define TDE_SDE_DEC_MODE_DISABLE 0x00
|
||||
#define TDE_SDE_DEC_MODE_RAW 0x01
|
||||
#define TDE_SDE_DEC_MODE_DECRYPT 0x02
|
||||
#define TDE_SDE_DEC_MODE_MIXED 0x03
|
||||
uint8_t algo_index;
|
||||
uint8_t lbe_key_format;
|
||||
#define TDE_SDE_KEY_PLAINTEXT 0x00
|
||||
#define TDE_SDE_KEY_VENDOR_SPEC 0x01
|
||||
#define TDE_SDE_KEY_PUBLIC_WRAP 0x02
|
||||
#define TDE_SDE_KEY_ESP_SCSI 0x03
|
||||
uint8_t kad_format;
|
||||
#define TDE_SDE_KAD_ASCII 0x02
|
||||
#define TDE_SDE_KAD_BINARY 0x01
|
||||
#define TDE_SDE_KAD_UNSPECIFIED 0x00
|
||||
uint8_t reserved[7];
|
||||
uint8_t lbe_key_length[2];
|
||||
uint8_t lbe_key[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Used for the Vendor Specific key format (0x01).
|
||||
*/
|
||||
struct tde_key_format_vendor {
|
||||
uint8_t t10_vendor_id[8];
|
||||
uint8_t vendor_key[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Used for the public key wrapped format (0x02).
|
||||
*/
|
||||
struct tde_key_format_public_wrap {
|
||||
uint8_t parameter_set[2];
|
||||
#define TDE_PARAM_SET_RSA2048 0x0000
|
||||
#define TDE_PARAM_SET_ECC521 0x0010
|
||||
uint8_t label_length[2];
|
||||
uint8_t label[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tape Data Encryption SA Encapsulation page (0x0011).
|
||||
*/
|
||||
struct tde_sa_encap_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t data_desc[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tape Data Encryption Set Encryption Management Attributes page (0x0022).
|
||||
*/
|
||||
struct tde_set_enc_mgmt_attr_page {
|
||||
uint8_t page_code[2];
|
||||
uint8_t reserved[3];
|
||||
uint8_t byte5;
|
||||
#define TDE_SEMA_CAOD 0x01
|
||||
uint8_t page_length[2];
|
||||
uint8_t attr_desc[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Tape Data Encryption descriptor format.
|
||||
* SSC4r03 Section 8.5.4.2.1 Table 197
|
||||
*/
|
||||
struct tde_data_enc_desc {
|
||||
uint8_t key_desc_type;
|
||||
#define TDE_KEY_DESC_WK_KAD 0x04
|
||||
#define TDE_KEY_DESC_M_KAD 0x03
|
||||
#define TDE_KEY_DESC_NONCE_VALUE 0x02
|
||||
#define TDE_KEY_DESC_A_KAD 0x01
|
||||
#define TDE_KEY_DESC_U_KAD 0x00
|
||||
uint8_t byte2;
|
||||
#define TDE_KEY_DESC_AUTH_MASK 0x07
|
||||
#define TDE_KEY_DESC_AUTH_FAILED 0x04
|
||||
#define TDE_KEY_DESC_AUTH_SUCCESS 0x03
|
||||
#define TDE_KEY_DESC_AUTH_NO_ATTEMPT 0x02
|
||||
#define TDE_KEY_DESC_AUTH_U_KAD 0x01
|
||||
uint8_t key_desc_length[2];
|
||||
uint8_t key_desc[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrapped Key descriptor format.
|
||||
* SSC4r03 Section 8.5.4.3.1 Table 200
|
||||
*/
|
||||
struct tde_wrapped_key_desc {
|
||||
uint8_t wrapped_key_type;
|
||||
#define TDE_WRAP_KEY_DESC_LENGTH 0x04
|
||||
#define TDE_WRAP_KEY_DESC_IDENT 0x03
|
||||
#define TDE_WRAP_KEY_DESC_INFO 0x02
|
||||
#define TDE_WRAP_KEY_DESC_ENTITY_ID 0x01
|
||||
#define TDE_WRAP_KEY_DESC_DEVICE_ID 0x00
|
||||
uint8_t reserved;
|
||||
uint8_t wrapped_desc_length[2];
|
||||
uint8_t wrapped_desc[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Encryption management attributes descriptor format.
|
||||
* SSC4r03 Section 8.5.4.4.1 Table 202
|
||||
*/
|
||||
struct tde_enc_mgmt_attr_desc {
|
||||
uint8_t enc_mgmt_attr_type[2];
|
||||
#define TDE_EMAD_DESIRED_KEY_MGR_OP 0x0000
|
||||
#define TDE_EMAD_LOG_BLOCK_ENC_KEY_CRIT 0x0001
|
||||
#define TDE_EMAD_LOG_BLOCK_ENC_KEY_WRAP 0x0002
|
||||
uint8_t reserved;
|
||||
uint8_t byte2;
|
||||
#define TDE_EMAD_CRIT 0x80
|
||||
uint8_t attr_length[2];
|
||||
uint8_t attributes[];
|
||||
#define TDE_EMAD_DESIRED_KEY_CREATE 0x0001
|
||||
#define TDE_EMAD_DESIRED_KEY_RESOLVE 0x0002
|
||||
};
|
||||
|
||||
/*
|
||||
* Logical block encryption key selection criteria descriptor format.
|
||||
* SSC4r03 Section 8.5.4.4.3.1 Table 206
|
||||
*/
|
||||
struct tde_lb_enc_key_sel_desc {
|
||||
uint8_t lbe_key_sel_crit_type[2];
|
||||
/*
|
||||
* The CRIT bit is the top bit of the first byte of the type.
|
||||
*/
|
||||
#define TDE_LBE_KEY_SEL_CRIT 0x80
|
||||
#define TDE_LBE_KEY_SEL_ALGO 0x0001
|
||||
#define TDE_LBE_KEY_SEL_ID 0x0002
|
||||
uint8_t lbe_key_sel_crit_length[2];
|
||||
uint8_t lbe_key_sel_crit[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Logical block encryption key wrapping attribute descriptor format.
|
||||
* SSC4r03 Section 8.5.4.4.4.1 Table 209
|
||||
*/
|
||||
struct tde_lb_enc_key_wrap_desc {
|
||||
uint8_t lbe_key_wrap_type[2];
|
||||
/*
|
||||
* The CRIT bit is the top bit of the first byte of the type.
|
||||
*/
|
||||
#define TDE_LBE_KEY_WRAP_CRIT 0x80
|
||||
#define TDE_LBE_KEY_WRAP_KEKS 0x0001
|
||||
uint8_t lbe_key_wrap_length[2];
|
||||
uint8_t lbe_key_wrap_attr[];
|
||||
};
|
||||
|
||||
/*
|
||||
* Opcodes
|
||||
*/
|
||||
#define REWIND 0x01
|
||||
#define FORMAT_MEDIUM 0x04
|
||||
#define READ_BLOCK_LIMITS 0x05
|
||||
#define SA_READ 0x08
|
||||
#define SA_WRITE 0x0A
|
||||
#define SET_CAPACITY 0x0B
|
||||
#define WRITE_FILEMARKS 0x10
|
||||
#define SPACE 0x11
|
||||
#define RESERVE_UNIT 0x16
|
||||
@ -273,6 +932,9 @@ struct scsi_tape_locate {
|
||||
#define LOAD_UNLOAD 0x1B
|
||||
#define LOCATE 0x2B
|
||||
#define READ_POSITION 0x34
|
||||
#define REPORT_DENSITY_SUPPORT 0x44
|
||||
#define ALLOW_OVERWRITE 0x82
|
||||
#define LOCATE_16 0x92
|
||||
|
||||
/*
|
||||
* Tape specific density codes- only enough of them here to recognize
|
||||
@ -352,11 +1014,55 @@ void scsi_read_position(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
u_int8_t tag_action, int hardsoft,
|
||||
struct scsi_tape_position_data *sbp,
|
||||
u_int8_t sense_len, u_int32_t timeout);
|
||||
void scsi_read_position_10(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, int service_action,
|
||||
u_int8_t *data_ptr, u_int32_t length,
|
||||
u_int32_t sense_len, u_int32_t timeout);
|
||||
|
||||
void scsi_set_position(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, int hardsoft, u_int32_t blkno,
|
||||
u_int8_t sense_len, u_int32_t timeout);
|
||||
|
||||
void scsi_locate_10(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, int immed, int cp, int hard,
|
||||
int64_t partition, u_int32_t block_address,
|
||||
int sense_len, u_int32_t timeout);
|
||||
|
||||
void scsi_locate_16(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, int immed, int cp,
|
||||
u_int8_t dest_type, int bam, int64_t partition,
|
||||
u_int64_t logical_id, int sense_len,
|
||||
u_int32_t timeout);
|
||||
|
||||
void scsi_report_density_support(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *,
|
||||
union ccb *),
|
||||
u_int8_t tag_action, int media,
|
||||
int medium_type, u_int8_t *data_ptr,
|
||||
u_int32_t length, u_int32_t sense_len,
|
||||
u_int32_t timeout);
|
||||
|
||||
void scsi_set_capacity(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, int byte1, u_int32_t proportion,
|
||||
u_int32_t sense_len, u_int32_t timeout);
|
||||
|
||||
void scsi_format_medium(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, int byte1, int byte2,
|
||||
u_int8_t *data_ptr, u_int32_t length,
|
||||
u_int32_t sense_len, u_int32_t timeout);
|
||||
|
||||
void scsi_allow_overwrite(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int8_t tag_action, int allow_overwrite,
|
||||
int partition, u_int64_t logical_id,
|
||||
u_int32_t sense_len, u_int32_t timeout);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _SCSI_SCSI_SA_H */
|
||||
|
@ -2161,6 +2161,37 @@ dev/sdhci/sdhci.c optional sdhci
|
||||
dev/sdhci/sdhci_if.m optional sdhci
|
||||
dev/sdhci/sdhci_pci.c optional sdhci pci
|
||||
dev/sf/if_sf.c optional sf pci
|
||||
dev/sfxge/common/efx_bootcfg.c optional sfxge pci
|
||||
dev/sfxge/common/efx_ev.c optional sfxge pci
|
||||
dev/sfxge/common/efx_filter.c optional sfxge pci
|
||||
dev/sfxge/common/efx_intr.c optional sfxge pci
|
||||
dev/sfxge/common/efx_mac.c optional sfxge pci
|
||||
dev/sfxge/common/efx_mcdi.c optional sfxge pci
|
||||
dev/sfxge/common/efx_mon.c optional sfxge pci
|
||||
dev/sfxge/common/efx_nic.c optional sfxge pci
|
||||
dev/sfxge/common/efx_nvram.c optional sfxge pci
|
||||
dev/sfxge/common/efx_phy.c optional sfxge pci
|
||||
dev/sfxge/common/efx_port.c optional sfxge pci
|
||||
dev/sfxge/common/efx_rx.c optional sfxge pci
|
||||
dev/sfxge/common/efx_sram.c optional sfxge pci
|
||||
dev/sfxge/common/efx_tx.c optional sfxge pci
|
||||
dev/sfxge/common/efx_vpd.c optional sfxge pci
|
||||
dev/sfxge/common/efx_wol.c optional sfxge pci
|
||||
dev/sfxge/common/siena_mac.c optional sfxge pci
|
||||
dev/sfxge/common/siena_mon.c optional sfxge pci
|
||||
dev/sfxge/common/siena_nic.c optional sfxge pci
|
||||
dev/sfxge/common/siena_nvram.c optional sfxge pci
|
||||
dev/sfxge/common/siena_phy.c optional sfxge pci
|
||||
dev/sfxge/common/siena_sram.c optional sfxge pci
|
||||
dev/sfxge/common/siena_vpd.c optional sfxge pci
|
||||
dev/sfxge/sfxge.c optional sfxge pci
|
||||
dev/sfxge/sfxge_dma.c optional sfxge pci
|
||||
dev/sfxge/sfxge_ev.c optional sfxge pci
|
||||
dev/sfxge/sfxge_intr.c optional sfxge pci
|
||||
dev/sfxge/sfxge_mcdi.c optional sfxge pci
|
||||
dev/sfxge/sfxge_port.c optional sfxge pci
|
||||
dev/sfxge/sfxge_rx.c optional sfxge pci
|
||||
dev/sfxge/sfxge_tx.c optional sfxge pci
|
||||
dev/sge/if_sge.c optional sge pci
|
||||
dev/si/si.c optional si
|
||||
dev/si/si2_z280.c optional si
|
||||
|
@ -419,7 +419,7 @@
|
||||
/* Returns FALSE in "defects" per 2^31 - 1 calls, otherwise returns TRUE. */
|
||||
#define DB_RANDOMFALSE(defects) (random() > defects)
|
||||
#define DB_OR_RANDOMFALSE(defects) || (random() > defects)
|
||||
#define DB_AND_RANDOMFALSE(defects) && (random() > ddfects)
|
||||
#define DB_AND_RANDOMFALSE(defects) && (random() > defects)
|
||||
|
||||
/* Returns TRUE in "defects" per 2^31 - 1 calls, otherwise returns FALSE. */
|
||||
#define DB_RANDOMTRUE(defects) (random() < defects)
|
||||
|
@ -1030,6 +1030,7 @@ void t4_update_fl_bufsize(struct ifnet *);
|
||||
int parse_pkt(struct mbuf **);
|
||||
void *start_wrq_wr(struct sge_wrq *, int, struct wrq_cookie *);
|
||||
void commit_wrq_wr(struct sge_wrq *, void *, struct wrq_cookie *);
|
||||
int tnl_cong(struct port_info *);
|
||||
|
||||
/* t4_tracer.c */
|
||||
struct t4_tracer;
|
||||
|
@ -226,9 +226,9 @@ cxgbe_nm_qflush(struct ifnet *ifp)
|
||||
}
|
||||
|
||||
static int
|
||||
alloc_nm_rxq_hwq(struct port_info *pi, struct sge_nm_rxq *nm_rxq)
|
||||
alloc_nm_rxq_hwq(struct port_info *pi, struct sge_nm_rxq *nm_rxq, int cong)
|
||||
{
|
||||
int rc, cntxt_id;
|
||||
int rc, cntxt_id, i;
|
||||
__be32 v;
|
||||
struct adapter *sc = pi->adapter;
|
||||
struct netmap_adapter *na = NA(pi->nm_ifp);
|
||||
@ -267,6 +267,11 @@ alloc_nm_rxq_hwq(struct port_info *pi, struct sge_nm_rxq *nm_rxq)
|
||||
V_FW_IQ_CMD_IQESIZE(ilog2(IQ_ESIZE) - 4));
|
||||
c.iqsize = htobe16(pi->qsize_rxq);
|
||||
c.iqaddr = htobe64(nm_rxq->iq_ba);
|
||||
if (cong >= 0) {
|
||||
c.iqns_to_fl0congen = htobe32(F_FW_IQ_CMD_IQFLINTCONGEN |
|
||||
V_FW_IQ_CMD_FL0CNGCHMAP(cong) | F_FW_IQ_CMD_FL0CONGCIF |
|
||||
F_FW_IQ_CMD_FL0CONGEN);
|
||||
}
|
||||
c.iqns_to_fl0congen |=
|
||||
htobe32(V_FW_IQ_CMD_FL0HOSTFCMODE(X_HOSTFCMODE_NONE) |
|
||||
F_FW_IQ_CMD_FL0FETCHRO | F_FW_IQ_CMD_FL0DATARO |
|
||||
@ -310,7 +315,36 @@ alloc_nm_rxq_hwq(struct port_info *pi, struct sge_nm_rxq *nm_rxq)
|
||||
if (is_t5(sc))
|
||||
nm_rxq->fl_db_val |= F_DBTYPE;
|
||||
|
||||
t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), V_SEINTARM(F_QINTR_CNT_EN) |
|
||||
if (is_t5(sc) && cong >= 0) {
|
||||
uint32_t param, val;
|
||||
|
||||
param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
|
||||
V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_CONM_CTXT) |
|
||||
V_FW_PARAMS_PARAM_YZ(nm_rxq->iq_cntxt_id);
|
||||
param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
|
||||
V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_CONM_CTXT) |
|
||||
V_FW_PARAMS_PARAM_YZ(nm_rxq->iq_cntxt_id);
|
||||
if (cong == 0)
|
||||
val = 1 << 19;
|
||||
else {
|
||||
val = 2 << 19;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (cong & (1 << i))
|
||||
val |= 1 << (i << 2);
|
||||
}
|
||||
}
|
||||
|
||||
rc = -t4_set_params(sc, sc->mbox, sc->pf, 0, 1, ¶m, &val);
|
||||
if (rc != 0) {
|
||||
/* report error but carry on */
|
||||
device_printf(sc->dev,
|
||||
"failed to set congestion manager context for "
|
||||
"ingress queue %d: %d\n", nm_rxq->iq_cntxt_id, rc);
|
||||
}
|
||||
}
|
||||
|
||||
t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS),
|
||||
V_SEINTARM(V_QINTR_TIMER_IDX(1)) |
|
||||
V_INGRESSQID(nm_rxq->iq_cntxt_id));
|
||||
|
||||
return (rc);
|
||||
@ -351,7 +385,8 @@ alloc_nm_txq_hwq(struct port_info *pi, struct sge_nm_txq *nm_txq)
|
||||
V_FW_EQ_ETH_CMD_VFN(0));
|
||||
c.alloc_to_len16 = htobe32(F_FW_EQ_ETH_CMD_ALLOC |
|
||||
F_FW_EQ_ETH_CMD_EQSTART | FW_LEN16(c));
|
||||
c.autoequiqe_to_viid = htobe32(V_FW_EQ_ETH_CMD_VIID(pi->nm_viid));
|
||||
c.autoequiqe_to_viid = htobe32(F_FW_EQ_ETH_CMD_AUTOEQUEQE |
|
||||
V_FW_EQ_ETH_CMD_VIID(pi->nm_viid));
|
||||
c.fetchszm_to_iqid =
|
||||
htobe32(V_FW_EQ_ETH_CMD_HOSTFCMODE(X_HOSTFCMODE_NONE) |
|
||||
V_FW_EQ_ETH_CMD_PCIECHN(pi->tx_chan) | F_FW_EQ_ETH_CMD_FETCHRO |
|
||||
@ -448,7 +483,7 @@ cxgbe_netmap_on(struct adapter *sc, struct port_info *pi, struct ifnet *ifp,
|
||||
nm_set_native_flags(na);
|
||||
|
||||
for_each_nm_rxq(pi, i, nm_rxq) {
|
||||
alloc_nm_rxq_hwq(pi, nm_rxq);
|
||||
alloc_nm_rxq_hwq(pi, nm_rxq, tnl_cong(pi));
|
||||
nm_rxq->fl_hwidx = hwidx;
|
||||
slot = netmap_reset(na, NR_RX, i, 0);
|
||||
MPASS(slot != NULL); /* XXXNM: error check, not assert */
|
||||
@ -513,12 +548,17 @@ cxgbe_netmap_off(struct adapter *sc, struct port_info *pi, struct ifnet *ifp,
|
||||
if_printf(ifp, "netmap disable_vi failed: %d\n", rc);
|
||||
nm_clear_native_flags(na);
|
||||
|
||||
/*
|
||||
* XXXNM: We need to make sure that the tx queues are quiet and won't
|
||||
* request any more SGE_EGR_UPDATEs.
|
||||
*/
|
||||
|
||||
for_each_nm_txq(pi, i, nm_txq) {
|
||||
struct sge_qstat *spg = (void *)&nm_txq->desc[nm_txq->sidx];
|
||||
|
||||
/* Wait for hw pidx to catch up ... */
|
||||
while (be16toh(nm_txq->pidx) != spg->pidx)
|
||||
pause("nmpidx", 1);
|
||||
|
||||
/* ... and then for the cidx. */
|
||||
while (spg->pidx != spg->cidx)
|
||||
pause("nmcidx", 1);
|
||||
|
||||
free_nm_txq_hwq(pi, nm_txq);
|
||||
}
|
||||
for_each_nm_rxq(pi, i, nm_rxq) {
|
||||
@ -641,7 +681,7 @@ int lazy_tx_credit_flush = 1;
|
||||
*/
|
||||
static void
|
||||
cxgbe_nm_tx(struct adapter *sc, struct sge_nm_txq *nm_txq,
|
||||
struct netmap_kring *kring, int npkt, int npkt_remaining)
|
||||
struct netmap_kring *kring, int npkt, int npkt_remaining, int txcsum)
|
||||
{
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
struct netmap_slot *slot;
|
||||
@ -677,10 +717,12 @@ cxgbe_nm_tx(struct adapter *sc, struct sge_nm_txq *nm_txq,
|
||||
* checksum offloading, TCP segmentation offloading,
|
||||
* encryption, VLAN encapsulation/decapsulation, etc."
|
||||
*
|
||||
* XXXNM: it makes sense to enable checksum offload.
|
||||
* So the ncxl interfaces have tx hardware checksumming
|
||||
* disabled by default. But you can override netmap by
|
||||
* enabling IFCAP_TXCSUM on the interface manully.
|
||||
*/
|
||||
cpl->ctrl1 = htobe64(F_TXPKT_IPCSUM_DIS |
|
||||
F_TXPKT_L4CSUM_DIS);
|
||||
cpl->ctrl1 = txcsum ? 0 :
|
||||
htobe64(F_TXPKT_IPCSUM_DIS | F_TXPKT_L4CSUM_DIS);
|
||||
|
||||
usgl = (void *)(cpl + 1);
|
||||
usgl->cmd_nsge = htobe32(V_ULPTX_CMD(ULP_TX_SC_DSGL) |
|
||||
@ -793,7 +835,7 @@ cxgbe_netmap_txsync(struct netmap_kring *kring, int flags)
|
||||
struct sge_nm_txq *nm_txq = &sc->sge.nm_txq[pi->first_nm_txq + kring->ring_id];
|
||||
const u_int head = kring->rhead;
|
||||
u_int reclaimed = 0;
|
||||
int n, d, npkt_remaining, ndesc_remaining;
|
||||
int n, d, npkt_remaining, ndesc_remaining, txcsum;
|
||||
|
||||
/*
|
||||
* Tx was at kring->nr_hwcur last time around and now we need to advance
|
||||
@ -804,6 +846,7 @@ cxgbe_netmap_txsync(struct netmap_kring *kring, int flags)
|
||||
|
||||
npkt_remaining = head >= kring->nr_hwcur ? head - kring->nr_hwcur :
|
||||
kring->nkr_num_slots - kring->nr_hwcur + head;
|
||||
txcsum = ifp->if_capenable & (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6);
|
||||
while (npkt_remaining) {
|
||||
reclaimed += reclaim_nm_tx_desc(nm_txq);
|
||||
ndesc_remaining = contiguous_ndesc_available(nm_txq);
|
||||
@ -827,7 +870,7 @@ cxgbe_netmap_txsync(struct netmap_kring *kring, int flags)
|
||||
|
||||
/* Send n packets and update nm_txq->pidx and kring->nr_hwcur */
|
||||
npkt_remaining -= n;
|
||||
cxgbe_nm_tx(sc, nm_txq, kring, n, npkt_remaining);
|
||||
cxgbe_nm_tx(sc, nm_txq, kring, n, npkt_remaining, txcsum);
|
||||
}
|
||||
MPASS(npkt_remaining == 0);
|
||||
MPASS(kring->nr_hwcur == head);
|
||||
@ -1133,6 +1176,7 @@ t4_nm_intr(void *arg)
|
||||
netmap_rx_irq(ifp, nm_rxq->nid, &processed);
|
||||
}
|
||||
t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), V_CIDXINC(n) |
|
||||
V_INGRESSQID((u32)nm_rxq->iq_cntxt_id) | V_SEINTARM(F_QINTR_CNT_EN));
|
||||
V_INGRESSQID((u32)nm_rxq->iq_cntxt_id) |
|
||||
V_SEINTARM(V_QINTR_TIMER_IDX(1)));
|
||||
}
|
||||
#endif
|
||||
|
@ -2912,7 +2912,7 @@ free_mgmtq(struct adapter *sc)
|
||||
return free_wrq(sc, &sc->sge.mgmtq);
|
||||
}
|
||||
|
||||
static inline int
|
||||
int
|
||||
tnl_cong(struct port_info *pi)
|
||||
{
|
||||
|
||||
|
@ -2460,6 +2460,9 @@ igb_allocate_msix(struct adapter *adapter)
|
||||
struct igb_queue *que = adapter->queues;
|
||||
int error, rid, vector = 0;
|
||||
int cpu_id = 0;
|
||||
#ifdef RSS
|
||||
cpuset_t cpu_mask;
|
||||
#endif
|
||||
|
||||
/* Be sure to start with all interrupts disabled */
|
||||
E1000_WRITE_REG(&adapter->hw, E1000_IMC, ~0);
|
||||
@ -2566,8 +2569,9 @@ igb_allocate_msix(struct adapter *adapter)
|
||||
* round-robin bucket -> queue -> CPU allocation.
|
||||
*/
|
||||
#ifdef RSS
|
||||
taskqueue_start_threads_pinned(&que->tq, 1, PI_NET,
|
||||
cpu_id,
|
||||
CPU_SETOF(cpu_id, &cpu_mask);
|
||||
taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET,
|
||||
&cpu_mask,
|
||||
"%s que (bucket %d)",
|
||||
device_get_nameunit(adapter->dev),
|
||||
cpu_id);
|
||||
|
@ -2373,6 +2373,9 @@ ixgbe_allocate_msix(struct adapter *adapter)
|
||||
struct tx_ring *txr = adapter->tx_rings;
|
||||
int error, rid, vector = 0;
|
||||
int cpu_id = 0;
|
||||
#ifdef RSS
|
||||
cpuset_t cpu_mask;
|
||||
#endif
|
||||
|
||||
#ifdef RSS
|
||||
/*
|
||||
@ -2460,8 +2463,9 @@ ixgbe_allocate_msix(struct adapter *adapter)
|
||||
que->tq = taskqueue_create_fast("ixgbe_que", M_NOWAIT,
|
||||
taskqueue_thread_enqueue, &que->tq);
|
||||
#ifdef RSS
|
||||
taskqueue_start_threads_pinned(&que->tq, 1, PI_NET,
|
||||
cpu_id,
|
||||
CPU_SETOF(cpu_id, &cpu_mask);
|
||||
taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET,
|
||||
&cpu_mask,
|
||||
"%s (bucket %d)",
|
||||
device_get_nameunit(adapter->dev),
|
||||
cpu_id);
|
||||
|
@ -213,6 +213,9 @@ DRIVER_MODULE(ixl, pci, ixl_driver, ixl_devclass, 0, 0);
|
||||
|
||||
MODULE_DEPEND(ixl, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(ixl, ether, 1, 1, 1);
|
||||
#ifdef DEV_NETMAP
|
||||
MODULE_DEPEND(ixl, netmap, 1, 1, 1);
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
/*
|
||||
** Global reset mutex
|
||||
@ -287,6 +290,10 @@ int ixl_atr_rate = 20;
|
||||
TUNABLE_INT("hw.ixl.atr_rate", &ixl_atr_rate);
|
||||
#endif
|
||||
|
||||
#ifdef DEV_NETMAP
|
||||
#define NETMAP_IXL_MAIN /* only bring in one part of the netmap code */
|
||||
#include <dev/netmap/if_ixl_netmap.h>
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
static char *ixl_fc_string[6] = {
|
||||
"None",
|
||||
@ -647,6 +654,9 @@ ixl_attach(device_t dev)
|
||||
ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST);
|
||||
|
||||
|
||||
#ifdef DEV_NETMAP
|
||||
ixl_netmap_attach(vsi);
|
||||
#endif /* DEV_NETMAP */
|
||||
INIT_DEBUGOUT("ixl_attach: end");
|
||||
return (0);
|
||||
|
||||
@ -725,6 +735,9 @@ ixl_detach(device_t dev)
|
||||
EVENTHANDLER_DEREGISTER(vlan_unconfig, vsi->vlan_detach);
|
||||
|
||||
callout_drain(&pf->timer);
|
||||
#ifdef DEV_NETMAP
|
||||
netmap_detach(vsi->ifp);
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
|
||||
ixl_free_pci_resources(pf);
|
||||
@ -1867,6 +1880,9 @@ ixl_assign_vsi_msix(struct ixl_pf *pf)
|
||||
struct ixl_queue *que = vsi->queues;
|
||||
struct tx_ring *txr;
|
||||
int error, rid, vector = 0;
|
||||
#ifdef RSS
|
||||
cpuset_t cpu_mask;
|
||||
#endif
|
||||
|
||||
/* Admin Que is vector 0*/
|
||||
rid = vector + 1;
|
||||
@ -1929,8 +1945,9 @@ ixl_assign_vsi_msix(struct ixl_pf *pf)
|
||||
que->tq = taskqueue_create_fast("ixl_que", M_NOWAIT,
|
||||
taskqueue_thread_enqueue, &que->tq);
|
||||
#ifdef RSS
|
||||
taskqueue_start_threads_pinned(&que->tq, 1, PI_NET,
|
||||
cpu_id, "%s (bucket %d)",
|
||||
CPU_SETOF(cpu_id, &cpu_mask);
|
||||
taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET,
|
||||
&cpu_mask, "%s (bucket %d)",
|
||||
device_get_nameunit(dev), cpu_id);
|
||||
#else
|
||||
taskqueue_start_threads(&que->tq, 1, PI_NET,
|
||||
@ -2662,6 +2679,15 @@ ixl_initialize_vsi(struct ixl_vsi *vsi)
|
||||
break;
|
||||
}
|
||||
wr32(vsi->hw, I40E_QRX_TAIL(que->me), 0);
|
||||
#ifdef DEV_NETMAP
|
||||
/* preserve queue */
|
||||
if (vsi->ifp->if_capenable & IFCAP_NETMAP) {
|
||||
struct netmap_adapter *na = NA(vsi->ifp);
|
||||
struct netmap_kring *kring = &na->rx_rings[i];
|
||||
int t = na->num_rx_desc - 1 - nm_kr_rxspace(kring);
|
||||
wr32(vsi->hw, I40E_QRX_TAIL(que->me), t);
|
||||
} else
|
||||
#endif /* DEV_NETMAP */
|
||||
wr32(vsi->hw, I40E_QRX_TAIL(que->me), que->num_desc - 1);
|
||||
}
|
||||
return (err);
|
||||
|
@ -1382,6 +1382,9 @@ ixlv_assign_msix(struct ixlv_sc *sc)
|
||||
struct ixl_queue *que = vsi->queues;
|
||||
struct tx_ring *txr;
|
||||
int error, rid, vector = 1;
|
||||
#ifdef RSS
|
||||
cpuset_t cpu_mask;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < vsi->num_queues; i++, vector++, que++) {
|
||||
int cpu_id = i;
|
||||
@ -1416,8 +1419,9 @@ ixlv_assign_msix(struct ixlv_sc *sc)
|
||||
que->tq = taskqueue_create_fast("ixlv_que", M_NOWAIT,
|
||||
taskqueue_thread_enqueue, &que->tq);
|
||||
#ifdef RSS
|
||||
taskqueue_start_threads_pinned(&que->tq, 1, PI_NET,
|
||||
cpu_id, "%s (bucket %d)",
|
||||
CPU_SETOF(cpu_id, &cpu_mask);
|
||||
taskqueue_start_threads_cpuset(&que->tq, 1, PI_NET,
|
||||
&cpu_mask, "%s (bucket %d)",
|
||||
device_get_nameunit(dev), cpu_id);
|
||||
#else
|
||||
taskqueue_start_threads(&que->tq, 1, PI_NET,
|
||||
|
@ -62,6 +62,10 @@ static __inline void ixl_rx_discard(struct rx_ring *, int);
|
||||
static __inline void ixl_rx_input(struct rx_ring *, struct ifnet *,
|
||||
struct mbuf *, u8);
|
||||
|
||||
#ifdef DEV_NETMAP
|
||||
#include <dev/netmap/if_ixl_netmap.h>
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
/*
|
||||
** Multiqueue Transmit driver
|
||||
**
|
||||
@ -486,9 +490,21 @@ ixl_init_tx_ring(struct ixl_queue *que)
|
||||
{
|
||||
struct tx_ring *txr = &que->txr;
|
||||
struct ixl_tx_buf *buf;
|
||||
#ifdef DEV_NETMAP
|
||||
struct netmap_adapter *na = NA(que->vsi->ifp);
|
||||
struct netmap_slot *slot;
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
/* Clear the old ring contents */
|
||||
IXL_TX_LOCK(txr);
|
||||
#ifdef DEV_NETMAP
|
||||
/*
|
||||
* (under lock): if in netmap mode, do some consistency
|
||||
* checks and set slot to entry 0 of the netmap ring.
|
||||
*/
|
||||
slot = netmap_reset(na, NR_TX, que->me, 0);
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
bzero((void *)txr->base,
|
||||
(sizeof(struct i40e_tx_desc)) * que->num_desc);
|
||||
|
||||
@ -512,6 +528,19 @@ ixl_init_tx_ring(struct ixl_queue *que)
|
||||
m_freem(buf->m_head);
|
||||
buf->m_head = NULL;
|
||||
}
|
||||
#ifdef DEV_NETMAP
|
||||
/*
|
||||
* In netmap mode, set the map for the packet buffer.
|
||||
* NOTE: Some drivers (not this one) also need to set
|
||||
* the physical buffer address in the NIC ring.
|
||||
* netmap_idx_n2k() maps a nic index, i, into the corresponding
|
||||
* netmap slot index, si
|
||||
*/
|
||||
if (slot) {
|
||||
int si = netmap_idx_n2k(&na->tx_rings[que->me], i);
|
||||
netmap_load_map(na, buf->tag, buf->map, NMB(na, slot + si));
|
||||
}
|
||||
#endif /* DEV_NETMAP */
|
||||
/* Clear the EOP index */
|
||||
buf->eop_index = -1;
|
||||
}
|
||||
@ -823,6 +852,11 @@ ixl_txeof(struct ixl_queue *que)
|
||||
|
||||
mtx_assert(&txr->mtx, MA_OWNED);
|
||||
|
||||
#ifdef DEV_NETMAP
|
||||
// XXX todo: implement moderation
|
||||
if (netmap_tx_irq(que->vsi->ifp, que->me))
|
||||
return FALSE;
|
||||
#endif /* DEF_NETMAP */
|
||||
|
||||
/* These are not the descriptors you seek, move along :) */
|
||||
if (txr->avail == que->num_desc) {
|
||||
@ -1124,8 +1158,16 @@ ixl_init_rx_ring(struct ixl_queue *que)
|
||||
struct ixl_rx_buf *buf;
|
||||
bus_dma_segment_t pseg[1], hseg[1];
|
||||
int rsize, nsegs, error = 0;
|
||||
#ifdef DEV_NETMAP
|
||||
struct netmap_adapter *na = NA(que->vsi->ifp);
|
||||
struct netmap_slot *slot;
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
IXL_RX_LOCK(rxr);
|
||||
#ifdef DEV_NETMAP
|
||||
/* same as in ixl_init_tx_ring() */
|
||||
slot = netmap_reset(na, NR_RX, que->me, 0);
|
||||
#endif /* DEV_NETMAP */
|
||||
/* Clear the ring contents */
|
||||
rsize = roundup2(que->num_desc *
|
||||
sizeof(union i40e_rx_desc), DBA_ALIGN);
|
||||
@ -1159,6 +1201,28 @@ ixl_init_rx_ring(struct ixl_queue *que)
|
||||
struct mbuf *mh, *mp;
|
||||
|
||||
buf = &rxr->buffers[j];
|
||||
#ifdef DEV_NETMAP
|
||||
/*
|
||||
* In netmap mode, fill the map and set the buffer
|
||||
* address in the NIC ring, considering the offset
|
||||
* between the netmap and NIC rings (see comment in
|
||||
* ixgbe_setup_transmit_ring() ). No need to allocate
|
||||
* an mbuf, so end the block with a continue;
|
||||
*/
|
||||
if (slot) {
|
||||
int sj = netmap_idx_n2k(&na->rx_rings[que->me], j);
|
||||
uint64_t paddr;
|
||||
void *addr;
|
||||
|
||||
addr = PNMB(na, slot + sj, &paddr);
|
||||
netmap_load_map(na, rxr->dma.tag, buf->pmap, addr);
|
||||
/* Update descriptor and the cached value */
|
||||
rxr->base[j].read.pkt_addr = htole64(paddr);
|
||||
rxr->base[j].read.hdr_addr = 0;
|
||||
continue;
|
||||
}
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
/*
|
||||
** Don't allocate mbufs if not
|
||||
** doing header split, its wasteful
|
||||
@ -1458,6 +1522,12 @@ ixl_rxeof(struct ixl_queue *que, int count)
|
||||
|
||||
IXL_RX_LOCK(rxr);
|
||||
|
||||
#ifdef DEV_NETMAP
|
||||
if (netmap_rx_irq(ifp, que->me, &count)) {
|
||||
IXL_RX_UNLOCK(rxr);
|
||||
return (FALSE);
|
||||
}
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
for (i = rxr->next_check; count != 0;) {
|
||||
struct mbuf *sendmp, *mh, *mp;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2006-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2012 LSI Corporation.
|
||||
* Copyright (c) 2006-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2006-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2012 LSI Corporation.
|
||||
* Copyright (c) 2006-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_cnfg.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2009-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009-2012 LSI Corporation.
|
||||
* Copyright (c) 2009-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_hbd.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2000-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,7 +24,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -32,7 +33,8 @@
|
||||
Fusion-MPT MPI 2.0 Header File Change History
|
||||
==============================
|
||||
|
||||
Copyright (c) 2000-2012 LSI Corporation.
|
||||
Copyright (c) 2000-2015 LSI Corporation.
|
||||
Copyright (c) 2013-2015 Avago Technologies
|
||||
|
||||
---------------------------------------
|
||||
Header Set Release Version: 02.00.18
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2006-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2012 LSI Corporation.
|
||||
* Copyright (c) 2006-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_init.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2006-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2012 LSI Corporation.
|
||||
* Copyright (c) 2006-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_ioc.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2009-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 LSI Corporation.
|
||||
* Copyright (c) 2009-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_ra.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2007-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2012 LSI Corporation.
|
||||
* Copyright (c) 2007-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_raid.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2007-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2012 LSI Corporation.
|
||||
* Copyright (c) 2007-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_sas.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2006-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2012 LSI Corporation.
|
||||
* Copyright (c) 2006-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_targ.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2007-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2012 LSI Corporation.
|
||||
* Copyright (c) 2007-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_tool.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2006-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2012 LSI Corporation.
|
||||
* Copyright (c) 2006-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_type.h
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Yahoo! Inc.
|
||||
* Copyright (c) 2012 LSI Corp.
|
||||
* Copyright (c) 2011-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -24,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -32,7 +33,7 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/* Communications core for LSI MPT2 */
|
||||
/* Communications core for Avago Technologies (LSI) MPT2 */
|
||||
|
||||
/* TODO Move headers to mpsvar */
|
||||
#include <sys/types.h>
|
||||
@ -1349,6 +1350,8 @@ mps_get_tunables(struct mps_softc *sc)
|
||||
sc->disable_msix = 0;
|
||||
sc->disable_msi = 0;
|
||||
sc->max_chains = MPS_CHAIN_FRAMES;
|
||||
sc->enable_ssu = MPS_SSU_ENABLE_SSD_DISABLE_HDD;
|
||||
sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
|
||||
|
||||
/*
|
||||
* Grab the global variables.
|
||||
@ -1357,6 +1360,8 @@ mps_get_tunables(struct mps_softc *sc)
|
||||
TUNABLE_INT_FETCH("hw.mps.disable_msix", &sc->disable_msix);
|
||||
TUNABLE_INT_FETCH("hw.mps.disable_msi", &sc->disable_msi);
|
||||
TUNABLE_INT_FETCH("hw.mps.max_chains", &sc->max_chains);
|
||||
TUNABLE_INT_FETCH("hw.mps.enable_ssu", &sc->enable_ssu);
|
||||
TUNABLE_INT_FETCH("hw.mps.spinup_wait_time", &sc->spinup_wait_time);
|
||||
|
||||
/* Grab the unit-instance variables */
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.debug_level",
|
||||
@ -1379,6 +1384,14 @@ mps_get_tunables(struct mps_softc *sc)
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.exclude_ids",
|
||||
device_get_unit(sc->mps_dev));
|
||||
TUNABLE_STR_FETCH(tmpstr, sc->exclude_ids, sizeof(sc->exclude_ids));
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.enable_ssu",
|
||||
device_get_unit(sc->mps_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->enable_ssu);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mps.%d.spinup_wait_time",
|
||||
device_get_unit(sc->mps_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1451,11 +1464,20 @@ mps_setup_sysctl(struct mps_softc *sc)
|
||||
OID_AUTO, "max_chains", CTLFLAG_RD,
|
||||
&sc->max_chains, 0,"maximum chain frames that will be allocated");
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "enable_ssu", CTLFLAG_RW, &sc->enable_ssu, 0,
|
||||
"enable SSU to SATA SSD/HDD at shutdown");
|
||||
|
||||
#if __FreeBSD_version >= 900030
|
||||
SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "chain_alloc_fail", CTLFLAG_RD,
|
||||
&sc->chain_alloc_fail, "chain allocation failures");
|
||||
#endif //FreeBSD_version >= 900030
|
||||
|
||||
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
|
||||
OID_AUTO, "spinup_wait_time", CTLFLAG_RD,
|
||||
&sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for "
|
||||
"spinup after SATA ID error");
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2011-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,7 +24,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
@ -27,12 +27,13 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD userland interface
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2011-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -56,7 +57,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2011-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,7 +24,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
@ -889,14 +890,14 @@ _mapping_get_dev_info(struct mps_softc *sc,
|
||||
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
Mpi2SasDevicePage0_t sas_device_pg0;
|
||||
u8 entry, enc_idx, phy_idx;
|
||||
u8 entry, enc_idx, phy_idx, sata_end_device;
|
||||
u32 map_idx, index, device_info;
|
||||
struct _map_phy_change *phy_change, *tmp_phy_change;
|
||||
uint64_t sas_address;
|
||||
struct enc_mapping_table *et_entry;
|
||||
struct dev_mapping_table *mt_entry;
|
||||
u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED;
|
||||
int rc;
|
||||
int rc = 1;
|
||||
|
||||
for (entry = 0; entry < topo_change->num_entries; entry++) {
|
||||
phy_change = &topo_change->phy_details[entry];
|
||||
@ -910,42 +911,36 @@ _mapping_get_dev_info(struct mps_softc *sc,
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always get SATA Identify information because this is used
|
||||
* to determine if Start/Stop Unit should be sent to the drive
|
||||
* when the system is shutdown.
|
||||
*/
|
||||
device_info = le32toh(sas_device_pg0.DeviceInfo);
|
||||
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
|
||||
MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
|
||||
if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
|
||||
(device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
|
||||
rc = mpssas_get_sas_address_for_sata_disk(sc,
|
||||
&sas_address, phy_change->dev_handle,
|
||||
device_info);
|
||||
if (rc) {
|
||||
printf("%s: failed to compute the "
|
||||
"hashed SAS Address for SATA "
|
||||
"device with handle 0x%04x\n",
|
||||
__func__, phy_change->dev_handle);
|
||||
sas_address =
|
||||
sas_device_pg0.SASAddress.High;
|
||||
sas_address = (sas_address << 32) |
|
||||
sas_device_pg0.SASAddress.Low;
|
||||
}
|
||||
mps_dprint(sc, MPS_MAPPING,
|
||||
"SAS Address for SATA device = %jx\n",
|
||||
sas_address);
|
||||
sas_address = sas_device_pg0.SASAddress.High;
|
||||
sas_address = (sas_address << 32) |
|
||||
sas_device_pg0.SASAddress.Low;
|
||||
sata_end_device = 0;
|
||||
if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
|
||||
(device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
|
||||
sata_end_device = 1;
|
||||
rc = mpssas_get_sas_address_for_sata_disk(sc,
|
||||
&sas_address, phy_change->dev_handle, device_info,
|
||||
&phy_change->is_SATA_SSD);
|
||||
if (rc) {
|
||||
mps_dprint(sc, MPS_ERROR, "%s: failed to get "
|
||||
"disk type (SSD or HDD) and SAS Address "
|
||||
"for SATA device with handle 0x%04x\n",
|
||||
__func__, phy_change->dev_handle);
|
||||
} else {
|
||||
sas_address =
|
||||
sas_device_pg0.SASAddress.High;
|
||||
sas_address = (sas_address << 32) |
|
||||
sas_device_pg0.SASAddress.Low;
|
||||
mps_dprint(sc, MPS_INFO, "SAS Address for SATA "
|
||||
"device = %jx\n", sas_address);
|
||||
}
|
||||
} else {
|
||||
sas_address = sas_device_pg0.SASAddress.High;
|
||||
sas_address = (sas_address << 32) |
|
||||
sas_device_pg0.SASAddress.Low;
|
||||
}
|
||||
|
||||
phy_change->physical_id = sas_address;
|
||||
phy_change->slot = le16toh(sas_device_pg0.Slot);
|
||||
phy_change->device_info =
|
||||
le32toh(sas_device_pg0.DeviceInfo);
|
||||
phy_change->device_info = le32toh(sas_device_pg0.DeviceInfo);
|
||||
|
||||
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
|
||||
MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
|
||||
@ -953,10 +948,10 @@ _mapping_get_dev_info(struct mps_softc *sc,
|
||||
topo_change->enc_handle);
|
||||
if (enc_idx == MPS_ENCTABLE_BAD_IDX) {
|
||||
phy_change->is_processed = 1;
|
||||
printf("%s: failed to add the device with "
|
||||
"handle 0x%04x because the enclosure is "
|
||||
"not in the mapping table\n", __func__,
|
||||
phy_change->dev_handle);
|
||||
mps_dprint(sc, MPS_MAPPING, "%s: failed to add "
|
||||
"the device with handle 0x%04x because the "
|
||||
"enclosure is not in the mapping table\n",
|
||||
__func__, phy_change->dev_handle);
|
||||
continue;
|
||||
}
|
||||
if (!((phy_change->device_info &
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2011-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,7 +24,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -38,6 +39,7 @@
|
||||
* @dev_handle: device handle for the device pointed by this entry
|
||||
* @slot: slot ID
|
||||
* @is_processed: Flag to indicate whether this entry is processed or not
|
||||
* @is_SATA_SSD: 1 if this is a SATA device AND an SSD, 0 otherwise
|
||||
*/
|
||||
struct _map_phy_change {
|
||||
uint64_t physical_id;
|
||||
@ -46,6 +48,8 @@ struct _map_phy_change {
|
||||
uint16_t slot;
|
||||
uint8_t reason;
|
||||
uint8_t is_processed;
|
||||
uint8_t is_SATA_SSD;
|
||||
uint8_t reserved;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -66,6 +70,6 @@ struct _map_topology_change {
|
||||
|
||||
extern int
|
||||
mpssas_get_sas_address_for_sata_disk(struct mps_softc *ioc,
|
||||
u64 *sas_address, u16 handle, u32 device_info);
|
||||
u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD);
|
||||
|
||||
#endif
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/* PCI/PCI-X/PCIe bus interface for the LSI MPT2 controllers */
|
||||
/* PCI/PCI-X/PCIe bus interface for the Avago Tech (LSI) MPT2 controllers */
|
||||
|
||||
/* TODO Move headers to mpsvar */
|
||||
#include <sys/types.h>
|
||||
@ -98,33 +98,33 @@ struct mps_ident {
|
||||
const char *desc;
|
||||
} mps_identifiers[] = {
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
|
||||
0xffff, 0xffff, 0, "LSI SAS2004" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2004" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
|
||||
0xffff, 0xffff, 0, "LSI SAS2008" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2008" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
|
||||
0xffff, 0xffff, 0, "LSI SAS2108" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2108" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
|
||||
0xffff, 0xffff, 0, "LSI SAS2108" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2108" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
|
||||
0xffff, 0xffff, 0, "LSI SAS2108" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2108" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
|
||||
0xffff, 0xffff, 0, "LSI SAS2116" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2116" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
|
||||
0xffff, 0xffff, 0, "LSI SAS2116" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2116" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1,
|
||||
0xffff, 0xffff, 0, "LSI SAS2208" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2,
|
||||
0xffff, 0xffff, 0, "LSI SAS2208" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3,
|
||||
0xffff, 0xffff, 0, "LSI SAS2208" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4,
|
||||
0xffff, 0xffff, 0, "LSI SAS2208" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5,
|
||||
0xffff, 0xffff, 0, "LSI SAS2208" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6,
|
||||
0xffff, 0xffff, 0, "LSI SAS2208" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2208" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1,
|
||||
0xffff, 0xffff, 0, "LSI SAS2308" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2308" },
|
||||
// Add Customer specific vender/subdevice id before generic
|
||||
// (0xffff) vender/subdevice id.
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
|
||||
@ -136,11 +136,11 @@ struct mps_ident {
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
|
||||
0x8086, 0x3519, 0, "Intel(R) Integrated RAID Module RMS25KB040" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
|
||||
0xffff, 0xffff, 0, "LSI SAS2308" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2308" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
|
||||
0xffff, 0xffff, 0, "LSI SAS2308" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS2308" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
|
||||
0xffff, 0xffff, MPS_FLAGS_WD_AVAILABLE, "LSI SSS6200" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SSS6200" },
|
||||
{ 0, 0, 0, 0, 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Yahoo! Inc.
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2011-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -24,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -32,7 +33,7 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/* Communications core for LSI MPT2 */
|
||||
/* Communications core for Avago Technologies (LSI) MPT2 */
|
||||
|
||||
/* TODO Move headers to mpsvar */
|
||||
#include <sys/types.h>
|
||||
@ -119,6 +120,8 @@ static void mpssas_remove_device(struct mps_softc *, struct mps_command *);
|
||||
static void mpssas_remove_complete(struct mps_softc *, struct mps_command *);
|
||||
static void mpssas_action(struct cam_sim *sim, union ccb *ccb);
|
||||
static void mpssas_poll(struct cam_sim *sim);
|
||||
static int mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm,
|
||||
struct mps_command *cm);
|
||||
static void mpssas_scsiio_timeout(void *data);
|
||||
static void mpssas_abort_complete(struct mps_softc *sc, struct mps_command *cm);
|
||||
static void mpssas_direct_drive_io(struct mpssas_softc *sassc,
|
||||
@ -133,8 +136,6 @@ static void mpssas_send_smpcmd(struct mpssas_softc *sassc, union ccb *ccb,
|
||||
static void mpssas_action_smpio(struct mpssas_softc *sassc, union ccb *ccb);
|
||||
#endif //FreeBSD_version >= 900026
|
||||
static void mpssas_resetdev_complete(struct mps_softc *, struct mps_command *);
|
||||
static int mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_command *cm);
|
||||
static int mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type);
|
||||
static void mpssas_async(void *callback_arg, uint32_t code,
|
||||
struct cam_path *path, void *arg);
|
||||
#if (__FreeBSD_version < 901503) || \
|
||||
@ -224,7 +225,7 @@ mpssas_startup_decrement(struct mpssas_softc *sassc)
|
||||
}
|
||||
}
|
||||
|
||||
/* LSI's firmware requires us to stop sending commands when we're doing task
|
||||
/* The firmware requires us to stop sending commands when we're doing task
|
||||
* management, so refcount the TMs and keep the simq frozen when any are in
|
||||
* use.
|
||||
*/
|
||||
@ -233,37 +234,31 @@ mpssas_alloc_tm(struct mps_softc *sc)
|
||||
{
|
||||
struct mps_command *tm;
|
||||
|
||||
MPS_FUNCTRACE(sc);
|
||||
tm = mps_alloc_high_priority_command(sc);
|
||||
if (tm != NULL) {
|
||||
if (sc->sassc->tm_count++ == 0) {
|
||||
mps_dprint(sc, MPS_RECOVERY,
|
||||
"%s freezing simq\n", __func__);
|
||||
xpt_freeze_simq(sc->sassc->sim, 1);
|
||||
}
|
||||
mps_dprint(sc, MPS_RECOVERY, "%s tm_count %u\n", __func__,
|
||||
sc->sassc->tm_count);
|
||||
}
|
||||
return tm;
|
||||
}
|
||||
|
||||
void
|
||||
mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm)
|
||||
{
|
||||
mps_dprint(sc, MPS_TRACE, "%s", __func__);
|
||||
if (tm == NULL)
|
||||
return;
|
||||
|
||||
/* if there are no TMs in use, we can release the simq. We use our
|
||||
* own refcount so that it's easier for a diag reset to cleanup and
|
||||
* release the simq.
|
||||
/*
|
||||
* For TM's the devq is frozen for the device. Unfreeze it here and
|
||||
* free the resources used for freezing the devq. Must clear the
|
||||
* INRESET flag as well or scsi I/O will not work.
|
||||
*/
|
||||
if (--sc->sassc->tm_count == 0) {
|
||||
mps_dprint(sc, MPS_RECOVERY, "%s releasing simq\n", __func__);
|
||||
xpt_release_simq(sc->sassc->sim, 1);
|
||||
if (tm->cm_targ != NULL) {
|
||||
tm->cm_targ->flags &= ~MPSSAS_TARGET_INRESET;
|
||||
}
|
||||
if (tm->cm_ccb) {
|
||||
mps_dprint(sc, MPS_INFO, "Unfreezing devq for target ID %d\n",
|
||||
tm->cm_targ->tid);
|
||||
xpt_release_devq(tm->cm_ccb->ccb_h.path, 1, TRUE);
|
||||
xpt_free_path(tm->cm_ccb->ccb_h.path);
|
||||
xpt_free_ccb(tm->cm_ccb);
|
||||
}
|
||||
mps_dprint(sc, MPS_RECOVERY, "%s tm_count %u\n", __func__,
|
||||
sc->sassc->tm_count);
|
||||
|
||||
mps_free_high_priority_command(sc, tm);
|
||||
}
|
||||
@ -371,7 +366,8 @@ mpssas_remove_volume(struct mps_softc *sc, struct mps_command *tm)
|
||||
if (reply == NULL) {
|
||||
/* XXX retry the remove after the diag reset completes? */
|
||||
mps_dprint(sc, MPS_FAULT,
|
||||
"%s NULL reply reseting device 0x%04x\n", __func__, handle);
|
||||
"%s NULL reply resetting device 0x%04x\n", __func__,
|
||||
handle);
|
||||
mpssas_free_tm(sc, tm);
|
||||
return;
|
||||
}
|
||||
@ -475,6 +471,11 @@ mpssas_prepare_volume_remove(struct mpssas_softc *sassc, uint16_t handle)
|
||||
MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
|
||||
cm->cm_complete = mpssas_remove_volume;
|
||||
cm->cm_complete_data = (void *)(uintptr_t)handle;
|
||||
|
||||
mps_dprint(sc, MPS_INFO, "%s: Sending reset for target ID %d\n",
|
||||
__func__, targ->tid);
|
||||
mpssas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
|
||||
|
||||
mps_map_command(sc, cm);
|
||||
}
|
||||
|
||||
@ -533,6 +534,11 @@ mpssas_prepare_remove(struct mpssas_softc *sassc, uint16_t handle)
|
||||
cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
|
||||
cm->cm_complete = mpssas_remove_device;
|
||||
cm->cm_complete_data = (void *)(uintptr_t)handle;
|
||||
|
||||
mps_dprint(sc, MPS_INFO, "%s: Sending reset for target ID %d\n",
|
||||
__func__, targ->tid);
|
||||
mpssas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
|
||||
|
||||
mps_map_command(sc, cm);
|
||||
}
|
||||
|
||||
@ -785,9 +791,6 @@ mps_attach_sas(struct mps_softc *sc)
|
||||
mpssas_startup_increment(sassc);
|
||||
|
||||
callout_init(&sassc->discovery_callout, 1 /*mpsafe*/);
|
||||
sassc->discovery_timeouts = 0;
|
||||
|
||||
sassc->tm_count = 0;
|
||||
|
||||
/*
|
||||
* Register for async events so we can determine the EEDP
|
||||
@ -938,7 +941,7 @@ mpssas_action(struct cam_sim *sim, union ccb *ccb)
|
||||
cpi->max_lun = 255;
|
||||
cpi->initiator_id = sassc->maxtargets - 1;
|
||||
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
|
||||
strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN);
|
||||
strncpy(cpi->hba_vid, "Avago Tech (LSI)", HBA_IDLEN);
|
||||
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
|
||||
cpi->unit_number = cam_sim_unit(sim);
|
||||
cpi->bus_id = cam_sim_bus(sim);
|
||||
@ -1134,8 +1137,8 @@ mpssas_handle_reinit(struct mps_softc *sc)
|
||||
mpssas_complete_all_commands(sc);
|
||||
|
||||
mps_dprint(sc, MPS_INIT,
|
||||
"%s startup %u tm %u after command completion\n",
|
||||
__func__, sc->sassc->startup_refcount, sc->sassc->tm_count);
|
||||
"%s startup %u after command completion\n", __func__,
|
||||
sc->sassc->startup_refcount);
|
||||
|
||||
/* zero all the target handles, since they may change after the
|
||||
* reset, and we have to rediscover all the targets and use the new
|
||||
@ -1198,7 +1201,6 @@ mpssas_logical_unit_reset_complete(struct mps_softc *sc, struct mps_command *tm)
|
||||
"NULL reset reply for tm %p\n", tm);
|
||||
if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) {
|
||||
/* this completion was due to a reset, just cleanup */
|
||||
targ->flags &= ~MPSSAS_TARGET_INRESET;
|
||||
targ->tm = NULL;
|
||||
mpssas_free_tm(sc, tm);
|
||||
}
|
||||
@ -1287,7 +1289,6 @@ mpssas_target_reset_complete(struct mps_softc *sc, struct mps_command *tm)
|
||||
"NULL reset reply for tm %p\n", tm);
|
||||
if ((sc->mps_flags & MPS_FLAGS_DIAGRESET) != 0) {
|
||||
/* this completion was due to a reset, just cleanup */
|
||||
targ->flags &= ~MPSSAS_TARGET_INRESET;
|
||||
targ->tm = NULL;
|
||||
mpssas_free_tm(sc, tm);
|
||||
}
|
||||
@ -1303,8 +1304,6 @@ mpssas_target_reset_complete(struct mps_softc *sc, struct mps_command *tm)
|
||||
le16toh(reply->IOCStatus), le32toh(reply->ResponseCode),
|
||||
le32toh(reply->TerminationCount));
|
||||
|
||||
targ->flags &= ~MPSSAS_TARGET_INRESET;
|
||||
|
||||
if (targ->outstanding == 0) {
|
||||
/* we've finished recovery for this target and all
|
||||
* of its logical units.
|
||||
@ -1332,7 +1331,7 @@ mpssas_target_reset_complete(struct mps_softc *sc, struct mps_command *tm)
|
||||
|
||||
#define MPS_RESET_TIMEOUT 30
|
||||
|
||||
static int
|
||||
int
|
||||
mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type)
|
||||
{
|
||||
MPI2_SCSI_TASK_MANAGE_REQUEST *req;
|
||||
@ -1358,15 +1357,19 @@ mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm, uint8_t type)
|
||||
mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO,
|
||||
"sending logical unit reset\n");
|
||||
tm->cm_complete = mpssas_logical_unit_reset_complete;
|
||||
mpssas_prepare_for_tm(sc, tm, target, tm->cm_lun);
|
||||
}
|
||||
else if (type == MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET) {
|
||||
/* Target reset method = SAS Hard Link Reset / SATA Link Reset */
|
||||
/*
|
||||
* Target reset method =
|
||||
* SAS Hard Link Reset / SATA Link Reset
|
||||
*/
|
||||
req->MsgFlags = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
|
||||
tm->cm_targ->target_resets++;
|
||||
tm->cm_targ->flags |= MPSSAS_TARGET_INRESET;
|
||||
mpssas_log_command(tm, MPS_RECOVERY|MPS_INFO,
|
||||
"sending target reset\n");
|
||||
tm->cm_complete = mpssas_target_reset_complete;
|
||||
mpssas_prepare_for_tm(sc, tm, target, CAM_LUN_WILDCARD);
|
||||
}
|
||||
else {
|
||||
mps_dprint(sc, MPS_ERROR, "unexpected reset type 0x%x\n", type);
|
||||
@ -1513,6 +1516,10 @@ mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_comma
|
||||
|
||||
targ->aborts++;
|
||||
|
||||
mps_dprint(sc, MPS_INFO, "Sending reset from %s for target ID %d\n",
|
||||
__func__, targ->tid);
|
||||
mpssas_prepare_for_tm(sc, tm, targ, tm->cm_lun);
|
||||
|
||||
err = mps_map_command(sc, tm);
|
||||
if (err)
|
||||
mpssas_log_command(tm, MPS_RECOVERY,
|
||||
@ -1521,7 +1528,6 @@ mpssas_send_abort(struct mps_softc *sc, struct mps_command *tm, struct mps_comma
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
mpssas_scsiio_timeout(void *data)
|
||||
{
|
||||
@ -1667,6 +1673,19 @@ mpssas_action_scsiio(struct mpssas_softc *sassc, union ccb *ccb)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If target has a reset in progress, freeze the devq and return. The
|
||||
* devq will be released when the TM reset is finished.
|
||||
*/
|
||||
if (targ->flags & MPSSAS_TARGET_INRESET) {
|
||||
ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN;
|
||||
mps_dprint(sc, MPS_INFO, "%s: Freezing devq for target ID %d\n",
|
||||
__func__, targ->tid);
|
||||
xpt_freeze_devq(ccb->ccb_h.path, 1);
|
||||
xpt_done(ccb);
|
||||
return;
|
||||
}
|
||||
|
||||
cm = mps_alloc_command(sc);
|
||||
if (cm == NULL || (sc->mps_flags & MPS_FLAGS_DIAGRESET)) {
|
||||
if (cm != NULL) {
|
||||
@ -2056,6 +2075,8 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
|
||||
u8 *TLR_bits, TLR_on;
|
||||
int dir = 0, i;
|
||||
u16 alloc_len;
|
||||
struct mpssas_target *target;
|
||||
target_id_t target_id;
|
||||
|
||||
MPS_FUNCTRACE(sc);
|
||||
mps_dprint(sc, MPS_TRACE,
|
||||
@ -2069,6 +2090,7 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
|
||||
sassc = sc->sassc;
|
||||
ccb = cm->cm_complete_data;
|
||||
csio = &ccb->csio;
|
||||
target_id = csio->ccb_h.target_id;
|
||||
rep = (MPI2_SCSI_IO_REPLY *)cm->cm_reply;
|
||||
/*
|
||||
* XXX KDM if the chain allocation fails, does it matter if we do
|
||||
@ -2250,9 +2272,10 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
|
||||
* TLR_bits for the target.
|
||||
*/
|
||||
if ((rep->SCSIState & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) &&
|
||||
((le32toh(rep->ResponseInfo) & MPI2_SCSI_RI_MASK_REASONCODE) ==
|
||||
((le32toh(rep->ResponseInfo) &
|
||||
MPI2_SCSI_RI_MASK_REASONCODE) ==
|
||||
MPS_SCSI_RI_INVALID_FRAME)) {
|
||||
sc->mapping_table[csio->ccb_h.target_id].TLR_bits =
|
||||
sc->mapping_table[target_id].TLR_bits =
|
||||
(u8)MPI2_SCSIIO_CONTROL_NO_TLR;
|
||||
}
|
||||
|
||||
@ -2309,12 +2332,11 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
|
||||
(csio->data_ptr != NULL) &&
|
||||
((csio->data_ptr[0] & 0x1f) == T_SEQUENTIAL) &&
|
||||
(sc->control_TLR) &&
|
||||
(sc->mapping_table[csio->ccb_h.target_id].device_info &
|
||||
(sc->mapping_table[target_id].device_info &
|
||||
MPI2_SAS_DEVICE_INFO_SSP_TARGET)) {
|
||||
vpd_list = (struct scsi_vpd_supported_page_list *)
|
||||
csio->data_ptr;
|
||||
TLR_bits = &sc->mapping_table[csio->ccb_h.target_id].
|
||||
TLR_bits;
|
||||
TLR_bits = &sc->mapping_table[target_id].TLR_bits;
|
||||
*TLR_bits = (u8)MPI2_SCSIIO_CONTROL_NO_TLR;
|
||||
TLR_on = (u8)MPI2_SCSIIO_CONTROL_TLR_ON;
|
||||
alloc_len = ((u16)csio->cdb_io.cdb_bytes[3] << 8) +
|
||||
@ -2327,6 +2349,24 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a SATA direct-access end device, mark it so that
|
||||
* a SCSI StartStopUnit command will be sent to it when the
|
||||
* driver is being shutdown.
|
||||
*/
|
||||
if ((csio->cdb_io.cdb_bytes[0] == INQUIRY) &&
|
||||
((csio->data_ptr[0] & 0x1f) == T_DIRECT) &&
|
||||
(sc->mapping_table[target_id].device_info &
|
||||
MPI2_SAS_DEVICE_INFO_SATA_DEVICE) &&
|
||||
((sc->mapping_table[target_id].device_info &
|
||||
MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) ==
|
||||
MPI2_SAS_DEVICE_INFO_END_DEVICE)) {
|
||||
target = &sassc->targets[target_id];
|
||||
target->supports_SSU = TRUE;
|
||||
mps_dprint(sc, MPS_XINFO, "Target %d supports SSU\n",
|
||||
target_id);
|
||||
}
|
||||
break;
|
||||
case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
|
||||
case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
|
||||
@ -3098,6 +3138,8 @@ mpssas_action_resetdev(struct mpssas_softc *sassc, union ccb *ccb)
|
||||
tm->cm_complete = mpssas_resetdev_complete;
|
||||
tm->cm_complete_data = ccb;
|
||||
tm->cm_targ = targ;
|
||||
targ->flags |= MPSSAS_TARGET_INRESET;
|
||||
|
||||
mps_map_command(sc, tm);
|
||||
}
|
||||
|
||||
@ -3370,9 +3412,9 @@ mpssas_check_eedp(struct mps_softc *sc, struct cam_path *path,
|
||||
* shutdown.
|
||||
*/
|
||||
if ((cgd.inq_data.device == T_DIRECT) &&
|
||||
(target->devinfo & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) &&
|
||||
((target->devinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) ==
|
||||
MPI2_SAS_DEVICE_INFO_END_DEVICE)) {
|
||||
(target->devinfo & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) &&
|
||||
((target->devinfo & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) ==
|
||||
MPI2_SAS_DEVICE_INFO_END_DEVICE)) {
|
||||
lun->stop_at_shutdown = TRUE;
|
||||
}
|
||||
|
||||
@ -3489,6 +3531,34 @@ mpssas_read_cap_done(struct cam_periph *periph, union ccb *done_ccb)
|
||||
#endif /* (__FreeBSD_version < 901503) || \
|
||||
((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000006)) */
|
||||
|
||||
void
|
||||
mpssas_prepare_for_tm(struct mps_softc *sc, struct mps_command *tm,
|
||||
struct mpssas_target *target, lun_id_t lun_id)
|
||||
{
|
||||
union ccb *ccb;
|
||||
path_id_t path_id;
|
||||
|
||||
/*
|
||||
* Set the INRESET flag for this target so that no I/O will be sent to
|
||||
* the target until the reset has completed. If an I/O request does
|
||||
* happen, the devq will be frozen. The CCB holds the path which is
|
||||
* used to release the devq. The devq is released and the CCB is freed
|
||||
* when the TM completes.
|
||||
*/
|
||||
ccb = xpt_alloc_ccb_nowait();
|
||||
if (ccb) {
|
||||
path_id = cam_sim_path(sc->sassc->sim);
|
||||
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, path_id,
|
||||
target->tid, lun_id) != CAM_REQ_CMP) {
|
||||
xpt_free_ccb(ccb);
|
||||
} else {
|
||||
tm->cm_ccb = ccb;
|
||||
tm->cm_targ = target;
|
||||
target->flags |= MPSSAS_TARGET_INRESET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mpssas_startup(struct mps_softc *sc)
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2011-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,7 +24,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -35,7 +36,6 @@ struct mpssas_lun {
|
||||
lun_id_t lun_id;
|
||||
uint8_t eedp_formatted;
|
||||
uint32_t eedp_block_size;
|
||||
uint8_t stop_at_shutdown;
|
||||
};
|
||||
|
||||
struct mpssas_target {
|
||||
@ -52,11 +52,10 @@ struct mpssas_target {
|
||||
#define MPSSAS_TARGET_INREMOVAL (1 << 3)
|
||||
#define MPS_TARGET_FLAGS_RAID_COMPONENT (1 << 4)
|
||||
#define MPS_TARGET_FLAGS_VOLUME (1 << 5)
|
||||
#define MPS_TARGET_IS_SATA_SSD (1 << 6)
|
||||
#define MPSSAS_TARGET_INRECOVERY (MPSSAS_TARGET_INABORT | \
|
||||
MPSSAS_TARGET_INRESET | MPSSAS_TARGET_INCHIPRESET)
|
||||
|
||||
#define MPSSAS_TARGET_ADD (1 << 29)
|
||||
#define MPSSAS_TARGET_REMOVE (1 << 30)
|
||||
uint16_t tid;
|
||||
SLIST_HEAD(, mpssas_lun) luns;
|
||||
TAILQ_HEAD(, mps_command) commands;
|
||||
@ -78,6 +77,8 @@ struct mpssas_target {
|
||||
unsigned int aborts;
|
||||
unsigned int logical_unit_resets;
|
||||
unsigned int target_resets;
|
||||
uint8_t stop_at_shutdown;
|
||||
uint8_t supports_SSU;
|
||||
};
|
||||
|
||||
struct mpssas_softc {
|
||||
@ -95,11 +96,9 @@ struct mpssas_softc {
|
||||
struct cam_path *path;
|
||||
struct intr_config_hook sas_ich;
|
||||
struct callout discovery_callout;
|
||||
u_int discovery_timeouts;
|
||||
struct mps_event_handle *mpssas_eh;
|
||||
|
||||
u_int startup_refcount;
|
||||
u_int tm_count;
|
||||
struct proc *sysctl_proc;
|
||||
|
||||
struct taskqueue *ev_tq;
|
||||
@ -167,6 +166,8 @@ do { \
|
||||
|
||||
void mpssas_rescan_target(struct mps_softc *sc, struct mpssas_target *targ);
|
||||
void mpssas_discovery_end(struct mpssas_softc *sassc);
|
||||
void mpssas_prepare_for_tm(struct mps_softc *sc, struct mps_command *tm,
|
||||
struct mpssas_target *target, lun_id_t lun_id);
|
||||
void mpssas_startup_increment(struct mpssas_softc *sassc);
|
||||
void mpssas_startup_decrement(struct mpssas_softc *sassc);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2011-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -23,13 +24,13 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/* Communications core for LSI MPT2 */
|
||||
/* Communications core for Avago Technologies (LSI) MPT2 */
|
||||
|
||||
/* TODO Move headers to mpsvar */
|
||||
#include <sys/types.h>
|
||||
@ -105,7 +106,9 @@ struct _ata_identify_device_data {
|
||||
u16 serial_number[10]; /* 10-19 */
|
||||
u16 reserved2[7]; /* 20-26 */
|
||||
u16 model_number[20]; /* 27-46*/
|
||||
u16 reserved3[209]; /* 47-255*/
|
||||
u16 reserved3[170]; /* 47-216 */
|
||||
u16 rotational_speed; /* 217 */
|
||||
u16 reserved4[38]; /* 218-255 */
|
||||
};
|
||||
static u32 event_count;
|
||||
static void mpssas_fw_work(struct mps_softc *sc,
|
||||
@ -116,8 +119,9 @@ static int mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate);
|
||||
static int mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
|
||||
Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
|
||||
u32 devinfo);
|
||||
static void mpssas_ata_id_timeout(void *data);
|
||||
int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
|
||||
u64 *sas_address, u16 handle, u32 device_info);
|
||||
u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD);
|
||||
static int mpssas_volume_add(struct mps_softc *sc,
|
||||
u16 handle);
|
||||
static void mpssas_SSU_to_SATA_devices(struct mps_softc *sc);
|
||||
@ -606,14 +610,14 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
|
||||
struct mpssas_target *targ;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
Mpi2SasDevicePage0_t config_page;
|
||||
uint64_t sas_address, sata_sas_address;
|
||||
uint64_t sas_address;
|
||||
uint64_t parent_sas_address = 0;
|
||||
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
|
||||
u32 device_info, parent_devinfo = 0;
|
||||
unsigned int id;
|
||||
int ret;
|
||||
int error = 0;
|
||||
int ret = 1, error = 0, i;
|
||||
struct mpssas_lun *lun;
|
||||
u8 is_SATA_SSD = 0;
|
||||
struct mps_command *cm;
|
||||
|
||||
sassc = sc->sassc;
|
||||
mpssas_startup_increment(sassc);
|
||||
@ -645,26 +649,27 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
|
||||
}
|
||||
/* TODO Check proper endianess */
|
||||
sas_address = config_page.SASAddress.High;
|
||||
sas_address = (sas_address << 32) |
|
||||
config_page.SASAddress.Low;
|
||||
sas_address = (sas_address << 32) | config_page.SASAddress.Low;
|
||||
|
||||
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE)
|
||||
== MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
|
||||
if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
|
||||
ret = mpssas_get_sas_address_for_sata_disk(sc,
|
||||
&sata_sas_address, handle, device_info);
|
||||
if (!ret)
|
||||
id = mps_mapping_get_sas_id(sc,
|
||||
sata_sas_address, handle);
|
||||
else
|
||||
id = mps_mapping_get_sas_id(sc,
|
||||
sas_address, handle);
|
||||
} else
|
||||
id = mps_mapping_get_sas_id(sc, sas_address,
|
||||
handle);
|
||||
} else
|
||||
id = mps_mapping_get_sas_id(sc, sas_address, handle);
|
||||
/*
|
||||
* Always get SATA Identify information because this is used to
|
||||
* determine if Start/Stop Unit should be sent to the drive when the
|
||||
* system is shutdown.
|
||||
*/
|
||||
if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
|
||||
ret = mpssas_get_sas_address_for_sata_disk(sc, &sas_address,
|
||||
handle, device_info, &is_SATA_SSD);
|
||||
if (ret) {
|
||||
mps_dprint(sc, MPS_INFO, "%s: failed to get disk type "
|
||||
"(SSD or HDD) for SATA device with handle 0x%04x\n",
|
||||
__func__, handle);
|
||||
} else {
|
||||
mps_dprint(sc, MPS_INFO, "SAS Address from SATA "
|
||||
"device = %jx\n", sas_address);
|
||||
}
|
||||
}
|
||||
|
||||
id = mps_mapping_get_sas_id(sc, sas_address, handle);
|
||||
if (id == MPS_MAP_BAD_ID) {
|
||||
printf("failure at %s:%d/%s()! Could not get ID for device "
|
||||
"with handle 0x%04x\n", __FILE__, __LINE__, __func__,
|
||||
@ -696,6 +701,9 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
|
||||
targ->tid = id;
|
||||
targ->linkrate = (linkrate>>4);
|
||||
targ->flags = 0;
|
||||
if (is_SATA_SSD) {
|
||||
targ->flags = MPS_TARGET_IS_SATA_SSD;
|
||||
}
|
||||
TAILQ_INIT(&targ->commands);
|
||||
TAILQ_INIT(&targ->timedout_commands);
|
||||
while(!SLIST_EMPTY(&targ->luns)) {
|
||||
@ -706,8 +714,8 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
|
||||
SLIST_INIT(&targ->luns);
|
||||
|
||||
mps_describe_devinfo(targ->devinfo, devstring, 80);
|
||||
mps_dprint(sc, MPS_MAPPING, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring,
|
||||
mps_describe_table(mps_linkrate_names, targ->linkrate),
|
||||
mps_dprint(sc, MPS_MAPPING, "Found device <%s> <%s> <0x%04x> <%d/%d>\n",
|
||||
devstring, mps_describe_table(mps_linkrate_names, targ->linkrate),
|
||||
targ->handle, targ->encl_handle, targ->encl_slot);
|
||||
|
||||
#if __FreeBSD_version < 1000039
|
||||
@ -715,7 +723,50 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
|
||||
#endif
|
||||
mpssas_rescan_target(sc, targ);
|
||||
mps_dprint(sc, MPS_MAPPING, "Target id 0x%x added\n", targ->tid);
|
||||
|
||||
/*
|
||||
* Check all commands to see if the SATA_ID_TIMEOUT flag has been set.
|
||||
* If so, send a Target Reset TM to the target that was just created.
|
||||
* An Abort Task TM should be used instead of a Target Reset, but that
|
||||
* would be much more difficult because targets have not been fully
|
||||
* discovered yet, and LUN's haven't been setup. So, just reset the
|
||||
* target instead of the LUN.
|
||||
*/
|
||||
for (i = 1; i < sc->num_reqs; i++) {
|
||||
cm = &sc->commands[i];
|
||||
if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) {
|
||||
targ->timeouts++;
|
||||
cm->cm_state = MPS_CM_STATE_TIMEDOUT;
|
||||
|
||||
if ((targ->tm = mpssas_alloc_tm(sc)) != NULL) {
|
||||
mps_dprint(sc, MPS_INFO, "%s: sending Target "
|
||||
"Reset for stuck SATA identify command "
|
||||
"(cm = %p)\n", __func__, cm);
|
||||
targ->tm->cm_targ = targ;
|
||||
mpssas_send_reset(sc, targ->tm,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
|
||||
} else {
|
||||
mps_dprint(sc, MPS_ERROR, "Failed to allocate "
|
||||
"tm for Target Reset after SATA ID command "
|
||||
"timed out (cm %p)\n", cm);
|
||||
}
|
||||
/*
|
||||
* No need to check for more since the target is
|
||||
* already being reset.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
out:
|
||||
/*
|
||||
* Free the commands that may not have been freed from the SATA ID call
|
||||
*/
|
||||
for (i = 1; i < sc->num_reqs; i++) {
|
||||
cm = &sc->commands[i];
|
||||
if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) {
|
||||
mps_free_command(sc, cm);
|
||||
}
|
||||
}
|
||||
mpssas_startup_decrement(sassc);
|
||||
return (error);
|
||||
|
||||
@ -723,7 +774,7 @@ mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
|
||||
|
||||
int
|
||||
mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
|
||||
u64 *sas_address, u16 handle, u32 device_info)
|
||||
u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD)
|
||||
{
|
||||
Mpi2SataPassthroughReply_t mpi_reply;
|
||||
int i, rc, try_count;
|
||||
@ -743,16 +794,25 @@ mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
|
||||
ioc_status = le16toh(mpi_reply.IOCStatus)
|
||||
& MPI2_IOCSTATUS_MASK;
|
||||
sas_status = mpi_reply.SASStatus;
|
||||
} while ((rc == -EAGAIN || ioc_status || sas_status) &&
|
||||
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
||||
if (sc->spinup_wait_time > 0) {
|
||||
mps_dprint(sc, MPS_INFO, "Sleeping %d seconds "
|
||||
"after SATA ID error to wait for spinup\n",
|
||||
sc->spinup_wait_time);
|
||||
msleep(&sc->msleep_fake_chan, &sc->mps_mtx, 0,
|
||||
"mpsid", sc->spinup_wait_time * hz);
|
||||
}
|
||||
}
|
||||
} while (((rc && (rc != EWOULDBLOCK)) || ioc_status || sas_status) &&
|
||||
(try_count < 5));
|
||||
|
||||
if (rc == 0 && !ioc_status && !sas_status) {
|
||||
mps_dprint(sc, MPS_MAPPING, "%s: got SATA identify successfully "
|
||||
"for handle = 0x%x with try_count = %d\n",
|
||||
__func__, handle, try_count);
|
||||
mps_dprint(sc, MPS_MAPPING, "%s: got SATA identify "
|
||||
"successfully for handle = 0x%x with try_count = %d\n",
|
||||
__func__, handle, try_count);
|
||||
} else {
|
||||
mps_dprint(sc, MPS_MAPPING, "%s: handle = 0x%x failed\n",
|
||||
__func__, handle);
|
||||
__func__, handle);
|
||||
return -1;
|
||||
}
|
||||
/* Copy & byteswap the 40 byte model number to a buffer */
|
||||
@ -763,9 +823,9 @@ mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
|
||||
/* Copy & byteswap the 20 byte serial number to a buffer */
|
||||
for (i = 0; i < MPT2SAS_SN_LEN; i += 2) {
|
||||
buffer[MPT2SAS_MN_LEN + i] =
|
||||
((u8 *)ata_identify.serial_number)[i + 1];
|
||||
((u8 *)ata_identify.serial_number)[i + 1];
|
||||
buffer[MPT2SAS_MN_LEN + i + 1] =
|
||||
((u8 *)ata_identify.serial_number)[i];
|
||||
((u8 *)ata_identify.serial_number)[i];
|
||||
}
|
||||
bufferptr = (u32 *)buffer;
|
||||
/* There are 60 bytes to hash down to 8. 60 isn't divisible by 8,
|
||||
@ -792,6 +852,10 @@ mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
|
||||
(u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 |
|
||||
(u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] << 8 |
|
||||
(u64)hash_address.wwid[7];
|
||||
if (ata_identify.rotational_speed == 1) {
|
||||
*is_SATA_SSD = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -831,7 +895,22 @@ mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
cm->cm_data = buffer;
|
||||
cm->cm_length = htole32(sz);
|
||||
error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
|
||||
/*
|
||||
* Start a timeout counter specifically for the SATA ID command. This
|
||||
* is used to fix a problem where the FW does not send a reply sometimes
|
||||
* when a bad disk is in the topology. So, this is used to timeout the
|
||||
* command so that processing can continue normally.
|
||||
*/
|
||||
mps_dprint(sc, MPS_XINFO, "%s start timeout counter for SATA ID "
|
||||
"command\n", __func__);
|
||||
callout_reset(&cm->cm_callout, MPS_ATA_ID_TIMEOUT * hz,
|
||||
mpssas_ata_id_timeout, cm);
|
||||
error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
mps_dprint(sc, MPS_XINFO, "%s stop timeout counter for SATA ID "
|
||||
"command\n", __func__);
|
||||
callout_stop(&cm->cm_callout);
|
||||
|
||||
reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
|
||||
if (error || (reply == NULL)) {
|
||||
/* FIXME */
|
||||
@ -854,11 +933,66 @@ mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
mps_free_command(sc, cm);
|
||||
free(buffer, M_MPT2);
|
||||
/*
|
||||
* If the SATA_ID_TIMEOUT flag has been set for this command, don't free
|
||||
* it. The command will be freed after sending a target reset TM. If
|
||||
* the command did timeout, use EWOULDBLOCK.
|
||||
*/
|
||||
if ((cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) == 0)
|
||||
mps_free_command(sc, cm);
|
||||
else if (error == 0)
|
||||
error = EWOULDBLOCK;
|
||||
free(buffer, M_MPT2);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
mpssas_ata_id_timeout(void *data)
|
||||
{
|
||||
struct mps_softc *sc;
|
||||
struct mps_command *cm;
|
||||
|
||||
cm = (struct mps_command *)data;
|
||||
sc = cm->cm_sc;
|
||||
mtx_assert(&sc->mps_mtx, MA_OWNED);
|
||||
|
||||
mps_dprint(sc, MPS_INFO, "%s checking ATA ID command %p sc %p\n",
|
||||
__func__, cm, sc);
|
||||
if ((callout_pending(&cm->cm_callout)) ||
|
||||
(!callout_active(&cm->cm_callout))) {
|
||||
mps_dprint(sc, MPS_INFO, "%s ATA ID command almost timed out\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
callout_deactivate(&cm->cm_callout);
|
||||
|
||||
/*
|
||||
* Run the interrupt handler to make sure it's not pending. This
|
||||
* isn't perfect because the command could have already completed
|
||||
* and been re-used, though this is unlikely.
|
||||
*/
|
||||
mps_intr_locked(sc);
|
||||
if (cm->cm_state == MPS_CM_STATE_FREE) {
|
||||
mps_dprint(sc, MPS_INFO, "%s ATA ID command almost timed out\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
mps_dprint(sc, MPS_INFO, "ATA ID command timeout cm %p\n", cm);
|
||||
|
||||
/*
|
||||
* Send wakeup() to the sleeping thread that issued this ATA ID command.
|
||||
* wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), and this
|
||||
* will keep reinit() from being called. This way, an Abort Task TM can
|
||||
* be issued so that the timed out command can be cleared. The Abort
|
||||
* Task cannot be sent from here because the driver has not completed
|
||||
* setting up targets. Instead, the command is flagged so that special
|
||||
* handling will be used to send the abort.
|
||||
*/
|
||||
cm->cm_flags |= MPS_CM_FLAGS_SATA_ID_TIMEOUT;
|
||||
wakeup(cm);
|
||||
}
|
||||
|
||||
static int
|
||||
mpssas_volume_add(struct mps_softc *sc, u16 handle)
|
||||
{
|
||||
@ -931,13 +1065,11 @@ mpssas_SSU_to_SATA_devices(struct mps_softc *sc)
|
||||
path_id_t pathid = cam_sim_path(sassc->sim);
|
||||
target_id_t targetid;
|
||||
struct mpssas_target *target;
|
||||
struct mpssas_lun *lun;
|
||||
char path_str[64];
|
||||
struct timeval cur_time, start_time;
|
||||
|
||||
/*
|
||||
* For each LUN of each target, issue a StartStopUnit command to stop
|
||||
* the device.
|
||||
* For each target, issue a StartStopUnit command to stop the device.
|
||||
*/
|
||||
sc->SSU_started = TRUE;
|
||||
sc->SSU_refcount = 0;
|
||||
@ -947,63 +1079,58 @@ mpssas_SSU_to_SATA_devices(struct mps_softc *sc)
|
||||
continue;
|
||||
}
|
||||
|
||||
SLIST_FOREACH(lun, &target->luns, lun_link) {
|
||||
ccb = xpt_alloc_ccb_nowait();
|
||||
if (ccb == NULL) {
|
||||
mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB "
|
||||
"to stop unit.\n");
|
||||
ccb = xpt_alloc_ccb_nowait();
|
||||
if (ccb == NULL) {
|
||||
mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB to stop "
|
||||
"unit.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The stop_at_shutdown flag will be set if this device is
|
||||
* a SATA direct-access end device.
|
||||
*/
|
||||
if (target->stop_at_shutdown) {
|
||||
if (xpt_create_path(&ccb->ccb_h.path,
|
||||
xpt_periph, pathid, targetid,
|
||||
CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
mps_dprint(sc, MPS_FAULT, "Unable to create "
|
||||
"LUN path to stop unit.\n");
|
||||
xpt_free_ccb(ccb);
|
||||
return;
|
||||
}
|
||||
xpt_path_string(ccb->ccb_h.path, path_str,
|
||||
sizeof(path_str));
|
||||
|
||||
/*
|
||||
* The stop_at_shutdown flag will be set if this LUN is
|
||||
* a SATA direct-access end device.
|
||||
*/
|
||||
if (lun->stop_at_shutdown) {
|
||||
if (xpt_create_path(&ccb->ccb_h.path,
|
||||
xpt_periph, pathid, targetid,
|
||||
lun->lun_id) != CAM_REQ_CMP) {
|
||||
mps_dprint(sc, MPS_FAULT, "Unable to "
|
||||
"create LUN path to stop unit.\n");
|
||||
xpt_free_ccb(ccb);
|
||||
return;
|
||||
}
|
||||
xpt_path_string(ccb->ccb_h.path, path_str,
|
||||
sizeof(path_str));
|
||||
|
||||
mps_dprint(sc, MPS_INFO, "Sending StopUnit: "
|
||||
"path %s handle %d\n", path_str,
|
||||
target->handle);
|
||||
mps_dprint(sc, MPS_INFO, "Sending StopUnit: path %s "
|
||||
"handle %d\n", path_str, target->handle);
|
||||
|
||||
/*
|
||||
* Issue a START STOP UNIT command for the LUN.
|
||||
* Increment the SSU counter to be used to
|
||||
* count the number of required replies.
|
||||
*/
|
||||
mps_dprint(sc, MPS_INFO, "Incrementing SSU "
|
||||
"count\n");
|
||||
sc->SSU_refcount++;
|
||||
ccb->ccb_h.target_id =
|
||||
xpt_path_target_id(ccb->ccb_h.path);
|
||||
ccb->ccb_h.target_lun = lun->lun_id;
|
||||
ccb->ccb_h.ppriv_ptr1 = sassc;
|
||||
scsi_start_stop(&ccb->csio,
|
||||
/*retries*/0,
|
||||
mpssas_stop_unit_done,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
/*start*/FALSE,
|
||||
/*load/eject*/0,
|
||||
/*immediate*/FALSE,
|
||||
MPS_SENSE_LEN,
|
||||
/*timeout*/10000);
|
||||
xpt_action(ccb);
|
||||
}
|
||||
/*
|
||||
* Issue a START STOP UNIT command for the target.
|
||||
* Increment the SSU counter to be used to count the
|
||||
* number of required replies.
|
||||
*/
|
||||
mps_dprint(sc, MPS_INFO, "Incrementing SSU count\n");
|
||||
sc->SSU_refcount++;
|
||||
ccb->ccb_h.target_id =
|
||||
xpt_path_target_id(ccb->ccb_h.path);
|
||||
ccb->ccb_h.ppriv_ptr1 = sassc;
|
||||
scsi_start_stop(&ccb->csio,
|
||||
/*retries*/0,
|
||||
mpssas_stop_unit_done,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
/*start*/FALSE,
|
||||
/*load/eject*/0,
|
||||
/*immediate*/FALSE,
|
||||
MPS_SENSE_LEN,
|
||||
/*timeout*/10000);
|
||||
xpt_action(ccb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait until all of the SSU commands have completed or time has
|
||||
* expired (60 seconds). pause for 100ms each time through. If any
|
||||
* expired (60 seconds). Pause for 100ms each time through. If any
|
||||
* command times out, the target will be reset in the SCSI command
|
||||
* timeout routine.
|
||||
*/
|
||||
@ -1063,6 +1190,8 @@ mpssas_ir_shutdown(struct mps_softc *sc)
|
||||
unsigned int id, found_volume = 0;
|
||||
struct mps_command *cm;
|
||||
Mpi2RaidActionRequest_t *action;
|
||||
target_id_t targetid;
|
||||
struct mpssas_target *target;
|
||||
|
||||
mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
|
||||
|
||||
@ -1105,7 +1234,7 @@ mpssas_ir_shutdown(struct mps_softc *sc)
|
||||
action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
mps_lock(sc);
|
||||
mps_wait_command(sc, cm, 5, CAN_SLEEP);
|
||||
mps_wait_command(sc, cm, 5, CAN_SLEEP);
|
||||
mps_unlock(sc);
|
||||
|
||||
/*
|
||||
@ -1115,5 +1244,47 @@ mpssas_ir_shutdown(struct mps_softc *sc)
|
||||
mps_free_command(sc, cm);
|
||||
|
||||
out:
|
||||
/*
|
||||
* All of the targets must have the correct value set for
|
||||
* 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable.
|
||||
*
|
||||
* The possible values for the 'enable_ssu' variable are:
|
||||
* 0: disable to SSD and HDD
|
||||
* 1: disable only to HDD (default)
|
||||
* 2: disable only to SSD
|
||||
* 3: enable to SSD and HDD
|
||||
* anything else will default to 1.
|
||||
*/
|
||||
for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
|
||||
target = &sc->sassc->targets[targetid];
|
||||
if (target->handle == 0x0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (target->supports_SSU) {
|
||||
switch (sc->enable_ssu) {
|
||||
case MPS_SSU_DISABLE_SSD_DISABLE_HDD:
|
||||
target->stop_at_shutdown = FALSE;
|
||||
break;
|
||||
case MPS_SSU_DISABLE_SSD_ENABLE_HDD:
|
||||
target->stop_at_shutdown = TRUE;
|
||||
if (target->flags & MPS_TARGET_IS_SATA_SSD) {
|
||||
target->stop_at_shutdown = FALSE;
|
||||
}
|
||||
break;
|
||||
case MPS_SSU_ENABLE_SSD_ENABLE_HDD:
|
||||
target->stop_at_shutdown = TRUE;
|
||||
break;
|
||||
case MPS_SSU_ENABLE_SSD_DISABLE_HDD:
|
||||
default:
|
||||
target->stop_at_shutdown = TRUE;
|
||||
if ((target->flags &
|
||||
MPS_TARGET_IS_SATA_SSD) == 0) {
|
||||
target->stop_at_shutdown = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mpssas_SSU_to_SATA_devices(sc);
|
||||
}
|
||||
|
@ -27,10 +27,11 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD userland interface
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2011-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -54,7 +55,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -90,6 +91,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
|
||||
#include <dev/mps/mpi/mpi2_type.h>
|
||||
@ -101,6 +103,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/mps/mps_ioctl.h>
|
||||
#include <dev/mps/mpsvar.h>
|
||||
#include <dev/mps/mps_table.h>
|
||||
#include <dev/mps/mps_sas.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
|
||||
@ -700,7 +703,7 @@ mps_user_command(struct mps_softc *sc, struct mps_usr_command *cmd)
|
||||
mps_printf(sc, "Cannot allocate memory %s %d\n",
|
||||
__func__, __LINE__);
|
||||
return (ENOMEM);
|
||||
}
|
||||
}
|
||||
cm->cm_data = buf;
|
||||
cm->cm_length = cmd->len;
|
||||
} else {
|
||||
@ -767,6 +770,7 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
|
||||
int err = 0, dir = 0, sz;
|
||||
uint8_t function = 0;
|
||||
u_int sense_len;
|
||||
struct mpssas_target *targ = NULL;
|
||||
|
||||
/*
|
||||
* Only allow one passthru command at a time. Use the MPS_FLAGS_BUSY
|
||||
@ -848,11 +852,22 @@ mps_user_pass_thru(struct mps_softc *sc, mps_pass_thru_t *data)
|
||||
task->TaskMID = cm->cm_desc.Default.SMID;
|
||||
|
||||
cm->cm_data = NULL;
|
||||
cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
|
||||
cm->cm_desc.HighPriority.RequestFlags =
|
||||
MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
|
||||
cm->cm_complete = NULL;
|
||||
cm->cm_complete_data = NULL;
|
||||
|
||||
err = mps_wait_command(sc, cm, 30, CAN_SLEEP);
|
||||
targ = mpssas_find_target_by_handle(sc->sassc, 0,
|
||||
task->DevHandle);
|
||||
if (targ == NULL) {
|
||||
mps_dprint(sc, MPS_INFO,
|
||||
"%s %d : invalid handle for requested TM 0x%x \n",
|
||||
__func__, __LINE__, task->DevHandle);
|
||||
err = 1;
|
||||
} else {
|
||||
mpssas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
|
||||
err = mps_wait_command(sc, cm, 30, CAN_SLEEP);
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
err = EIO;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Yahoo! Inc.
|
||||
* Copyright (c) 2011, 2012 LSI Corp.
|
||||
* Copyright (c) 2011-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -24,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* LSI MPT-Fusion Host Adapter FreeBSD
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
@ -32,7 +33,7 @@
|
||||
#ifndef _MPSVAR_H
|
||||
#define _MPSVAR_H
|
||||
|
||||
#define MPS_DRIVER_VERSION "19.00.00.00-fbsd"
|
||||
#define MPS_DRIVER_VERSION "20.00.00.00-fbsd"
|
||||
|
||||
#define MPS_DB_MAX_WAIT 2500
|
||||
|
||||
@ -50,10 +51,13 @@
|
||||
#define NO_SLEEP 0
|
||||
|
||||
#define MPS_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */
|
||||
#define MPS_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */
|
||||
|
||||
#define MPS_SCSI_RI_INVALID_FRAME (0x00000002)
|
||||
#define MPS_STRING_LENGTH 64
|
||||
|
||||
#define DEFAULT_SPINUP_WAIT 3 /* seconds to wait for spinup */
|
||||
|
||||
#include <sys/endian.h>
|
||||
|
||||
/*
|
||||
@ -232,6 +236,7 @@ struct mps_command {
|
||||
#define MPS_CM_FLAGS_CHAIN_FAILED (1 << 9)
|
||||
#define MPS_CM_FLAGS_ERROR_MASK MPS_CM_FLAGS_CHAIN_FAILED
|
||||
#define MPS_CM_FLAGS_USE_CCB (1 << 10)
|
||||
#define MPS_CM_FLAGS_SATA_ID_TIMEOUT (1 << 11)
|
||||
u_int cm_state;
|
||||
#define MPS_CM_STATE_FREE 0
|
||||
#define MPS_CM_STATE_BUSY 1
|
||||
@ -276,6 +281,8 @@ struct mps_softc {
|
||||
int chain_free;
|
||||
int max_chains;
|
||||
int chain_free_lowwater;
|
||||
u_int enable_ssu;
|
||||
int spinup_wait_time;
|
||||
#if __FreeBSD_version >= 900030
|
||||
uint64_t chain_alloc_fail;
|
||||
#endif
|
||||
@ -599,6 +606,11 @@ mps_unlock(struct mps_softc *sc)
|
||||
#define MPS_MAPPING (1 << 9) /* Trace device mappings */
|
||||
#define MPS_TRACE (1 << 10) /* Function-by-function trace */
|
||||
|
||||
#define MPS_SSU_DISABLE_SSD_DISABLE_HDD 0
|
||||
#define MPS_SSU_ENABLE_SSD_DISABLE_HDD 1
|
||||
#define MPS_SSU_DISABLE_SSD_ENABLE_HDD 2
|
||||
#define MPS_SSU_ENABLE_SSD_ENABLE_HDD 3
|
||||
|
||||
#define mps_printf(sc, args...) \
|
||||
device_printf((sc)->mps_dev, ##args)
|
||||
|
||||
@ -764,6 +776,8 @@ void mpssas_realloc_targets(struct mps_softc *sc, int maxtargets);
|
||||
struct mps_command * mpssas_alloc_tm(struct mps_softc *sc);
|
||||
void mpssas_free_tm(struct mps_softc *sc, struct mps_command *tm);
|
||||
void mpssas_release_simq_reinit(struct mpssas_softc *sassc);
|
||||
int mpssas_send_reset(struct mps_softc *sc, struct mps_command *tm,
|
||||
uint8_t type);
|
||||
|
||||
SYSCTL_DECL(_hw_mps);
|
||||
|
||||
|
422
sys/dev/netmap/if_ixl_netmap.h
Normal file
422
sys/dev/netmap/if_ixl_netmap.h
Normal file
@ -0,0 +1,422 @@
|
||||
/*
|
||||
* Copyright (C) 2015, Luigi Rizzo. 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$
|
||||
*
|
||||
* netmap support for: ixl
|
||||
*
|
||||
* derived from ixgbe
|
||||
* netmap support for a network driver.
|
||||
* This file contains code but only static or inline functions used
|
||||
* by a single driver. To avoid replication of code we just #include
|
||||
* it near the beginning of the standard driver.
|
||||
* For ixl the file is imported in two places, hence the conditional at the
|
||||
* beginning.
|
||||
*/
|
||||
|
||||
#include <net/netmap.h>
|
||||
#include <sys/selinfo.h>
|
||||
|
||||
/*
|
||||
* Some drivers may need the following headers. Others
|
||||
* already include them by default
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
*/
|
||||
#include <dev/netmap/netmap_kern.h>
|
||||
|
||||
int ixl_netmap_txsync(struct netmap_kring *kring, int flags);
|
||||
int ixl_netmap_rxsync(struct netmap_kring *kring, int flags);
|
||||
|
||||
extern int ixl_rx_miss, ixl_rx_miss_bufs, ixl_crcstrip;
|
||||
|
||||
#ifdef NETMAP_IXL_MAIN
|
||||
/*
|
||||
* device-specific sysctl variables:
|
||||
*
|
||||
* ixl_crcstrip: 0: keep CRC in rx frames (default), 1: strip it.
|
||||
* During regular operations the CRC is stripped, but on some
|
||||
* hardware reception of frames not multiple of 64 is slower,
|
||||
* so using crcstrip=0 helps in benchmarks.
|
||||
*
|
||||
* ixl_rx_miss, ixl_rx_miss_bufs:
|
||||
* count packets that might be missed due to lost interrupts.
|
||||
*/
|
||||
SYSCTL_DECL(_dev_netmap);
|
||||
int ixl_rx_miss, ixl_rx_miss_bufs, ixl_crcstrip;
|
||||
SYSCTL_INT(_dev_netmap, OID_AUTO, ixl_crcstrip,
|
||||
CTLFLAG_RW, &ixl_crcstrip, 0, "strip CRC on rx frames");
|
||||
SYSCTL_INT(_dev_netmap, OID_AUTO, ixl_rx_miss,
|
||||
CTLFLAG_RW, &ixl_rx_miss, 0, "potentially missed rx intr");
|
||||
SYSCTL_INT(_dev_netmap, OID_AUTO, ixl_rx_miss_bufs,
|
||||
CTLFLAG_RW, &ixl_rx_miss_bufs, 0, "potentially missed rx intr bufs");
|
||||
|
||||
|
||||
/*
|
||||
* Register/unregister. We are already under netmap lock.
|
||||
* Only called on the first register or the last unregister.
|
||||
*/
|
||||
static int
|
||||
ixl_netmap_reg(struct netmap_adapter *na, int onoff)
|
||||
{
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct ixl_vsi *vsi = ifp->if_softc;
|
||||
struct ixl_pf *pf = (struct ixl_pf *)vsi->back;
|
||||
|
||||
IXL_PF_LOCK(pf);
|
||||
ixl_disable_intr(vsi);
|
||||
|
||||
/* Tell the stack that the interface is no longer active */
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
//set_crcstrip(&adapter->hw, onoff);
|
||||
/* enable or disable flags and callbacks in na and ifp */
|
||||
if (onoff) {
|
||||
nm_set_native_flags(na);
|
||||
} else {
|
||||
nm_clear_native_flags(na);
|
||||
}
|
||||
ixl_init_locked(pf); /* also enables intr */
|
||||
//set_crcstrip(&adapter->hw, onoff); // XXX why twice ?
|
||||
IXL_PF_UNLOCK(pf);
|
||||
return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The attach routine, called near the end of ixl_attach(),
|
||||
* fills the parameters for netmap_attach() and calls it.
|
||||
* It cannot fail, in the worst case (such as no memory)
|
||||
* netmap mode will be disabled and the driver will only
|
||||
* operate in standard mode.
|
||||
*/
|
||||
static void
|
||||
ixl_netmap_attach(struct ixl_vsi *vsi)
|
||||
{
|
||||
struct netmap_adapter na;
|
||||
|
||||
bzero(&na, sizeof(na));
|
||||
|
||||
na.ifp = vsi->ifp;
|
||||
na.na_flags = NAF_BDG_MAYSLEEP;
|
||||
// XXX check that queues is set.
|
||||
printf("queues is %p\n", vsi->queues);
|
||||
if (vsi->queues) {
|
||||
na.num_tx_desc = vsi->queues[0].num_desc;
|
||||
na.num_rx_desc = vsi->queues[0].num_desc;
|
||||
}
|
||||
na.nm_txsync = ixl_netmap_txsync;
|
||||
na.nm_rxsync = ixl_netmap_rxsync;
|
||||
na.nm_register = ixl_netmap_reg;
|
||||
na.num_tx_rings = na.num_rx_rings = vsi->num_queues;
|
||||
netmap_attach(&na);
|
||||
}
|
||||
|
||||
|
||||
#else /* !NETMAP_IXL_MAIN, code for ixl_txrx.c */
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the transmit ring.
|
||||
*
|
||||
* All information is in the kring.
|
||||
* Userspace wants to send packets up to the one before kring->rhead,
|
||||
* kernel knows kring->nr_hwcur is the first unsent packet.
|
||||
*
|
||||
* Here we push packets out (as many as possible), and possibly
|
||||
* reclaim buffers from previously completed transmission.
|
||||
*
|
||||
* The caller (netmap) guarantees that there is only one instance
|
||||
* running at any time. Any interference with other driver
|
||||
* methods should be handled by the individual drivers.
|
||||
*/
|
||||
int
|
||||
ixl_netmap_txsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = kring->rhead;
|
||||
/*
|
||||
* interrupts on every tx packet are expensive so request
|
||||
* them every half ring, or where NS_REPORT is set
|
||||
*/
|
||||
u_int report_frequency = kring->nkr_num_slots >> 1;
|
||||
|
||||
/* device-specific */
|
||||
struct ixl_vsi *vsi = ifp->if_softc;
|
||||
struct ixl_queue *que = &vsi->queues[kring->ring_id];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
|
||||
bus_dmamap_sync(txr->dma.tag, txr->dma.map,
|
||||
BUS_DMASYNC_POSTREAD);
|
||||
|
||||
/*
|
||||
* First part: process new packets to send.
|
||||
* nm_i is the current index in the netmap ring,
|
||||
* nic_i is the corresponding index in the NIC ring.
|
||||
*
|
||||
* If we have packets to send (nm_i != head)
|
||||
* iterate over the netmap ring, fetch length and update
|
||||
* the corresponding slot in the NIC ring. Some drivers also
|
||||
* need to update the buffer's physical address in the NIC slot
|
||||
* even NS_BUF_CHANGED is not set (PNMB computes the addresses).
|
||||
*
|
||||
* The netmap_reload_map() calls is especially expensive,
|
||||
* even when (as in this case) the tag is 0, so do only
|
||||
* when the buffer has actually changed.
|
||||
*
|
||||
* If possible do not set the report/intr bit on all slots,
|
||||
* but only a few times per ring or when NS_REPORT is set.
|
||||
*
|
||||
* Finally, on 10G and faster drivers, it might be useful
|
||||
* to prefetch the next slot and txr entry.
|
||||
*/
|
||||
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) { /* we have new packets to send */
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
|
||||
__builtin_prefetch(&ring->slot[nm_i]);
|
||||
__builtin_prefetch(&txr->buffers[nic_i]);
|
||||
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
u_int len = slot->len;
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(na, slot, &paddr);
|
||||
|
||||
/* device-specific */
|
||||
struct i40e_tx_desc *curr = &txr->base[nic_i];
|
||||
struct ixl_tx_buf *txbuf = &txr->buffers[nic_i];
|
||||
u64 flags = (slot->flags & NS_REPORT ||
|
||||
nic_i == 0 || nic_i == report_frequency) ?
|
||||
((u64)I40E_TX_DESC_CMD_RS << I40E_TXD_QW1_CMD_SHIFT) : 0;
|
||||
|
||||
/* prefetch for next round */
|
||||
__builtin_prefetch(&ring->slot[nm_i + 1]);
|
||||
__builtin_prefetch(&txr->buffers[nic_i + 1]);
|
||||
|
||||
NM_CHECK_ADDR_LEN(na, addr, len);
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
netmap_reload_map(na, txr->dma.tag, txbuf->map, addr);
|
||||
}
|
||||
slot->flags &= ~(NS_REPORT | NS_BUF_CHANGED);
|
||||
|
||||
/* Fill the slot in the NIC ring. */
|
||||
curr->buffer_addr = htole64(paddr);
|
||||
curr->cmd_type_offset_bsz = htole64(
|
||||
((u64)len << I40E_TXD_QW1_TX_BUF_SZ_SHIFT) |
|
||||
flags |
|
||||
((u64)I40E_TX_DESC_CMD_EOP << I40E_TXD_QW1_CMD_SHIFT)
|
||||
); // XXX more ?
|
||||
|
||||
/* make sure changes to the buffer are synced */
|
||||
bus_dmamap_sync(txr->dma.tag, txbuf->map,
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
|
||||
/* synchronize the NIC ring */
|
||||
bus_dmamap_sync(txr->dma.tag, txr->dma.map,
|
||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
|
||||
|
||||
/* (re)start the tx unit up to slot nic_i (excluded) */
|
||||
wr32(vsi->hw, txr->tail, nic_i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: reclaim buffers for completed transmissions.
|
||||
*/
|
||||
nic_i = LE32_TO_CPU(*(volatile __le32 *)&txr->base[que->num_desc]);
|
||||
if (nic_i != txr->next_to_clean) {
|
||||
/* some tx completed, increment avail */
|
||||
txr->next_to_clean = nic_i;
|
||||
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim);
|
||||
}
|
||||
|
||||
nm_txsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reconcile kernel and user view of the receive ring.
|
||||
* Same as for the txsync, this routine must be efficient.
|
||||
* The caller guarantees a single invocations, but races against
|
||||
* the rest of the driver should be handled here.
|
||||
*
|
||||
* On call, kring->rhead is the first packet that userspace wants
|
||||
* to keep, and kring->rcur is the wakeup point.
|
||||
* The kernel has previously reported packets up to kring->rtail.
|
||||
*
|
||||
* If (flags & NAF_FORCE_READ) also check for incoming packets irrespective
|
||||
* of whether or not we received an interrupt.
|
||||
*/
|
||||
int
|
||||
ixl_netmap_rxsync(struct netmap_kring *kring, int flags)
|
||||
{
|
||||
struct netmap_adapter *na = kring->na;
|
||||
struct ifnet *ifp = na->ifp;
|
||||
struct netmap_ring *ring = kring->ring;
|
||||
u_int nm_i; /* index into the netmap ring */
|
||||
u_int nic_i; /* index into the NIC ring */
|
||||
u_int n;
|
||||
u_int const lim = kring->nkr_num_slots - 1;
|
||||
u_int const head = nm_rxsync_prologue(kring);
|
||||
int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
|
||||
|
||||
/* device-specific */
|
||||
struct ixl_vsi *vsi = ifp->if_softc;
|
||||
struct ixl_queue *que = &vsi->queues[kring->ring_id];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
|
||||
if (head > lim)
|
||||
return netmap_ring_reinit(kring);
|
||||
|
||||
/* XXX check sync modes */
|
||||
bus_dmamap_sync(rxr->dma.tag, rxr->dma.map,
|
||||
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
|
||||
|
||||
/*
|
||||
* First part: import newly received packets.
|
||||
*
|
||||
* nm_i is the index of the next free slot in the netmap ring,
|
||||
* nic_i is the index of the next received packet in the NIC ring,
|
||||
* and they may differ in case if_init() has been called while
|
||||
* in netmap mode. For the receive ring we have
|
||||
*
|
||||
* nic_i = rxr->next_check;
|
||||
* nm_i = kring->nr_hwtail (previous)
|
||||
* and
|
||||
* nm_i == (nic_i + kring->nkr_hwofs) % ring_size
|
||||
*
|
||||
* rxr->next_check is set to 0 on a ring reinit
|
||||
*/
|
||||
if (netmap_no_pendintr || force_update) {
|
||||
int crclen = ixl_crcstrip ? 0 : 4;
|
||||
uint16_t slot_flags = kring->nkr_slot_flags;
|
||||
|
||||
nic_i = rxr->next_check; // or also k2n(kring->nr_hwtail)
|
||||
nm_i = netmap_idx_n2k(kring, nic_i);
|
||||
|
||||
for (n = 0; ; n++) {
|
||||
union i40e_32byte_rx_desc *curr = &rxr->base[nic_i];
|
||||
uint64_t qword = le64toh(curr->wb.qword1.status_error_len);
|
||||
uint32_t staterr = (qword & I40E_RXD_QW1_STATUS_MASK)
|
||||
>> I40E_RXD_QW1_STATUS_SHIFT;
|
||||
|
||||
if ((staterr & (1<<I40E_RX_DESC_STATUS_DD_SHIFT)) == 0)
|
||||
break;
|
||||
ring->slot[nm_i].len = ((qword & I40E_RXD_QW1_LENGTH_PBUF_MASK)
|
||||
>> I40E_RXD_QW1_LENGTH_PBUF_SHIFT) - crclen;
|
||||
ring->slot[nm_i].flags = slot_flags;
|
||||
bus_dmamap_sync(rxr->ptag,
|
||||
rxr->buffers[nic_i].pmap, BUS_DMASYNC_POSTREAD);
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
if (n) { /* update the state variables */
|
||||
if (netmap_no_pendintr && !force_update) {
|
||||
/* diagnostics */
|
||||
ixl_rx_miss ++;
|
||||
ixl_rx_miss_bufs += n;
|
||||
}
|
||||
rxr->next_check = nic_i;
|
||||
kring->nr_hwtail = nm_i;
|
||||
}
|
||||
kring->nr_kflags &= ~NKR_PENDINTR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Second part: skip past packets that userspace has released.
|
||||
* (kring->nr_hwcur to head excluded),
|
||||
* and make the buffers available for reception.
|
||||
* As usual nm_i is the index in the netmap ring,
|
||||
* nic_i is the index in the NIC ring, and
|
||||
* nm_i == (nic_i + kring->nkr_hwofs) % ring_size
|
||||
*/
|
||||
nm_i = kring->nr_hwcur;
|
||||
if (nm_i != head) {
|
||||
nic_i = netmap_idx_k2n(kring, nm_i);
|
||||
for (n = 0; nm_i != head; n++) {
|
||||
struct netmap_slot *slot = &ring->slot[nm_i];
|
||||
uint64_t paddr;
|
||||
void *addr = PNMB(na, slot, &paddr);
|
||||
|
||||
union i40e_32byte_rx_desc *curr = &rxr->base[nic_i];
|
||||
struct ixl_rx_buf *rxbuf = &rxr->buffers[nic_i];
|
||||
|
||||
if (addr == NETMAP_BUF_BASE(na)) /* bad buf */
|
||||
goto ring_reset;
|
||||
|
||||
if (slot->flags & NS_BUF_CHANGED) {
|
||||
/* buffer has changed, reload map */
|
||||
netmap_reload_map(na, rxr->ptag, rxbuf->pmap, addr);
|
||||
slot->flags &= ~NS_BUF_CHANGED;
|
||||
}
|
||||
curr->read.pkt_addr = htole64(paddr);
|
||||
curr->read.hdr_addr = 0; // XXX needed
|
||||
bus_dmamap_sync(rxr->ptag, rxbuf->pmap,
|
||||
BUS_DMASYNC_PREREAD);
|
||||
nm_i = nm_next(nm_i, lim);
|
||||
nic_i = nm_next(nic_i, lim);
|
||||
}
|
||||
kring->nr_hwcur = head;
|
||||
|
||||
bus_dmamap_sync(rxr->dma.tag, rxr->dma.map,
|
||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
|
||||
/*
|
||||
* IMPORTANT: we must leave one free slot in the ring,
|
||||
* so move nic_i back by one unit
|
||||
*/
|
||||
nic_i = nm_prev(nic_i, lim);
|
||||
wr32(vsi->hw, rxr->tail, nic_i);
|
||||
}
|
||||
|
||||
/* tell userspace that there might be new packets */
|
||||
nm_rxsync_finalize(kring);
|
||||
|
||||
return 0;
|
||||
|
||||
ring_reset:
|
||||
return netmap_ring_reinit(kring);
|
||||
}
|
||||
|
||||
#endif /* !NETMAP_IXL_MAIN */
|
||||
|
||||
/* end of file */
|
@ -830,3 +830,4 @@ netmap_loader(__unused struct module *module, int event, __unused void *arg)
|
||||
|
||||
|
||||
DEV_MODULE(netmap, netmap_loader, NULL);
|
||||
MODULE_VERSION(netmap, 1);
|
||||
|
@ -94,6 +94,15 @@ extern "C" {
|
||||
#define ISP2(x) (((x) & ((x) - 1)) == 0)
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if !defined(bus_space_read_stream_8)
|
||||
#define bus_space_read_stream_8(t, h, o) \
|
||||
bus_space_read_8((t), (h), (o))
|
||||
#define bus_space_write_stream_8(t, h, o, v) \
|
||||
bus_space_write_8((t), (h), (o), (v))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define ENOTACTIVE EINVAL
|
||||
|
||||
/* Memory type to use on FreeBSD */
|
||||
@ -641,8 +650,9 @@ typedef struct efsys_bar_s {
|
||||
if (_lock) \
|
||||
SFXGE_BAR_LOCK(_esbp); \
|
||||
\
|
||||
(_edp)->ed_u32[0] = bus_space_read_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset)); \
|
||||
(_edp)->ed_u32[0] = bus_space_read_stream_4( \
|
||||
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
||||
(_offset)); \
|
||||
\
|
||||
EFSYS_PROBE2(bar_readd, unsigned int, (_offset), \
|
||||
uint32_t, (_edp)->ed_u32[0]); \
|
||||
@ -662,8 +672,9 @@ typedef struct efsys_bar_s {
|
||||
\
|
||||
SFXGE_BAR_LOCK(_esbp); \
|
||||
\
|
||||
(_eqp)->eq_u64[0] = bus_space_read_8((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset)); \
|
||||
(_eqp)->eq_u64[0] = bus_space_read_stream_8( \
|
||||
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
||||
(_offset)); \
|
||||
\
|
||||
EFSYS_PROBE3(bar_readq, unsigned int, (_offset), \
|
||||
uint32_t, (_eqp)->eq_u32[1], \
|
||||
@ -683,10 +694,12 @@ typedef struct efsys_bar_s {
|
||||
if (_lock) \
|
||||
SFXGE_BAR_LOCK(_esbp); \
|
||||
\
|
||||
(_eop)->eo_u64[0] = bus_space_read_8((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset)); \
|
||||
(_eop)->eo_u64[1] = bus_space_read_8((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset+8)); \
|
||||
(_eop)->eo_u64[0] = bus_space_read_stream_8( \
|
||||
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
||||
(_offset)); \
|
||||
(_eop)->eo_u64[1] = bus_space_read_stream_8( \
|
||||
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
||||
(_offset) + 8); \
|
||||
\
|
||||
EFSYS_PROBE5(bar_reado, unsigned int, (_offset), \
|
||||
uint32_t, (_eop)->eo_u32[3], \
|
||||
@ -709,10 +722,12 @@ typedef struct efsys_bar_s {
|
||||
\
|
||||
SFXGE_BAR_LOCK(_esbp); \
|
||||
\
|
||||
(_eqp)->eq_u32[0] = bus_space_read_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset)); \
|
||||
(_eqp)->eq_u32[1] = bus_space_read_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset+4)); \
|
||||
(_eqp)->eq_u32[0] = bus_space_read_stream_4( \
|
||||
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
||||
(_offset)); \
|
||||
(_eqp)->eq_u32[1] = bus_space_read_stream_4( \
|
||||
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
||||
(_offset) + 4); \
|
||||
\
|
||||
EFSYS_PROBE3(bar_readq, unsigned int, (_offset), \
|
||||
uint32_t, (_eqp)->eq_u32[1], \
|
||||
@ -732,14 +747,18 @@ typedef struct efsys_bar_s {
|
||||
if (_lock) \
|
||||
SFXGE_BAR_LOCK(_esbp); \
|
||||
\
|
||||
(_eop)->eo_u32[0] = bus_space_read_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset)); \
|
||||
(_eop)->eo_u32[1] = bus_space_read_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset+4)); \
|
||||
(_eop)->eo_u32[2] = bus_space_read_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset+8)); \
|
||||
(_eop)->eo_u32[3] = bus_space_read_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset+12)); \
|
||||
(_eop)->eo_u32[0] = bus_space_read_stream_4( \
|
||||
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
||||
(_offset)); \
|
||||
(_eop)->eo_u32[1] = bus_space_read_stream_4( \
|
||||
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
||||
(_offset) + 4); \
|
||||
(_eop)->eo_u32[2] = bus_space_read_stream_4( \
|
||||
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
||||
(_offset) + 8); \
|
||||
(_eop)->eo_u32[3] = bus_space_read_stream_4( \
|
||||
(_esbp)->esb_tag, (_esbp)->esb_handle, \
|
||||
(_offset) + 12); \
|
||||
\
|
||||
EFSYS_PROBE5(bar_reado, unsigned int, (_offset), \
|
||||
uint32_t, (_eop)->eo_u32[3], \
|
||||
@ -767,7 +786,8 @@ typedef struct efsys_bar_s {
|
||||
EFSYS_PROBE2(bar_writed, unsigned int, (_offset), \
|
||||
uint32_t, (_edp)->ed_u32[0]); \
|
||||
\
|
||||
bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
bus_space_write_stream_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, \
|
||||
(_offset), (_edp)->ed_u32[0]); \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
@ -789,7 +809,8 @@ typedef struct efsys_bar_s {
|
||||
uint32_t, (_eqp)->eq_u32[1], \
|
||||
uint32_t, (_eqp)->eq_u32[0]); \
|
||||
\
|
||||
bus_space_write_8((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
bus_space_write_stream_8((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, \
|
||||
(_offset), (_eqp)->eq_u64[0]); \
|
||||
\
|
||||
SFXGE_BAR_UNLOCK(_esbp); \
|
||||
@ -808,10 +829,12 @@ typedef struct efsys_bar_s {
|
||||
uint32_t, (_eqp)->eq_u32[1], \
|
||||
uint32_t, (_eqp)->eq_u32[0]); \
|
||||
\
|
||||
bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
bus_space_write_stream_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, \
|
||||
(_offset), (_eqp)->eq_u32[0]); \
|
||||
bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
(_offset+4), (_eqp)->eq_u32[1]); \
|
||||
bus_space_write_stream_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, \
|
||||
(_offset) + 4, (_eqp)->eq_u32[1]); \
|
||||
\
|
||||
SFXGE_BAR_UNLOCK(_esbp); \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
@ -835,10 +858,12 @@ typedef struct efsys_bar_s {
|
||||
uint32_t, (_eop)->eo_u32[1], \
|
||||
uint32_t, (_eop)->eo_u32[0]); \
|
||||
\
|
||||
bus_space_write_8((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
bus_space_write_stream_8((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, \
|
||||
(_offset), (_eop)->eo_u64[0]); \
|
||||
bus_space_write_8((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
(_offset+8), (_eop)->eo_u64[1]); \
|
||||
bus_space_write_stream_8((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, \
|
||||
(_offset) + 8, (_eop)->eo_u64[1]); \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
if (_lock) \
|
||||
@ -863,14 +888,18 @@ typedef struct efsys_bar_s {
|
||||
uint32_t, (_eop)->eo_u32[1], \
|
||||
uint32_t, (_eop)->eo_u32[0]); \
|
||||
\
|
||||
bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
bus_space_write_stream_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, \
|
||||
(_offset), (_eop)->eo_u32[0]); \
|
||||
bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
(_offset+4), (_eop)->eo_u32[1]); \
|
||||
bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
(_offset+8), (_eop)->eo_u32[2]); \
|
||||
bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
(_offset+12), (_eop)->eo_u32[3]); \
|
||||
bus_space_write_stream_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, \
|
||||
(_offset) + 4, (_eop)->eo_u32[1]); \
|
||||
bus_space_write_stream_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, \
|
||||
(_offset) + 8, (_eop)->eo_u32[2]); \
|
||||
bus_space_write_stream_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, \
|
||||
(_offset) + 12, (_eop)->eo_u32[3]); \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
if (_lock) \
|
||||
@ -912,7 +941,11 @@ typedef clock_t efsys_timestamp_t;
|
||||
#define EFSYS_KMEM_ALLOC(_esip, _size, _p) \
|
||||
do { \
|
||||
(_esip) = (_esip); \
|
||||
(_p) = malloc((_size), M_SFXGE, M_WAITOK|M_ZERO); \
|
||||
/* \
|
||||
* The macro is used in non-sleepable contexts, for \
|
||||
* example, holding a mutex. \
|
||||
*/ \
|
||||
(_p) = malloc((_size), M_SFXGE, M_NOWAIT|M_ZERO); \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
|
||||
|
@ -895,7 +895,8 @@ typedef struct efx_nic_cfg_s {
|
||||
uint32_t enc_txq_limit;
|
||||
uint32_t enc_rxq_limit;
|
||||
uint32_t enc_buftbl_limit;
|
||||
uint32_t enc_evq_moderation_max;
|
||||
uint32_t enc_evq_timer_quantum_ns;
|
||||
uint32_t enc_evq_timer_max_us;
|
||||
uint32_t enc_clk_mult;
|
||||
#if EFSYS_OPT_LOOPBACK
|
||||
uint32_t enc_loopback_types[EFX_LINK_NMODES];
|
||||
@ -1024,6 +1025,10 @@ typedef enum efx_nvram_type_e {
|
||||
EFX_NVRAM_MC_GOLDEN,
|
||||
EFX_NVRAM_PHY,
|
||||
EFX_NVRAM_NULLPHY,
|
||||
EFX_NVRAM_FPGA,
|
||||
EFX_NVRAM_FCFW,
|
||||
EFX_NVRAM_CPLD,
|
||||
EFX_NVRAM_FPGA_BACKUP,
|
||||
EFX_NVRAM_NTYPES,
|
||||
} efx_nvram_type_t;
|
||||
|
||||
@ -1731,6 +1736,11 @@ efx_tx_qpost(
|
||||
__in unsigned int completed,
|
||||
__inout unsigned int *addedp);
|
||||
|
||||
extern __checkReturn int
|
||||
efx_tx_qpace(
|
||||
__in efx_txq_t *etp,
|
||||
__in unsigned int ns);
|
||||
|
||||
extern void
|
||||
efx_tx_qpush(
|
||||
__in efx_txq_t *etp,
|
||||
|
@ -857,7 +857,7 @@ efx_ev_qmoderate(
|
||||
|
||||
EFSYS_ASSERT3U(eep->ee_magic, ==, EFX_EVQ_MAGIC);
|
||||
|
||||
if (us > encp->enc_evq_moderation_max) {
|
||||
if (us > encp->enc_evq_timer_max_us) {
|
||||
rc = EINVAL;
|
||||
goto fail1;
|
||||
}
|
||||
@ -876,7 +876,7 @@ efx_ev_qmoderate(
|
||||
uint32_t timer_val;
|
||||
|
||||
/* Calculate the timer value in quanta */
|
||||
timer_val = us * encp->enc_clk_mult / EFX_EV_TIMER_QUANTUM;
|
||||
timer_val = us * 1000 / encp->enc_evq_timer_quantum_ns;
|
||||
|
||||
/* Moderation value is base 0 so we need to deduct 1 */
|
||||
if (timer_val > 0)
|
||||
|
@ -204,7 +204,7 @@ typedef struct efx_nic_ops_s {
|
||||
# define EFX_TXQ_LIMIT_TARGET 259
|
||||
#endif
|
||||
#ifndef EFX_RXQ_LIMIT_TARGET
|
||||
# define EFX_RXQ_LIMIT_TARGET 768
|
||||
# define EFX_RXQ_LIMIT_TARGET 512
|
||||
#endif
|
||||
#ifndef EFX_TXQ_DC_SIZE
|
||||
#define EFX_TXQ_DC_SIZE 1 /* 16 descriptors */
|
||||
@ -408,7 +408,8 @@ struct efx_evq_s {
|
||||
|
||||
#define EFX_EVQ_MAGIC 0x08081997
|
||||
|
||||
#define EFX_EV_TIMER_QUANTUM 5
|
||||
#define EFX_EVQ_FALCON_TIMER_QUANTUM_NS 4968 /* 621 cycles */
|
||||
#define EFX_EVQ_SIENA_TIMER_QUANTUM_NS 6144 /* 768 cycles */
|
||||
|
||||
struct efx_rxq_s {
|
||||
uint32_t er_magic;
|
||||
|
@ -34,6 +34,13 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Falcon/Siena registers and descriptors
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* FR_AB_EE_VPD_CFG0_REG_SF(128bit):
|
||||
* SPI/VPD configuration register 0
|
||||
@ -3838,6 +3845,18 @@ extern "C" {
|
||||
#define FSF_AZ_DRIVER_EV_RX_DESCQ_ID_WIDTH 12
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Falcon non-volatile configuration
|
||||
*
|
||||
**************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#define FR_AZ_TX_PACE_TBL_OFST FR_BZ_TX_PACE_TBL_OFST
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -224,6 +224,53 @@ efx_tx_qpush(
|
||||
etp->et_index, &dword, B_FALSE);
|
||||
}
|
||||
|
||||
#define EFX_MAX_PACE_VALUE 20
|
||||
#define EFX_TX_PACE_CLOCK_BASE 104
|
||||
|
||||
__checkReturn int
|
||||
efx_tx_qpace(
|
||||
__in efx_txq_t *etp,
|
||||
__in unsigned int ns)
|
||||
{
|
||||
efx_nic_t *enp = etp->et_enp;
|
||||
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
|
||||
efx_oword_t oword;
|
||||
unsigned int pace_val;
|
||||
unsigned int timer_period;
|
||||
int rc;
|
||||
|
||||
EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
|
||||
|
||||
if (ns == 0) {
|
||||
pace_val = 0;
|
||||
} else {
|
||||
/*
|
||||
* The pace_val to write into the table is s.t
|
||||
* ns <= timer_period * (2 ^ pace_val)
|
||||
*/
|
||||
timer_period = EFX_TX_PACE_CLOCK_BASE / encp->enc_clk_mult;
|
||||
for (pace_val = 1; pace_val <= EFX_MAX_PACE_VALUE; pace_val++) {
|
||||
if ((timer_period << pace_val) >= ns)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pace_val > EFX_MAX_PACE_VALUE) {
|
||||
rc = EINVAL;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
/* Update the pacing table */
|
||||
EFX_POPULATE_OWORD_1(oword, FRF_AZ_TX_PACE, pace_val);
|
||||
EFX_BAR_TBL_WRITEO(enp, FR_AZ_TX_PACE_TBL, etp->et_index, &oword);
|
||||
|
||||
return (0);
|
||||
|
||||
fail1:
|
||||
EFSYS_PROBE1(fail1, int, rc);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
void
|
||||
efx_tx_qflush(
|
||||
__in efx_txq_t *etp)
|
||||
@ -234,6 +281,8 @@ efx_tx_qflush(
|
||||
|
||||
EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
|
||||
|
||||
efx_tx_qpace(etp, 0);
|
||||
|
||||
label = etp->et_index;
|
||||
|
||||
/* Flush the queue */
|
||||
|
@ -81,7 +81,9 @@ typedef struct siena_mc_static_config_hdr_s { /* GENERATED BY scripts/genfwdef *
|
||||
efx_byte_t green_mode_valid; /* Whether cal holds a valid value */
|
||||
efx_word_t mac_addr_count;
|
||||
efx_word_t mac_addr_stride;
|
||||
efx_dword_t reserved2[2]; /* (write as zero) */
|
||||
efx_word_t calibrated_vref;
|
||||
efx_word_t adc_vref;
|
||||
efx_dword_t reserved2[1]; /* (write as zero) */
|
||||
efx_dword_t num_dbi_items;
|
||||
struct {
|
||||
efx_word_t addr;
|
||||
|
@ -70,6 +70,21 @@ static __cs uint16_t __siena_mon_port0_map[] = {
|
||||
EFX_MON_STAT_2_5V, /* MC_CMD_SENSOR_IN_2V5 */
|
||||
EFX_MON_STAT_3_3V, /* MC_CMD_SENSOR_IN_3V3 */
|
||||
EFX_MON_STAT_12V, /* MC_CMD_SENSOR_IN_12V0 */
|
||||
EFX_MON_STAT_1_2VA, /* MC_CMD_SENSOR_IN_1V2A */
|
||||
EFX_MON_STAT_VREF, /* MC_CMD_SENSOR_IN_VREF */
|
||||
EFX_MON_STAT_VAOE, /* MC_CMD_SENSOR_OUT_VAOE */
|
||||
EFX_MON_STAT_AOE_TEMP, /* MC_CMD_SENSOR_AOE_TEMP */
|
||||
EFX_MON_STAT_PSU_AOE_TEMP, /* MC_CMD_SENSOR_PSU_AOE_TEMP */
|
||||
EFX_MON_STAT_PSU_TEMP, /* MC_CMD_SENSOR_PSE_TEMP */
|
||||
EFX_MON_STAT_FAN0, /* MC_CMD_SENSOR_FAN_0 */
|
||||
EFX_MON_STAT_FAN1, /* MC_CMD_SENSOR_FAN_1 */
|
||||
EFX_MON_STAT_FAN2, /* MC_CMD_SENSOR_FAN_2 */
|
||||
EFX_MON_STAT_FAN3, /* MC_CMD_SENSOR_FAN_3 */
|
||||
EFX_MON_STAT_FAN4, /* MC_CMD_SENSOR_FAN_4 */
|
||||
EFX_MON_STAT_VAOE_IN, /* MC_CMD_SENSOR_IN_VAOE */
|
||||
EFX_MON_STAT_IAOE, /* MC_CMD_SENSOR_OUT_IAOE */
|
||||
EFX_MON_STAT_IAOE_IN, /* MC_CMD_SENSOR_IN_IAOE */
|
||||
|
||||
};
|
||||
|
||||
static __cs uint16_t __siena_mon_port1_map[] = {
|
||||
@ -86,6 +101,21 @@ static __cs uint16_t __siena_mon_port1_map[] = {
|
||||
EFX_MON_STAT_2_5V, /* MC_CMD_SENSOR_IN_2V5 */
|
||||
EFX_MON_STAT_3_3V, /* MC_CMD_SENSOR_IN_3V3 */
|
||||
EFX_MON_STAT_12V, /* MC_CMD_SENSOR_IN_12V0 */
|
||||
EFX_MON_STAT_1_2VA, /* MC_CMD_SENSOR_IN_1V2A */
|
||||
EFX_MON_STAT_VREF, /* MC_CMD_SENSOR_IN_VREF */
|
||||
EFX_MON_STAT_VAOE, /* MC_CMD_SENSOR_OUT_VAOE */
|
||||
EFX_MON_STAT_AOE_TEMP, /* MC_CMD_SENSOR_AOE_TEMP */
|
||||
EFX_MON_STAT_PSU_AOE_TEMP, /* MC_CMD_SENSOR_PSU_AOE_TEMP */
|
||||
EFX_MON_STAT_PSU_TEMP, /* MC_CMD_SENSOR_PSE_TEMP */
|
||||
EFX_MON_STAT_FAN0, /* MC_CMD_SENSOR_FAN_0 */
|
||||
EFX_MON_STAT_FAN1, /* MC_CMD_SENSOR_FAN_1 */
|
||||
EFX_MON_STAT_FAN2, /* MC_CMD_SENSOR_FAN_2 */
|
||||
EFX_MON_STAT_FAN3, /* MC_CMD_SENSOR_FAN_3 */
|
||||
EFX_MON_STAT_FAN4, /* MC_CMD_SENSOR_FAN_4 */
|
||||
EFX_MON_STAT_VAOE_IN, /* MC_CMD_SENSOR_IN_VAOE */
|
||||
EFX_MON_STAT_IAOE, /* MC_CMD_SENSOR_OUT_IAOE */
|
||||
EFX_MON_STAT_IAOE_IN, /* MC_CMD_SENSOR_IN_IAOE */
|
||||
|
||||
};
|
||||
|
||||
#define SIENA_STATIC_SENSOR_ASSERT(_field) \
|
||||
|
@ -329,8 +329,10 @@ siena_board_cfg(
|
||||
encp->enc_clk_mult = 2;
|
||||
}
|
||||
|
||||
encp->enc_evq_moderation_max = EFX_EV_TIMER_QUANTUM <<
|
||||
FRF_AB_TIMER_VAL_WIDTH / encp->enc_clk_mult;
|
||||
encp->enc_evq_timer_quantum_ns =
|
||||
EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
|
||||
encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
|
||||
FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
|
||||
|
||||
/* Resource limits */
|
||||
req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS;
|
||||
|
@ -330,6 +330,14 @@ static siena_parttbl_entry_t siena_parttbl[] = {
|
||||
{MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1, 2, EFX_NVRAM_BOOTROM_CFG},
|
||||
{MC_CMD_NVRAM_TYPE_PHY_PORT0, 1, EFX_NVRAM_PHY},
|
||||
{MC_CMD_NVRAM_TYPE_PHY_PORT1, 2, EFX_NVRAM_PHY},
|
||||
{MC_CMD_NVRAM_TYPE_FPGA, 1, EFX_NVRAM_FPGA},
|
||||
{MC_CMD_NVRAM_TYPE_FPGA, 2, EFX_NVRAM_FPGA},
|
||||
{MC_CMD_NVRAM_TYPE_FPGA_BACKUP, 1, EFX_NVRAM_FPGA_BACKUP},
|
||||
{MC_CMD_NVRAM_TYPE_FPGA_BACKUP, 2, EFX_NVRAM_FPGA_BACKUP},
|
||||
{MC_CMD_NVRAM_TYPE_FC_FW, 1, EFX_NVRAM_FCFW},
|
||||
{MC_CMD_NVRAM_TYPE_FC_FW, 2, EFX_NVRAM_FCFW},
|
||||
{MC_CMD_NVRAM_TYPE_CPLD, 1, EFX_NVRAM_CPLD},
|
||||
{MC_CMD_NVRAM_TYPE_CPLD, 2, EFX_NVRAM_CPLD},
|
||||
{0, 0, 0},
|
||||
};
|
||||
|
||||
|
@ -61,10 +61,10 @@ __FBSDID("$FreeBSD$");
|
||||
#define SFXGE_CAP (IFCAP_VLAN_MTU | \
|
||||
IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM | IFCAP_TSO | \
|
||||
IFCAP_JUMBO_MTU | IFCAP_LRO | \
|
||||
IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE)
|
||||
IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE | IFCAP_HWSTATS)
|
||||
#define SFXGE_CAP_ENABLE SFXGE_CAP
|
||||
#define SFXGE_CAP_FIXED (IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM | \
|
||||
IFCAP_JUMBO_MTU | IFCAP_LINKSTATE)
|
||||
IFCAP_JUMBO_MTU | IFCAP_LINKSTATE | IFCAP_HWSTATS)
|
||||
|
||||
MALLOC_DEFINE(M_SFXGE, "sfxge", "Solarflare 10GigE driver");
|
||||
|
||||
@ -343,6 +343,8 @@ sfxge_ifnet_init(struct ifnet *ifp, struct sfxge_softc *sc)
|
||||
mtx_init(&sc->tx_lock, sc->tx_lock_name, NULL, MTX_DEF);
|
||||
#endif
|
||||
|
||||
ifp->if_get_counter = sfxge_get_counter;
|
||||
|
||||
if ((rc = sfxge_port_ifmedia_init(sc)) != 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -324,6 +324,7 @@ extern void sfxge_mac_link_update(struct sfxge_softc *sc,
|
||||
efx_link_mode_t mode);
|
||||
extern int sfxge_mac_filter_set(struct sfxge_softc *sc);
|
||||
extern int sfxge_port_ifmedia_init(struct sfxge_softc *sc);
|
||||
extern uint64_t sfxge_get_counter(struct ifnet *ifp, ift_counter c);
|
||||
|
||||
#define SFXGE_MAX_MTU (9 * 1024)
|
||||
|
||||
|
@ -141,7 +141,7 @@ sfxge_dma_alloc(struct sfxge_softc *sc, bus_size_t len, efsys_mem_t *esmp)
|
||||
MIN(0x3FFFFFFFFFFFUL, BUS_SPACE_MAXADDR), BUS_SPACE_MAXADDR, NULL,
|
||||
NULL, len, 1, len, 0, NULL, NULL, &esmp->esm_tag) != 0) {
|
||||
device_printf(sc->dev, "Couldn't allocate txq DMA tag\n");
|
||||
return (ENOMEM);
|
||||
goto fail_tag_create;
|
||||
}
|
||||
|
||||
/* Allocate kernel memory. */
|
||||
@ -149,17 +149,14 @@ sfxge_dma_alloc(struct sfxge_softc *sc, bus_size_t len, efsys_mem_t *esmp)
|
||||
BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO,
|
||||
&esmp->esm_map) != 0) {
|
||||
device_printf(sc->dev, "Couldn't allocate DMA memory\n");
|
||||
bus_dma_tag_destroy(esmp->esm_tag);
|
||||
return (ENOMEM);
|
||||
goto fail_alloc;
|
||||
}
|
||||
|
||||
/* Load map into device memory. */
|
||||
if (bus_dmamap_load(esmp->esm_tag, esmp->esm_map, vaddr, len,
|
||||
sfxge_dma_cb, &esmp->esm_addr, 0) != 0) {
|
||||
device_printf(sc->dev, "Couldn't load DMA mapping\n");
|
||||
bus_dmamem_free(esmp->esm_tag, vaddr, esmp->esm_map);
|
||||
bus_dma_tag_destroy(esmp->esm_tag);
|
||||
return (ENOMEM);
|
||||
goto fail_load;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -167,15 +164,20 @@ sfxge_dma_alloc(struct sfxge_softc *sc, bus_size_t len, efsys_mem_t *esmp)
|
||||
* and will have set esm_addr to 0 if something went
|
||||
* wrong.
|
||||
*/
|
||||
if (esmp->esm_addr == 0) {
|
||||
bus_dmamem_free(esmp->esm_tag, esmp->esm_base, esmp->esm_map);
|
||||
bus_dma_tag_destroy(esmp->esm_tag);
|
||||
return (ENOMEM);
|
||||
}
|
||||
if (esmp->esm_addr == 0)
|
||||
goto fail_load_check;
|
||||
|
||||
esmp->esm_base = vaddr;
|
||||
|
||||
return (0);
|
||||
|
||||
fail_load_check:
|
||||
fail_load:
|
||||
bus_dmamem_free(esmp->esm_tag, vaddr, esmp->esm_map);
|
||||
fail_alloc:
|
||||
bus_dma_tag_destroy(esmp->esm_tag);
|
||||
fail_tag_create:
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -50,6 +50,8 @@ sfxge_ev_qcomplete(struct sfxge_evq *evq, boolean_t eop)
|
||||
struct sfxge_rxq *rxq;
|
||||
struct sfxge_txq *txq;
|
||||
|
||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
|
||||
|
||||
sc = evq->sc;
|
||||
index = evq->index;
|
||||
rxq = sc->rxq[index];
|
||||
@ -89,6 +91,8 @@ sfxge_ev_rx(void *arg, uint32_t label, uint32_t id, uint32_t size,
|
||||
struct sfxge_rx_sw_desc *rx_desc;
|
||||
|
||||
evq = arg;
|
||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
|
||||
|
||||
sc = evq->sc;
|
||||
|
||||
if (evq->exception)
|
||||
@ -140,6 +144,8 @@ sfxge_ev_exception(void *arg, uint32_t code, uint32_t data)
|
||||
struct sfxge_softc *sc;
|
||||
|
||||
evq = (struct sfxge_evq *)arg;
|
||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
|
||||
|
||||
sc = evq->sc;
|
||||
|
||||
evq->exception = B_TRUE;
|
||||
@ -165,6 +171,8 @@ sfxge_ev_rxq_flush_done(void *arg, uint32_t rxq_index)
|
||||
uint16_t magic;
|
||||
|
||||
evq = (struct sfxge_evq *)arg;
|
||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
|
||||
|
||||
sc = evq->sc;
|
||||
rxq = sc->rxq[rxq_index];
|
||||
|
||||
@ -197,6 +205,8 @@ sfxge_ev_rxq_flush_failed(void *arg, uint32_t rxq_index)
|
||||
uint16_t magic;
|
||||
|
||||
evq = (struct sfxge_evq *)arg;
|
||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
|
||||
|
||||
sc = evq->sc;
|
||||
rxq = sc->rxq[rxq_index];
|
||||
|
||||
@ -238,6 +248,8 @@ sfxge_ev_tx(void *arg, uint32_t label, uint32_t id)
|
||||
unsigned int delta;
|
||||
|
||||
evq = (struct sfxge_evq *)arg;
|
||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
|
||||
|
||||
txq = sfxge_get_txq_by_label(evq, label);
|
||||
|
||||
KASSERT(txq != NULL, ("txq == NULL"));
|
||||
@ -278,6 +290,8 @@ sfxge_ev_txq_flush_done(void *arg, uint32_t txq_index)
|
||||
uint16_t magic;
|
||||
|
||||
evq = (struct sfxge_evq *)arg;
|
||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
|
||||
|
||||
sc = evq->sc;
|
||||
txq = sc->txq[txq_index];
|
||||
|
||||
@ -308,6 +322,8 @@ sfxge_ev_software(void *arg, uint16_t magic)
|
||||
unsigned int label;
|
||||
|
||||
evq = (struct sfxge_evq *)arg;
|
||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
|
||||
|
||||
sc = evq->sc;
|
||||
|
||||
label = magic & SFXGE_MAGIC_DMAQ_LABEL_MASK;
|
||||
@ -506,7 +522,7 @@ sfxge_int_mod_handler(SYSCTL_HANDLER_ARGS)
|
||||
* so we have to range-check the value ourselves.
|
||||
*/
|
||||
if (moderation >
|
||||
efx_nic_cfg_get(sc->enp)->enc_evq_moderation_max) {
|
||||
efx_nic_cfg_get(sc->enp)->enc_evq_timer_max_us) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -533,6 +549,7 @@ sfxge_ev_initialized(void *arg)
|
||||
struct sfxge_evq *evq;
|
||||
|
||||
evq = (struct sfxge_evq *)arg;
|
||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
|
||||
|
||||
KASSERT(evq->init_state == SFXGE_EVQ_STARTING,
|
||||
("evq not starting"));
|
||||
@ -549,6 +566,8 @@ sfxge_ev_link_change(void *arg, efx_link_mode_t link_mode)
|
||||
struct sfxge_softc *sc;
|
||||
|
||||
evq = (struct sfxge_evq *)arg;
|
||||
SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
|
||||
|
||||
sc = evq->sc;
|
||||
|
||||
sfxge_mac_link_update(sc, link_mode);
|
||||
|
@ -85,6 +85,68 @@ sfxge_mac_stat_update(struct sfxge_softc *sc)
|
||||
return (rc);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
sfxge_get_counter(struct ifnet *ifp, ift_counter c)
|
||||
{
|
||||
struct sfxge_softc *sc = ifp->if_softc;
|
||||
uint64_t *mac_stats;
|
||||
uint64_t val;
|
||||
|
||||
SFXGE_PORT_LOCK(&sc->port);
|
||||
|
||||
/* Ignore error and use old values */
|
||||
(void)sfxge_mac_stat_update(sc);
|
||||
|
||||
mac_stats = (uint64_t *)sc->port.mac_stats.decode_buf;
|
||||
|
||||
switch (c) {
|
||||
case IFCOUNTER_IPACKETS:
|
||||
val = mac_stats[EFX_MAC_RX_PKTS];
|
||||
break;
|
||||
case IFCOUNTER_IERRORS:
|
||||
val = mac_stats[EFX_MAC_RX_ERRORS];
|
||||
break;
|
||||
case IFCOUNTER_OPACKETS:
|
||||
val = mac_stats[EFX_MAC_TX_PKTS];
|
||||
break;
|
||||
case IFCOUNTER_OERRORS:
|
||||
val = mac_stats[EFX_MAC_TX_ERRORS];
|
||||
break;
|
||||
case IFCOUNTER_COLLISIONS:
|
||||
val = mac_stats[EFX_MAC_TX_SGL_COL_PKTS] +
|
||||
mac_stats[EFX_MAC_TX_MULT_COL_PKTS] +
|
||||
mac_stats[EFX_MAC_TX_EX_COL_PKTS] +
|
||||
mac_stats[EFX_MAC_TX_LATE_COL_PKTS];
|
||||
break;
|
||||
case IFCOUNTER_IBYTES:
|
||||
val = mac_stats[EFX_MAC_RX_OCTETS];
|
||||
break;
|
||||
case IFCOUNTER_OBYTES:
|
||||
val = mac_stats[EFX_MAC_TX_OCTETS];
|
||||
break;
|
||||
case IFCOUNTER_OMCASTS:
|
||||
val = mac_stats[EFX_MAC_TX_MULTICST_PKTS] +
|
||||
mac_stats[EFX_MAC_TX_BRDCST_PKTS];
|
||||
break;
|
||||
case IFCOUNTER_OQDROPS:
|
||||
SFXGE_PORT_UNLOCK(&sc->port);
|
||||
return (sfxge_tx_get_drops(sc));
|
||||
case IFCOUNTER_IMCASTS:
|
||||
/* if_imcasts is maintained in net/if_ethersubr.c */
|
||||
case IFCOUNTER_IQDROPS:
|
||||
/* if_iqdrops is maintained in net/if_ethersubr.c */
|
||||
case IFCOUNTER_NOPROTO:
|
||||
/* if_noproto is maintained in net/if_ethersubr.c */
|
||||
default:
|
||||
SFXGE_PORT_UNLOCK(&sc->port);
|
||||
return (if_get_counter_default(ifp, c));
|
||||
}
|
||||
|
||||
SFXGE_PORT_UNLOCK(&sc->port);
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
static int
|
||||
sfxge_mac_stat_handler(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
@ -228,7 +290,7 @@ static const uint64_t sfxge_link_baudrate[EFX_LINK_NMODES] = {
|
||||
[EFX_LINK_100FDX] = IF_Mbps(100),
|
||||
[EFX_LINK_1000HDX] = IF_Gbps(1),
|
||||
[EFX_LINK_1000FDX] = IF_Gbps(1),
|
||||
[EFX_LINK_10000FDX] = IF_Gbps(10),
|
||||
[EFX_LINK_10000FDX] = IF_Gbps(10),
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -1113,7 +1113,6 @@ sfxge_rx_qinit(struct sfxge_softc *sc, unsigned int index)
|
||||
/* Allocate and zero DMA space. */
|
||||
if ((rc = sfxge_dma_alloc(sc, EFX_RXQ_SIZE(sc->rxq_entries), esmp)) != 0)
|
||||
return (rc);
|
||||
(void)memset(esmp->esm_base, 0, EFX_RXQ_SIZE(sc->rxq_entries));
|
||||
|
||||
/* Allocate buffer table entries. */
|
||||
sfxge_sram_buf_tbl_alloc(sc, EFX_RXQ_NBUFS(sc->rxq_entries),
|
||||
|
@ -214,6 +214,9 @@ sfxge_tx_qdpl_swizzle(struct sfxge_txq *txq)
|
||||
count++;
|
||||
} while (mbuf != NULL);
|
||||
|
||||
if (count > stdp->std_put_hiwat)
|
||||
stdp->std_put_hiwat = count;
|
||||
|
||||
/* Append the reversed put list to the get list. */
|
||||
KASSERT(*get_tailp == NULL, ("*get_tailp != NULL"));
|
||||
*stdp->std_getp = get_next;
|
||||
@ -1400,7 +1403,6 @@ sfxge_tx_qinit(struct sfxge_softc *sc, unsigned int txq_index,
|
||||
/* Allocate and zero DMA space for the descriptor ring. */
|
||||
if ((rc = sfxge_dma_alloc(sc, EFX_TXQ_SIZE(sc->txq_entries), esmp)) != 0)
|
||||
return (rc);
|
||||
(void)memset(esmp->esm_base, 0, EFX_TXQ_SIZE(sc->txq_entries));
|
||||
|
||||
/* Allocate buffer table entries. */
|
||||
sfxge_sram_buf_tbl_alloc(sc, EFX_TXQ_NBUFS(sc->txq_entries),
|
||||
@ -1486,6 +1488,10 @@ sfxge_tx_qinit(struct sfxge_softc *sc, unsigned int txq_index,
|
||||
SYSCTL_CHILDREN(txq_node), OID_AUTO,
|
||||
"dpl_get_hiwat", CTLFLAG_RD | CTLFLAG_STATS,
|
||||
&stdp->std_get_hiwat, 0, "");
|
||||
SYSCTL_ADD_UINT(device_get_sysctl_ctx(sc->dev),
|
||||
SYSCTL_CHILDREN(txq_node), OID_AUTO,
|
||||
"dpl_put_hiwat", CTLFLAG_RD | CTLFLAG_STATS,
|
||||
&stdp->std_put_hiwat, 0, "");
|
||||
#endif
|
||||
|
||||
txq->type = type;
|
||||
@ -1567,6 +1573,29 @@ sfxge_tx_stat_init(struct sfxge_softc *sc)
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
sfxge_tx_get_drops(struct sfxge_softc *sc)
|
||||
{
|
||||
unsigned int index;
|
||||
uint64_t drops = 0;
|
||||
struct sfxge_txq *txq;
|
||||
|
||||
/* Sum across all TX queues */
|
||||
for (index = 0; index < sc->txq_count; index++) {
|
||||
txq = sc->txq[index];
|
||||
/*
|
||||
* In theory, txq->put_overflow and txq->netdown_drops
|
||||
* should use atomic operation and other should be
|
||||
* obtained under txq lock, but it is just statistics.
|
||||
*/
|
||||
drops += txq->drops + txq->get_overflow +
|
||||
txq->get_non_tcp_overflow +
|
||||
txq->put_overflow + txq->netdown_drops +
|
||||
txq->tso_pdrop_too_many + txq->tso_pdrop_no_rsrc;
|
||||
}
|
||||
return (drops);
|
||||
}
|
||||
|
||||
void
|
||||
sfxge_tx_fini(struct sfxge_softc *sc)
|
||||
{
|
||||
|
@ -102,6 +102,8 @@ struct sfxge_tx_dpl {
|
||||
* in get list */
|
||||
unsigned int std_get_hiwat; /* Packets in get list
|
||||
* high watermark */
|
||||
unsigned int std_put_hiwat; /* Packets in put list
|
||||
* high watermark */
|
||||
};
|
||||
|
||||
|
||||
@ -217,6 +219,7 @@ struct sfxge_txq {
|
||||
struct sfxge_evq;
|
||||
|
||||
extern int sfxge_tx_packet_add(struct sfxge_txq *, struct mbuf *);
|
||||
extern uint64_t sfxge_tx_get_drops(struct sfxge_softc *sc);
|
||||
|
||||
extern int sfxge_tx_init(struct sfxge_softc *sc);
|
||||
extern void sfxge_tx_fini(struct sfxge_softc *sc);
|
||||
|
@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
|
||||
#define UART_RIS 0x0f /* Raw interrupt status register */
|
||||
#define UART_RXREADY (1 << 4) /* RX buffer full */
|
||||
#define UART_TXEMPTY (1 << 5) /* TX buffer empty */
|
||||
#define RIS_RTIM (1 << 6) /* Receive timeout */
|
||||
#define RIS_FE (1 << 7) /* Framing error interrupt status */
|
||||
#define RIS_PE (1 << 8) /* Parity error interrupt status */
|
||||
#define RIS_BE (1 << 9) /* Break error interrupt status */
|
||||
@ -278,11 +279,15 @@ static int
|
||||
uart_pl011_bus_attach(struct uart_softc *sc)
|
||||
{
|
||||
struct uart_bas *bas;
|
||||
int reg;
|
||||
|
||||
bas = &sc->sc_bas;
|
||||
/* Enable RX & TX interrupts */
|
||||
__uart_setreg(bas, UART_IMSC, (UART_RXREADY | UART_TXEMPTY));
|
||||
/* Clear RX & TX interrupts */
|
||||
|
||||
/* Enable interrupts */
|
||||
reg = (UART_RXREADY | RIS_RTIM | UART_TXEMPTY);
|
||||
__uart_setreg(bas, UART_IMSC, reg);
|
||||
|
||||
/* Clear interrupts */
|
||||
__uart_setreg(bas, UART_ICR, IMSC_MASK_ALL);
|
||||
|
||||
return (0);
|
||||
@ -337,15 +342,16 @@ static int
|
||||
uart_pl011_bus_ipend(struct uart_softc *sc)
|
||||
{
|
||||
struct uart_bas *bas;
|
||||
int ipend;
|
||||
uint32_t ints;
|
||||
int ipend;
|
||||
int reg;
|
||||
|
||||
bas = &sc->sc_bas;
|
||||
uart_lock(sc->sc_hwmtx);
|
||||
ints = __uart_getreg(bas, UART_MIS);
|
||||
ipend = 0;
|
||||
|
||||
if (ints & UART_RXREADY)
|
||||
if (ints & (UART_RXREADY | RIS_RTIM))
|
||||
ipend |= SER_INT_RXREADY;
|
||||
if (ints & RIS_BE)
|
||||
ipend |= SER_INT_BREAK;
|
||||
@ -355,7 +361,10 @@ uart_pl011_bus_ipend(struct uart_softc *sc)
|
||||
if (sc->sc_txbusy)
|
||||
ipend |= SER_INT_TXIDLE;
|
||||
|
||||
__uart_setreg(bas, UART_IMSC, UART_RXREADY);
|
||||
/* Disable TX interrupt */
|
||||
reg = __uart_getreg(bas, UART_IMSC);
|
||||
reg &= ~(UART_TXEMPTY);
|
||||
__uart_setreg(bas, UART_IMSC, reg);
|
||||
}
|
||||
|
||||
uart_unlock(sc->sc_hwmtx);
|
||||
@ -391,14 +400,14 @@ static int
|
||||
uart_pl011_bus_receive(struct uart_softc *sc)
|
||||
{
|
||||
struct uart_bas *bas;
|
||||
int rx;
|
||||
uint32_t ints, xc;
|
||||
int rx;
|
||||
|
||||
bas = &sc->sc_bas;
|
||||
uart_lock(sc->sc_hwmtx);
|
||||
|
||||
ints = __uart_getreg(bas, UART_MIS);
|
||||
while (ints & UART_RXREADY) {
|
||||
while (ints & (UART_RXREADY | RIS_RTIM)) {
|
||||
if (uart_rx_full(sc)) {
|
||||
sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
|
||||
break;
|
||||
@ -411,7 +420,7 @@ uart_pl011_bus_receive(struct uart_softc *sc)
|
||||
if (xc & DR_PE)
|
||||
rx |= UART_STAT_PARERR;
|
||||
|
||||
__uart_setreg(bas, UART_ICR, UART_RXREADY);
|
||||
__uart_setreg(bas, UART_ICR, (UART_RXREADY | RIS_RTIM));
|
||||
|
||||
uart_rx_put(sc, rx);
|
||||
ints = __uart_getreg(bas, UART_MIS);
|
||||
@ -433,6 +442,7 @@ static int
|
||||
uart_pl011_bus_transmit(struct uart_softc *sc)
|
||||
{
|
||||
struct uart_bas *bas;
|
||||
int reg;
|
||||
int i;
|
||||
|
||||
bas = &sc->sc_bas;
|
||||
@ -443,7 +453,12 @@ uart_pl011_bus_transmit(struct uart_softc *sc)
|
||||
uart_barrier(bas);
|
||||
}
|
||||
sc->sc_txbusy = 1;
|
||||
__uart_setreg(bas, UART_IMSC, (UART_RXREADY | UART_TXEMPTY));
|
||||
|
||||
/* Enable TX interrupt */
|
||||
reg = __uart_getreg(bas, UART_IMSC);
|
||||
reg |= (UART_TXEMPTY);
|
||||
__uart_setreg(bas, UART_IMSC, reg);
|
||||
|
||||
uart_unlock(sc->sc_hwmtx);
|
||||
|
||||
return (0);
|
||||
|
@ -108,12 +108,19 @@
|
||||
GINTSTS_WKUPINT | GINTSTS_USBSUSP | GINTMSK_OTGINTMSK | \
|
||||
GINTSTS_SESSREQINT)
|
||||
|
||||
static int dwc_otg_use_hsic;
|
||||
#define DWC_OTG_PHY_ULPI 0
|
||||
#define DWC_OTG_PHY_HSIC 1
|
||||
#define DWC_OTG_PHY_INTERNAL 2
|
||||
|
||||
#ifndef DWC_OTG_PHY_DEFAULT
|
||||
#define DWC_OTG_PHY_DEFAULT DWC_OTG_PHY_ULPI
|
||||
#endif
|
||||
|
||||
static int dwc_otg_phy_type = DWC_OTG_PHY_DEFAULT;
|
||||
|
||||
static SYSCTL_NODE(_hw_usb, OID_AUTO, dwc_otg, CTLFLAG_RW, 0, "USB DWC OTG");
|
||||
|
||||
SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, use_hsic, CTLFLAG_RDTUN,
|
||||
&dwc_otg_use_hsic, 0, "DWC OTG uses HSIC interface");
|
||||
SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, phy_type, CTLFLAG_RDTUN,
|
||||
&dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2 - ULPI/HSIC/INTERNAL");
|
||||
|
||||
#ifdef USB_DEBUG
|
||||
static int dwc_otg_debug;
|
||||
@ -3766,8 +3773,9 @@ dwc_otg_init(struct dwc_otg_softc *sc)
|
||||
break;
|
||||
}
|
||||
|
||||
/* select HSIC or non-HSIC mode */
|
||||
if (dwc_otg_use_hsic) {
|
||||
/* select HSIC, ULPI or internal PHY mode */
|
||||
switch (dwc_otg_phy_type) {
|
||||
case DWC_OTG_PHY_HSIC:
|
||||
DWC_OTG_WRITE_4(sc, DOTG_GUSBCFG,
|
||||
GUSBCFG_PHYIF |
|
||||
GUSBCFG_TRD_TIM_SET(5) | temp);
|
||||
@ -3779,7 +3787,8 @@ dwc_otg_init(struct dwc_otg_softc *sc)
|
||||
temp & ~GLPMCFG_HSIC_CONN);
|
||||
DWC_OTG_WRITE_4(sc, DOTG_GLPMCFG,
|
||||
temp | GLPMCFG_HSIC_CONN);
|
||||
} else {
|
||||
break;
|
||||
case DWC_OTG_PHY_ULPI:
|
||||
DWC_OTG_WRITE_4(sc, DOTG_GUSBCFG,
|
||||
GUSBCFG_ULPI_UTMI_SEL |
|
||||
GUSBCFG_TRD_TIM_SET(5) | temp);
|
||||
@ -3788,6 +3797,25 @@ dwc_otg_init(struct dwc_otg_softc *sc)
|
||||
temp = DWC_OTG_READ_4(sc, DOTG_GLPMCFG);
|
||||
DWC_OTG_WRITE_4(sc, DOTG_GLPMCFG,
|
||||
temp & ~GLPMCFG_HSIC_CONN);
|
||||
break;
|
||||
case DWC_OTG_PHY_INTERNAL:
|
||||
DWC_OTG_WRITE_4(sc, DOTG_GUSBCFG,
|
||||
GUSBCFG_PHYSEL |
|
||||
GUSBCFG_TRD_TIM_SET(5) | temp);
|
||||
DWC_OTG_WRITE_4(sc, DOTG_GOTGCTL, 0);
|
||||
|
||||
temp = DWC_OTG_READ_4(sc, DOTG_GLPMCFG);
|
||||
DWC_OTG_WRITE_4(sc, DOTG_GLPMCFG,
|
||||
temp & ~GLPMCFG_HSIC_CONN);
|
||||
|
||||
temp = DWC_OTG_READ_4(sc, DOTG_GGPIO);
|
||||
temp &= ~(DOTG_GGPIO_NOVBUSSENS | DOTG_GGPIO_I2CPADEN);
|
||||
temp |= (DOTG_GGPIO_VBUSASEN | DOTG_GGPIO_VBUSBSEN |
|
||||
DOTG_GGPIO_PWRDWN);
|
||||
DWC_OTG_WRITE_4(sc, DOTG_GGPIO, temp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* clear global nak */
|
||||
@ -3807,9 +3835,6 @@ dwc_otg_init(struct dwc_otg_softc *sc)
|
||||
/* wait 10ms */
|
||||
usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100);
|
||||
|
||||
/* pull up D+ */
|
||||
dwc_otg_pull_up(sc);
|
||||
|
||||
temp = DWC_OTG_READ_4(sc, DOTG_GHWCFG3);
|
||||
|
||||
sc->sc_fifo_size = 4 * GHWCFG3_DFIFODEPTH_GET(temp);
|
||||
@ -4548,11 +4573,15 @@ dwc_otg_roothub_exec(struct usb_device *udev,
|
||||
/* nops */
|
||||
break;
|
||||
case UHF_PORT_POWER:
|
||||
sc->sc_flags.port_powered = 1;
|
||||
if (sc->sc_mode == DWC_MODE_HOST || sc->sc_mode == DWC_MODE_OTG) {
|
||||
sc->sc_hprt_val |= HPRT_PRTPWR;
|
||||
DWC_OTG_WRITE_4(sc, DOTG_HPRT, sc->sc_hprt_val);
|
||||
}
|
||||
sc->sc_flags.port_powered = 1;
|
||||
if (sc->sc_mode == DWC_MODE_DEVICE || sc->sc_mode == DWC_MODE_OTG) {
|
||||
/* pull up D+, if any */
|
||||
dwc_otg_pull_up(sc);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
err = USB_ERR_IOERROR;
|
||||
|
@ -196,6 +196,14 @@
|
||||
#define GUSBCFG_TOUTCAL_MASK 0x00000007
|
||||
#define GUSBCFG_TOUTCAL_SHIFT 0
|
||||
|
||||
/* STM32F4 */
|
||||
#define DOTG_GGPIO_NOVBUSSENS (1 << 21)
|
||||
#define DOTG_GGPIO_SOFOUTEN (1 << 20)
|
||||
#define DOTG_GGPIO_VBUSBSEN (1 << 19)
|
||||
#define DOTG_GGPIO_VBUSASEN (1 << 18)
|
||||
#define DOTG_GGPIO_I2CPADEN (1 << 17)
|
||||
#define DOTG_GGPIO_PWRDWN (1 << 16)
|
||||
|
||||
#define GRSTCTL_AHBIDLE (1<<31)
|
||||
#define GRSTCTL_DMAREQ (1<<30)
|
||||
#define GRSTCTL_TXFNUM_MASK 0x000007c0
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user