Merge ^/head r283596 through r283770.
This commit is contained in:
commit
dce6917655
@ -38,7 +38,7 @@
|
||||
# xargs -n1 | sort | uniq -d;
|
||||
# done
|
||||
|
||||
# 20150529: new clang import which bumps version from 3.6.1 to 3.7.0.
|
||||
# 2015mmdd: new clang import which bumps version from 3.6.1 to 3.7.0.
|
||||
OLD_FILES+=usr/lib/clang/3.6.1/include/__stddef_max_align_t.h
|
||||
OLD_FILES+=usr/lib/clang/3.6.1/include/__wmmintrin_aes.h
|
||||
OLD_FILES+=usr/lib/clang/3.6.1/include/__wmmintrin_pclmul.h
|
||||
@ -99,6 +99,10 @@ OLD_FILES+=usr/lib/clang/3.6.1/lib/freebsd/libclang_rt.ubsan_cxx-x86_64.a
|
||||
OLD_DIRS+=usr/lib/clang/3.6.1/lib/freebsd
|
||||
OLD_DIRS+=usr/lib/clang/3.6.1/lib
|
||||
OLD_DIRS+=usr/lib/clang/3.6.1
|
||||
# 20150528: PCI IOV device driver methods moved to a separate kobj interface.
|
||||
OLD_FILES+=usr/share/man/man9/PCI_ADD_VF.9
|
||||
OLD_FILES+=usr/share/man/man9/PCI_INIT_IOV.9
|
||||
OLD_FILES+=usr/share/man/man9/PCI_UNINIT_IOV.9
|
||||
# 20150525: new clang import which bumps version from 3.6.0 to 3.6.1.
|
||||
OLD_FILES+=usr/lib/clang/3.6.0/include/__stddef_max_align_t.h
|
||||
OLD_FILES+=usr/lib/clang/3.6.0/include/__wmmintrin_aes.h
|
||||
|
@ -29,7 +29,7 @@
|
||||
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 22, 2015
|
||||
.Dd May 27, 2015
|
||||
.Dt PS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -350,6 +350,9 @@ the include file
|
||||
.In sys/proc.h :
|
||||
.Bl -column P2_INHERIT_PROTECTED 0x00000001
|
||||
.It Dv "P2_INHERIT_PROTECTED" Ta No "0x00000001" Ta "New children get P_PROTECTED"
|
||||
.It Dv "P2_NOTRACE" Ta No "0x00000002" Ta "No ptrace(2) attach or coredumps"
|
||||
.It Dv "P2_NOTRACE_EXEC" Ta No "0x00000004" Ta "Keep P2_NOPTRACE on exec(2)"
|
||||
.It Dv "P2_AST_SU" Ta No "0x00000008" Ta "Handles SU ast for kthreads"
|
||||
.El
|
||||
.It Cm label
|
||||
The MAC label of the process.
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: _elftc.h 3175 2015-03-27 17:21:24Z emaste $
|
||||
* $Id: _elftc.h 3209 2015-05-17 13:40:46Z kaiwang27 $
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -342,12 +342,13 @@ struct name { \
|
||||
|
||||
|
||||
#if defined(__GLIBC__) || defined(__linux__)
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
/*
|
||||
* GLIBC based systems have a global 'char *' pointer referencing
|
||||
* the executable's name.
|
||||
*/
|
||||
extern const char *program_invocation_short_name;
|
||||
#endif /* !_GNU_SOURCE */
|
||||
|
||||
#define ELFTC_GETPROGNAME() program_invocation_short_name
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: elfdefinitions.h 3178 2015-03-30 18:29:13Z emaste $
|
||||
* $Id: elfdefinitions.h 3198 2015-05-14 18:36:19Z emaste $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -565,6 +565,7 @@ _ELF_DEFINE_EM(EM_SPARC, 2, "SPARC") \
|
||||
_ELF_DEFINE_EM(EM_386, 3, "Intel 80386") \
|
||||
_ELF_DEFINE_EM(EM_68K, 4, "Motorola 68000") \
|
||||
_ELF_DEFINE_EM(EM_88K, 5, "Motorola 88000") \
|
||||
_ELF_DEFINE_EM(EM_IAMCU, 6, "Intel MCU") \
|
||||
_ELF_DEFINE_EM(EM_860, 7, "Intel 80860") \
|
||||
_ELF_DEFINE_EM(EM_MIPS, 8, "MIPS I Architecture") \
|
||||
_ELF_DEFINE_EM(EM_S370, 9, "IBM System/370 Processor") \
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: elfcopy.h 3173 2015-03-27 16:46:13Z emaste $
|
||||
* $Id: elfcopy.h 3221 2015-05-24 23:42:43Z kaiwang27 $
|
||||
*/
|
||||
|
||||
#include <sys/queue.h>
|
||||
@ -237,6 +237,7 @@ struct elfcopy {
|
||||
uint64_t *secndx; /* section index map. */
|
||||
uint64_t *symndx; /* symbol index map. */
|
||||
unsigned char *v_rel; /* symbols needed by relocation. */
|
||||
unsigned char *v_grp; /* symbols refered by section group. */
|
||||
unsigned char *v_secsym; /* sections with section symbol. */
|
||||
STAILQ_HEAD(, segment) v_seg; /* list of segments. */
|
||||
STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
#include "elfcopy.h"
|
||||
|
||||
ELFTC_VCSID("$Id: main.c 3174 2015-03-27 17:13:41Z emaste $");
|
||||
ELFTC_VCSID("$Id: main.c 3216 2015-05-23 21:16:36Z kaiwang27 $");
|
||||
|
||||
enum options
|
||||
{
|
||||
@ -404,8 +404,19 @@ create_elf(struct elfcopy *ecp)
|
||||
* Insert SHDR table into the internal section list as a "pseudo"
|
||||
* section, so later it will get sorted and resynced just as "normal"
|
||||
* sections.
|
||||
*
|
||||
* Under FreeBSD, Binutils objcopy always put the section header
|
||||
* at the end of all the sections. We want to do the same here.
|
||||
*
|
||||
* However, note that the behaviour is still different with Binutils:
|
||||
* elfcopy checks the FreeBSD OSABI tag to tell whether it needs to
|
||||
* move the section headers, while Binutils is probably configured
|
||||
* this way when it's compiled on FreeBSD.
|
||||
*/
|
||||
shtab = insert_shtab(ecp, 0);
|
||||
if (oeh.e_ident[EI_OSABI] == ELFOSABI_FREEBSD)
|
||||
shtab = insert_shtab(ecp, 1);
|
||||
else
|
||||
shtab = insert_shtab(ecp, 0);
|
||||
|
||||
/*
|
||||
* Resync section offsets in the output object. This is needed
|
||||
@ -485,6 +496,11 @@ free_elf(struct elfcopy *ecp)
|
||||
free(sec);
|
||||
}
|
||||
}
|
||||
|
||||
if (ecp->secndx != NULL) {
|
||||
free(ecp->secndx);
|
||||
ecp->secndx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a temporary file. */
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#include "elfcopy.h"
|
||||
|
||||
ELFTC_VCSID("$Id: sections.c 3185 2015-04-11 08:56:34Z kaiwang27 $");
|
||||
ELFTC_VCSID("$Id: sections.c 3220 2015-05-24 23:42:39Z kaiwang27 $");
|
||||
|
||||
static void add_gnu_debuglink(struct elfcopy *ecp);
|
||||
static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc);
|
||||
@ -56,6 +56,7 @@ static void print_data(const char *d, size_t sz);
|
||||
static void print_section(struct section *s);
|
||||
static void *read_section(struct section *s, size_t *size);
|
||||
static void update_reloc(struct elfcopy *ecp, struct section *s);
|
||||
static void update_section_group(struct elfcopy *ecp, struct section *s);
|
||||
|
||||
int
|
||||
is_remove_section(struct elfcopy *ecp, const char *name)
|
||||
@ -552,6 +553,14 @@ copy_content(struct elfcopy *ecp)
|
||||
(s->type == SHT_REL || s->type == SHT_RELA))
|
||||
filter_reloc(ecp, s);
|
||||
|
||||
/*
|
||||
* The section indices in the SHT_GROUP section needs
|
||||
* to be updated since we might have stripped some
|
||||
* sections and changed section numbering.
|
||||
*/
|
||||
if (s->type == SHT_GROUP)
|
||||
update_section_group(ecp, s);
|
||||
|
||||
if (is_modify_section(ecp, s->name))
|
||||
modify_section(ecp, s);
|
||||
|
||||
@ -571,6 +580,71 @@ copy_content(struct elfcopy *ecp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update section group section. The section indices in the SHT_GROUP
|
||||
* section need update after section numbering changed.
|
||||
*/
|
||||
static void
|
||||
update_section_group(struct elfcopy *ecp, struct section *s)
|
||||
{
|
||||
GElf_Shdr ish;
|
||||
Elf_Data *id;
|
||||
uint32_t *ws, *wd;
|
||||
uint64_t n;
|
||||
size_t ishnum;
|
||||
int i, j;
|
||||
|
||||
if (!elf_getshnum(ecp->ein, &ishnum))
|
||||
errx(EXIT_FAILURE, "elf_getshnum failed: %s",
|
||||
elf_errmsg(-1));
|
||||
|
||||
if (gelf_getshdr(s->is, &ish) == NULL)
|
||||
errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
|
||||
elf_errmsg(-1));
|
||||
|
||||
if ((id = elf_getdata(s->is, NULL)) == NULL)
|
||||
errx(EXIT_FAILURE, "elf_getdata() failed: %s",
|
||||
elf_errmsg(-1));
|
||||
|
||||
if (ish.sh_size == 0)
|
||||
return;
|
||||
|
||||
if (ish.sh_entsize == 0)
|
||||
ish.sh_entsize = 4;
|
||||
|
||||
ws = id->d_buf;
|
||||
|
||||
/* We only support COMDAT section. */
|
||||
#ifndef GRP_COMDAT
|
||||
#define GRP_COMDAT 0x1
|
||||
#endif
|
||||
if ((*ws & GRP_COMDAT) == 0)
|
||||
return;
|
||||
|
||||
if ((s->buf = malloc(ish.sh_size)) == NULL)
|
||||
err(EXIT_FAILURE, "malloc failed");
|
||||
|
||||
s->sz = ish.sh_size;
|
||||
|
||||
wd = s->buf;
|
||||
|
||||
/* Copy the flag word as-is. */
|
||||
*wd = *ws;
|
||||
|
||||
/* Update the section indices. */
|
||||
n = ish.sh_size / ish.sh_entsize;
|
||||
for(i = 1, j = 1; (uint64_t)i < n; i++) {
|
||||
if (ws[i] != SHN_UNDEF && ws[i] < ishnum &&
|
||||
ecp->secndx[ws[i]] != 0)
|
||||
wd[j++] = ecp->secndx[ws[i]];
|
||||
else
|
||||
s->sz -= 4;
|
||||
}
|
||||
|
||||
s->nocopy = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Filter relocation entries, only keep those entries whose
|
||||
* symbol is in the keep list.
|
||||
@ -1028,8 +1102,11 @@ copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
|
||||
osh.sh_flags |= SHF_WRITE;
|
||||
if (sec_flags & SF_CODE)
|
||||
osh.sh_flags |= SHF_EXECINSTR;
|
||||
} else
|
||||
} else {
|
||||
osh.sh_flags = ish.sh_flags;
|
||||
if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
|
||||
osh.sh_flags |= SHF_INFO_LINK;
|
||||
}
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "elfcopy.h"
|
||||
|
||||
ELFTC_VCSID("$Id: symbols.c 3191 2015-05-04 17:07:01Z jkoshy $");
|
||||
ELFTC_VCSID("$Id: symbols.c 3222 2015-05-24 23:47:23Z kaiwang27 $");
|
||||
|
||||
/* Symbol table buffer structure. */
|
||||
struct symbuf {
|
||||
@ -77,7 +77,8 @@ static int is_weak_symbol(unsigned char st_info);
|
||||
static int lookup_exact_string(hash_head *hash, const char *buf,
|
||||
const char *s);
|
||||
static int generate_symbols(struct elfcopy *ecp);
|
||||
static void mark_symbols(struct elfcopy *ecp, size_t sc);
|
||||
static void mark_reloc_symbols(struct elfcopy *ecp, size_t sc);
|
||||
static void mark_section_group_symbols(struct elfcopy *ecp, size_t sc);
|
||||
static int match_wildcard(const char *name, const char *pattern);
|
||||
uint32_t str_hash(const char *s);
|
||||
|
||||
@ -160,6 +161,10 @@ is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s)
|
||||
if (BIT_ISSET(ecp->v_rel, i))
|
||||
return (1);
|
||||
|
||||
/* Symbols refered by COMDAT sections are needed. */
|
||||
if (BIT_ISSET(ecp->v_grp, i))
|
||||
return (1);
|
||||
|
||||
/*
|
||||
* For relocatable files (.o files), global and weak symbols
|
||||
* are needed.
|
||||
@ -207,7 +212,10 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
|
||||
return (1);
|
||||
|
||||
if (ecp->v_rel == NULL)
|
||||
mark_symbols(ecp, sc);
|
||||
mark_reloc_symbols(ecp, sc);
|
||||
|
||||
if (ecp->v_grp == NULL)
|
||||
mark_section_group_symbols(ecp, sc);
|
||||
|
||||
if (is_needed_symbol(ecp, i, s))
|
||||
return (0);
|
||||
@ -233,7 +241,7 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
|
||||
* Mark symbols refered by relocation entries.
|
||||
*/
|
||||
static void
|
||||
mark_symbols(struct elfcopy *ecp, size_t sc)
|
||||
mark_reloc_symbols(struct elfcopy *ecp, size_t sc)
|
||||
{
|
||||
const char *name;
|
||||
Elf_Data *d;
|
||||
@ -311,6 +319,49 @@ mark_symbols(struct elfcopy *ecp, size_t sc)
|
||||
elf_errmsg(elferr));
|
||||
}
|
||||
|
||||
static void
|
||||
mark_section_group_symbols(struct elfcopy *ecp, size_t sc)
|
||||
{
|
||||
const char *name;
|
||||
Elf_Scn *s;
|
||||
GElf_Shdr sh;
|
||||
size_t indx;
|
||||
int elferr;
|
||||
|
||||
ecp->v_grp = calloc((sc + 7) / 8, 1);
|
||||
if (ecp->v_grp == NULL)
|
||||
err(EXIT_FAILURE, "calloc failed");
|
||||
|
||||
if (elf_getshstrndx(ecp->ein, &indx) == 0)
|
||||
errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
|
||||
elf_errmsg(-1));
|
||||
|
||||
s = NULL;
|
||||
while ((s = elf_nextscn(ecp->ein, s)) != NULL) {
|
||||
if (gelf_getshdr(s, &sh) != &sh)
|
||||
errx(EXIT_FAILURE, "elf_getshdr failed: %s",
|
||||
elf_errmsg(-1));
|
||||
|
||||
if (sh.sh_type != SHT_GROUP)
|
||||
continue;
|
||||
|
||||
if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == NULL)
|
||||
errx(EXIT_FAILURE, "elf_strptr failed: %s",
|
||||
elf_errmsg(-1));
|
||||
if (is_remove_section(ecp, name))
|
||||
continue;
|
||||
|
||||
if (sh.sh_info > 0 && sh.sh_info < sc)
|
||||
BIT_SET(ecp->v_grp, sh.sh_info);
|
||||
else if (sh.sh_info != 0)
|
||||
warnx("invalid symbox index");
|
||||
}
|
||||
elferr = elf_errno();
|
||||
if (elferr != 0)
|
||||
errx(EXIT_FAILURE, "elf_nextscn failed: %s",
|
||||
elf_errmsg(elferr));
|
||||
}
|
||||
|
||||
static int
|
||||
generate_symbols(struct elfcopy *ecp)
|
||||
{
|
||||
@ -351,6 +402,8 @@ generate_symbols(struct elfcopy *ecp)
|
||||
ecp->symtab->buf = sy_buf;
|
||||
ecp->strtab->buf = st_buf;
|
||||
|
||||
gsym = NULL;
|
||||
|
||||
/*
|
||||
* Create bit vector v_secsym, which is used to mark sections
|
||||
* that already have corresponding STT_SECTION symbols.
|
||||
@ -384,7 +437,7 @@ generate_symbols(struct elfcopy *ecp)
|
||||
/* Symbol table should exist if this function is called. */
|
||||
if (symndx == 0) {
|
||||
warnx("can't find .strtab section");
|
||||
return (0);
|
||||
goto clean;
|
||||
}
|
||||
|
||||
/* Locate .symtab of input object. */
|
||||
@ -413,7 +466,6 @@ generate_symbols(struct elfcopy *ecp)
|
||||
* output object, it is used by update_reloc() later to update
|
||||
* relocation information.
|
||||
*/
|
||||
gsym = NULL;
|
||||
sc = ish.sh_size / ish.sh_entsize;
|
||||
if (sc > 0) {
|
||||
ecp->symndx = calloc(sc, sizeof(*ecp->symndx));
|
||||
@ -427,7 +479,7 @@ generate_symbols(struct elfcopy *ecp)
|
||||
if (elferr != 0)
|
||||
errx(EXIT_FAILURE, "elf_getdata failed: %s",
|
||||
elf_errmsg(elferr));
|
||||
return (0);
|
||||
goto clean;
|
||||
}
|
||||
} else
|
||||
return (0);
|
||||
@ -523,7 +575,7 @@ generate_symbols(struct elfcopy *ecp)
|
||||
* check if that only local symbol is the reserved symbol.
|
||||
*/
|
||||
if (sy_buf->nls <= 1 && sy_buf->ngs == 0)
|
||||
return (0);
|
||||
goto clean;
|
||||
|
||||
/*
|
||||
* Create STT_SECTION symbols for sections that do not already
|
||||
@ -550,6 +602,7 @@ generate_symbols(struct elfcopy *ecp)
|
||||
sym.st_value = s->vma;
|
||||
sym.st_size = 0;
|
||||
sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION);
|
||||
sym.st_other = STV_DEFAULT;
|
||||
/*
|
||||
* Don't let add_to_symtab() touch sym.st_shndx.
|
||||
* In this case, we know the index already.
|
||||
@ -583,6 +636,12 @@ generate_symbols(struct elfcopy *ecp)
|
||||
}
|
||||
|
||||
return (1);
|
||||
|
||||
clean:
|
||||
free(gsym);
|
||||
free_symtab(ecp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -624,7 +683,9 @@ create_symtab(struct elfcopy *ecp)
|
||||
if (((ecp->flags & SYMTAB_INTACT) == 0) && !generate_symbols(ecp)) {
|
||||
TAILQ_REMOVE(&ecp->v_sec, ecp->symtab, sec_list);
|
||||
TAILQ_REMOVE(&ecp->v_sec, ecp->strtab, sec_list);
|
||||
free(ecp->symtab->buf);
|
||||
free(ecp->symtab);
|
||||
free(ecp->strtab->buf);
|
||||
free(ecp->strtab);
|
||||
ecp->symtab = NULL;
|
||||
ecp->strtab = NULL;
|
||||
@ -697,6 +758,23 @@ free_symtab(struct elfcopy *ecp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ecp->symndx != NULL) {
|
||||
free(ecp->symndx);
|
||||
ecp->symndx = NULL;
|
||||
}
|
||||
if (ecp->v_rel != NULL) {
|
||||
free(ecp->v_rel);
|
||||
ecp->v_rel = NULL;
|
||||
}
|
||||
if (ecp->v_grp != NULL) {
|
||||
free(ecp->v_grp);
|
||||
ecp->v_grp = NULL;
|
||||
}
|
||||
if (ecp->v_secsym != NULL) {
|
||||
free(ecp->v_secsym);
|
||||
ecp->v_secsym = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include "_libdwarf.h"
|
||||
|
||||
ELFTC_VCSID("$Id: libdwarf_reloc.c 3149 2015-02-15 19:00:06Z emaste $");
|
||||
ELFTC_VCSID("$Id: libdwarf_reloc.c 3198 2015-05-14 18:36:19Z emaste $");
|
||||
|
||||
Dwarf_Unsigned
|
||||
_dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64)
|
||||
@ -75,6 +75,7 @@ _dwarf_get_reloc_size(Dwarf_Debug dbg, Dwarf_Unsigned rel_type)
|
||||
return (4);
|
||||
break;
|
||||
case EM_386:
|
||||
case EM_IAMCU:
|
||||
if (rel_type == R_386_32)
|
||||
return (4);
|
||||
break;
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
#include "_libelftc.h"
|
||||
|
||||
ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3194 2015-05-05 17:55:16Z emaste $");
|
||||
ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3212 2015-05-17 13:40:55Z kaiwang27 $");
|
||||
|
||||
/**
|
||||
* @file cpp_demangle.c
|
||||
@ -50,7 +50,7 @@ ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3194 2015-05-05 17:55:16Z emaste $");
|
||||
|
||||
enum type_qualifier {
|
||||
TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT,
|
||||
TYPE_CST
|
||||
TYPE_CST, TYPE_VEC
|
||||
};
|
||||
|
||||
struct vector_type_qualifier {
|
||||
@ -84,6 +84,7 @@ struct cpp_demangle_data {
|
||||
int func_type;
|
||||
const char *cur; /* current mangled name ptr */
|
||||
const char *last_sname; /* last source name */
|
||||
int push_head;
|
||||
};
|
||||
|
||||
#define CPP_DEMANGLE_TRY_LIMIT 128
|
||||
@ -112,6 +113,8 @@ static int cpp_demangle_read_array(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_encoding(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_expr_primary(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_expression(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_expression_flat(struct cpp_demangle_data *,
|
||||
char **);
|
||||
static int cpp_demangle_read_expression_binary(struct cpp_demangle_data *,
|
||||
const char *, size_t);
|
||||
static int cpp_demangle_read_expression_unary(struct cpp_demangle_data *,
|
||||
@ -123,8 +126,12 @@ static int cpp_demangle_read_function(struct cpp_demangle_data *, int *,
|
||||
static int cpp_demangle_local_source_name(struct cpp_demangle_data *ddata);
|
||||
static int cpp_demangle_read_local_name(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_name(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_name_flat(struct cpp_demangle_data *,
|
||||
char**);
|
||||
static int cpp_demangle_read_nested_name(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_number(struct cpp_demangle_data *, long *);
|
||||
static int cpp_demangle_read_number_as_string(struct cpp_demangle_data *,
|
||||
char **);
|
||||
static int cpp_demangle_read_nv_offset(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_offset(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_offset_number(struct cpp_demangle_data *);
|
||||
@ -138,6 +145,8 @@ static int cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_tmpl_args(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_tmpl_param(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_type(struct cpp_demangle_data *, int);
|
||||
static int cpp_demangle_read_type_flat(struct cpp_demangle_data *,
|
||||
char **);
|
||||
static int cpp_demangle_read_uqname(struct cpp_demangle_data *);
|
||||
static int cpp_demangle_read_v_offset(struct cpp_demangle_data *);
|
||||
static char *decode_fp_to_double(const char *, size_t);
|
||||
@ -156,8 +165,6 @@ static int vector_type_qualifier_init(struct vector_type_qualifier *);
|
||||
static int vector_type_qualifier_push(struct vector_type_qualifier *,
|
||||
enum type_qualifier);
|
||||
|
||||
static int cpp_demangle_gnu3_push_head;
|
||||
|
||||
/**
|
||||
* @brief Decode the input string by IA-64 C++ ABI style.
|
||||
*
|
||||
@ -190,7 +197,6 @@ cpp_demangle_gnu3(const char *org)
|
||||
if (!cpp_demangle_data_init(&ddata, org + 2))
|
||||
return (NULL);
|
||||
|
||||
cpp_demangle_gnu3_push_head = 0;
|
||||
rtn = NULL;
|
||||
|
||||
if (!cpp_demangle_read_encoding(&ddata))
|
||||
@ -277,6 +283,7 @@ cpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur)
|
||||
d->func_type = 0;
|
||||
d->cur = cur;
|
||||
d->last_sname = NULL;
|
||||
d->push_head = 0;
|
||||
|
||||
return (1);
|
||||
|
||||
@ -309,7 +316,6 @@ cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
|
||||
fp = ddata->cur;
|
||||
while (*ddata->cur != 'E')
|
||||
++ddata->cur;
|
||||
++ddata->cur;
|
||||
|
||||
if ((f = decoder(fp, ddata->cur - fp)) == NULL)
|
||||
return (0);
|
||||
@ -320,6 +326,8 @@ cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
|
||||
|
||||
free(f);
|
||||
|
||||
++ddata->cur;
|
||||
|
||||
return (rtn);
|
||||
}
|
||||
|
||||
@ -331,7 +339,7 @@ cpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str,
|
||||
if (ddata == NULL || str == NULL || len == 0)
|
||||
return (0);
|
||||
|
||||
if (cpp_demangle_gnu3_push_head > 0)
|
||||
if (ddata->push_head > 0)
|
||||
return (vector_str_push(&ddata->output_tmp, str, len));
|
||||
|
||||
return (vector_str_push(&ddata->output, str, len));
|
||||
@ -403,7 +411,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, "*", 1))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
@ -414,7 +423,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, "&", 1))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
@ -425,7 +435,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, " complex", 8))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
@ -434,23 +445,26 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (!cpp_demangle_push_str(ddata, " imaginary", 10))
|
||||
goto clean;
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, " imaginary", 10))
|
||||
if (!vector_str_push(&subst_v, " imaginary",
|
||||
10))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_EXT:
|
||||
if (e_idx > v->ext_name.size - 1)
|
||||
if (v->ext_name.size == 0 ||
|
||||
e_idx > v->ext_name.size - 1)
|
||||
goto clean;
|
||||
if ((e_len = strlen(v->ext_name.container[e_idx])) == 0)
|
||||
if ((e_len = strlen(v->ext_name.container[e_idx])) ==
|
||||
0)
|
||||
goto clean;
|
||||
if ((buf = malloc(sizeof(char) * (e_len + 1))) == NULL)
|
||||
if ((buf = malloc(e_len + 2)) == NULL)
|
||||
goto clean;
|
||||
|
||||
memcpy(buf, " ", 1);
|
||||
memcpy(buf + 1, v->ext_name.container[e_idx], e_len);
|
||||
snprintf(buf, e_len + 2, " %s",
|
||||
v->ext_name.container[e_idx]);
|
||||
|
||||
if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) {
|
||||
free(buf);
|
||||
@ -463,7 +477,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
free(buf);
|
||||
goto clean;
|
||||
}
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v)) {
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v)) {
|
||||
free(buf);
|
||||
goto clean;
|
||||
}
|
||||
@ -478,7 +493,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, " restrict", 9))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
@ -489,7 +505,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, " volatile", 9))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
@ -500,11 +517,42 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, " const", 6))
|
||||
goto clean;
|
||||
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v))
|
||||
goto clean;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_VEC:
|
||||
if (v->ext_name.size == 0 ||
|
||||
e_idx > v->ext_name.size - 1)
|
||||
goto clean;
|
||||
if ((e_len = strlen(v->ext_name.container[e_idx])) ==
|
||||
0)
|
||||
goto clean;
|
||||
if ((buf = malloc(e_len + 12)) == NULL)
|
||||
goto clean;
|
||||
snprintf(buf, e_len + 12, " __vector(%s)",
|
||||
v->ext_name.container[e_idx]);
|
||||
if (!cpp_demangle_push_str(ddata, buf, e_len + 11)) {
|
||||
free(buf);
|
||||
goto clean;
|
||||
}
|
||||
if (type_str != NULL) {
|
||||
if (!vector_str_push(&subst_v, buf,
|
||||
e_len + 11)) {
|
||||
free(buf);
|
||||
goto clean;
|
||||
}
|
||||
if (!cpp_demangle_push_subst_v(ddata,
|
||||
&subst_v)) {
|
||||
free(buf);
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
++e_idx;
|
||||
break;
|
||||
};
|
||||
--idx;
|
||||
}
|
||||
@ -655,10 +703,14 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
|
||||
|
||||
switch (*ddata->cur) {
|
||||
case 'b':
|
||||
if (*(ddata->cur + 2) != 'E')
|
||||
return (0);
|
||||
switch (*(++ddata->cur)) {
|
||||
case '0':
|
||||
ddata->cur += 2;
|
||||
return (cpp_demangle_push_str(ddata, "false", 5));
|
||||
case '1':
|
||||
ddata->cur += 2;
|
||||
return (cpp_demangle_push_str(ddata, "true", 4));
|
||||
default:
|
||||
return (0);
|
||||
@ -707,7 +759,8 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
|
||||
++ddata->cur;
|
||||
}
|
||||
++ddata->cur;
|
||||
return (cpp_demangle_push_str(ddata, num, ddata->cur - num));
|
||||
return (cpp_demangle_push_str(ddata, num,
|
||||
ddata->cur - num - 1));
|
||||
|
||||
default:
|
||||
return (0);
|
||||
@ -998,6 +1051,38 @@ cpp_demangle_read_expression(struct cpp_demangle_data *ddata)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cpp_demangle_read_expression_flat(struct cpp_demangle_data *ddata, char **str)
|
||||
{
|
||||
struct vector_str *output;
|
||||
size_t i, p_idx, idx, exp_len;
|
||||
char *exp;
|
||||
|
||||
output = ddata->push_head > 0 ? &ddata->output_tmp :
|
||||
&ddata->output;
|
||||
|
||||
p_idx = output->size;
|
||||
|
||||
if (!cpp_demangle_read_expression(ddata))
|
||||
return (0);
|
||||
|
||||
if ((exp = vector_str_substr(output, p_idx, output->size - 1,
|
||||
&exp_len)) == NULL)
|
||||
return (0);
|
||||
|
||||
idx = output->size;
|
||||
for (i = p_idx; i < idx; ++i) {
|
||||
if (!vector_str_pop(output)) {
|
||||
free(exp);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
*str = exp;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
cpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata,
|
||||
const char *name, size_t len)
|
||||
@ -1127,12 +1212,65 @@ cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
|
||||
static int
|
||||
cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
|
||||
{
|
||||
char *name, *type, *num_str;
|
||||
long offset;
|
||||
int rtn;
|
||||
|
||||
if (ddata == NULL || *ddata->cur == '\0')
|
||||
return (0);
|
||||
|
||||
/* special name */
|
||||
switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
|
||||
case SIMPLE_HASH('G', 'A'):
|
||||
if (!cpp_demangle_push_str(ddata, "hidden alias for ", 17))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
return (cpp_demangle_read_encoding(ddata));
|
||||
|
||||
case SIMPLE_HASH('G', 'R'):
|
||||
if (!cpp_demangle_push_str(ddata, "reference temporary #", 21))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
if (!cpp_demangle_read_name_flat(ddata, &name))
|
||||
return (0);
|
||||
rtn = 0;
|
||||
if (!cpp_demangle_read_number_as_string(ddata, &num_str))
|
||||
goto clean1;
|
||||
if (!cpp_demangle_push_str(ddata, num_str, strlen(num_str)))
|
||||
goto clean2;
|
||||
if (!cpp_demangle_push_str(ddata, " for ", 5))
|
||||
goto clean2;
|
||||
if (!cpp_demangle_push_str(ddata, name, strlen(name)))
|
||||
goto clean2;
|
||||
rtn = 1;
|
||||
clean2:
|
||||
free(num_str);
|
||||
clean1:
|
||||
free(name);
|
||||
return (rtn);
|
||||
|
||||
case SIMPLE_HASH('G', 'T'):
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
switch (*ddata->cur) {
|
||||
case 'n':
|
||||
if (!cpp_demangle_push_str(ddata,
|
||||
"non-transaction clone for ", 26))
|
||||
return (0);
|
||||
case 't':
|
||||
default:
|
||||
if (!cpp_demangle_push_str(ddata,
|
||||
"transaction clone for ", 22))
|
||||
return (0);
|
||||
}
|
||||
++ddata->cur;
|
||||
return (cpp_demangle_read_encoding(ddata));
|
||||
|
||||
case SIMPLE_HASH('G', 'V'):
|
||||
/* sentry object for 1 time init */
|
||||
if (!cpp_demangle_push_str(ddata, "guard variable for ", 20))
|
||||
@ -1154,14 +1292,49 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
|
||||
return (0);
|
||||
return (cpp_demangle_read_encoding(ddata));
|
||||
|
||||
case SIMPLE_HASH('T', 'C'):
|
||||
/* construction vtable */
|
||||
if (!cpp_demangle_push_str(ddata, "construction vtable for ",
|
||||
24))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
if (!cpp_demangle_read_type_flat(ddata, &type))
|
||||
return (0);
|
||||
rtn = 0;
|
||||
if (!cpp_demangle_read_number(ddata, &offset))
|
||||
goto clean3;
|
||||
if (*ddata->cur++ != '_')
|
||||
goto clean3;
|
||||
if (!cpp_demangle_read_type(ddata, 0))
|
||||
goto clean3;
|
||||
if (!cpp_demangle_push_str(ddata, "-in-", 4))
|
||||
goto clean3;
|
||||
if (!cpp_demangle_push_str(ddata, type, strlen(type)))
|
||||
goto clean3;
|
||||
rtn = 1;
|
||||
clean3:
|
||||
free(type);
|
||||
return (rtn);
|
||||
|
||||
case SIMPLE_HASH('T', 'D'):
|
||||
/* typeinfo common proxy */
|
||||
break;
|
||||
|
||||
case SIMPLE_HASH('T', 'F'):
|
||||
/* typeinfo fn */
|
||||
if (!cpp_demangle_push_str(ddata, "typeinfo fn for ", 16))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
return (cpp_demangle_read_type(ddata, 0));
|
||||
|
||||
case SIMPLE_HASH('T', 'h'):
|
||||
/* virtual function non-virtual override thunk */
|
||||
if (cpp_demangle_push_str(ddata,
|
||||
"virtual function non-virtual override ", 38) == 0)
|
||||
if (!cpp_demangle_push_str(ddata,
|
||||
"virtual function non-virtual override ", 38))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
@ -1170,24 +1343,51 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
|
||||
return (0);
|
||||
return (cpp_demangle_read_encoding(ddata));
|
||||
|
||||
case SIMPLE_HASH('T', 'I'):
|
||||
/* typeinfo structure */
|
||||
/* FALLTHROUGH */
|
||||
case SIMPLE_HASH('T', 'S'):
|
||||
/* RTTI name (NTBS) */
|
||||
if (!cpp_demangle_push_str(ddata, "typeinfo for ", 14))
|
||||
case SIMPLE_HASH('T', 'H'):
|
||||
/* TLS init function */
|
||||
if (!cpp_demangle_push_str(ddata, "TLS init function for ",
|
||||
22))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
return (cpp_demangle_read_type(ddata, 1));
|
||||
break;
|
||||
|
||||
case SIMPLE_HASH('T', 'I'):
|
||||
/* typeinfo structure */
|
||||
if (!cpp_demangle_push_str(ddata, "typeinfo for ", 13))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
return (cpp_demangle_read_type(ddata, 0));
|
||||
|
||||
case SIMPLE_HASH('T', 'J'):
|
||||
/* java class */
|
||||
if (!cpp_demangle_push_str(ddata, "java Class for ", 15))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
return (cpp_demangle_read_type(ddata, 0));
|
||||
|
||||
case SIMPLE_HASH('T', 'S'):
|
||||
/* RTTI name (NTBS) */
|
||||
if (!cpp_demangle_push_str(ddata, "typeinfo name for ", 18))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
return (cpp_demangle_read_type(ddata, 0));
|
||||
|
||||
case SIMPLE_HASH('T', 'T'):
|
||||
/* VTT table */
|
||||
if (!cpp_demangle_push_str(ddata, "VTT for ", 8))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
return (cpp_demangle_read_type(ddata, 1));
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
return (cpp_demangle_read_type(ddata, 0));
|
||||
|
||||
case SIMPLE_HASH('T', 'v'):
|
||||
/* virtual function virtual override thunk */
|
||||
@ -1208,7 +1408,17 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
return (cpp_demangle_read_type(ddata, 1));
|
||||
return (cpp_demangle_read_type(ddata, 0));
|
||||
|
||||
case SIMPLE_HASH('T', 'W'):
|
||||
/* TLS wrapper function */
|
||||
if (!cpp_demangle_push_str(ddata, "TLS wrapper function for ",
|
||||
25))
|
||||
return (0);
|
||||
ddata->cur += 2;
|
||||
if (*ddata->cur == '\0')
|
||||
return (0);
|
||||
break;
|
||||
};
|
||||
|
||||
return (cpp_demangle_read_name(ddata));
|
||||
@ -1270,8 +1480,7 @@ cpp_demangle_read_name(struct cpp_demangle_data *ddata)
|
||||
if (ddata == NULL || *ddata->cur == '\0')
|
||||
return (0);
|
||||
|
||||
output = cpp_demangle_gnu3_push_head > 0 ?
|
||||
&ddata->output_tmp : &ddata->output;
|
||||
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
|
||||
|
||||
subst_str = NULL;
|
||||
|
||||
@ -1326,6 +1535,38 @@ clean:
|
||||
return (rtn);
|
||||
}
|
||||
|
||||
static int
|
||||
cpp_demangle_read_name_flat(struct cpp_demangle_data *ddata, char **str)
|
||||
{
|
||||
struct vector_str *output;
|
||||
size_t i, p_idx, idx, name_len;
|
||||
char *name;
|
||||
|
||||
output = ddata->push_head > 0 ? &ddata->output_tmp :
|
||||
&ddata->output;
|
||||
|
||||
p_idx = output->size;
|
||||
|
||||
if (!cpp_demangle_read_name(ddata))
|
||||
return (0);
|
||||
|
||||
if ((name = vector_str_substr(output, p_idx, output->size - 1,
|
||||
&name_len)) == NULL)
|
||||
return (0);
|
||||
|
||||
idx = output->size;
|
||||
for (i = p_idx; i < idx; ++i) {
|
||||
if (!vector_str_pop(output)) {
|
||||
free(name);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
*str = name;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
|
||||
{
|
||||
@ -1355,8 +1596,7 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
|
||||
++ddata->cur;
|
||||
}
|
||||
|
||||
output = cpp_demangle_gnu3_push_head > 0 ?
|
||||
&ddata->output_tmp : &ddata->output;
|
||||
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
|
||||
if (!vector_str_init(&v))
|
||||
return (0);
|
||||
|
||||
@ -1452,6 +1692,24 @@ cpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn)
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
cpp_demangle_read_number_as_string(struct cpp_demangle_data *ddata, char **str)
|
||||
{
|
||||
long n;
|
||||
|
||||
if (!cpp_demangle_read_number(ddata, &n)) {
|
||||
*str = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (asprintf(str, "%ld", n) < 0) {
|
||||
*str = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
cpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata)
|
||||
{
|
||||
@ -1581,9 +1839,18 @@ static int
|
||||
cpp_demangle_read_sname(struct cpp_demangle_data *ddata)
|
||||
{
|
||||
long len;
|
||||
int err;
|
||||
|
||||
if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 ||
|
||||
len <= 0 || cpp_demangle_push_str(ddata, ddata->cur, len) == 0)
|
||||
len <= 0)
|
||||
return (0);
|
||||
|
||||
if (len == 12 && (memcmp("_GLOBAL__N_1", ddata->cur, 12) == 0))
|
||||
err = cpp_demangle_push_str(ddata, "(anonymous namespace)", 21);
|
||||
else
|
||||
err = cpp_demangle_push_str(ddata, ddata->cur, len);
|
||||
|
||||
if (err == 0)
|
||||
return (0);
|
||||
|
||||
assert(ddata->output.size > 0);
|
||||
@ -1732,8 +1999,7 @@ cpp_demangle_read_subst_std(struct cpp_demangle_data *ddata)
|
||||
|
||||
ddata->cur += 2;
|
||||
|
||||
output = cpp_demangle_gnu3_push_head > 0 ?
|
||||
&ddata->output_tmp : &ddata->output;
|
||||
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
|
||||
|
||||
p_idx = output->size;
|
||||
if (!cpp_demangle_read_uqname(ddata))
|
||||
@ -1783,8 +2049,7 @@ cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata,
|
||||
if (ddata == NULL || str == NULL || len == 0)
|
||||
return (0);
|
||||
|
||||
output = cpp_demangle_gnu3_push_head > 0 ? &ddata->output_tmp :
|
||||
&ddata->output;
|
||||
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
|
||||
|
||||
p_idx = output->size;
|
||||
substr = NULL;
|
||||
@ -1852,8 +2117,7 @@ cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
|
||||
return (0);
|
||||
|
||||
limit = 0;
|
||||
v = cpp_demangle_gnu3_push_head > 0 ?
|
||||
&ddata->output_tmp : &ddata->output;
|
||||
v = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
|
||||
for (;;) {
|
||||
idx = v->size;
|
||||
if (!cpp_demangle_read_tmpl_arg(ddata))
|
||||
@ -1936,14 +2200,14 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
|
||||
size_t p_idx, type_str_len;
|
||||
int extern_c, is_builtin;
|
||||
long len;
|
||||
char *type_str;
|
||||
char *type_str, *exp_str, *num_str;
|
||||
|
||||
if (ddata == NULL)
|
||||
return (0);
|
||||
|
||||
output = &ddata->output;
|
||||
if (!strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) {
|
||||
cpp_demangle_gnu3_push_head++;
|
||||
ddata->push_head++;
|
||||
output = &ddata->output_tmp;
|
||||
} else if (delimit == 1) {
|
||||
if (ddata->paren == false) {
|
||||
@ -1978,7 +2242,7 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
|
||||
extern_c = 0;
|
||||
is_builtin = 1;
|
||||
p_idx = output->size;
|
||||
type_str = NULL;
|
||||
type_str = exp_str = num_str = NULL;
|
||||
again:
|
||||
/* builtin type */
|
||||
switch (*ddata->cur) {
|
||||
@ -2024,6 +2288,82 @@ again:
|
||||
++ddata->cur;
|
||||
goto rtn;
|
||||
|
||||
case 'D':
|
||||
++ddata->cur;
|
||||
switch (*ddata->cur) {
|
||||
case 'd':
|
||||
/* IEEE 754r decimal floating point (64 bits) */
|
||||
if (!cpp_demangle_push_str(ddata, "decimal64", 9))
|
||||
goto clean;
|
||||
++ddata->cur;
|
||||
break;
|
||||
case 'e':
|
||||
/* IEEE 754r decimal floating point (128 bits) */
|
||||
if (!cpp_demangle_push_str(ddata, "decimal128", 10))
|
||||
goto clean;
|
||||
++ddata->cur;
|
||||
break;
|
||||
case 'f':
|
||||
/* IEEE 754r decimal floating point (32 bits) */
|
||||
if (!cpp_demangle_push_str(ddata, "decimal32", 9))
|
||||
goto clean;
|
||||
++ddata->cur;
|
||||
break;
|
||||
case 'h':
|
||||
/* IEEE 754r half-precision floating point (16 bits) */
|
||||
if (!cpp_demangle_push_str(ddata, "half", 4))
|
||||
goto clean;
|
||||
++ddata->cur;
|
||||
break;
|
||||
case 'i':
|
||||
/* char32_t */
|
||||
if (!cpp_demangle_push_str(ddata, "char32_t", 8))
|
||||
goto clean;
|
||||
++ddata->cur;
|
||||
break;
|
||||
case 'n':
|
||||
/* std::nullptr_t (i.e., decltype(nullptr)) */
|
||||
if (!cpp_demangle_push_str(ddata, "decltype(nullptr)",
|
||||
17))
|
||||
goto clean;
|
||||
++ddata->cur;
|
||||
break;
|
||||
case 's':
|
||||
/* char16_t */
|
||||
if (!cpp_demangle_push_str(ddata, "char16_t", 8))
|
||||
goto clean;
|
||||
++ddata->cur;
|
||||
break;
|
||||
case 'v':
|
||||
/* gcc vector_size extension. */
|
||||
++ddata->cur;
|
||||
if (*ddata->cur == '_') {
|
||||
++ddata->cur;
|
||||
if (!cpp_demangle_read_expression_flat(ddata,
|
||||
&exp_str))
|
||||
goto clean;
|
||||
if (!vector_str_push(&v.ext_name, exp_str,
|
||||
strlen(exp_str)))
|
||||
goto clean;
|
||||
} else {
|
||||
if (!cpp_demangle_read_number_as_string(ddata,
|
||||
&num_str))
|
||||
goto clean;
|
||||
if (!vector_str_push(&v.ext_name, num_str,
|
||||
strlen(num_str)))
|
||||
goto clean;
|
||||
}
|
||||
if (*ddata->cur != '_')
|
||||
goto clean;
|
||||
++ddata->cur;
|
||||
if (!vector_type_qualifier_push(&v, TYPE_VEC))
|
||||
goto clean;
|
||||
goto again;
|
||||
default:
|
||||
goto clean;
|
||||
}
|
||||
goto rtn;
|
||||
|
||||
case 'e':
|
||||
/* long double */
|
||||
if (!cpp_demangle_push_str(ddata, "long double", 11))
|
||||
@ -2118,7 +2458,7 @@ again:
|
||||
|
||||
case 'o':
|
||||
/* unsigned __int128 */
|
||||
if (!cpp_demangle_push_str(ddata, "unsigned _;int128", 17))
|
||||
if (!cpp_demangle_push_str(ddata, "unsigned __int128", 17))
|
||||
goto clean;
|
||||
++ddata->cur;
|
||||
goto rtn;
|
||||
@ -2189,6 +2529,8 @@ again:
|
||||
if (!vector_str_push(&v.ext_name, ddata->cur, len))
|
||||
return (0);
|
||||
ddata->cur += len;
|
||||
if (!vector_type_qualifier_push(&v, TYPE_EXT))
|
||||
goto clean;
|
||||
goto again;
|
||||
|
||||
case 'v':
|
||||
@ -2253,14 +2595,16 @@ rtn:
|
||||
goto clean;
|
||||
|
||||
free(type_str);
|
||||
free(exp_str);
|
||||
free(num_str);
|
||||
vector_type_qualifier_dest(&v);
|
||||
|
||||
if (cpp_demangle_gnu3_push_head > 0) {
|
||||
if (ddata->push_head > 0) {
|
||||
if (*ddata->cur == 'I' && cpp_demangle_read_tmpl_args(ddata)
|
||||
== 0)
|
||||
return (0);
|
||||
|
||||
if (--cpp_demangle_gnu3_push_head > 0)
|
||||
if (--ddata->push_head > 0)
|
||||
return (1);
|
||||
|
||||
if (!vector_str_push(&ddata->output_tmp, " ", 1))
|
||||
@ -2284,11 +2628,45 @@ rtn:
|
||||
return (1);
|
||||
clean:
|
||||
free(type_str);
|
||||
free(exp_str);
|
||||
free(num_str);
|
||||
vector_type_qualifier_dest(&v);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cpp_demangle_read_type_flat(struct cpp_demangle_data *ddata, char **str)
|
||||
{
|
||||
struct vector_str *output;
|
||||
size_t i, p_idx, idx, type_len;
|
||||
char *type;
|
||||
|
||||
output = ddata->push_head > 0 ? &ddata->output_tmp :
|
||||
&ddata->output;
|
||||
|
||||
p_idx = output->size;
|
||||
|
||||
if (!cpp_demangle_read_type(ddata, 0))
|
||||
return (0);
|
||||
|
||||
if ((type = vector_str_substr(output, p_idx, output->size - 1,
|
||||
&type_len)) == NULL)
|
||||
return (0);
|
||||
|
||||
idx = output->size;
|
||||
for (i = p_idx; i < idx; ++i) {
|
||||
if (!vector_str_pop(output)) {
|
||||
free(type);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
*str = type;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* read unqualified-name, unqualified name are operator-name, ctor-dtor-name,
|
||||
* source-name
|
||||
|
@ -1,3 +1,3 @@
|
||||
# $Id: os.Linux.mk 994 2010-06-13 10:39:19Z jkoshy $
|
||||
# $Id: os.Linux.mk 3210 2015-05-17 13:40:49Z kaiwang27 $
|
||||
|
||||
CFLAGS+= -Wall
|
||||
CFLAGS+= -Wall -D_GNU_SOURCE
|
||||
|
@ -22,7 +22,7 @@
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $Id: readelf.1 3195 2015-05-12 17:22:19Z emaste $
|
||||
.\" $Id: readelf.1 3219 2015-05-24 23:42:34Z kaiwang27 $
|
||||
.\"
|
||||
.Dd September 13, 2012
|
||||
.Os
|
||||
@ -90,7 +90,7 @@ sections in the ELF object.
|
||||
.It Fl e | Fl -headers
|
||||
Print all program, file and section headers in the ELF object.
|
||||
.It Fl g | Fl -section-groups
|
||||
This option is recognized, but is ignored.
|
||||
Print the contents of the section groups in the ELF object.
|
||||
.It Fl h | Fl -file-header
|
||||
Print the file header of the ELF object.
|
||||
.It Fl l | Fl -program-headers
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2009-2014 Kai Wang
|
||||
* Copyright (c) 2009-2015 Kai Wang
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
#include "_elftc.h"
|
||||
|
||||
ELFTC_VCSID("$Id: readelf.c 3189 2015-04-20 17:02:01Z emaste $");
|
||||
ELFTC_VCSID("$Id: readelf.c 3223 2015-05-25 20:37:57Z emaste $");
|
||||
|
||||
/*
|
||||
* readelf(1) options.
|
||||
@ -302,6 +302,7 @@ static void dump_gnu_hash(struct readelf *re, struct section *s);
|
||||
static void dump_hash(struct readelf *re);
|
||||
static void dump_phdr(struct readelf *re);
|
||||
static void dump_ppc_attributes(uint8_t *p, uint8_t *pe);
|
||||
static void dump_section_groups(struct readelf *re);
|
||||
static void dump_symtab(struct readelf *re, int i);
|
||||
static void dump_symtabs(struct readelf *re);
|
||||
static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p);
|
||||
@ -445,6 +446,7 @@ elf_machine(unsigned int mach)
|
||||
case EM_SPARC: return "Sun SPARC";
|
||||
case EM_386: return "Intel i386";
|
||||
case EM_68K: return "Motorola 68000";
|
||||
case EM_IAMCU: return "Intel MCU";
|
||||
case EM_88K: return "Motorola 88000";
|
||||
case EM_860: return "Intel i860";
|
||||
case EM_MIPS: return "MIPS R3000 Big-Endian only";
|
||||
@ -1050,6 +1052,7 @@ r_type(unsigned int mach, unsigned int type)
|
||||
switch(mach) {
|
||||
case EM_NONE: return "";
|
||||
case EM_386:
|
||||
case EM_IAMCU:
|
||||
switch(type) {
|
||||
case 0: return "R_386_NONE";
|
||||
case 1: return "R_386_32";
|
||||
@ -2381,6 +2384,7 @@ dwarf_reg(unsigned int mach, unsigned int reg)
|
||||
|
||||
switch (mach) {
|
||||
case EM_386:
|
||||
case EM_IAMCU:
|
||||
switch (reg) {
|
||||
case 0: return "eax";
|
||||
case 1: return "ecx";
|
||||
@ -4047,6 +4051,61 @@ dump_liblist(struct readelf *re)
|
||||
|
||||
#undef Elf_Lib
|
||||
|
||||
static void
|
||||
dump_section_groups(struct readelf *re)
|
||||
{
|
||||
struct section *s;
|
||||
const char *symname;
|
||||
Elf_Data *d;
|
||||
uint32_t *w;
|
||||
int i, j, elferr;
|
||||
size_t n;
|
||||
|
||||
for (i = 0; (size_t) i < re->shnum; i++) {
|
||||
s = &re->sl[i];
|
||||
if (s->type != SHT_GROUP)
|
||||
continue;
|
||||
(void) elf_errno();
|
||||
if ((d = elf_getdata(s->scn, NULL)) == NULL) {
|
||||
elferr = elf_errno();
|
||||
if (elferr != 0)
|
||||
warnx("elf_getdata failed: %s",
|
||||
elf_errmsg(elferr));
|
||||
continue;
|
||||
}
|
||||
if (d->d_size <= 0)
|
||||
continue;
|
||||
|
||||
w = d->d_buf;
|
||||
|
||||
/* We only support COMDAT section. */
|
||||
#ifndef GRP_COMDAT
|
||||
#define GRP_COMDAT 0x1
|
||||
#endif
|
||||
if ((*w++ & GRP_COMDAT) == 0)
|
||||
return;
|
||||
|
||||
if (s->entsize == 0)
|
||||
s->entsize = 4;
|
||||
|
||||
symname = get_symbol_name(re, s->link, s->info);
|
||||
n = s->sz / s->entsize;
|
||||
if (n-- < 1)
|
||||
return;
|
||||
|
||||
printf("\nCOMDAT group section [%5d] `%s' [%s] contains %ju"
|
||||
" sections:\n", i, s->name, symname, (uintmax_t)n);
|
||||
printf(" %-10.10s %s\n", "[Index]", "Name");
|
||||
for (j = 0; (size_t) j < n; j++, w++) {
|
||||
if (*w >= re->shnum) {
|
||||
warnx("invalid section index: %u", *w);
|
||||
continue;
|
||||
}
|
||||
printf(" [%5u] %s\n", *w, re->sl[*w].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t *
|
||||
dump_unknown_tag(uint64_t tag, uint8_t *p)
|
||||
{
|
||||
@ -6838,6 +6897,8 @@ dump_elf(struct readelf *re)
|
||||
dump_phdr(re);
|
||||
if (re->options & RE_SS)
|
||||
dump_shdr(re);
|
||||
if (re->options & RE_G)
|
||||
dump_section_groups(re);
|
||||
if (re->options & RE_D)
|
||||
dump_dynamic(re);
|
||||
if (re->options & RE_R)
|
||||
@ -7311,7 +7372,7 @@ Usage: %s [options] file...\n\
|
||||
-c | --archive-index Print the archive symbol table for archives.\n\
|
||||
-d | --dynamic Print the contents of SHT_DYNAMIC sections.\n\
|
||||
-e | --headers Print all headers in the object.\n\
|
||||
-g | --section-groups (accepted, but ignored)\n\
|
||||
-g | --section-groups Print the contents of the section groups.\n\
|
||||
-h | --file-header Print the file header for the object.\n\
|
||||
-l | --program-headers Print the PHDR table for the object.\n\
|
||||
-n | --notes Print the contents of SHT_NOTE sections.\n\
|
||||
@ -7365,8 +7426,8 @@ main(int argc, char **argv)
|
||||
re->options |= RE_AA;
|
||||
break;
|
||||
case 'a':
|
||||
re->options |= RE_AA | RE_D | RE_H | RE_II | RE_L |
|
||||
RE_R | RE_SS | RE_S | RE_VV;
|
||||
re->options |= RE_AA | RE_D | RE_G | RE_H | RE_II |
|
||||
RE_L | RE_R | RE_SS | RE_S | RE_VV;
|
||||
break;
|
||||
case 'c':
|
||||
re->options |= RE_C;
|
||||
|
@ -29,6 +29,8 @@
|
||||
|
||||
#include <sys/endian.h>
|
||||
|
||||
#include <machine/float.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@ -84,10 +86,18 @@ __fpclassifyl(long double e)
|
||||
return (FP_SUBNORMAL);
|
||||
}
|
||||
mask_nbit_l(u); /* Mask normalization bit if applicable. */
|
||||
#if LDBL_MANT_DIG == 53
|
||||
if (u.bits.exp == 2047) {
|
||||
if ((u.bits.manl | u.bits.manh) == 0)
|
||||
return (FP_INFINITE);
|
||||
return (FP_NAN);
|
||||
}
|
||||
#else
|
||||
if (u.bits.exp == 32767) {
|
||||
if ((u.bits.manl | u.bits.manh) == 0)
|
||||
return (FP_INFINITE);
|
||||
return (FP_NAN);
|
||||
}
|
||||
#endif
|
||||
return (FP_NORMAL);
|
||||
}
|
||||
|
@ -26,6 +26,8 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <machine/float.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "fpmath.h"
|
||||
@ -62,9 +64,9 @@ __isinfl(long double e)
|
||||
|
||||
u.e = e;
|
||||
mask_nbit_l(u);
|
||||
#ifndef __alpha__
|
||||
return (u.bits.exp == 32767 && u.bits.manl == 0 && u.bits.manh == 0);
|
||||
#else
|
||||
#if LDBL_MANT_DIG == 53
|
||||
return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0);
|
||||
#else
|
||||
return (u.bits.exp == 32767 && u.bits.manl == 0 && u.bits.manh == 0);
|
||||
#endif
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
SRCS+= trivial-vdso_tc.c
|
||||
|
||||
MDASM= Ovfork.S brk.S cerror.S exect.S \
|
||||
fork.S pipe.S ptrace.S sbrk.S syscall.S
|
||||
pipe.S ptrace.S sbrk.S syscall.S
|
||||
|
||||
# Don't generate default code for these syscalls:
|
||||
NOASM= break.o exit.o getlogin.o openbsd_poll.o sstk.o vfork.o yield.o
|
||||
|
@ -1,57 +0,0 @@
|
||||
/* $NetBSD: fork.S,v 1.11 2003/08/07 16:42:17 agc Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Ralph Campbell.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include "SYS.h"
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
ASMSTR("from: @(#)fork.s 8.1 (Berkeley) 6/4/93")
|
||||
ASMSTR("$NetBSD: fork.S,v 1.11 2003/08/07 16:42:17 agc Exp $")
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
LEAF(__sys_fork)
|
||||
WEAK_ALIAS(fork, __sys_fork)
|
||||
WEAK_ALIAS(_fork, __sys_fork)
|
||||
PIC_PROLOGUE(__sys_fork)
|
||||
li v0, SYS_fork # pid = fork()
|
||||
syscall
|
||||
bne a3, zero, 2f
|
||||
beq v1, zero, 1f # v1 == 0 in parent, 1 in child
|
||||
move v0, zero
|
||||
1:
|
||||
PIC_RETURN()
|
||||
2:
|
||||
PIC_TAILCALL(__cerror)
|
||||
END(__sys_fork)
|
@ -6,5 +6,5 @@
|
||||
const char *
|
||||
elftc_version(void)
|
||||
{
|
||||
return "elftoolchain r3197M";
|
||||
return "elftoolchain r3223M";
|
||||
}
|
||||
|
@ -10,7 +10,8 @@ SHLIB_MAJOR= 9
|
||||
|
||||
SRCS= _secure_path.c auth.c expand_number.c flopen.c fparseln.c gr_util.c \
|
||||
hexdump.c humanize_number.c kinfo_getfile.c kinfo_getfile.c \
|
||||
kinfo_getallproc.c kinfo_getproc.c kinfo_getvmmap.c kld.c \
|
||||
kinfo_getallproc.c kinfo_getproc.c kinfo_getvmmap.c \
|
||||
kinfo_getvmobject.c kld.c \
|
||||
login_auth.c login_cap.c \
|
||||
login_class.c login_crypt.c login_ok.c login_times.c login_tty.c \
|
||||
pidfile.c property.c pty.c pw_util.c quotafile.c realhostname.c \
|
||||
@ -27,7 +28,8 @@ CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../libc/gen/
|
||||
|
||||
MAN+= expand_number.3 flopen.3 fparseln.3 hexdump.3 \
|
||||
humanize_number.3 kinfo_getallproc.3 kinfo_getfile.3 \
|
||||
kinfo_getproc.3 kinfo_getvmmap.3 kld.3 login_auth.3 login_cap.3 \
|
||||
kinfo_getproc.3 kinfo_getvmmap.3 kinfo_getvmobject.3 kld.3 \
|
||||
login_auth.3 login_cap.3 \
|
||||
login_class.3 login_ok.3 login_times.3 login_tty.3 pidfile.3 \
|
||||
property.3 pty.3 quotafile.3 realhostname.3 realhostname_sa.3 \
|
||||
_secure_path.3 trimdomain.3 uucplock.3 pw_util.3
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 9, 2009
|
||||
.Dd May 27, 2015
|
||||
.Dt KINFO_GETALLPROC 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -35,6 +35,7 @@
|
||||
.Lb libutil
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In sys/user.h
|
||||
.In libutil.h
|
||||
.Ft struct kinfo_proc *
|
||||
.Fn kinfo_getallproc "int *cntp"
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 6, 2008
|
||||
.Dd May 27, 2015
|
||||
.Dt KINFO_GETFILE 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -35,6 +35,7 @@
|
||||
.Lb libutil
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In sys/user.h
|
||||
.In libutil.h
|
||||
.Ft struct kinfo_file *
|
||||
.Fn kinfo_getfile "pid_t pid" "int *cntp"
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 1, 2013
|
||||
.Dd May 27, 2015
|
||||
.Dt KINFO_GETPROC 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -35,6 +35,7 @@
|
||||
.Lb libutil
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In sys/user.h
|
||||
.In libutil.h
|
||||
.Ft struct kinfo_proc *
|
||||
.Fn kinfo_getproc "pid_t pid"
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 6, 2008
|
||||
.Dd May 27, 2015
|
||||
.Dt KINFO_GETVMMAP 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -35,6 +35,7 @@
|
||||
.Lb libutil
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In sys/user.h
|
||||
.In libutil.h
|
||||
.Ft struct kinfo_vmentry *
|
||||
.Fn kinfo_getvmmap "pid_t pid" "int *cntp"
|
||||
|
74
lib/libutil/kinfo_getvmobject.3
Normal file
74
lib/libutil/kinfo_getvmobject.3
Normal file
@ -0,0 +1,74 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 27, 2015
|
||||
.Dt KINFO_GETVMOBJECT 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm kinfo_getvmobject
|
||||
.Nd function for getting system-wide memory information
|
||||
.Sh LIBRARY
|
||||
.Lb libutil
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In sys/user.h
|
||||
.In libutil.h
|
||||
.Ft struct kinfo_vmobject *
|
||||
.Fn kinfo_getvmobject "int *cntp"
|
||||
.Sh DESCRIPTION
|
||||
This function is used to obtain information about the objects using memory
|
||||
in the system.
|
||||
.Pp
|
||||
The
|
||||
.Ar cntp
|
||||
argument allows the caller to know how many records are returned.
|
||||
.Pp
|
||||
This function is a wrapper around the
|
||||
.Dq vm.objects
|
||||
.Xr sysctl 3
|
||||
MIB.
|
||||
While the kernel returns a packed structure, this function expands the
|
||||
data into a fixed record format.
|
||||
.Sh RETURN VALUES
|
||||
On success the
|
||||
.Fn kinfo_getvmobject
|
||||
function returns a pointer to an array of
|
||||
.Vt struct kinfo_vmobject
|
||||
structures as defined by
|
||||
.In sys/user.h .
|
||||
The array is allocated by an internal call to
|
||||
.Xr malloc 3
|
||||
and must be freed by the caller with a call to
|
||||
.Xr free 3 .
|
||||
On failure the
|
||||
.Fn kinfo_getvmobject
|
||||
function returns
|
||||
.Dv NULL .
|
||||
.Sh SEE ALSO
|
||||
.Xr free 3 ,
|
||||
.Xr kinfo_getvmmap 3 ,
|
||||
.Xr malloc 3
|
94
lib/libutil/kinfo_getvmobject.c
Normal file
94
lib/libutil/kinfo_getvmobject.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Hudson River Trading LLC
|
||||
* Written by: John H. Baldwin <jhb@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libutil.h"
|
||||
|
||||
struct kinfo_vmobject *
|
||||
kinfo_getvmobject(int *cntp)
|
||||
{
|
||||
char *buf, *bp, *ep;
|
||||
struct kinfo_vmobject *kvo, *list, *kp;
|
||||
size_t len;
|
||||
int cnt, i;
|
||||
|
||||
buf = NULL;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (sysctlbyname("vm.objects", NULL, &len, NULL, 0) < 0)
|
||||
return (NULL);
|
||||
buf = reallocf(buf, len);
|
||||
if (buf == NULL)
|
||||
return (NULL);
|
||||
if (sysctlbyname("vm.objects", buf, &len, NULL, 0) == 0)
|
||||
goto unpack;
|
||||
if (errno != ENOMEM) {
|
||||
free(buf);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
return (NULL);
|
||||
|
||||
unpack:
|
||||
/* Count items */
|
||||
cnt = 0;
|
||||
bp = buf;
|
||||
ep = buf + len;
|
||||
while (bp < ep) {
|
||||
kvo = (struct kinfo_vmobject *)(uintptr_t)bp;
|
||||
bp += kvo->kvo_structsize;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
list = calloc(cnt, sizeof(*list));
|
||||
if (list == NULL) {
|
||||
free(buf);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Unpack */
|
||||
bp = buf;
|
||||
kp = list;
|
||||
while (bp < ep) {
|
||||
kvo = (struct kinfo_vmobject *)(uintptr_t)bp;
|
||||
memcpy(kp, kvo, kvo->kvo_structsize);
|
||||
bp += kvo->kvo_structsize;
|
||||
kp->kvo_structsize = sizeof(*kp);
|
||||
kp++;
|
||||
}
|
||||
free(buf);
|
||||
*cntp = cnt;
|
||||
return (list);
|
||||
}
|
@ -102,6 +102,8 @@ struct kinfo_file *
|
||||
kinfo_getfile(pid_t _pid, int *_cntp);
|
||||
struct kinfo_vmentry *
|
||||
kinfo_getvmmap(pid_t _pid, int *_cntp);
|
||||
struct kinfo_vmobject *
|
||||
kinfo_getvmobject(int *_cntp);
|
||||
struct kinfo_proc *
|
||||
kinfo_getallproc(int *_cntp);
|
||||
struct kinfo_proc *
|
||||
|
@ -49,7 +49,7 @@ BUILDDATE!= cd ${.CURDIR} && date -j -f '%s' $$(stat -f "%c" ${.OBJDIR}/dist/ba
|
||||
BUILDDATE!= date +%Y%m%d
|
||||
. endif
|
||||
. endif
|
||||
_SNAP_SUFFIX:= -r${SVNREVISION}-${BUILDDATE}
|
||||
_SNAP_SUFFIX:= ${BUILDDATE}-r${SVNREVISION}
|
||||
.else
|
||||
# release
|
||||
SNAPSHOT=
|
||||
|
@ -8,13 +8,13 @@ EMBEDDED_TARGET="arm"
|
||||
EMBEDDED_TARGET_ARCH="armv6"
|
||||
EMBEDDEDPORTS="sysutils/u-boot-pandaboard"
|
||||
KERNEL="PANDABOARD"
|
||||
NODOC=1
|
||||
WORLD_FLAGS="${WORLD_FLAGS} UBLDR_LOADADDR=0x88000000"
|
||||
IMAGE_SIZE="1G"
|
||||
PART_SCHEME="MBR"
|
||||
FAT_SIZE="2m"
|
||||
FAT_TYPE="12"
|
||||
MD_ARGS="-x 63 -y 255"
|
||||
NODOC=1
|
||||
|
||||
arm_install_uboot() {
|
||||
UBOOT_DIR="/usr/local/share/u-boot/u-boot-pandaboard"
|
||||
|
@ -8,13 +8,13 @@ EMBEDDED_TARGET="arm"
|
||||
EMBEDDED_TARGET_ARCH="armv6"
|
||||
EMBEDDEDPORTS="sysutils/u-boot-rpi2"
|
||||
KERNEL="RPI2"
|
||||
NODOC=1
|
||||
WORLD_FLAGS="${WORLD_FLAGS} UBLDR_LOADADDR=0x2000000"
|
||||
IMAGE_SIZE="1G"
|
||||
PART_SCHEME="MBR"
|
||||
FAT_SIZE="50m"
|
||||
FAT_TYPE="16"
|
||||
MD_ARGS="-x 63 -y 255"
|
||||
NODOC=1
|
||||
|
||||
arm_install_uboot() {
|
||||
UBOOT_DIR="/usr/local/share/u-boot/u-boot-rpi2"
|
||||
|
@ -15,6 +15,7 @@ FAT_SIZE="50m -b 16384"
|
||||
FAT_TYPE="16"
|
||||
MD_ARGS="-x 63 -y 255"
|
||||
NODOC=1
|
||||
export BOARDNAME="WANDBOARD"
|
||||
|
||||
arm_install_uboot() {
|
||||
UBOOT_DIR="/usr/local/share/u-boot/u-boot-wandboard"
|
||||
|
@ -1845,12 +1845,16 @@ rewrite_client_leases(void)
|
||||
leaseFile = fopen(path_dhclient_db, "w");
|
||||
if (!leaseFile)
|
||||
error("can't create %s: %m", path_dhclient_db);
|
||||
cap_rights_init(&rights, CAP_FSTAT, CAP_FSYNC, CAP_FTRUNCATE,
|
||||
CAP_SEEK, CAP_WRITE);
|
||||
cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
|
||||
CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
|
||||
if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
|
||||
errno != ENOSYS) {
|
||||
error("can't limit lease descriptor: %m");
|
||||
}
|
||||
if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
|
||||
errno != ENOSYS) {
|
||||
error("can't limit lease descriptor fcntls: %m");
|
||||
}
|
||||
} else {
|
||||
fflush(leaseFile);
|
||||
rewind(leaseFile);
|
||||
|
@ -67,7 +67,10 @@ is undefined.
|
||||
The
|
||||
.Fn pthread_setspecific
|
||||
function may be called from a thread-specific data destructor function,
|
||||
however this may result in lost storage or infinite loops.
|
||||
however this may result in lost storage or infinite loops if doing so
|
||||
causes non-NULL key values to remain after
|
||||
.Bq PTHREAD_DESTRUCTOR_ITERATIONS
|
||||
iterations of destructor calls have been made.
|
||||
.Sh RETURN VALUES
|
||||
If successful, the
|
||||
.Fn pthread_setspecific
|
||||
|
@ -192,6 +192,7 @@ MAN= aac.4 \
|
||||
icmp6.4 \
|
||||
ida.4 \
|
||||
ifmib.4 \
|
||||
ig4.4 \
|
||||
igb.4 \
|
||||
igmp.4 \
|
||||
iic.4 \
|
||||
|
79
share/man/man4/ig4.4
Normal file
79
share/man/man4/ig4.4
Normal file
@ -0,0 +1,79 @@
|
||||
.\" Copyright (c) 2015 Michael Gmelin <freebsd@grem.de>
|
||||
.\" 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$
|
||||
.\"
|
||||
.Dd May 30, 2015
|
||||
.Dt IG4 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ig4
|
||||
.Nd Intel(R) fourth generation mobile CPU integrated I2C SMBus driver
|
||||
.Sh SYNOPSIS
|
||||
To compile this driver into the kernel, place the following lines into
|
||||
the kernel configuration file:
|
||||
.Bd -ragged -offset indent
|
||||
.Cd "device ig4"
|
||||
.Cd "device smbus"
|
||||
.Ed
|
||||
.Pp
|
||||
Alternatively, to load the driver as a module at boot time, place the following line in
|
||||
.Xr loader.conf 5 :
|
||||
.Bd -literal -offset indent
|
||||
ig4_load="YES"
|
||||
.Ed
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
driver provides access to peripherals attached to an I2C SMB controller.
|
||||
.Nm
|
||||
supports the SMBus controller found in fourth generation Intel(R) Core(TM)
|
||||
processors based on the mobile U-processor line for intelligent systems.
|
||||
This includes the i7-4650U, i5-4300U, i3-4010U, and 2980U.
|
||||
.Sh SYSCTL VARIABLES
|
||||
These
|
||||
.Xr sysctl 8
|
||||
variables are available:
|
||||
.Bl -tag -width "debug.ig4_dump"
|
||||
.It Va debug.ig4_dump
|
||||
Setting this to a non-zero value dumps controller registers to console and
|
||||
syslog once.
|
||||
The sysctl resets to zero immediately.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr smb 4 ,
|
||||
.Xr smbus 4
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm
|
||||
driver was written for DragonFly BSD by
|
||||
.An Matthew Dillon
|
||||
and subsequently ported to
|
||||
.Fx
|
||||
by
|
||||
.An Michael Gmelin Aq Mt freebsd@grem.de .
|
||||
.Pp
|
||||
This manual page was written by
|
||||
.An Michael Gmelin Aq Mt freebsd@grem.de .
|
@ -195,10 +195,10 @@ MAN= accept_filter.9 \
|
||||
p_candebug.9 \
|
||||
p_cansee.9 \
|
||||
pci.9 \
|
||||
PCI_ADD_VF.9 \
|
||||
PCI_INIT_IOV.9 \
|
||||
PCI_IOV_ADD_VF.9 \
|
||||
PCI_IOV_INIT.9 \
|
||||
pci_iov_schema.9 \
|
||||
PCI_UNINIT_IOV.9 \
|
||||
PCI_IOV_UNINIT.9 \
|
||||
pfil.9 \
|
||||
pfind.9 \
|
||||
pget.9 \
|
||||
|
@ -25,38 +25,37 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 24, 2014
|
||||
.Dt PCI_ADD_VF 9
|
||||
.Dd May 28, 2015
|
||||
.Dt PCI_IOV_ADD_VF 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm PCI_ADD_VF
|
||||
.Nm PCI_IOV_ADD_VF
|
||||
.Nd inform a PF driver that a VF is being created
|
||||
.Sh SYNOPSIS
|
||||
.In sys/bus.h
|
||||
.In machine/stdarg.h
|
||||
.In sys/nv.h
|
||||
.In dev/pci/pcireg.h
|
||||
.In dev/pci/pcivar.h
|
||||
.In dev/pci/pci_iov.h
|
||||
.Ft int
|
||||
.Fn PCI_ADD_VF "device_t dev" "uint16_t vfnum" "const nvlist_t *vf_config"
|
||||
.Fn PCI_IOV_ADD_VF "device_t dev" "uint16_t vfnum" "const nvlist_t *vf_config"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn PCI_ADD_VF
|
||||
.Fn PCI_IOV_ADD_VF
|
||||
method is called by the PCI Single-Root I/O Virtualization
|
||||
.Pq SR-IOV
|
||||
infrastructure when it is initializating a new Virtual Function (VF) as a child
|
||||
of the given Physical Function (PF) device.
|
||||
This method will not be called until a successful call to
|
||||
.Xr PCI_INIT_IOV 9
|
||||
.Xr PCI_IOV_INIT 9
|
||||
has been made.
|
||||
It is not guaranteed that this method will be called following a successful call
|
||||
to
|
||||
.Xr PCI_INIT_IOV 9 .
|
||||
.Xr PCI_IOV_INIT 9 .
|
||||
If the infrastructure encounters a failure to allocate resources following the
|
||||
call to
|
||||
.Xr PCI_INIT_IOV 9 ,
|
||||
.Xr PCI_IOV_INIT 9 ,
|
||||
the VF creation will be aborted and
|
||||
.Xr PCI_UNINIT_IOV 9
|
||||
.Xr PCI_IOV_UNINIT 9
|
||||
will be called immediately without any preceding calls to
|
||||
.Nm .
|
||||
.Pp
|
||||
@ -87,15 +86,15 @@ Note that it is possible for the user to set different configuration values on
|
||||
different VF devices that are children of the same PF.
|
||||
The PF driver must not cache configuration parameters passed in previous calls
|
||||
to
|
||||
.Fn PCI_ADD_VF
|
||||
.Fn PCI_IOV_ADD_VF
|
||||
for other VFs and apply those parameters to the current VF.
|
||||
.Pp
|
||||
This function will not be called twice for the same
|
||||
.Fa vf_num
|
||||
on the same PF device without
|
||||
.Xr PCI_UNINIT_IOV 9
|
||||
.Xr PCI_IOV_UNINIT 9
|
||||
and
|
||||
.Xr PCI_INIT_IOV 9
|
||||
.Xr PCI_IOV_INIT 9
|
||||
first being called, in that order.
|
||||
.Sh RETURN VALUES
|
||||
This method returns 0 on success, otherwise an appropriate error is returned.
|
||||
@ -106,8 +105,8 @@ the PF.
|
||||
.Xr nv 9 ,
|
||||
.Xr pci 9 ,
|
||||
.Xr pci_iov_schema 9 ,
|
||||
.Xr PCI_INIT_IOV 9 ,
|
||||
.Xr PCI_UNINIT_IOV 9
|
||||
.Xr PCI_IOV_INIT 9 ,
|
||||
.Xr PCI_IOV_UNINIT 9
|
||||
.Sh AUTHORS
|
||||
This manual page was written by
|
||||
.An Ryan Stone Aq Mt rstone@FreeBSD.org .
|
@ -25,23 +25,22 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 24, 2014
|
||||
.Dt PCI_INIT_IOV 9
|
||||
.Dd May 28, 2015
|
||||
.Dt PCI_IOV_INIT 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm PCI_INIT_IOV
|
||||
.Nm PCI_IOV_INIT
|
||||
.Nd enable SR-IOV on a PF device
|
||||
.Sh SYNOPSIS
|
||||
.In sys/bus.h
|
||||
.In machine/stdarg.h
|
||||
.In sys/nv.h
|
||||
.In dev/pci/pcireg.h
|
||||
.In dev/pci/pcivar.h
|
||||
.In dev/pci/pci_iov.h
|
||||
.Ft int
|
||||
.Fn PCI_INIT_IOV "device_t dev" "uint16_t num_vfs" "const nvlist_t *pf_config"
|
||||
.Fn PCI_IOV_INIT "device_t dev" "uint16_t num_vfs" "const nvlist_t *pf_config"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn PCI_INIT_IOV
|
||||
.Fn PCI_IOV_INIT
|
||||
method is called by the PCI Single-Root I/O Virtualization (SR-IOV)
|
||||
infrastucture when the user requests that SR-IOV be enabled on a Physical
|
||||
Function (PF).
|
||||
@ -70,7 +69,7 @@ valid values specified in the schema.
|
||||
.Pp
|
||||
If this method returns successfully, then this method will not be called again
|
||||
on the same device until after a call to
|
||||
.Xr PCI_UNINIT_IOV .
|
||||
.Xr PCI_IOV_UNINIT .
|
||||
.Sh RETURN VALUES
|
||||
Returns 0 on success, otherwise an appropriate error is returned.
|
||||
If this method returns an error then the SR-IOV configuration will be aborted
|
||||
@ -79,8 +78,8 @@ and no VFs will be created.
|
||||
.Xr nv 9 ,
|
||||
.Xr pci 9 ,
|
||||
.Xr pci_iov_schema 9 ,
|
||||
.Xr PCI_ADD_VF 9 ,
|
||||
.Xr PCI_UNINIT_IOV 9
|
||||
.Xr PCI_IOV_ADD_VF 9 ,
|
||||
.Xr PCI_IOV_UNINIT 9
|
||||
.Sh AUTHORS
|
||||
This manual page was written by
|
||||
.An Ryan Stone Aq Mt rstone@FreeBSD.org .
|
@ -25,21 +25,20 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 24, 2014
|
||||
.Dt PCI_UNINIT_IOV 9
|
||||
.Dd May 28, 2015
|
||||
.Dt PCI_IOV_UNINIT 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm PCI_UNINIT_IOV
|
||||
.Nm PCI_IOV_UNINIT
|
||||
.Nd disable SR-IOV on a PF device
|
||||
.Sh SYNOPSIS
|
||||
.In sys/bus.h
|
||||
.In dev/pci/pcireg.h
|
||||
.In dev/pci/pcivar.h
|
||||
.In dev/pci/pci_iov.h
|
||||
.Ft void
|
||||
.Fn PCI_UNINIT_IOV "device_t dev"
|
||||
.Fn PCI_IOV_UNINIT "device_t dev"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn PCI_UNINIT_IOV
|
||||
.Fn PCI_IOV_UNINIT
|
||||
method is called by the PCI Single-Root I/O Virtualization (SR-IOV)
|
||||
infrastructure when the user requests that SR-IOV be disabled on a Physical
|
||||
Function (PF).
|
||||
@ -48,17 +47,17 @@ resources that it has allocated and disable any device-specific SR-IOV
|
||||
configuration in the device.
|
||||
.Pp
|
||||
This method will only be called following a successful call to
|
||||
.Xr PCI_INIT_IOV .
|
||||
.Xr PCI_IOV_INIT .
|
||||
It is not guaranteed that
|
||||
.Xr PCI_ADD_VF
|
||||
.Xr PCI_IOV_ADD_VF
|
||||
will have been called for any Virtual Function (VF) after the call to
|
||||
.Xr PCI_INIT_IOV
|
||||
.Xr PCI_IOV_INIT
|
||||
and before the call to
|
||||
.Nm .
|
||||
.Sh SEE ALSO
|
||||
.Xr pci 9 ,
|
||||
.Xr PCI_ADD_VF 9 ,
|
||||
.Xr PCI_INIT_IOV 9
|
||||
.Xr PCI_IOV_ADD_VF 9 ,
|
||||
.Xr PCI_IOV_INIT 9
|
||||
.Sh AUTHORS
|
||||
This manual page was written by
|
||||
.An Ryan Stone Aq Mt rstone@FreeBSD.org .
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 24, 2014
|
||||
.Dd May 28, 2015
|
||||
.Dt PCI 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -97,10 +97,6 @@
|
||||
.Ft int
|
||||
.Fn pci_get_vpd_readonly "device_t dev" "const char *kw" "const char **vptr"
|
||||
.Ft int
|
||||
.Fn pci_iov_attach "device_t dev" "nvlist_t *pf_schema" "nvlist_t *vf_schema"
|
||||
.Ft int
|
||||
.Fn pci_iov_detach "device_t dev"
|
||||
.Ft int
|
||||
.Fn pci_msi_count "device_t dev"
|
||||
.Ft int
|
||||
.Fn pci_msix_count "device_t dev"
|
||||
@ -122,6 +118,11 @@
|
||||
.Fn pci_set_powerstate "device_t dev" "int state"
|
||||
.Ft void
|
||||
.Fn pci_write_config "device_t dev" "int reg" "uint32_t val" "int width"
|
||||
.In dev/pci/pci_iov.h
|
||||
.Ft int
|
||||
.Fn pci_iov_attach "device_t dev" "nvlist_t *pf_schema" "nvlist_t *vf_schema"
|
||||
.Ft int
|
||||
.Fn pci_iov_detach "device_t dev"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
@ -446,10 +447,10 @@ function is used to advertise that the given device
|
||||
supports PCI Single-Root I/O Virtualization
|
||||
.Po SR-IOV Pc .
|
||||
A driver that supports SR-IOV must implement the
|
||||
.Xr PCI_INIT_IOV 9 ,
|
||||
.Xr PCI_ADD_VF 9
|
||||
.Xr PCI_IOV_INIT 9 ,
|
||||
.Xr PCI_IOV_ADD_VF 9
|
||||
and
|
||||
.Xr PCI_UNIT_IOV 9
|
||||
.Xr PCI_IOV_UNINIT 9
|
||||
methods.
|
||||
This function should be called during the
|
||||
.Xr DEVICE_ATTACH 9
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 25, 2014
|
||||
.Dd May 28, 2015
|
||||
.Dt pci_iov_schema 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -258,8 +258,8 @@ The
|
||||
function returns a pointer to the allocated schema, or NULL if a failure occurs.
|
||||
.Sh SEE ALSO
|
||||
.Xr pci 9 ,
|
||||
.Xr PCI_ADD_VF 9 ,
|
||||
.Xr PCI_INIT_IOV 9
|
||||
.Xr PCI_IOV_ADD_VF 9 ,
|
||||
.Xr PCI_IOV_INIT 9
|
||||
.Sh AUTHORS
|
||||
This manual page was written by
|
||||
.An Ryan Stone Aq rstone@FreeBSD.org .
|
||||
|
@ -9,8 +9,12 @@
|
||||
|
||||
.include <src.opts.mk>
|
||||
|
||||
ROOTSRCDIR= ${.MAKE.MAKEFILES:M*/src.libnames.mk:H:H:H}
|
||||
ROOTOBJDIR= ${.OBJDIR:S/${.CURDIR}//}${ROOTSRCDIR}
|
||||
.if ${.OBJDIR:S,${.CURDIR},,} != ${.OBJDIR}
|
||||
ROOTOBJDIR= ${.OBJDIR:S,${.CURDIR},,}${SRCTOP}
|
||||
.elif defined(OBJTOP) && ${.OBJDIR:M${OBJTOP}*} != ""
|
||||
ROOTOBJDIR= ${OBJTOP}
|
||||
.endif
|
||||
|
||||
_PRIVATELIBS= \
|
||||
atf_c \
|
||||
atf_cxx \
|
||||
|
@ -5,13 +5,16 @@
|
||||
# to preserve historical (and useful) behavior. Changes here need to
|
||||
# be reflected there so SRCCONF isn't included multiple times.
|
||||
|
||||
# make sure this is defined in a consistent manner
|
||||
SRCTOP:= ${.PARSEDIR:tA:H:H}
|
||||
|
||||
# Allow user to configure things that only effect src tree builds.
|
||||
SRCCONF?= /etc/src.conf
|
||||
.if (exists(${SRCCONF}) || ${SRCCONF} != "/etc/src.conf") && !target(_srcconf_included_)
|
||||
.include "${SRCCONF}"
|
||||
.sinclude "${SRCCONF}"
|
||||
_srcconf_included_: .NOTMAIN
|
||||
.endif
|
||||
# If we were found via .../share/mk we need to replace that in
|
||||
# If we were found via .../share/mk we need to replace that
|
||||
# with ${.PARSEDIR:tA} so that we can be found by
|
||||
# sub-makes launched from objdir.
|
||||
.if ${.MAKEFLAGS:M.../share/mk} != ""
|
||||
|
@ -8,9 +8,9 @@ CSCOPEDIRS= boot bsm cam cddl compat conf contrib crypto ddb dev fs gdb \
|
||||
rpc security sys ufs vm xdr xen ${CSCOPE_ARCHDIR}
|
||||
.if !defined(CSCOPE_ARCHDIR)
|
||||
.if defined(ALL_ARCH)
|
||||
CSCOPE_ARCHDIR = amd64 arm i386 mips pc98 powerpc sparc64 x86
|
||||
CSCOPE_ARCHDIR = amd64 arm arm64 i386 mips pc98 powerpc sparc64 x86
|
||||
.else
|
||||
CSCOPE_ARCHDIR = ${MACHINE}
|
||||
CSCOPE_ARCHDIR = ${MACHINE}
|
||||
.if ${MACHINE} != ${MACHINE_CPUARCH}
|
||||
CSCOPE_ARCHDIR += ${MACHINE_CPUARCH}
|
||||
.endif
|
||||
|
@ -381,7 +381,7 @@ caddr_t CADDR1 = 0;
|
||||
|
||||
static int pmap_flags = PMAP_PDE_SUPERPAGE; /* flags for x86 pmaps */
|
||||
|
||||
int pmap_pcid_enabled = 0;
|
||||
int pmap_pcid_enabled = 1;
|
||||
SYSCTL_INT(_vm_pmap, OID_AUTO, pcid_enabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
|
||||
&pmap_pcid_enabled, 0, "Is TLB Context ID enabled ?");
|
||||
int invpcid_works = 0;
|
||||
@ -3935,7 +3935,6 @@ pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va,
|
||||
pd_entry_t newpde;
|
||||
pt_entry_t *firstpte, oldpte, pa, *pte;
|
||||
pt_entry_t PG_G, PG_A, PG_M, PG_RW, PG_V;
|
||||
vm_offset_t oldpteva;
|
||||
vm_page_t mpte;
|
||||
int PG_PTE_CACHE;
|
||||
|
||||
@ -3995,10 +3994,9 @@ setpte:
|
||||
if (!atomic_cmpset_long(pte, oldpte, oldpte & ~PG_RW))
|
||||
goto setpte;
|
||||
oldpte &= ~PG_RW;
|
||||
oldpteva = (oldpte & PG_FRAME & PDRMASK) |
|
||||
(va & ~PDRMASK);
|
||||
CTR2(KTR_PMAP, "pmap_promote_pde: protect for va %#lx"
|
||||
" in pmap %p", oldpteva, pmap);
|
||||
" in pmap %p", (oldpte & PG_FRAME & PDRMASK) |
|
||||
(va & ~PDRMASK), pmap);
|
||||
}
|
||||
if ((oldpte & PG_PTE_PROMOTE) != (newpde & PG_PTE_PROMOTE)) {
|
||||
atomic_add_long(&pmap_pde_p_failures, 1);
|
||||
|
@ -155,7 +155,6 @@ cpu_fork(td1, p2, td2, flags)
|
||||
struct pcb *pcb2;
|
||||
struct mdproc *mdp1, *mdp2;
|
||||
struct proc_ldt *pldt;
|
||||
pmap_t pmap2;
|
||||
|
||||
p1 = td1->td_proc;
|
||||
if ((flags & RFPROC) == 0) {
|
||||
@ -218,7 +217,6 @@ cpu_fork(td1, p2, td2, flags)
|
||||
* Set registers for trampoline to user mode. Leave space for the
|
||||
* return address on stack. These are the kernel mode register values.
|
||||
*/
|
||||
pmap2 = vmspace_pmap(p2->p_vmspace);
|
||||
pcb2->pcb_r12 = (register_t)fork_return; /* fork_trampoline argument */
|
||||
pcb2->pcb_rbp = 0;
|
||||
pcb2->pcb_rsp = (register_t)td2->td_frame - sizeof(void *);
|
||||
|
@ -79,11 +79,9 @@ __FBSDID("$FreeBSD$");
|
||||
int
|
||||
fill_regs32(struct thread *td, struct reg32 *regs)
|
||||
{
|
||||
struct pcb *pcb;
|
||||
struct trapframe *tp;
|
||||
|
||||
tp = td->td_frame;
|
||||
pcb = td->td_pcb;
|
||||
if (tp->tf_flags & TF_HASSEGS) {
|
||||
regs->r_gs = tp->tf_gs;
|
||||
regs->r_fs = tp->tf_fs;
|
||||
@ -113,18 +111,16 @@ fill_regs32(struct thread *td, struct reg32 *regs)
|
||||
int
|
||||
set_regs32(struct thread *td, struct reg32 *regs)
|
||||
{
|
||||
struct pcb *pcb;
|
||||
struct trapframe *tp;
|
||||
|
||||
tp = td->td_frame;
|
||||
if (!EFL_SECURE(regs->r_eflags, tp->tf_rflags) || !CS_SECURE(regs->r_cs))
|
||||
return (EINVAL);
|
||||
pcb = td->td_pcb;
|
||||
tp->tf_gs = regs->r_gs;
|
||||
tp->tf_fs = regs->r_fs;
|
||||
tp->tf_es = regs->r_es;
|
||||
tp->tf_ds = regs->r_ds;
|
||||
set_pcb_flags(pcb, PCB_FULL_IRET);
|
||||
set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
|
||||
tp->tf_flags = TF_HASSEGS;
|
||||
tp->tf_rdi = regs->r_edi;
|
||||
tp->tf_rsi = regs->r_esi;
|
||||
|
@ -120,13 +120,18 @@ struct vm_object;
|
||||
struct vm_guest_paging;
|
||||
struct pmap;
|
||||
|
||||
struct vm_eventinfo {
|
||||
void *rptr; /* rendezvous cookie */
|
||||
int *sptr; /* suspend cookie */
|
||||
int *iptr; /* reqidle cookie */
|
||||
};
|
||||
|
||||
typedef int (*vmm_init_func_t)(int ipinum);
|
||||
typedef int (*vmm_cleanup_func_t)(void);
|
||||
typedef void (*vmm_resume_func_t)(void);
|
||||
typedef void * (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap);
|
||||
typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip,
|
||||
struct pmap *pmap, void *rendezvous_cookie,
|
||||
void *suspend_cookie);
|
||||
struct pmap *pmap, struct vm_eventinfo *info);
|
||||
typedef void (*vmi_cleanup_func_t)(void *vmi);
|
||||
typedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num,
|
||||
uint64_t *retval);
|
||||
@ -208,6 +213,7 @@ struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);
|
||||
void vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip);
|
||||
void vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip);
|
||||
void vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip);
|
||||
void vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip);
|
||||
|
||||
#ifdef _SYS__CPUSET_H_
|
||||
/*
|
||||
@ -232,17 +238,24 @@ cpuset_t vm_suspended_cpus(struct vm *vm);
|
||||
#endif /* _SYS__CPUSET_H_ */
|
||||
|
||||
static __inline int
|
||||
vcpu_rendezvous_pending(void *rendezvous_cookie)
|
||||
vcpu_rendezvous_pending(struct vm_eventinfo *info)
|
||||
{
|
||||
|
||||
return (*(uintptr_t *)rendezvous_cookie != 0);
|
||||
return (*((uintptr_t *)(info->rptr)) != 0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
vcpu_suspended(void *suspend_cookie)
|
||||
vcpu_suspended(struct vm_eventinfo *info)
|
||||
{
|
||||
|
||||
return (*(int *)suspend_cookie);
|
||||
return (*info->sptr);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
vcpu_reqidle(struct vm_eventinfo *info)
|
||||
{
|
||||
|
||||
return (*info->iptr);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -506,6 +519,7 @@ enum vm_exitcode {
|
||||
VM_EXITCODE_MONITOR,
|
||||
VM_EXITCODE_MWAIT,
|
||||
VM_EXITCODE_SVM,
|
||||
VM_EXITCODE_REQIDLE,
|
||||
VM_EXITCODE_MAX
|
||||
};
|
||||
|
||||
|
@ -1900,7 +1900,7 @@ enable_gintr(void)
|
||||
*/
|
||||
static int
|
||||
svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap,
|
||||
void *rend_cookie, void *suspended_cookie)
|
||||
struct vm_eventinfo *evinfo)
|
||||
{
|
||||
struct svm_regctx *gctx;
|
||||
struct svm_softc *svm_sc;
|
||||
@ -1975,18 +1975,24 @@ svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap,
|
||||
*/
|
||||
disable_gintr();
|
||||
|
||||
if (vcpu_suspended(suspended_cookie)) {
|
||||
if (vcpu_suspended(evinfo)) {
|
||||
enable_gintr();
|
||||
vm_exit_suspended(vm, vcpu, state->rip);
|
||||
break;
|
||||
}
|
||||
|
||||
if (vcpu_rendezvous_pending(rend_cookie)) {
|
||||
if (vcpu_rendezvous_pending(evinfo)) {
|
||||
enable_gintr();
|
||||
vm_exit_rendezvous(vm, vcpu, state->rip);
|
||||
break;
|
||||
}
|
||||
|
||||
if (vcpu_reqidle(evinfo)) {
|
||||
enable_gintr();
|
||||
vm_exit_reqidle(vm, vcpu, state->rip);
|
||||
break;
|
||||
}
|
||||
|
||||
/* We are asked to give the cpu by scheduler. */
|
||||
if (vcpu_should_yield(vm, vcpu)) {
|
||||
enable_gintr();
|
||||
|
@ -2554,7 +2554,7 @@ vmx_exit_handle_nmi(struct vmx *vmx, int vcpuid, struct vm_exit *vmexit)
|
||||
|
||||
static int
|
||||
vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap,
|
||||
void *rendezvous_cookie, void *suspend_cookie)
|
||||
struct vm_eventinfo *evinfo)
|
||||
{
|
||||
int rc, handled, launched;
|
||||
struct vmx *vmx;
|
||||
@ -2623,18 +2623,24 @@ vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap,
|
||||
* vmx_inject_interrupts() can suspend the vcpu due to a
|
||||
* triple fault.
|
||||
*/
|
||||
if (vcpu_suspended(suspend_cookie)) {
|
||||
if (vcpu_suspended(evinfo)) {
|
||||
enable_intr();
|
||||
vm_exit_suspended(vmx->vm, vcpu, rip);
|
||||
break;
|
||||
}
|
||||
|
||||
if (vcpu_rendezvous_pending(rendezvous_cookie)) {
|
||||
if (vcpu_rendezvous_pending(evinfo)) {
|
||||
enable_intr();
|
||||
vm_exit_rendezvous(vmx->vm, vcpu, rip);
|
||||
break;
|
||||
}
|
||||
|
||||
if (vcpu_reqidle(evinfo)) {
|
||||
enable_intr();
|
||||
vm_exit_reqidle(vmx->vm, vcpu, rip);
|
||||
break;
|
||||
}
|
||||
|
||||
if (vcpu_should_yield(vm, vcpu)) {
|
||||
enable_intr();
|
||||
vm_exit_astpending(vmx->vm, vcpu, rip);
|
||||
|
@ -95,6 +95,7 @@ struct vcpu {
|
||||
struct mtx mtx; /* (o) protects 'state' and 'hostcpu' */
|
||||
enum vcpu_state state; /* (o) vcpu state */
|
||||
int hostcpu; /* (o) vcpu's host cpu */
|
||||
int reqidle; /* (i) request vcpu to idle */
|
||||
struct vlapic *vlapic; /* (i) APIC device model */
|
||||
enum x2apic_state x2apic_state; /* (i) APIC mode */
|
||||
uint64_t exitintinfo; /* (i) events pending at VM exit */
|
||||
@ -164,8 +165,8 @@ static struct vmm_ops *ops;
|
||||
#define VMM_RESUME() (ops != NULL ? (*ops->resume)() : 0)
|
||||
|
||||
#define VMINIT(vm, pmap) (ops != NULL ? (*ops->vminit)(vm, pmap): NULL)
|
||||
#define VMRUN(vmi, vcpu, rip, pmap, rptr, sptr) \
|
||||
(ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip, pmap, rptr, sptr) : ENXIO)
|
||||
#define VMRUN(vmi, vcpu, rip, pmap, evinfo) \
|
||||
(ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip, pmap, evinfo) : ENXIO)
|
||||
#define VMCLEANUP(vmi) (ops != NULL ? (*ops->vmcleanup)(vmi) : NULL)
|
||||
#define VMSPACE_ALLOC(min, max) \
|
||||
(ops != NULL ? (*ops->vmspace_alloc)(min, max) : NULL)
|
||||
@ -221,6 +222,28 @@ TUNABLE_INT("hw.vmm.force_iommu", &vmm_force_iommu);
|
||||
SYSCTL_INT(_hw_vmm, OID_AUTO, force_iommu, CTLFLAG_RDTUN, &vmm_force_iommu, 0,
|
||||
"Force use of I/O MMU even if no passthrough devices were found.");
|
||||
|
||||
static void vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr);
|
||||
|
||||
#ifdef KTR
|
||||
static const char *
|
||||
vcpu_state2str(enum vcpu_state state)
|
||||
{
|
||||
|
||||
switch (state) {
|
||||
case VCPU_IDLE:
|
||||
return ("idle");
|
||||
case VCPU_FROZEN:
|
||||
return ("frozen");
|
||||
case VCPU_RUNNING:
|
||||
return ("running");
|
||||
case VCPU_SLEEPING:
|
||||
return ("sleeping");
|
||||
default:
|
||||
return ("unknown");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
vcpu_cleanup(struct vm *vm, int i, bool destroy)
|
||||
{
|
||||
@ -255,6 +278,7 @@ vcpu_init(struct vm *vm, int vcpu_id, bool create)
|
||||
|
||||
vcpu->vlapic = VLAPIC_INIT(vm->cookie, vcpu_id);
|
||||
vm_set_x2apic_state(vm, vcpu_id, X2APIC_DISABLED);
|
||||
vcpu->reqidle = 0;
|
||||
vcpu->exitintinfo = 0;
|
||||
vcpu->nmi_pending = 0;
|
||||
vcpu->extint_pending = 0;
|
||||
@ -980,11 +1004,13 @@ save_guest_fpustate(struct vcpu *vcpu)
|
||||
static VMM_STAT(VCPU_IDLE_TICKS, "number of ticks vcpu was idle");
|
||||
|
||||
static int
|
||||
vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
|
||||
vcpu_set_state_locked(struct vm *vm, int vcpuid, enum vcpu_state newstate,
|
||||
bool from_idle)
|
||||
{
|
||||
struct vcpu *vcpu;
|
||||
int error;
|
||||
|
||||
vcpu = &vm->vcpu[vcpuid];
|
||||
vcpu_assert_locked(vcpu);
|
||||
|
||||
/*
|
||||
@ -993,8 +1019,13 @@ vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
|
||||
* ioctl() operating on a vcpu at any point.
|
||||
*/
|
||||
if (from_idle) {
|
||||
while (vcpu->state != VCPU_IDLE)
|
||||
while (vcpu->state != VCPU_IDLE) {
|
||||
vcpu->reqidle = 1;
|
||||
vcpu_notify_event_locked(vcpu, false);
|
||||
VCPU_CTR1(vm, vcpuid, "vcpu state change from %s to "
|
||||
"idle requested", vcpu_state2str(vcpu->state));
|
||||
msleep_spin(&vcpu->state, &vcpu->mtx, "vmstat", hz);
|
||||
}
|
||||
} else {
|
||||
KASSERT(vcpu->state != VCPU_IDLE, ("invalid transition from "
|
||||
"vcpu idle state"));
|
||||
@ -1031,6 +1062,9 @@ vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
|
||||
if (error)
|
||||
return (EBUSY);
|
||||
|
||||
VCPU_CTR2(vm, vcpuid, "vcpu state changed from %s to %s",
|
||||
vcpu_state2str(vcpu->state), vcpu_state2str(newstate));
|
||||
|
||||
vcpu->state = newstate;
|
||||
if (newstate == VCPU_RUNNING)
|
||||
vcpu->hostcpu = curcpu;
|
||||
@ -1053,11 +1087,11 @@ vcpu_require_state(struct vm *vm, int vcpuid, enum vcpu_state newstate)
|
||||
}
|
||||
|
||||
static void
|
||||
vcpu_require_state_locked(struct vcpu *vcpu, enum vcpu_state newstate)
|
||||
vcpu_require_state_locked(struct vm *vm, int vcpuid, enum vcpu_state newstate)
|
||||
{
|
||||
int error;
|
||||
|
||||
if ((error = vcpu_set_state_locked(vcpu, newstate, false)) != 0)
|
||||
if ((error = vcpu_set_state_locked(vm, vcpuid, newstate, false)) != 0)
|
||||
panic("Error %d setting state to %d", error, newstate);
|
||||
}
|
||||
|
||||
@ -1145,7 +1179,7 @@ vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu)
|
||||
* vcpu returned from VMRUN() and before it acquired the
|
||||
* vcpu lock above.
|
||||
*/
|
||||
if (vm->rendezvous_func != NULL || vm->suspend)
|
||||
if (vm->rendezvous_func != NULL || vm->suspend || vcpu->reqidle)
|
||||
break;
|
||||
if (vm_nmi_pending(vm, vcpuid))
|
||||
break;
|
||||
@ -1182,13 +1216,13 @@ vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu)
|
||||
}
|
||||
|
||||
t = ticks;
|
||||
vcpu_require_state_locked(vcpu, VCPU_SLEEPING);
|
||||
vcpu_require_state_locked(vm, vcpuid, VCPU_SLEEPING);
|
||||
/*
|
||||
* XXX msleep_spin() cannot be interrupted by signals so
|
||||
* wake up periodically to check pending signals.
|
||||
*/
|
||||
msleep_spin(vcpu, &vcpu->mtx, wmesg, hz);
|
||||
vcpu_require_state_locked(vcpu, VCPU_FROZEN);
|
||||
vcpu_require_state_locked(vm, vcpuid, VCPU_FROZEN);
|
||||
vmm_stat_incr(vm, vcpuid, VCPU_IDLE_TICKS, ticks - t);
|
||||
}
|
||||
|
||||
@ -1350,9 +1384,9 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu)
|
||||
|
||||
if (vm->rendezvous_func == NULL) {
|
||||
VCPU_CTR0(vm, vcpuid, "Sleeping during suspend");
|
||||
vcpu_require_state_locked(vcpu, VCPU_SLEEPING);
|
||||
vcpu_require_state_locked(vm, vcpuid, VCPU_SLEEPING);
|
||||
msleep_spin(vcpu, &vcpu->mtx, "vmsusp", hz);
|
||||
vcpu_require_state_locked(vcpu, VCPU_FROZEN);
|
||||
vcpu_require_state_locked(vm, vcpuid, VCPU_FROZEN);
|
||||
} else {
|
||||
VCPU_CTR0(vm, vcpuid, "Rendezvous during suspend");
|
||||
vcpu_unlock(vcpu);
|
||||
@ -1375,6 +1409,19 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
vm_handle_reqidle(struct vm *vm, int vcpuid, bool *retu)
|
||||
{
|
||||
struct vcpu *vcpu = &vm->vcpu[vcpuid];
|
||||
|
||||
vcpu_lock(vcpu);
|
||||
KASSERT(vcpu->reqidle, ("invalid vcpu reqidle %d", vcpu->reqidle));
|
||||
vcpu->reqidle = 0;
|
||||
vcpu_unlock(vcpu);
|
||||
*retu = true;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
vm_suspend(struct vm *vm, enum vm_suspend_how how)
|
||||
{
|
||||
@ -1431,6 +1478,18 @@ vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip)
|
||||
vmm_stat_incr(vm, vcpuid, VMEXIT_RENDEZVOUS, 1);
|
||||
}
|
||||
|
||||
void
|
||||
vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip)
|
||||
{
|
||||
struct vm_exit *vmexit;
|
||||
|
||||
vmexit = vm_exitinfo(vm, vcpuid);
|
||||
vmexit->rip = rip;
|
||||
vmexit->inst_length = 0;
|
||||
vmexit->exitcode = VM_EXITCODE_REQIDLE;
|
||||
vmm_stat_incr(vm, vcpuid, VMEXIT_REQIDLE, 1);
|
||||
}
|
||||
|
||||
void
|
||||
vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip)
|
||||
{
|
||||
@ -1446,6 +1505,7 @@ vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip)
|
||||
int
|
||||
vm_run(struct vm *vm, struct vm_run *vmrun)
|
||||
{
|
||||
struct vm_eventinfo evinfo;
|
||||
int error, vcpuid;
|
||||
struct vcpu *vcpu;
|
||||
struct pcb *pcb;
|
||||
@ -1453,7 +1513,6 @@ vm_run(struct vm *vm, struct vm_run *vmrun)
|
||||
struct vm_exit *vme;
|
||||
bool retu, intr_disabled;
|
||||
pmap_t pmap;
|
||||
void *rptr, *sptr;
|
||||
|
||||
vcpuid = vmrun->cpuid;
|
||||
|
||||
@ -1466,11 +1525,12 @@ vm_run(struct vm *vm, struct vm_run *vmrun)
|
||||
if (CPU_ISSET(vcpuid, &vm->suspended_cpus))
|
||||
return (EINVAL);
|
||||
|
||||
rptr = &vm->rendezvous_func;
|
||||
sptr = &vm->suspend;
|
||||
pmap = vmspace_pmap(vm->vmspace);
|
||||
vcpu = &vm->vcpu[vcpuid];
|
||||
vme = &vcpu->exitinfo;
|
||||
evinfo.rptr = &vm->rendezvous_func;
|
||||
evinfo.sptr = &vm->suspend;
|
||||
evinfo.iptr = &vcpu->reqidle;
|
||||
restart:
|
||||
critical_enter();
|
||||
|
||||
@ -1485,7 +1545,7 @@ restart:
|
||||
restore_guest_fpustate(vcpu);
|
||||
|
||||
vcpu_require_state(vm, vcpuid, VCPU_RUNNING);
|
||||
error = VMRUN(vm->cookie, vcpuid, vcpu->nextrip, pmap, rptr, sptr);
|
||||
error = VMRUN(vm->cookie, vcpuid, vcpu->nextrip, pmap, &evinfo);
|
||||
vcpu_require_state(vm, vcpuid, VCPU_FROZEN);
|
||||
|
||||
save_guest_fpustate(vcpu);
|
||||
@ -1498,6 +1558,9 @@ restart:
|
||||
retu = false;
|
||||
vcpu->nextrip = vme->rip + vme->inst_length;
|
||||
switch (vme->exitcode) {
|
||||
case VM_EXITCODE_REQIDLE:
|
||||
error = vm_handle_reqidle(vm, vcpuid, &retu);
|
||||
break;
|
||||
case VM_EXITCODE_SUSPENDED:
|
||||
error = vm_handle_suspend(vm, vcpuid, &retu);
|
||||
break;
|
||||
@ -1536,6 +1599,8 @@ restart:
|
||||
if (error == 0 && retu == false)
|
||||
goto restart;
|
||||
|
||||
VCPU_CTR2(vm, vcpuid, "retu %d/%d", error, vme->exitcode);
|
||||
|
||||
/* copy the exit information */
|
||||
bcopy(vme, &vmrun->vm_exit, sizeof(struct vm_exit));
|
||||
return (error);
|
||||
@ -2072,7 +2137,7 @@ vcpu_set_state(struct vm *vm, int vcpuid, enum vcpu_state newstate,
|
||||
vcpu = &vm->vcpu[vcpuid];
|
||||
|
||||
vcpu_lock(vcpu);
|
||||
error = vcpu_set_state_locked(vcpu, newstate, from_idle);
|
||||
error = vcpu_set_state_locked(vm, vcpuid, newstate, from_idle);
|
||||
vcpu_unlock(vcpu);
|
||||
|
||||
return (error);
|
||||
@ -2168,15 +2233,11 @@ vm_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state)
|
||||
* - If the vcpu is running on a different host_cpu then an IPI will be directed
|
||||
* to the host_cpu to cause the vcpu to trap into the hypervisor.
|
||||
*/
|
||||
void
|
||||
vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr)
|
||||
static void
|
||||
vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr)
|
||||
{
|
||||
int hostcpu;
|
||||
struct vcpu *vcpu;
|
||||
|
||||
vcpu = &vm->vcpu[vcpuid];
|
||||
|
||||
vcpu_lock(vcpu);
|
||||
hostcpu = vcpu->hostcpu;
|
||||
if (vcpu->state == VCPU_RUNNING) {
|
||||
KASSERT(hostcpu != NOCPU, ("vcpu running on invalid hostcpu"));
|
||||
@ -2201,6 +2262,15 @@ vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr)
|
||||
if (vcpu->state == VCPU_SLEEPING)
|
||||
wakeup_one(vcpu);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr)
|
||||
{
|
||||
struct vcpu *vcpu = &vm->vcpu[vcpuid];
|
||||
|
||||
vcpu_lock(vcpu);
|
||||
vcpu_notify_event_locked(vcpu, lapic_intr);
|
||||
vcpu_unlock(vcpu);
|
||||
}
|
||||
|
||||
|
@ -164,6 +164,7 @@ VMM_STAT(VMEXIT_NESTED_FAULT, "vm exits due to nested page fault");
|
||||
VMM_STAT(VMEXIT_INST_EMUL, "vm exits for instruction emulation");
|
||||
VMM_STAT(VMEXIT_UNKNOWN, "number of vm exits for unknown reason");
|
||||
VMM_STAT(VMEXIT_ASTPENDING, "number of times astpending at exit");
|
||||
VMM_STAT(VMEXIT_REQIDLE, "number of times idle requested at exit");
|
||||
VMM_STAT(VMEXIT_USERSPACE, "number of vm exits handled in userspace");
|
||||
VMM_STAT(VMEXIT_RENDEZVOUS, "number of times rendezvous pending at exit");
|
||||
VMM_STAT(VMEXIT_EXCEPTION, "number of vm exits due to exceptions");
|
||||
|
@ -157,4 +157,5 @@ VMM_STAT_DECLARE(VMEXIT_ASTPENDING);
|
||||
VMM_STAT_DECLARE(VMEXIT_USERSPACE);
|
||||
VMM_STAT_DECLARE(VMEXIT_RENDEZVOUS);
|
||||
VMM_STAT_DECLARE(VMEXIT_EXCEPTION);
|
||||
VMM_STAT_DECLARE(VMEXIT_REQIDLE);
|
||||
#endif
|
||||
|
@ -697,6 +697,7 @@ zfsctl_unmount_snap(zfs_snapentry_t *sep, int fflags, cred_t *cr)
|
||||
|
||||
return (0);
|
||||
#else
|
||||
vfs_ref(vn_mountedvfs(svp));
|
||||
return (dounmount(vn_mountedvfs(svp), fflags, curthread));
|
||||
#endif
|
||||
}
|
||||
|
@ -3481,6 +3481,7 @@ zfs_unmount_snap(const char *snapname)
|
||||
#ifdef illumos
|
||||
(void) dounmount(vfsp, MS_FORCE, kcred);
|
||||
#else
|
||||
vfs_ref(vfsp);
|
||||
(void) dounmount(vfsp, MS_FORCE, curthread);
|
||||
#endif
|
||||
return (0);
|
||||
|
@ -2314,8 +2314,10 @@ bail:
|
||||
* Since we couldn't setup the sa framework, try to force
|
||||
* unmount this file system.
|
||||
*/
|
||||
if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0)
|
||||
if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0) {
|
||||
vfs_ref(zfsvfs->z_vfs);
|
||||
(void) dounmount(zfsvfs->z_vfs, MS_FORCE, curthread);
|
||||
}
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
@ -1427,6 +1427,8 @@ dev/hptiop/hptiop.c optional hptiop scbus
|
||||
dev/hwpmc/hwpmc_logging.c optional hwpmc
|
||||
dev/hwpmc/hwpmc_mod.c optional hwpmc
|
||||
dev/hwpmc/hwpmc_soft.c optional hwpmc
|
||||
dev/ichiic/ig4_iic.c optional ichiic
|
||||
dev/ichiic/ig4_pci.c optional ichiic pci
|
||||
dev/ichsmb/ichsmb.c optional ichsmb
|
||||
dev/ichsmb/ichsmb_pci.c optional ichsmb pci
|
||||
dev/ida/ida.c optional ida
|
||||
@ -2024,6 +2026,7 @@ dev/pci/isa_pci.c optional pci isa
|
||||
dev/pci/pci.c optional pci
|
||||
dev/pci/pci_if.m standard
|
||||
dev/pci/pci_iov.c optional pci pci_iov
|
||||
dev/pci/pci_iov_if.m standard
|
||||
dev/pci/pci_iov_schema.c optional pci pci_iov
|
||||
dev/pci/pci_pci.c optional pci
|
||||
dev/pci/pci_subr.c optional pci
|
||||
|
@ -349,7 +349,7 @@ MFILES?= dev/acpica/acpi_if.m dev/acpi_support/acpi_wmi_if.m \
|
||||
dev/mbox/mbox_if.m dev/mmc/mmcbr_if.m dev/mmc/mmcbus_if.m \
|
||||
dev/mii/miibus_if.m dev/mvs/mvs_if.m dev/ofw/ofw_bus_if.m \
|
||||
dev/pccard/card_if.m dev/pccard/power_if.m dev/pci/pci_if.m \
|
||||
dev/pci/pcib_if.m dev/ppbus/ppbus_if.m \
|
||||
dev/pci/pci_iov_if.m dev/pci/pcib_if.m dev/ppbus/ppbus_if.m \
|
||||
dev/sdhci/sdhci_if.m dev/smbus/smbus_if.m dev/spibus/spibus_if.m \
|
||||
dev/sound/pci/hda/hdac_if.m \
|
||||
dev/sound/pcm/ac97_if.m dev/sound/pcm/channel_if.m \
|
||||
|
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_acpi.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <machine/cpufunc.h>
|
||||
@ -261,6 +262,37 @@ static struct {
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Per-model default list of event mask.
|
||||
*/
|
||||
#define ACPI_IBM_HKEY_RFKILL_MASK (1 << 4)
|
||||
#define ACPI_IBM_HKEY_DSWITCH_MASK (1 << 6)
|
||||
#define ACPI_IBM_HKEY_BRIGHTNESS_UP_MASK (1 << 15)
|
||||
#define ACPI_IBM_HKEY_BRIGHTNESS_DOWN_MASK (1 << 16)
|
||||
#define ACPI_IBM_HKEY_SEARCH_MASK (1 << 18)
|
||||
#define ACPI_IBM_HKEY_MICMUTE_MASK (1 << 26)
|
||||
#define ACPI_IBM_HKEY_SETTINGS_MASK (1 << 28)
|
||||
#define ACPI_IBM_HKEY_VIEWOPEN_MASK (1 << 30)
|
||||
#define ACPI_IBM_HKEY_VIEWALL_MASK (1 << 31)
|
||||
|
||||
struct acpi_ibm_models {
|
||||
const char *maker;
|
||||
const char *product;
|
||||
uint32_t eventmask;
|
||||
} acpi_ibm_models[] = {
|
||||
{ "LENOVO", "20BSCTO1WW",
|
||||
ACPI_IBM_HKEY_RFKILL_MASK |
|
||||
ACPI_IBM_HKEY_DSWITCH_MASK |
|
||||
ACPI_IBM_HKEY_BRIGHTNESS_UP_MASK |
|
||||
ACPI_IBM_HKEY_BRIGHTNESS_DOWN_MASK |
|
||||
ACPI_IBM_HKEY_SEARCH_MASK |
|
||||
ACPI_IBM_HKEY_MICMUTE_MASK |
|
||||
ACPI_IBM_HKEY_SETTINGS_MASK |
|
||||
ACPI_IBM_HKEY_VIEWOPEN_MASK |
|
||||
ACPI_IBM_HKEY_VIEWALL_MASK
|
||||
}
|
||||
};
|
||||
|
||||
ACPI_SERIAL_DECL(ibm, "ACPI IBM extras");
|
||||
|
||||
static int acpi_ibm_probe(device_t dev);
|
||||
@ -354,7 +386,9 @@ acpi_ibm_probe(device_t dev)
|
||||
static int
|
||||
acpi_ibm_attach(device_t dev)
|
||||
{
|
||||
int i;
|
||||
struct acpi_ibm_softc *sc;
|
||||
char *maker, *product;
|
||||
devclass_t ec_devclass;
|
||||
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
|
||||
@ -448,6 +482,27 @@ acpi_ibm_attach(device_t dev)
|
||||
sc->led_dev = led_create_state(ibm_led, sc, "thinklight",
|
||||
(sc->light_val ? 1 : 0));
|
||||
|
||||
/* Enable per-model events. */
|
||||
maker = kern_getenv("smbios.system.maker");
|
||||
product = kern_getenv("smbios.system.product");
|
||||
for (i = 0; i < nitems(acpi_ibm_models); i++) {
|
||||
if (strcmp(maker, acpi_ibm_models[i].maker) == 0 &&
|
||||
strcmp(product, acpi_ibm_models[i].product) == 0) {
|
||||
ACPI_SERIAL_BEGIN(ibm);
|
||||
acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTMASK,
|
||||
acpi_ibm_models[i].eventmask);
|
||||
ACPI_SERIAL_END(ibm);
|
||||
}
|
||||
}
|
||||
freeenv(maker);
|
||||
freeenv(product);
|
||||
|
||||
/* Enable events by default. */
|
||||
ACPI_SERIAL_BEGIN(ibm);
|
||||
acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTS, 1);
|
||||
ACPI_SERIAL_END(ibm);
|
||||
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -770,7 +825,6 @@ acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method)
|
||||
|
||||
switch (method) {
|
||||
case ACPI_IBM_METHOD_EVENTS:
|
||||
/* Events are disabled by default */
|
||||
return (TRUE);
|
||||
|
||||
case ACPI_IBM_METHOD_EVENTMASK:
|
||||
@ -1229,7 +1283,6 @@ acpi_ibm_notify(ACPI_HANDLE h, UINT32 notify, void *context)
|
||||
|
||||
for (;;) {
|
||||
acpi_GetInteger(acpi_get_handle(dev), IBM_NAME_EVENTS_GET, &event);
|
||||
|
||||
if (event == 0)
|
||||
break;
|
||||
|
||||
|
@ -843,9 +843,11 @@ update_stats(struct ath_softc *sc, struct ath_node *an,
|
||||
}
|
||||
|
||||
static void
|
||||
badrate(struct ifnet *ifp, int series, int hwrate, int tries, int status)
|
||||
badrate(struct ath_softc *sc, int series, int hwrate, int tries, int status)
|
||||
{
|
||||
if_printf(ifp, "bad series%d hwrate 0x%x, tries %u ts_status 0x%x\n",
|
||||
|
||||
device_printf(sc->sc_dev,
|
||||
"bad series%d hwrate 0x%x, tries %u ts_status 0x%x\n",
|
||||
series, hwrate, tries, status);
|
||||
}
|
||||
|
||||
@ -891,9 +893,10 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
|
||||
|
||||
if (!mrr || ts->ts_finaltsi == 0) {
|
||||
if (!IS_RATE_DEFINED(sn, final_rix)) {
|
||||
device_printf(sc->sc_dev, "%s: ts_rate=%d ts_finaltsi=%d, final_rix=%d\n",
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: ts_rate=%d ts_finaltsi=%d, final_rix=%d\n",
|
||||
__func__, ts->ts_rate, ts->ts_finaltsi, final_rix);
|
||||
badrate(ifp, 0, ts->ts_rate, long_tries, status);
|
||||
badrate(sc, 0, ts->ts_rate, long_tries, status);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
@ -945,7 +948,7 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (rc[i].tries && !IS_RATE_DEFINED(sn, rc[i].rix))
|
||||
badrate(ifp, 0, rc[i].ratecode, rc[i].tries,
|
||||
badrate(sc, 0, rc[i].ratecode, rc[i].tries,
|
||||
status);
|
||||
}
|
||||
|
||||
|
@ -595,7 +595,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
|
||||
ic->ic_softc = sc;
|
||||
ic->ic_name = device_get_nameunit(sc->sc_dev);
|
||||
|
||||
/* set these up early for if_printf use */
|
||||
if_initname(ifp, device_get_name(sc->sc_dev),
|
||||
device_get_unit(sc->sc_dev));
|
||||
CURVNET_RESTORE();
|
||||
@ -612,8 +611,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
|
||||
ah = ath_hal_attach(devid, sc, sc->sc_st, sc->sc_sh,
|
||||
sc->sc_eepromdata, &ah_config, &status);
|
||||
if (ah == NULL) {
|
||||
if_printf(ifp, "unable to attach hardware; HAL status %u\n",
|
||||
status);
|
||||
device_printf(sc->sc_dev,
|
||||
"unable to attach hardware; HAL status %u\n", status);
|
||||
error = ENXIO;
|
||||
goto bad;
|
||||
}
|
||||
@ -664,8 +663,9 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
|
||||
*/
|
||||
sc->sc_keymax = ath_hal_keycachesize(ah);
|
||||
if (sc->sc_keymax > ATH_KEYMAX) {
|
||||
if_printf(ifp, "Warning, using only %u of %u key cache slots\n",
|
||||
ATH_KEYMAX, sc->sc_keymax);
|
||||
device_printf(sc->sc_dev,
|
||||
"Warning, using only %u of %u key cache slots\n",
|
||||
ATH_KEYMAX, sc->sc_keymax);
|
||||
sc->sc_keymax = ATH_KEYMAX;
|
||||
}
|
||||
/*
|
||||
@ -704,14 +704,14 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
|
||||
*/
|
||||
error = ath_desc_alloc(sc);
|
||||
if (error != 0) {
|
||||
if_printf(ifp, "failed to allocate TX descriptors: %d\n",
|
||||
error);
|
||||
device_printf(sc->sc_dev,
|
||||
"failed to allocate TX descriptors: %d\n", error);
|
||||
goto bad;
|
||||
}
|
||||
error = ath_txdma_setup(sc);
|
||||
if (error != 0) {
|
||||
if_printf(ifp, "failed to allocate TX descriptors: %d\n",
|
||||
error);
|
||||
device_printf(sc->sc_dev,
|
||||
"failed to allocate TX descriptors: %d\n", error);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@ -720,8 +720,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
|
||||
*/
|
||||
error = ath_rxdma_setup(sc);
|
||||
if (error != 0) {
|
||||
if_printf(ifp, "failed to allocate RX descriptors: %d\n",
|
||||
error);
|
||||
device_printf(sc->sc_dev,
|
||||
"failed to allocate RX descriptors: %d\n", error);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@ -752,20 +752,22 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
|
||||
*/
|
||||
sc->sc_bhalq = ath_beaconq_setup(sc);
|
||||
if (sc->sc_bhalq == (u_int) -1) {
|
||||
if_printf(ifp, "unable to setup a beacon xmit queue!\n");
|
||||
device_printf(sc->sc_dev,
|
||||
"unable to setup a beacon xmit queue!\n");
|
||||
error = EIO;
|
||||
goto bad2;
|
||||
}
|
||||
sc->sc_cabq = ath_txq_setup(sc, HAL_TX_QUEUE_CAB, 0);
|
||||
if (sc->sc_cabq == NULL) {
|
||||
if_printf(ifp, "unable to setup CAB xmit queue!\n");
|
||||
device_printf(sc->sc_dev, "unable to setup CAB xmit queue!\n");
|
||||
error = EIO;
|
||||
goto bad2;
|
||||
}
|
||||
/* NB: insure BK queue is the lowest priority h/w queue */
|
||||
if (!ath_tx_setup(sc, WME_AC_BK, HAL_WME_AC_BK)) {
|
||||
if_printf(ifp, "unable to setup xmit queue for %s traffic!\n",
|
||||
ieee80211_wme_acnames[WME_AC_BK]);
|
||||
device_printf(sc->sc_dev,
|
||||
"unable to setup xmit queue for %s traffic!\n",
|
||||
ieee80211_wme_acnames[WME_AC_BK]);
|
||||
error = EIO;
|
||||
goto bad2;
|
||||
}
|
||||
@ -1828,8 +1830,8 @@ ath_vap_delete(struct ieee80211vap *vap)
|
||||
* be reset if we just destroyed the last vap).
|
||||
*/
|
||||
if (ath_startrecv(sc) != 0)
|
||||
if_printf(ifp, "%s: unable to restart recv logic\n",
|
||||
__func__);
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: unable to restart recv logic\n", __func__);
|
||||
if (sc->sc_beacons) { /* restart beacons */
|
||||
#ifdef IEEE80211_SUPPORT_TDMA
|
||||
if (sc->sc_tdma)
|
||||
@ -2316,7 +2318,7 @@ ath_fatal_proc(void *arg, int pending)
|
||||
u_int32_t len;
|
||||
void *sp;
|
||||
|
||||
if_printf(ifp, "hardware error; resetting\n");
|
||||
device_printf(sc->sc_dev, "hardware error; resetting\n");
|
||||
/*
|
||||
* Fatal errors are unrecoverable. Typically these
|
||||
* are caused by DMA errors. Collect h/w state from
|
||||
@ -2325,9 +2327,9 @@ ath_fatal_proc(void *arg, int pending)
|
||||
if (ath_hal_getfatalstate(sc->sc_ah, &sp, &len)) {
|
||||
KASSERT(len >= 6*sizeof(u_int32_t), ("len %u bytes", len));
|
||||
state = sp;
|
||||
if_printf(ifp, "0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n",
|
||||
state[0], state[1] , state[2], state[3],
|
||||
state[4], state[5]);
|
||||
device_printf(sc->sc_dev,
|
||||
"0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n", state[0],
|
||||
state[1] , state[2], state[3], state[4], state[5]);
|
||||
}
|
||||
ath_reset(ifp, ATH_RESET_NOLOSS);
|
||||
}
|
||||
@ -2434,7 +2436,8 @@ ath_bmiss_proc(void *arg, int pending)
|
||||
*/
|
||||
if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) {
|
||||
ath_reset(ifp, ATH_RESET_NOLOSS);
|
||||
if_printf(ifp, "bb hang detected (0x%x), resetting\n", hangs);
|
||||
device_printf(sc->sc_dev,
|
||||
"bb hang detected (0x%x), resetting\n", hangs);
|
||||
} else {
|
||||
ath_reset(ifp, ATH_RESET_NOLOSS);
|
||||
ieee80211_beacon_miss(ifp->if_l2com);
|
||||
@ -2509,9 +2512,10 @@ ath_init(void *arg)
|
||||
ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
|
||||
sc->sc_cur_rxchainmask);
|
||||
|
||||
if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_FALSE, &status)) {
|
||||
if_printf(ifp, "unable to reset hardware; hal status %u\n",
|
||||
status);
|
||||
if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_FALSE,
|
||||
&status)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"unable to reset hardware; hal status %u\n", status);
|
||||
ATH_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
@ -2569,7 +2573,7 @@ ath_init(void *arg)
|
||||
* here except setup the interrupt mask.
|
||||
*/
|
||||
if (ath_startrecv(sc) != 0) {
|
||||
if_printf(ifp, "unable to start recv logic\n");
|
||||
device_printf(sc->sc_dev, "unable to start recv logic\n");
|
||||
ath_power_restore_power_state(sc);
|
||||
ATH_UNLOCK(sc);
|
||||
return;
|
||||
@ -2911,8 +2915,9 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
|
||||
ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
|
||||
sc->sc_cur_rxchainmask);
|
||||
if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_TRUE, &status))
|
||||
if_printf(ifp, "%s: unable to reset hardware; hal status %u\n",
|
||||
__func__, status);
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: unable to reset hardware; hal status %u\n",
|
||||
__func__, status);
|
||||
sc->sc_diversity = ath_hal_getdiversity(ah);
|
||||
|
||||
ATH_RX_LOCK(sc);
|
||||
@ -2941,7 +2946,8 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
|
||||
ath_hal_setenforcetxop(sc->sc_ah, 0);
|
||||
|
||||
if (ath_startrecv(sc) != 0) /* restart recv */
|
||||
if_printf(ifp, "%s: unable to start recv logic\n", __func__);
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: unable to start recv logic\n", __func__);
|
||||
/*
|
||||
* We may be doing a reset in response to an ioctl
|
||||
* that changes the channel so update any state that
|
||||
@ -3747,7 +3753,7 @@ ath_reset_proc(void *arg, int pending)
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
#if 0
|
||||
if_printf(ifp, "%s: resetting\n", __func__);
|
||||
device_printf(sc->sc_dev, "%s: resetting\n", __func__);
|
||||
#endif
|
||||
ath_reset(ifp, ATH_RESET_NOLOSS);
|
||||
}
|
||||
@ -3763,15 +3769,15 @@ ath_bstuck_proc(void *arg, int pending)
|
||||
uint32_t hangs = 0;
|
||||
|
||||
if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0)
|
||||
if_printf(ifp, "bb hang detected (0x%x)\n", hangs);
|
||||
device_printf(sc->sc_dev, "bb hang detected (0x%x)\n", hangs);
|
||||
|
||||
#ifdef ATH_DEBUG_ALQ
|
||||
if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_STUCK_BEACON))
|
||||
if_ath_alq_post(&sc->sc_alq, ATH_ALQ_STUCK_BEACON, 0, NULL);
|
||||
#endif
|
||||
|
||||
if_printf(ifp, "stuck beacon; resetting (bmiss count %u)\n",
|
||||
sc->sc_bmisscount);
|
||||
device_printf(sc->sc_dev, "stuck beacon; resetting (bmiss count %u)\n",
|
||||
sc->sc_bmisscount);
|
||||
sc->sc_stats.ast_bstuck++;
|
||||
/*
|
||||
* This assumes that there's no simultaneous channel mode change
|
||||
@ -3803,7 +3809,6 @@ ath_descdma_alloc_desc(struct ath_softc *sc,
|
||||
((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
|
||||
#define ATH_DESC_4KB_BOUND_CHECK(_daddr, _len) \
|
||||
((((u_int32_t)(_daddr) & 0xFFF) > (0x1000 - (_len))) ? 1 : 0)
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int error;
|
||||
|
||||
dd->dd_descsize = ds_size;
|
||||
@ -3844,7 +3849,8 @@ ath_descdma_alloc_desc(struct ath_softc *sc,
|
||||
NULL, /* lockarg */
|
||||
&dd->dd_dmat);
|
||||
if (error != 0) {
|
||||
if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name);
|
||||
device_printf(sc->sc_dev,
|
||||
"cannot allocate %s DMA tag\n", dd->dd_name);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -3853,8 +3859,9 @@ ath_descdma_alloc_desc(struct ath_softc *sc,
|
||||
BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
|
||||
&dd->dd_dmamap);
|
||||
if (error != 0) {
|
||||
if_printf(ifp, "unable to alloc memory for %u %s descriptors, "
|
||||
"error %u\n", ndesc, dd->dd_name, error);
|
||||
device_printf(sc->sc_dev,
|
||||
"unable to alloc memory for %u %s descriptors, error %u\n",
|
||||
ndesc, dd->dd_name, error);
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
@ -3863,8 +3870,9 @@ ath_descdma_alloc_desc(struct ath_softc *sc,
|
||||
ath_load_cb, &dd->dd_desc_paddr,
|
||||
BUS_DMA_NOWAIT);
|
||||
if (error != 0) {
|
||||
if_printf(ifp, "unable to map %s descriptors, error %u\n",
|
||||
dd->dd_name, error);
|
||||
device_printf(sc->sc_dev,
|
||||
"unable to map %s descriptors, error %u\n",
|
||||
dd->dd_name, error);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
@ -3894,7 +3902,6 @@ ath_descdma_setup(struct ath_softc *sc,
|
||||
((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
|
||||
#define ATH_DESC_4KB_BOUND_CHECK(_daddr, _len) \
|
||||
((((u_int32_t)(_daddr) & 0xFFF) > (0x1000 - (_len))) ? 1 : 0)
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint8_t *ds;
|
||||
struct ath_buf *bf;
|
||||
int i, bsize, error;
|
||||
@ -3914,8 +3921,9 @@ ath_descdma_setup(struct ath_softc *sc,
|
||||
bsize = sizeof(struct ath_buf) * nbuf;
|
||||
bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO);
|
||||
if (bf == NULL) {
|
||||
if_printf(ifp, "malloc of %s buffers failed, size %u\n",
|
||||
dd->dd_name, bsize);
|
||||
device_printf(sc->sc_dev,
|
||||
"malloc of %s buffers failed, size %u\n",
|
||||
dd->dd_name, bsize);
|
||||
goto fail3;
|
||||
}
|
||||
dd->dd_bufptr = bf;
|
||||
@ -3941,8 +3949,9 @@ ath_descdma_setup(struct ath_softc *sc,
|
||||
error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
|
||||
&bf->bf_dmamap);
|
||||
if (error != 0) {
|
||||
if_printf(ifp, "unable to create dmamap for %s "
|
||||
"buffer %u, error %u\n", dd->dd_name, i, error);
|
||||
device_printf(sc->sc_dev, "unable to create dmamap "
|
||||
"for %s buffer %u, error %u\n",
|
||||
dd->dd_name, i, error);
|
||||
ath_descdma_cleanup(sc, dd, head);
|
||||
return error;
|
||||
}
|
||||
@ -3978,7 +3987,6 @@ ath_descdma_setup_rx_edma(struct ath_softc *sc,
|
||||
struct ath_descdma *dd, ath_bufhead *head,
|
||||
const char *name, int nbuf, int rx_status_len)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ath_buf *bf;
|
||||
int i, bsize, error;
|
||||
|
||||
@ -4001,8 +4009,9 @@ ath_descdma_setup_rx_edma(struct ath_softc *sc,
|
||||
bsize = sizeof(struct ath_buf) * nbuf;
|
||||
bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO);
|
||||
if (bf == NULL) {
|
||||
if_printf(ifp, "malloc of %s buffers failed, size %u\n",
|
||||
dd->dd_name, bsize);
|
||||
device_printf(sc->sc_dev,
|
||||
"malloc of %s buffers failed, size %u\n",
|
||||
dd->dd_name, bsize);
|
||||
error = ENOMEM;
|
||||
goto fail3;
|
||||
}
|
||||
@ -4017,8 +4026,9 @@ ath_descdma_setup_rx_edma(struct ath_softc *sc,
|
||||
error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
|
||||
&bf->bf_dmamap);
|
||||
if (error != 0) {
|
||||
if_printf(ifp, "unable to create dmamap for %s "
|
||||
"buffer %u, error %u\n", dd->dd_name, i, error);
|
||||
device_printf(sc->sc_dev, "unable to create dmamap "
|
||||
"for %s buffer %u, error %u\n",
|
||||
dd->dd_name, i, error);
|
||||
ath_descdma_cleanup(sc, dd, head);
|
||||
return error;
|
||||
}
|
||||
@ -4392,9 +4402,8 @@ ath_txq_update(struct ath_softc *sc, int ac)
|
||||
qi.tqi_aifs, qi.tqi_cwmin, qi.tqi_cwmax, qi.tqi_burstTime);
|
||||
|
||||
if (!ath_hal_settxqueueprops(ah, txq->axq_qnum, &qi)) {
|
||||
if_printf(ifp, "unable to update hardware queue "
|
||||
"parameters for %s traffic!\n",
|
||||
ieee80211_wme_acnames[ac]);
|
||||
device_printf(sc->sc_dev, "unable to update hardware queue "
|
||||
"parameters for %s traffic!\n", ieee80211_wme_acnames[ac]);
|
||||
return 0;
|
||||
} else {
|
||||
ath_hal_resettxqueue(ah, txq->axq_qnum); /* push to h/w */
|
||||
@ -5560,7 +5569,7 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
|
||||
ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
|
||||
sc->sc_cur_rxchainmask);
|
||||
if (!ath_hal_reset(ah, sc->sc_opmode, chan, AH_TRUE, &status)) {
|
||||
if_printf(ifp, "%s: unable to reset "
|
||||
device_printf(sc->sc_dev, "%s: unable to reset "
|
||||
"channel %u (%u MHz, flags 0x%x), hal status %u\n",
|
||||
__func__, ieee80211_chan2ieee(ic, chan),
|
||||
chan->ic_freq, chan->ic_flags, status);
|
||||
@ -5599,8 +5608,8 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
|
||||
* Re-enable rx framework.
|
||||
*/
|
||||
if (ath_startrecv(sc) != 0) {
|
||||
if_printf(ifp, "%s: unable to restart recv logic\n",
|
||||
__func__);
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: unable to restart recv logic\n", __func__);
|
||||
ret = EIO;
|
||||
goto finish;
|
||||
}
|
||||
@ -6375,8 +6384,9 @@ ath_getchannels(struct ath_softc *sc)
|
||||
status = ath_hal_init_channels(ah, ic->ic_channels, IEEE80211_CHAN_MAX,
|
||||
&ic->ic_nchans, HAL_MODE_ALL, CTRY_DEFAULT, SKU_NONE, AH_TRUE);
|
||||
if (status != HAL_OK) {
|
||||
if_printf(ifp, "%s: unable to collect channel list from hal, "
|
||||
"status %d\n", __func__, status);
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: unable to collect channel list from hal, status %d\n",
|
||||
__func__, status);
|
||||
return EINVAL;
|
||||
}
|
||||
(void) ath_hal_getregdomain(ah, &sc->sc_eerd);
|
||||
@ -6538,10 +6548,10 @@ ath_watchdog(void *arg)
|
||||
|
||||
if (ath_hal_gethangstate(sc->sc_ah, 0xffff, &hangs) &&
|
||||
hangs != 0) {
|
||||
if_printf(ifp, "%s hang detected (0x%x)\n",
|
||||
device_printf(sc->sc_dev, "%s hang detected (0x%x)\n",
|
||||
hangs & 0xff ? "bb" : "mac", hangs);
|
||||
} else
|
||||
if_printf(ifp, "device timeout\n");
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
do_reset = 1;
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
sc->sc_stats.ast_watchdog++;
|
||||
@ -6786,31 +6796,32 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
static void
|
||||
ath_announce(struct ath_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
|
||||
if_printf(ifp, "AR%s mac %d.%d RF%s phy %d.%d\n",
|
||||
device_printf(sc->sc_dev, "AR%s mac %d.%d RF%s phy %d.%d\n",
|
||||
ath_hal_mac_name(ah), ah->ah_macVersion, ah->ah_macRev,
|
||||
ath_hal_rf_name(ah), ah->ah_phyRev >> 4, ah->ah_phyRev & 0xf);
|
||||
if_printf(ifp, "2GHz radio: 0x%.4x; 5GHz radio: 0x%.4x\n",
|
||||
device_printf(sc->sc_dev, "2GHz radio: 0x%.4x; 5GHz radio: 0x%.4x\n",
|
||||
ah->ah_analog2GhzRev, ah->ah_analog5GhzRev);
|
||||
if (bootverbose) {
|
||||
int i;
|
||||
for (i = 0; i <= WME_AC_VO; i++) {
|
||||
struct ath_txq *txq = sc->sc_ac2q[i];
|
||||
if_printf(ifp, "Use hw queue %u for %s traffic\n",
|
||||
txq->axq_qnum, ieee80211_wme_acnames[i]);
|
||||
device_printf(sc->sc_dev,
|
||||
"Use hw queue %u for %s traffic\n",
|
||||
txq->axq_qnum, ieee80211_wme_acnames[i]);
|
||||
}
|
||||
if_printf(ifp, "Use hw queue %u for CAB traffic\n",
|
||||
sc->sc_cabq->axq_qnum);
|
||||
if_printf(ifp, "Use hw queue %u for beacons\n", sc->sc_bhalq);
|
||||
device_printf(sc->sc_dev, "Use hw queue %u for CAB traffic\n",
|
||||
sc->sc_cabq->axq_qnum);
|
||||
device_printf(sc->sc_dev, "Use hw queue %u for beacons\n",
|
||||
sc->sc_bhalq);
|
||||
}
|
||||
if (ath_rxbuf != ATH_RXBUF)
|
||||
if_printf(ifp, "using %u rx buffers\n", ath_rxbuf);
|
||||
device_printf(sc->sc_dev, "using %u rx buffers\n", ath_rxbuf);
|
||||
if (ath_txbuf != ATH_TXBUF)
|
||||
if_printf(ifp, "using %u tx buffers\n", ath_txbuf);
|
||||
device_printf(sc->sc_dev, "using %u tx buffers\n", ath_txbuf);
|
||||
if (sc->sc_mcastkey && bootverbose)
|
||||
if_printf(ifp, "using multicast key search\n");
|
||||
device_printf(sc->sc_dev, "using multicast key search\n");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1037,7 +1037,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
|
||||
|
||||
bf = TAILQ_FIRST(&sc->sc_rxbuf);
|
||||
if (sc->sc_rxslink && bf == NULL) { /* NB: shouldn't happen */
|
||||
if_printf(ifp, "%s: no buffer!\n", __func__);
|
||||
device_printf(sc->sc_dev, "%s: no buffer!\n", __func__);
|
||||
break;
|
||||
} else if (bf == NULL) {
|
||||
/*
|
||||
@ -1054,7 +1054,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
|
||||
* will be no mbuf; try again to re-populate it.
|
||||
*/
|
||||
/* XXX make debug msg */
|
||||
if_printf(ifp, "%s: no mbuf!\n", __func__);
|
||||
device_printf(sc->sc_dev, "%s: no mbuf!\n", __func__);
|
||||
TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list);
|
||||
goto rx_proc_next;
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap)
|
||||
if (vap == NULL) {
|
||||
vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */
|
||||
if (vap == NULL) {
|
||||
if_printf(ifp, "%s: no vaps?\n", __func__);
|
||||
device_printf(sc->sc_dev, "%s: no vaps?\n", __func__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1691,8 +1691,8 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
flags |= HAL_TXDESC_NOACK;
|
||||
break;
|
||||
default:
|
||||
if_printf(ifp, "bogus frame type 0x%x (%s)\n",
|
||||
wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
|
||||
device_printf(sc->sc_dev, "bogus frame type 0x%x (%s)\n",
|
||||
wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
|
||||
/* XXX statistic */
|
||||
/* XXX free tx dmamap */
|
||||
ath_freetx(m0);
|
||||
|
@ -101,7 +101,6 @@ static void bwi_mac_opmode_init(struct bwi_mac *);
|
||||
static void bwi_mac_hostflags_init(struct bwi_mac *);
|
||||
static void bwi_mac_bss_param_init(struct bwi_mac *);
|
||||
|
||||
static int bwi_mac_fw_alloc(struct bwi_mac *);
|
||||
static void bwi_mac_fw_free(struct bwi_mac *);
|
||||
static int bwi_mac_fw_load(struct bwi_mac *);
|
||||
static int bwi_mac_fw_init(struct bwi_mac *);
|
||||
@ -325,10 +324,6 @@ bwi_mac_init(struct bwi_mac *mac)
|
||||
/*
|
||||
* Load and initialize firmwares
|
||||
*/
|
||||
error = bwi_mac_fw_alloc(mac);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = bwi_mac_fw_load(mac);
|
||||
if (error)
|
||||
return error;
|
||||
@ -879,11 +874,10 @@ bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw,
|
||||
/*
|
||||
* XXX Error cleanup
|
||||
*/
|
||||
static int
|
||||
int
|
||||
bwi_mac_fw_alloc(struct bwi_mac *mac)
|
||||
{
|
||||
struct bwi_softc *sc = mac->mac_sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
char fwname[64];
|
||||
int idx;
|
||||
|
||||
@ -895,10 +889,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
|
||||
snprintf(fwname, sizeof(fwname), BWI_FW_STUB_PATH,
|
||||
sc->sc_fw_version);
|
||||
mac->mac_stub = firmware_get(fwname);
|
||||
if (mac->mac_stub == NULL) {
|
||||
if_printf(ifp, "request firmware %s failed\n", fwname);
|
||||
return ENOMEM;
|
||||
}
|
||||
if (mac->mac_stub == NULL)
|
||||
goto no_firmware;
|
||||
}
|
||||
|
||||
if (mac->mac_ucode == NULL) {
|
||||
@ -907,11 +899,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
|
||||
mac->mac_rev >= 5 ? 5 : mac->mac_rev);
|
||||
|
||||
mac->mac_ucode = firmware_get(fwname);
|
||||
if (mac->mac_ucode == NULL) {
|
||||
if_printf(ifp, "request firmware %s failed\n", fwname);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (mac->mac_ucode == NULL)
|
||||
goto no_firmware;
|
||||
if (!bwi_fwimage_is_valid(sc, mac->mac_ucode, BWI_FW_T_UCODE))
|
||||
return EINVAL;
|
||||
}
|
||||
@ -922,11 +911,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
|
||||
mac->mac_rev < 5 ? 4 : 5);
|
||||
|
||||
mac->mac_pcm = firmware_get(fwname);
|
||||
if (mac->mac_pcm == NULL) {
|
||||
if_printf(ifp, "request firmware %s failed\n", fwname);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (mac->mac_pcm == NULL)
|
||||
goto no_firmware;
|
||||
if (!bwi_fwimage_is_valid(sc, mac->mac_pcm, BWI_FW_T_PCM))
|
||||
return EINVAL;
|
||||
}
|
||||
@ -938,8 +924,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
|
||||
} else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
|
||||
idx = 5;
|
||||
} else {
|
||||
if_printf(ifp, "no suitible IV for MAC rev %d\n",
|
||||
mac->mac_rev);
|
||||
device_printf(sc->sc_dev,
|
||||
"no suitible IV for MAC rev %d\n", mac->mac_rev);
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
@ -947,10 +933,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
|
||||
sc->sc_fw_version, idx);
|
||||
|
||||
mac->mac_iv = firmware_get(fwname);
|
||||
if (mac->mac_iv == NULL) {
|
||||
if_printf(ifp, "request firmware %s failed\n", fwname);
|
||||
return ENOMEM;
|
||||
}
|
||||
if (mac->mac_iv == NULL)
|
||||
goto no_firmware;
|
||||
if (!bwi_fwimage_is_valid(sc, mac->mac_iv, BWI_FW_T_IV))
|
||||
return EINVAL;
|
||||
}
|
||||
@ -960,12 +944,12 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
|
||||
if (mac->mac_rev == 2 || mac->mac_rev == 4 ||
|
||||
mac->mac_rev >= 11) {
|
||||
/* No extended IV */
|
||||
goto back;
|
||||
return (0);
|
||||
} else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
|
||||
idx = 5;
|
||||
} else {
|
||||
if_printf(ifp, "no suitible ExtIV for MAC rev %d\n",
|
||||
mac->mac_rev);
|
||||
device_printf(sc->sc_dev,
|
||||
"no suitible ExtIV for MAC rev %d\n", mac->mac_rev);
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
@ -973,15 +957,16 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
|
||||
sc->sc_fw_version, idx);
|
||||
|
||||
mac->mac_iv_ext = firmware_get(fwname);
|
||||
if (mac->mac_iv_ext == NULL) {
|
||||
if_printf(ifp, "request firmware %s failed\n", fwname);
|
||||
return ENOMEM;
|
||||
}
|
||||
if (mac->mac_iv_ext == NULL)
|
||||
goto no_firmware;
|
||||
if (!bwi_fwimage_is_valid(sc, mac->mac_iv_ext, BWI_FW_T_IV))
|
||||
return EINVAL;
|
||||
}
|
||||
back:
|
||||
return 0;
|
||||
return (0);
|
||||
|
||||
no_firmware:
|
||||
device_printf(sc->sc_dev, "request firmware %s failed\n", fwname);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -57,6 +57,7 @@ void bwi_mac_init_tpctl_11bg(struct bwi_mac *);
|
||||
void bwi_mac_dummy_xmit(struct bwi_mac *);
|
||||
void bwi_mac_reset_hwkeys(struct bwi_mac *);
|
||||
int bwi_mac_config_ps(struct bwi_mac *);
|
||||
int bwi_mac_fw_alloc(struct bwi_mac *);
|
||||
|
||||
uint16_t bwi_memobj_read_2(struct bwi_mac *, uint16_t, uint16_t);
|
||||
uint32_t bwi_memobj_read_4(struct bwi_mac *, uint16_t, uint16_t);
|
||||
|
@ -446,6 +446,10 @@ bwi_attach(struct bwi_softc *sc)
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
error = bwi_mac_fw_alloc(mac);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(dev, "can not if_alloc()\n");
|
||||
@ -1921,7 +1925,7 @@ bwi_dma_alloc(struct bwi_softc *sc)
|
||||
BUS_SPACE_MAXSIZE, /* maxsize */
|
||||
BUS_SPACE_UNRESTRICTED, /* nsegments */
|
||||
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
|
||||
BUS_DMA_ALLOCNOW, /* flags */
|
||||
0, /* flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&sc->sc_parent_dtag);
|
||||
if (error) {
|
||||
@ -1941,8 +1945,8 @@ bwi_dma_alloc(struct bwi_softc *sc)
|
||||
NULL, NULL,
|
||||
tx_ring_sz,
|
||||
1,
|
||||
BUS_SPACE_MAXSIZE_32BIT,
|
||||
BUS_DMA_ALLOCNOW,
|
||||
tx_ring_sz,
|
||||
0,
|
||||
NULL, NULL,
|
||||
&sc->sc_txring_dtag);
|
||||
if (error) {
|
||||
@ -1971,8 +1975,8 @@ bwi_dma_alloc(struct bwi_softc *sc)
|
||||
NULL, NULL,
|
||||
rx_ring_sz,
|
||||
1,
|
||||
BUS_SPACE_MAXSIZE_32BIT,
|
||||
BUS_DMA_ALLOCNOW,
|
||||
rx_ring_sz,
|
||||
0,
|
||||
NULL, NULL,
|
||||
&sc->sc_rxring_dtag);
|
||||
if (error) {
|
||||
@ -2096,8 +2100,8 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
|
||||
NULL, NULL,
|
||||
dma_size,
|
||||
1,
|
||||
BUS_SPACE_MAXSIZE_32BIT,
|
||||
BUS_DMA_ALLOCNOW,
|
||||
dma_size,
|
||||
0,
|
||||
NULL, NULL,
|
||||
&st->stats_ring_dtag);
|
||||
if (error) {
|
||||
@ -2144,8 +2148,8 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
|
||||
NULL, NULL,
|
||||
dma_size,
|
||||
1,
|
||||
BUS_SPACE_MAXSIZE_32BIT,
|
||||
BUS_DMA_ALLOCNOW,
|
||||
dma_size,
|
||||
0,
|
||||
NULL, NULL,
|
||||
&st->stats_dtag);
|
||||
if (error) {
|
||||
@ -2227,7 +2231,7 @@ bwi_dma_mbuf_create(struct bwi_softc *sc)
|
||||
NULL, NULL,
|
||||
MCLBYTES,
|
||||
1,
|
||||
BUS_SPACE_MAXSIZE_32BIT,
|
||||
MCLBYTES,
|
||||
BUS_DMA_ALLOCNOW,
|
||||
NULL, NULL,
|
||||
&sc->sc_buf_dtag);
|
||||
|
@ -161,12 +161,6 @@ bwi_pci_attach(device_t dev)
|
||||
device_printf(dev, "could not map interrupt\n");
|
||||
goto bad1;
|
||||
}
|
||||
if (bus_setup_intr(dev, sc->sc_irq_res,
|
||||
INTR_TYPE_NET | INTR_MPSAFE,
|
||||
NULL, bwi_intr, sc, &sc->sc_irq_handle)) {
|
||||
device_printf(dev, "could not establish interrupt\n");
|
||||
goto bad2;
|
||||
}
|
||||
|
||||
/* Get more PCI information */
|
||||
sc->sc_pci_did = pci_get_device(dev);
|
||||
@ -174,11 +168,17 @@ bwi_pci_attach(device_t dev)
|
||||
sc->sc_pci_subvid = pci_get_subvendor(dev);
|
||||
sc->sc_pci_subdid = pci_get_subdevice(dev);
|
||||
|
||||
error = bwi_attach(sc);
|
||||
if (error == 0) /* success */
|
||||
return 0;
|
||||
if ((error = bwi_attach(sc)) != 0)
|
||||
goto bad2;
|
||||
|
||||
if (bus_setup_intr(dev, sc->sc_irq_res,
|
||||
INTR_TYPE_NET | INTR_MPSAFE,
|
||||
NULL, bwi_intr, sc, &sc->sc_irq_handle)) {
|
||||
device_printf(dev, "could not establish interrupt\n");
|
||||
goto bad2;
|
||||
}
|
||||
return (0);
|
||||
|
||||
bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle);
|
||||
bad2:
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
|
||||
bad1:
|
||||
|
966
sys/dev/ichiic/ig4_iic.c
Normal file
966
sys/dev/ichiic/ig4_iic.c
Normal file
@ -0,0 +1,966 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The DragonFly Project. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The DragonFly Project
|
||||
* by Matthew Dillon <dillon@backplane.com> and was subsequently ported
|
||||
* to FreeBSD by Michael Gmelin <freebsd@grem.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of The DragonFly Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific, prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* Intel fourth generation mobile cpus integrated I2C device, smbus driver.
|
||||
*
|
||||
* See ig4_reg.h for datasheet reference and notes.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/smbus/smbconf.h>
|
||||
|
||||
#include <dev/ichiic/ig4_reg.h>
|
||||
#include <dev/ichiic/ig4_var.h>
|
||||
|
||||
#define TRANS_NORMAL 1
|
||||
#define TRANS_PCALL 2
|
||||
#define TRANS_BLOCK 3
|
||||
|
||||
static void ig4iic_start(void *xdev);
|
||||
static void ig4iic_intr(void *cookie);
|
||||
static void ig4iic_dump(ig4iic_softc_t *sc);
|
||||
|
||||
static int ig4_dump;
|
||||
SYSCTL_INT(_debug, OID_AUTO, ig4_dump, CTLTYPE_INT | CTLFLAG_RW,
|
||||
&ig4_dump, 0, "");
|
||||
|
||||
/*
|
||||
* Low-level inline support functions
|
||||
*/
|
||||
static __inline void
|
||||
reg_write(ig4iic_softc_t *sc, uint32_t reg, uint32_t value)
|
||||
{
|
||||
bus_write_4(sc->regs_res, reg, value);
|
||||
bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_WRITE);
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
reg_read(ig4iic_softc_t *sc, uint32_t reg)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_READ);
|
||||
value = bus_read_4(sc->regs_res, reg);
|
||||
return (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable or disable the controller and wait for the controller to acknowledge
|
||||
* the state change.
|
||||
*/
|
||||
static int
|
||||
set_controller(ig4iic_softc_t *sc, uint32_t ctl)
|
||||
{
|
||||
int retry;
|
||||
int error;
|
||||
uint32_t v;
|
||||
|
||||
reg_write(sc, IG4_REG_I2C_EN, ctl);
|
||||
error = SMB_ETIMEOUT;
|
||||
|
||||
for (retry = 100; retry > 0; --retry) {
|
||||
v = reg_read(sc, IG4_REG_ENABLE_STATUS);
|
||||
if (((v ^ ctl) & IG4_I2C_ENABLE) == 0) {
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
mtx_sleep(sc, &sc->mutex, 0, "i2cslv", 1);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait up to 25ms for the requested status using a 25uS polling loop.
|
||||
*/
|
||||
static int
|
||||
wait_status(ig4iic_softc_t *sc, uint32_t status)
|
||||
{
|
||||
uint32_t v;
|
||||
int error;
|
||||
int txlvl = -1;
|
||||
u_int count_us = 0;
|
||||
u_int limit_us = 25000; /* 25ms */
|
||||
|
||||
error = SMB_ETIMEOUT;
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* Check requested status
|
||||
*/
|
||||
v = reg_read(sc, IG4_REG_I2C_STA);
|
||||
if (v & status) {
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* When waiting for receive data break-out if the interrupt
|
||||
* loaded data into the FIFO.
|
||||
*/
|
||||
if (status & IG4_STATUS_RX_NOTEMPTY) {
|
||||
if (sc->rpos != sc->rnext) {
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When waiting for the transmit FIFO to become empty,
|
||||
* reset the timeout if we see a change in the transmit
|
||||
* FIFO level as progress is being made.
|
||||
*/
|
||||
if (status & IG4_STATUS_TX_EMPTY) {
|
||||
v = reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK;
|
||||
if (txlvl != v) {
|
||||
txlvl = v;
|
||||
count_us = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop if we've run out of time.
|
||||
*/
|
||||
if (count_us >= limit_us)
|
||||
break;
|
||||
|
||||
/*
|
||||
* When waiting for receive data let the interrupt do its
|
||||
* work, otherwise poll with the lock held.
|
||||
*/
|
||||
if (status & IG4_STATUS_RX_NOTEMPTY) {
|
||||
mtx_sleep(sc, &sc->mutex, PZERO, "i2cwait",
|
||||
(hz + 99) / 100); /* sleep up to 10ms */
|
||||
count_us += 10000;
|
||||
} else {
|
||||
DELAY(25);
|
||||
count_us += 25;
|
||||
}
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read I2C data. The data might have already been read by
|
||||
* the interrupt code, otherwise it is sitting in the data
|
||||
* register.
|
||||
*/
|
||||
static uint8_t
|
||||
data_read(ig4iic_softc_t *sc)
|
||||
{
|
||||
uint8_t c;
|
||||
|
||||
if (sc->rpos == sc->rnext) {
|
||||
c = (uint8_t)reg_read(sc, IG4_REG_DATA_CMD);
|
||||
} else {
|
||||
c = sc->rbuf[sc->rpos & IG4_RBUFMASK];
|
||||
++sc->rpos;
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the slave address. The controller must be disabled when
|
||||
* changing the address.
|
||||
*
|
||||
* This operation does not issue anything to the I2C bus but sets
|
||||
* the target address for when the controller later issues a START.
|
||||
*/
|
||||
static void
|
||||
set_slave_addr(ig4iic_softc_t *sc, uint8_t slave, int trans_op)
|
||||
{
|
||||
uint32_t tar;
|
||||
uint32_t ctl;
|
||||
int use_10bit;
|
||||
|
||||
use_10bit = sc->use_10bit;
|
||||
if (trans_op & SMB_TRANS_7BIT)
|
||||
use_10bit = 0;
|
||||
if (trans_op & SMB_TRANS_10BIT)
|
||||
use_10bit = 1;
|
||||
|
||||
if (sc->slave_valid && sc->last_slave == slave &&
|
||||
sc->use_10bit == use_10bit) {
|
||||
return;
|
||||
}
|
||||
sc->use_10bit = use_10bit;
|
||||
|
||||
/*
|
||||
* Wait for TXFIFO to drain before disabling the controller.
|
||||
*
|
||||
* If a write message has not been completed it's really a
|
||||
* programming error, but for now in that case issue an extra
|
||||
* byte + STOP.
|
||||
*
|
||||
* If a read message has not been completed it's also a programming
|
||||
* error, for now just ignore it.
|
||||
*/
|
||||
wait_status(sc, IG4_STATUS_TX_NOTFULL);
|
||||
if (sc->write_started) {
|
||||
reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_STOP);
|
||||
sc->write_started = 0;
|
||||
}
|
||||
if (sc->read_started)
|
||||
sc->read_started = 0;
|
||||
wait_status(sc, IG4_STATUS_TX_EMPTY);
|
||||
|
||||
set_controller(sc, 0);
|
||||
ctl = reg_read(sc, IG4_REG_CTL);
|
||||
ctl &= ~IG4_CTL_10BIT;
|
||||
ctl |= IG4_CTL_RESTARTEN;
|
||||
|
||||
tar = slave;
|
||||
if (sc->use_10bit) {
|
||||
tar |= IG4_TAR_10BIT;
|
||||
ctl |= IG4_CTL_10BIT;
|
||||
}
|
||||
reg_write(sc, IG4_REG_CTL, ctl);
|
||||
reg_write(sc, IG4_REG_TAR_ADD, tar);
|
||||
set_controller(sc, IG4_I2C_ENABLE);
|
||||
sc->slave_valid = 1;
|
||||
sc->last_slave = slave;
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue START with byte command, possible count, and a variable length
|
||||
* read or write buffer, then possible turn-around read. The read also
|
||||
* has a possible count received.
|
||||
*
|
||||
* For SMBUS -
|
||||
*
|
||||
* Quick: START+ADDR+RD/WR STOP
|
||||
*
|
||||
* Normal: START+ADDR+WR CMD DATA..DATA STOP
|
||||
*
|
||||
* START+ADDR+RD CMD
|
||||
* RESTART+ADDR RDATA..RDATA STOP
|
||||
* (can also be used for I2C transactions)
|
||||
*
|
||||
* Process Call: START+ADDR+WR CMD DATAL DATAH
|
||||
* RESTART+ADDR+RD RDATAL RDATAH STOP
|
||||
*
|
||||
* Block: START+ADDR+RD CMD
|
||||
* RESTART+ADDR+RD RCOUNT DATA... STOP
|
||||
*
|
||||
* START+ADDR+WR CMD
|
||||
* RESTART+ADDR+WR WCOUNT DATA... STOP
|
||||
*
|
||||
* For I2C - basically, no *COUNT fields, possibly no *CMD field. If the
|
||||
* sender needs to issue a 2-byte command it will incorporate it
|
||||
* into the write buffer and also set NOCMD.
|
||||
*
|
||||
* Generally speaking, the START+ADDR / RESTART+ADDR is handled automatically
|
||||
* by the controller at the beginning of a command sequence or on a data
|
||||
* direction turn-around, and we only need to tell it when to issue the STOP.
|
||||
*/
|
||||
static int
|
||||
smb_transaction(ig4iic_softc_t *sc, char cmd, int op,
|
||||
char *wbuf, int wcount, char *rbuf, int rcount, int *actualp)
|
||||
{
|
||||
int error;
|
||||
int unit;
|
||||
uint32_t last;
|
||||
|
||||
/*
|
||||
* Debugging - dump registers
|
||||
*/
|
||||
if (ig4_dump) {
|
||||
unit = device_get_unit(sc->dev);
|
||||
if (ig4_dump & (1 << unit)) {
|
||||
ig4_dump &= ~(1 << unit);
|
||||
ig4iic_dump(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue START or RESTART with next data byte, clear any previous
|
||||
* abort condition that may have been holding the txfifo in reset.
|
||||
*/
|
||||
last = IG4_DATA_RESTART;
|
||||
reg_read(sc, IG4_REG_CLR_TX_ABORT);
|
||||
if (actualp)
|
||||
*actualp = 0;
|
||||
|
||||
/*
|
||||
* Issue command if not told otherwise (smbus).
|
||||
*/
|
||||
if ((op & SMB_TRANS_NOCMD) == 0) {
|
||||
error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
|
||||
if (error)
|
||||
goto done;
|
||||
last |= (u_char)cmd;
|
||||
if (wcount == 0 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0)
|
||||
last |= IG4_DATA_STOP;
|
||||
reg_write(sc, IG4_REG_DATA_CMD, last);
|
||||
last = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean out any previously received data.
|
||||
*/
|
||||
if (sc->rpos != sc->rnext &&
|
||||
(op & SMB_TRANS_NOREPORT) == 0) {
|
||||
device_printf(sc->dev,
|
||||
"discarding %d bytes of spurious data\n",
|
||||
sc->rnext - sc->rpos);
|
||||
}
|
||||
sc->rpos = 0;
|
||||
sc->rnext = 0;
|
||||
|
||||
/*
|
||||
* If writing and not told otherwise, issue the write count (smbus).
|
||||
*/
|
||||
if (wcount && (op & SMB_TRANS_NOCNT) == 0) {
|
||||
error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
|
||||
if (error)
|
||||
goto done;
|
||||
last |= (u_char)cmd;
|
||||
reg_write(sc, IG4_REG_DATA_CMD, last);
|
||||
last = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bulk write (i2c)
|
||||
*/
|
||||
while (wcount) {
|
||||
error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
|
||||
if (error)
|
||||
goto done;
|
||||
last |= (u_char)*wbuf;
|
||||
if (wcount == 1 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0)
|
||||
last |= IG4_DATA_STOP;
|
||||
reg_write(sc, IG4_REG_DATA_CMD, last);
|
||||
--wcount;
|
||||
++wbuf;
|
||||
last = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue reads to xmit FIFO (strange, I know) to tell the controller
|
||||
* to clock in data. At the moment just issue one read ahead to
|
||||
* pipeline the incoming data.
|
||||
*
|
||||
* NOTE: In the case of NOCMD and wcount == 0 we still issue a
|
||||
* RESTART here, even if the data direction has not changed
|
||||
* from the previous CHAINing call. This we force the RESTART.
|
||||
* (A new START is issued automatically by the controller in
|
||||
* the other nominal cases such as a data direction change or
|
||||
* a previous STOP was issued).
|
||||
*
|
||||
* If this will be the last byte read we must also issue the STOP
|
||||
* at the end of the read.
|
||||
*/
|
||||
if (rcount) {
|
||||
last = IG4_DATA_RESTART | IG4_DATA_COMMAND_RD;
|
||||
if (rcount == 1 &&
|
||||
(op & (SMB_TRANS_NOSTOP | SMB_TRANS_NOCNT)) ==
|
||||
SMB_TRANS_NOCNT) {
|
||||
last |= IG4_DATA_STOP;
|
||||
}
|
||||
reg_write(sc, IG4_REG_DATA_CMD, last);
|
||||
last = IG4_DATA_COMMAND_RD;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bulk read (i2c) and count field handling (smbus)
|
||||
*/
|
||||
while (rcount) {
|
||||
/*
|
||||
* Maintain a pipeline by queueing the allowance for the next
|
||||
* read before waiting for the current read.
|
||||
*/
|
||||
if (rcount > 1) {
|
||||
if (op & SMB_TRANS_NOCNT)
|
||||
last = (rcount == 2) ? IG4_DATA_STOP : 0;
|
||||
else
|
||||
last = 0;
|
||||
reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD |
|
||||
last);
|
||||
}
|
||||
error = wait_status(sc, IG4_STATUS_RX_NOTEMPTY);
|
||||
if (error) {
|
||||
if ((op & SMB_TRANS_NOREPORT) == 0) {
|
||||
device_printf(sc->dev,
|
||||
"rx timeout addr 0x%02x\n",
|
||||
sc->last_slave);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
last = data_read(sc);
|
||||
|
||||
if (op & SMB_TRANS_NOCNT) {
|
||||
*rbuf = (u_char)last;
|
||||
++rbuf;
|
||||
--rcount;
|
||||
if (actualp)
|
||||
++*actualp;
|
||||
} else {
|
||||
/*
|
||||
* Handle count field (smbus), which is not part of
|
||||
* the rcount'ed buffer. The first read data in a
|
||||
* bulk transfer is the count.
|
||||
*
|
||||
* XXX if rcount is loaded as 0 how do I generate a
|
||||
* STOP now without issuing another RD or WR?
|
||||
*/
|
||||
if (rcount > (u_char)last)
|
||||
rcount = (u_char)last;
|
||||
op |= SMB_TRANS_NOCNT;
|
||||
}
|
||||
}
|
||||
error = 0;
|
||||
done:
|
||||
/* XXX wait for xmit buffer to become empty */
|
||||
last = reg_read(sc, IG4_REG_TX_ABRT_SOURCE);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* SMBUS API FUNCTIONS
|
||||
*
|
||||
* Called from ig4iic_pci_attach/detach()
|
||||
*/
|
||||
int
|
||||
ig4iic_attach(ig4iic_softc_t *sc)
|
||||
{
|
||||
int error;
|
||||
uint32_t v;
|
||||
|
||||
v = reg_read(sc, IG4_REG_COMP_TYPE);
|
||||
v = reg_read(sc, IG4_REG_COMP_PARAM1);
|
||||
v = reg_read(sc, IG4_REG_GENERAL);
|
||||
if ((v & IG4_GENERAL_SWMODE) == 0) {
|
||||
v |= IG4_GENERAL_SWMODE;
|
||||
reg_write(sc, IG4_REG_GENERAL, v);
|
||||
v = reg_read(sc, IG4_REG_GENERAL);
|
||||
}
|
||||
|
||||
v = reg_read(sc, IG4_REG_SW_LTR_VALUE);
|
||||
v = reg_read(sc, IG4_REG_AUTO_LTR_VALUE);
|
||||
|
||||
v = reg_read(sc, IG4_REG_COMP_VER);
|
||||
if (v != IG4_COMP_VER) {
|
||||
error = ENXIO;
|
||||
goto done;
|
||||
}
|
||||
v = reg_read(sc, IG4_REG_SS_SCL_HCNT);
|
||||
v = reg_read(sc, IG4_REG_SS_SCL_LCNT);
|
||||
v = reg_read(sc, IG4_REG_FS_SCL_HCNT);
|
||||
v = reg_read(sc, IG4_REG_FS_SCL_LCNT);
|
||||
v = reg_read(sc, IG4_REG_SDA_HOLD);
|
||||
|
||||
v = reg_read(sc, IG4_REG_SS_SCL_HCNT);
|
||||
reg_write(sc, IG4_REG_FS_SCL_HCNT, v);
|
||||
v = reg_read(sc, IG4_REG_SS_SCL_LCNT);
|
||||
reg_write(sc, IG4_REG_FS_SCL_LCNT, v);
|
||||
|
||||
/*
|
||||
* Program based on a 25000 Hz clock. This is a bit of a
|
||||
* hack (obviously). The defaults are 400 and 470 for standard
|
||||
* and 60 and 130 for fast. The defaults for standard fail
|
||||
* utterly (presumably cause an abort) because the clock time
|
||||
* is ~18.8ms by default. This brings it down to ~4ms (for now).
|
||||
*/
|
||||
reg_write(sc, IG4_REG_SS_SCL_HCNT, 100);
|
||||
reg_write(sc, IG4_REG_SS_SCL_LCNT, 125);
|
||||
reg_write(sc, IG4_REG_FS_SCL_HCNT, 100);
|
||||
reg_write(sc, IG4_REG_FS_SCL_LCNT, 125);
|
||||
|
||||
/*
|
||||
* Use a threshold of 1 so we get interrupted on each character,
|
||||
* allowing us to use mtx_sleep() in our poll code. Not perfect
|
||||
* but this is better than using DELAY() for receiving data.
|
||||
*/
|
||||
reg_write(sc, IG4_REG_RX_TL, 1);
|
||||
|
||||
reg_write(sc, IG4_REG_CTL,
|
||||
IG4_CTL_MASTER |
|
||||
IG4_CTL_SLAVE_DISABLE |
|
||||
IG4_CTL_RESTARTEN |
|
||||
IG4_CTL_SPEED_STD);
|
||||
|
||||
sc->smb = device_add_child(sc->dev, "smbus", -1);
|
||||
if (sc->smb == NULL) {
|
||||
device_printf(sc->dev, "smbus driver not found\n");
|
||||
error = ENXIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Don't do this, it blows up the PCI config
|
||||
*/
|
||||
reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT);
|
||||
reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interrupt on STOP detect or receive character ready
|
||||
*/
|
||||
reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET |
|
||||
IG4_INTR_RX_FULL);
|
||||
mtx_lock(&sc->mutex);
|
||||
if (set_controller(sc, 0))
|
||||
device_printf(sc->dev, "controller error during attach-1\n");
|
||||
if (set_controller(sc, IG4_I2C_ENABLE))
|
||||
device_printf(sc->dev, "controller error during attach-2\n");
|
||||
mtx_unlock(&sc->mutex);
|
||||
error = bus_setup_intr(sc->dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE,
|
||||
NULL, ig4iic_intr, sc, &sc->intr_handle);
|
||||
if (error) {
|
||||
device_printf(sc->dev,
|
||||
"Unable to setup irq: error %d\n", error);
|
||||
}
|
||||
|
||||
sc->enum_hook.ich_func = ig4iic_start;
|
||||
sc->enum_hook.ich_arg = sc->dev;
|
||||
|
||||
/* We have to wait until interrupts are enabled. I2C read and write
|
||||
* only works if the interrupts are available.
|
||||
*/
|
||||
if (config_intrhook_establish(&sc->enum_hook) != 0)
|
||||
error = ENOMEM;
|
||||
else
|
||||
error = 0;
|
||||
|
||||
done:
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
ig4iic_start(void *xdev)
|
||||
{
|
||||
int error;
|
||||
ig4iic_softc_t *sc;
|
||||
device_t dev = (device_t)xdev;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
config_intrhook_disestablish(&sc->enum_hook);
|
||||
|
||||
/* Attach us to the smbus */
|
||||
error = bus_generic_attach(sc->dev);
|
||||
if (error) {
|
||||
device_printf(sc->dev,
|
||||
"failed to attach child: error %d\n", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
ig4iic_detach(ig4iic_softc_t *sc)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (device_is_attached(sc->dev)) {
|
||||
error = bus_generic_detach(sc->dev);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
if (sc->smb)
|
||||
device_delete_child(sc->dev, sc->smb);
|
||||
if (sc->intr_handle)
|
||||
bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle);
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
sc->smb = NULL;
|
||||
sc->intr_handle = NULL;
|
||||
reg_write(sc, IG4_REG_INTR_MASK, 0);
|
||||
reg_read(sc, IG4_REG_CLR_INTR);
|
||||
set_controller(sc, 0);
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ig4iic_smb_callback(device_t dev, int index, void *data)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
switch (index) {
|
||||
case SMB_REQUEST_BUS:
|
||||
error = 0;
|
||||
break;
|
||||
case SMB_RELEASE_BUS:
|
||||
error = 0;
|
||||
break;
|
||||
default:
|
||||
error = SMB_EABORT;
|
||||
break;
|
||||
}
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Quick command. i.e. START + cmd + R/W + STOP and no data. It is
|
||||
* unclear to me how I could implement this with the intel i2c controller
|
||||
* because the controler sends STARTs and STOPs automatically with data.
|
||||
*/
|
||||
int
|
||||
ig4iic_smb_quick(device_t dev, u_char slave, int how)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
switch (how) {
|
||||
case SMB_QREAD:
|
||||
error = SMB_ENOTSUPP;
|
||||
break;
|
||||
case SMB_QWRITE:
|
||||
error = SMB_ENOTSUPP;
|
||||
break;
|
||||
default:
|
||||
error = SMB_ENOTSUPP;
|
||||
break;
|
||||
}
|
||||
mtx_unlock(&sc->mutex);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Incremental send byte without stop (?). It is unclear why the slave
|
||||
* address is specified if this presumably is used in combination with
|
||||
* ig4iic_smb_quick().
|
||||
*
|
||||
* (Also, how would this work anyway? Issue the last byte with writeb()?)
|
||||
*/
|
||||
int
|
||||
ig4iic_smb_sendb(device_t dev, u_char slave, char byte)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
uint32_t cmd;
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
set_slave_addr(sc, slave, 0);
|
||||
cmd = byte;
|
||||
if (wait_status(sc, IG4_STATUS_TX_NOTFULL) == 0) {
|
||||
reg_write(sc, IG4_REG_DATA_CMD, cmd);
|
||||
error = 0;
|
||||
} else {
|
||||
error = SMB_ETIMEOUT;
|
||||
}
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Incremental receive byte without stop (?). It is unclear why the slave
|
||||
* address is specified if this presumably is used in combination with
|
||||
* ig4iic_smb_quick().
|
||||
*/
|
||||
int
|
||||
ig4iic_smb_recvb(device_t dev, u_char slave, char *byte)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
set_slave_addr(sc, slave, 0);
|
||||
reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD);
|
||||
if (wait_status(sc, IG4_STATUS_RX_NOTEMPTY) == 0) {
|
||||
*byte = data_read(sc);
|
||||
error = 0;
|
||||
} else {
|
||||
*byte = 0;
|
||||
error = SMB_ETIMEOUT;
|
||||
}
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write command and single byte in transaction.
|
||||
*/
|
||||
int
|
||||
ig4iic_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
set_slave_addr(sc, slave, 0);
|
||||
error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
|
||||
&byte, 1, NULL, 0, NULL);
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write command and single word in transaction.
|
||||
*/
|
||||
int
|
||||
ig4iic_smb_writew(device_t dev, u_char slave, char cmd, short word)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
char buf[2];
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
set_slave_addr(sc, slave, 0);
|
||||
buf[0] = word & 0xFF;
|
||||
buf[1] = word >> 8;
|
||||
error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
|
||||
buf, 2, NULL, 0, NULL);
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* write command and read single byte in transaction.
|
||||
*/
|
||||
int
|
||||
ig4iic_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
set_slave_addr(sc, slave, 0);
|
||||
error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
|
||||
NULL, 0, byte, 1, NULL);
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* write command and read word in transaction.
|
||||
*/
|
||||
int
|
||||
ig4iic_smb_readw(device_t dev, u_char slave, char cmd, short *word)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
char buf[2];
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
set_slave_addr(sc, slave, 0);
|
||||
if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
|
||||
NULL, 0, buf, 2, NULL)) == 0) {
|
||||
*word = (u_char)buf[0] | ((u_char)buf[1] << 8);
|
||||
}
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* write command and word and read word in transaction
|
||||
*/
|
||||
int
|
||||
ig4iic_smb_pcall(device_t dev, u_char slave, char cmd,
|
||||
short sdata, short *rdata)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
char rbuf[2];
|
||||
char wbuf[2];
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
set_slave_addr(sc, slave, 0);
|
||||
wbuf[0] = sdata & 0xFF;
|
||||
wbuf[1] = sdata >> 8;
|
||||
if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
|
||||
wbuf, 2, rbuf, 2, NULL)) == 0) {
|
||||
*rdata = (u_char)rbuf[0] | ((u_char)rbuf[1] << 8);
|
||||
}
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
ig4iic_smb_bwrite(device_t dev, u_char slave, char cmd,
|
||||
u_char wcount, char *buf)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
set_slave_addr(sc, slave, 0);
|
||||
error = smb_transaction(sc, cmd, 0,
|
||||
buf, wcount, NULL, 0, NULL);
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
ig4iic_smb_bread(device_t dev, u_char slave, char cmd,
|
||||
u_char *countp_char, char *buf)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
int rcount = *countp_char;
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
set_slave_addr(sc, slave, 0);
|
||||
error = smb_transaction(sc, cmd, 0,
|
||||
NULL, 0, buf, rcount, &rcount);
|
||||
*countp_char = rcount;
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
ig4iic_smb_trans(device_t dev, int slave, char cmd, int op,
|
||||
char *wbuf, int wcount, char *rbuf, int rcount,
|
||||
int *actualp)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
|
||||
set_slave_addr(sc, slave, op);
|
||||
error = smb_transaction(sc, cmd, op,
|
||||
wbuf, wcount, rbuf, rcount, actualp);
|
||||
|
||||
mtx_unlock(&sc->mutex);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt Operation
|
||||
*/
|
||||
static void
|
||||
ig4iic_intr(void *cookie)
|
||||
{
|
||||
ig4iic_softc_t *sc = cookie;
|
||||
uint32_t status;
|
||||
|
||||
mtx_lock(&sc->mutex);
|
||||
/* reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET);*/
|
||||
status = reg_read(sc, IG4_REG_I2C_STA);
|
||||
while (status & IG4_STATUS_RX_NOTEMPTY) {
|
||||
sc->rbuf[sc->rnext & IG4_RBUFMASK] =
|
||||
(uint8_t)reg_read(sc, IG4_REG_DATA_CMD);
|
||||
++sc->rnext;
|
||||
status = reg_read(sc, IG4_REG_I2C_STA);
|
||||
}
|
||||
reg_read(sc, IG4_REG_CLR_INTR);
|
||||
wakeup(sc);
|
||||
mtx_unlock(&sc->mutex);
|
||||
}
|
||||
|
||||
#define REGDUMP(sc, reg) \
|
||||
device_printf(sc->dev, " %-23s %08x\n", #reg, reg_read(sc, reg))
|
||||
|
||||
static void
|
||||
ig4iic_dump(ig4iic_softc_t *sc)
|
||||
{
|
||||
device_printf(sc->dev, "ig4iic register dump:\n");
|
||||
REGDUMP(sc, IG4_REG_CTL);
|
||||
REGDUMP(sc, IG4_REG_TAR_ADD);
|
||||
REGDUMP(sc, IG4_REG_SS_SCL_HCNT);
|
||||
REGDUMP(sc, IG4_REG_SS_SCL_LCNT);
|
||||
REGDUMP(sc, IG4_REG_FS_SCL_HCNT);
|
||||
REGDUMP(sc, IG4_REG_FS_SCL_LCNT);
|
||||
REGDUMP(sc, IG4_REG_INTR_STAT);
|
||||
REGDUMP(sc, IG4_REG_INTR_MASK);
|
||||
REGDUMP(sc, IG4_REG_RAW_INTR_STAT);
|
||||
REGDUMP(sc, IG4_REG_RX_TL);
|
||||
REGDUMP(sc, IG4_REG_TX_TL);
|
||||
REGDUMP(sc, IG4_REG_I2C_EN);
|
||||
REGDUMP(sc, IG4_REG_I2C_STA);
|
||||
REGDUMP(sc, IG4_REG_TXFLR);
|
||||
REGDUMP(sc, IG4_REG_RXFLR);
|
||||
REGDUMP(sc, IG4_REG_SDA_HOLD);
|
||||
REGDUMP(sc, IG4_REG_TX_ABRT_SOURCE);
|
||||
REGDUMP(sc, IG4_REG_SLV_DATA_NACK);
|
||||
REGDUMP(sc, IG4_REG_DMA_CTRL);
|
||||
REGDUMP(sc, IG4_REG_DMA_TDLR);
|
||||
REGDUMP(sc, IG4_REG_DMA_RDLR);
|
||||
REGDUMP(sc, IG4_REG_SDA_SETUP);
|
||||
REGDUMP(sc, IG4_REG_ENABLE_STATUS);
|
||||
REGDUMP(sc, IG4_REG_COMP_PARAM1);
|
||||
REGDUMP(sc, IG4_REG_COMP_VER);
|
||||
REGDUMP(sc, IG4_REG_COMP_TYPE);
|
||||
REGDUMP(sc, IG4_REG_CLK_PARMS);
|
||||
REGDUMP(sc, IG4_REG_RESETS);
|
||||
REGDUMP(sc, IG4_REG_GENERAL);
|
||||
REGDUMP(sc, IG4_REG_SW_LTR_VALUE);
|
||||
REGDUMP(sc, IG4_REG_AUTO_LTR_VALUE);
|
||||
}
|
||||
#undef REGDUMP
|
||||
|
||||
DRIVER_MODULE(smbus, ig4iic, smbus_driver, smbus_devclass, NULL, NULL);
|
192
sys/dev/ichiic/ig4_pci.c
Normal file
192
sys/dev/ichiic/ig4_pci.c
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The DragonFly Project. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The DragonFly Project
|
||||
* by Matthew Dillon <dillon@backplane.com> and was subsequently ported
|
||||
* to FreeBSD by Michael Gmelin <freebsd@grem.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of The DragonFly Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific, prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* Intel fourth generation mobile cpus integrated I2C device, smbus driver.
|
||||
*
|
||||
* See ig4_reg.h for datasheet reference and notes.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/smbus/smbconf.h>
|
||||
|
||||
#include "smbus_if.h"
|
||||
|
||||
#include <dev/ichiic/ig4_reg.h>
|
||||
#include <dev/ichiic/ig4_var.h>
|
||||
|
||||
static int ig4iic_pci_detach(device_t dev);
|
||||
|
||||
#define PCI_CHIP_LYNXPT_LP_I2C_1 0x9c618086
|
||||
#define PCI_CHIP_LYNXPT_LP_I2C_2 0x9c628086
|
||||
|
||||
static int
|
||||
ig4iic_pci_probe(device_t dev)
|
||||
{
|
||||
switch(pci_get_devid(dev)) {
|
||||
case PCI_CHIP_LYNXPT_LP_I2C_1:
|
||||
device_set_desc(dev, "Intel Lynx Point-LP I2C Controller-1");
|
||||
break;
|
||||
case PCI_CHIP_LYNXPT_LP_I2C_2:
|
||||
device_set_desc(dev, "Intel Lynx Point-LP I2C Controller-2");
|
||||
break;
|
||||
default:
|
||||
return (ENXIO);
|
||||
}
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
ig4iic_pci_attach(device_t dev)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
bzero(sc, sizeof(*sc));
|
||||
|
||||
mtx_init(&sc->mutex, device_get_nameunit(dev), "ig4iic", MTX_DEF);
|
||||
|
||||
sc->dev = dev;
|
||||
sc->regs_rid = PCIR_BAR(0);
|
||||
sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&sc->regs_rid, RF_ACTIVE);
|
||||
if (sc->regs_res == NULL) {
|
||||
device_printf(dev, "unable to map registers\n");
|
||||
ig4iic_pci_detach(dev);
|
||||
return (ENXIO);
|
||||
}
|
||||
sc->intr_rid = 0;
|
||||
if (pci_alloc_msi(dev, &sc->intr_rid)) {
|
||||
device_printf(dev, "Using MSI\n");
|
||||
}
|
||||
sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
|
||||
&sc->intr_rid, RF_SHAREABLE | RF_ACTIVE);
|
||||
if (sc->intr_res == NULL) {
|
||||
device_printf(dev, "unable to map interrupt\n");
|
||||
ig4iic_pci_detach(dev);
|
||||
return (ENXIO);
|
||||
}
|
||||
sc->pci_attached = 1;
|
||||
|
||||
error = ig4iic_attach(sc);
|
||||
if (error)
|
||||
ig4iic_pci_detach(dev);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
ig4iic_pci_detach(device_t dev)
|
||||
{
|
||||
ig4iic_softc_t *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
if (sc->pci_attached) {
|
||||
error = ig4iic_detach(sc);
|
||||
if (error)
|
||||
return (error);
|
||||
sc->pci_attached = 0;
|
||||
}
|
||||
|
||||
if (sc->intr_res) {
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
sc->intr_rid, sc->intr_res);
|
||||
sc->intr_res = NULL;
|
||||
}
|
||||
if (sc->intr_rid != 0)
|
||||
pci_release_msi(dev);
|
||||
if (sc->regs_res) {
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
sc->regs_rid, sc->regs_res);
|
||||
sc->regs_res = NULL;
|
||||
}
|
||||
mtx_destroy(&sc->mutex);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t ig4iic_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, ig4iic_pci_probe),
|
||||
DEVMETHOD(device_attach, ig4iic_pci_attach),
|
||||
DEVMETHOD(device_detach, ig4iic_pci_detach),
|
||||
|
||||
/* SMBus methods from ig4_smb.c */
|
||||
DEVMETHOD(smbus_callback, ig4iic_smb_callback),
|
||||
DEVMETHOD(smbus_quick, ig4iic_smb_quick),
|
||||
DEVMETHOD(smbus_sendb, ig4iic_smb_sendb),
|
||||
DEVMETHOD(smbus_recvb, ig4iic_smb_recvb),
|
||||
DEVMETHOD(smbus_writeb, ig4iic_smb_writeb),
|
||||
DEVMETHOD(smbus_writew, ig4iic_smb_writew),
|
||||
DEVMETHOD(smbus_readb, ig4iic_smb_readb),
|
||||
DEVMETHOD(smbus_readw, ig4iic_smb_readw),
|
||||
DEVMETHOD(smbus_pcall, ig4iic_smb_pcall),
|
||||
DEVMETHOD(smbus_bwrite, ig4iic_smb_bwrite),
|
||||
DEVMETHOD(smbus_bread, ig4iic_smb_bread),
|
||||
DEVMETHOD(smbus_trans, ig4iic_smb_trans),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t ig4iic_pci_driver = {
|
||||
"ig4iic",
|
||||
ig4iic_pci_methods,
|
||||
sizeof(struct ig4iic_softc)
|
||||
};
|
||||
|
||||
static devclass_t ig4iic_pci_devclass;
|
||||
|
||||
DRIVER_MODULE(ig4iic, pci, ig4iic_pci_driver, ig4iic_pci_devclass, 0, 0);
|
||||
MODULE_DEPEND(ig4iic, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(ig4iic, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
|
||||
MODULE_VERSION(ig4iic, 1);
|
622
sys/dev/ichiic/ig4_reg.h
Normal file
622
sys/dev/ichiic/ig4_reg.h
Normal file
@ -0,0 +1,622 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The DragonFly Project. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The DragonFly Project
|
||||
* by Matthew Dillon <dillon@backplane.com> and was subsequently ported
|
||||
* to FreeBSD by Michael Gmelin <freebsd@grem.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of The DragonFly Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific, prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDERS 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$
|
||||
*/
|
||||
/*
|
||||
* Intel fourth generation mobile cpus integrated I2C device.
|
||||
*
|
||||
* Datasheet reference: Section 22.
|
||||
*
|
||||
* http://www.intel.com/content/www/us/en/processors/core/4th-gen-core-family-mobile-i-o-datasheet.html?wapkw=datasheets+4th+generation
|
||||
*
|
||||
* This is a from-scratch driver under the BSD license using the Intel data
|
||||
* sheet and the linux driver for reference. All code is freshly written
|
||||
* without referencing the linux driver code. However, during testing
|
||||
* I am also using the linux driver code as a reference to help resolve any
|
||||
* issues that come. These will be specifically documented in the code.
|
||||
*
|
||||
* Please see protocol notes in section 5.21. This controller is an I2C
|
||||
* master only and cannot act as a slave. The IO voltage should be set by
|
||||
* the BIOS. Standard (100Kb/s) and Fast (400Kb/s) and fast mode plus
|
||||
* (1MB/s) is supported. High speed mode (3.4 MB/s) is NOT supported.
|
||||
*/
|
||||
|
||||
#ifndef _BUS_SMBUS_INTELGEN4_IG4_REG_H_
|
||||
#define _BUS_SMBUS_INTELGEN4_IG4_REG_H_
|
||||
|
||||
/*
|
||||
* 22.2 MMIO registers can be accessed through BAR0 in PCI mode or through
|
||||
* BAR1 when in ACPI mode.
|
||||
*
|
||||
* Register width is 32-bits
|
||||
*
|
||||
* 22.2 Default Values on device reset are 0 except as specified here:
|
||||
* TAR_ADD 0x00000055
|
||||
* SS_SCL_HCNT 0x00000264
|
||||
* SS_SCL_LCNT 0x000002C2
|
||||
* FS_SCL_HCNT 0x0000006E
|
||||
* FS_SCL_LCNT 0x000000CF
|
||||
* INTR_MASK 0x000008FF
|
||||
* I2C_STA 0x00000006
|
||||
* SDA_HOLD 0x00000001
|
||||
* SDA_SETUP 0x00000064
|
||||
* COMP_PARAM1 0x00FFFF6E
|
||||
* COMP_VER 0x3131352A
|
||||
*/
|
||||
|
||||
#define IG4_REG_CTL 0x0000 /* RW Control Register */
|
||||
#define IG4_REG_TAR_ADD 0x0004 /* RW Target Address */
|
||||
#define IG4_REG_DATA_CMD 0x0010 /* RW Data Buffer and Command */
|
||||
#define IG4_REG_SS_SCL_HCNT 0x0014 /* RW Std Speed clock High Count */
|
||||
#define IG4_REG_SS_SCL_LCNT 0x0018 /* RW Std Speed clock Low Count */
|
||||
#define IG4_REG_FS_SCL_HCNT 0x001C /* RW Fast Speed clock High Count */
|
||||
#define IG4_REG_FS_SCL_LCNT 0x0020 /* RW Fast Speed clock Low Count */
|
||||
#define IG4_REG_INTR_STAT 0x002C /* RO Interrupt Status */
|
||||
#define IG4_REG_INTR_MASK 0x0030 /* RW Interrupt Mask */
|
||||
#define IG4_REG_RAW_INTR_STAT 0x0034 /* RO Raw Interrupt Status */
|
||||
#define IG4_REG_RX_TL 0x0038 /* RW Receive FIFO Threshold */
|
||||
#define IG4_REG_TX_TL 0x003C /* RW Transmit FIFO Threshold */
|
||||
#define IG4_REG_CLR_INTR 0x0040 /* RO Clear Interrupt */
|
||||
#define IG4_REG_CLR_RX_UNDER 0x0044 /* RO Clear RX_Under Interrupt */
|
||||
#define IG4_REG_CLR_RX_OVER 0x0048 /* RO Clear RX_Over Interrupt */
|
||||
#define IG4_REG_CLR_TX_OVER 0x004C /* RO Clear TX_Over Interrupt */
|
||||
#define IG4_REG_CLR_TX_ABORT 0x0054 /* RO Clear TX_Abort Interrupt */
|
||||
#define IG4_REG_CLR_ACTIVITY 0x005C /* RO Clear Activity Interrupt */
|
||||
#define IG4_REG_CLR_STOP_DET 0x0060 /* RO Clear STOP Detection Int */
|
||||
#define IG4_REG_CLR_START_DET 0x0064 /* RO Clear START Detection Int */
|
||||
#define IG4_REG_CLR_GEN_CALL 0x0068 /* RO Clear General Call Interrupt */
|
||||
#define IG4_REG_I2C_EN 0x006C /* RW I2C Enable */
|
||||
#define IG4_REG_I2C_STA 0x0070 /* RO I2C Status */
|
||||
#define IG4_REG_TXFLR 0x0074 /* RO Transmit FIFO Level */
|
||||
#define IG4_REG_RXFLR 0x0078 /* RO Receive FIFO Level */
|
||||
#define IG4_REG_SDA_HOLD 0x007C /* RW SDA Hold Time Length */
|
||||
#define IG4_REG_TX_ABRT_SOURCE 0x0080 /* RO Transmit Abort Source */
|
||||
#define IG4_REG_SLV_DATA_NACK 0x0084 /* RW General Slave Data NACK */
|
||||
#define IG4_REG_DMA_CTRL 0x0088 /* RW DMA Control */
|
||||
#define IG4_REG_DMA_TDLR 0x008C /* RW DMA Transmit Data Level */
|
||||
#define IG4_REG_DMA_RDLR 0x0090 /* RW DMA Receive Data Level */
|
||||
#define IG4_REG_SDA_SETUP 0x0094 /* RW SDA Setup */
|
||||
#define IG4_REG_ENABLE_STATUS 0x009C /* RO Enable Status */
|
||||
#define IG4_REG_COMP_PARAM1 0x00F4 /* RO Component Parameter */
|
||||
#define IG4_REG_COMP_VER 0x00F8 /* RO Component Version */
|
||||
#define IG4_REG_COMP_TYPE 0x00FC /* RO Probe width/endian? (linux) */
|
||||
#define IG4_REG_CLK_PARMS 0x0800 /* RW Clock Parameters */
|
||||
#define IG4_REG_RESETS 0x0804 /* RW Reset Register */
|
||||
#define IG4_REG_GENERAL 0x0808 /* RW General Register */
|
||||
#define IG4_REG_SW_LTR_VALUE 0x0810 /* RW SW LTR Value */
|
||||
#define IG4_REG_AUTO_LTR_VALUE 0x0814 /* RW Auto LTR Value */
|
||||
|
||||
/*
|
||||
* CTL - Control Register 22.2.1
|
||||
* Default Value: 0x0000007F.
|
||||
*
|
||||
* RESTARTEN - RW Restart Enable
|
||||
* 10BIT - RW Controller operates in 10-bit mode, else 7-bit
|
||||
*
|
||||
* NOTE: When restart is disabled the controller is incapable of
|
||||
* performing the following functions:
|
||||
*
|
||||
* Sending a START Byte
|
||||
* Performing any high-speed mode op
|
||||
* Performing direction changes in combined format mode
|
||||
* Performing a read operation with a 10-bit address
|
||||
*
|
||||
* Attempting to perform the above operations will result in the
|
||||
* TX_ABORT bit being set in RAW_INTR_STAT.
|
||||
*/
|
||||
#define IG4_CTL_SLAVE_DISABLE 0x0040 /* snarfed from linux */
|
||||
#define IG4_CTL_RESTARTEN 0x0020 /* Allow Restart when master */
|
||||
#define IG4_CTL_10BIT 0x0010 /* ctlr accepts 10-bit addresses */
|
||||
#define IG4_CTL_SPEED_FAST 0x0004 /* snarfed from linux */
|
||||
#define IG4_CTL_SPEED_STD 0x0002 /* snarfed from linux */
|
||||
#define IG4_CTL_MASTER 0x0001 /* snarfed from linux */
|
||||
|
||||
/*
|
||||
* TAR_ADD - Target Address Register 22.2.2
|
||||
* Default Value: 0x00000055F
|
||||
*
|
||||
* 10BIT - RW controller starts its transfers in 10-bit
|
||||
* address mode, else 7-bit.
|
||||
*
|
||||
* SPECIAL - RW Indicates whether software performs a General Call
|
||||
* or START BYTE command.
|
||||
*
|
||||
* 0 Ignore GC_OR_START and use TAR address.
|
||||
*
|
||||
* 1 Perform special I2C Command based on GC_OR_START.
|
||||
*
|
||||
* GC_OR_START - RW (only if SPECIAL is set)
|
||||
*
|
||||
* 0 General Call Address. After issuing a General Call,
|
||||
* only writes may be performed. Attempting to issue
|
||||
* a read command results in IX_ABRT in RAW_INTR_STAT.
|
||||
* The controller remains in General Call mode until
|
||||
* bit 11 (SPECIAL) is cleared.
|
||||
*
|
||||
* 1 START BYTE.
|
||||
*
|
||||
*
|
||||
* IC_TAR - RW when transmitting a general call, these bits are
|
||||
* ignored. To generate a START BYTE, the address
|
||||
* needs to be written into these bits once.
|
||||
*
|
||||
* This register should only be updated when the IIC is disabled (I2C_ENABLE=0)
|
||||
*/
|
||||
#define IG4_TAR_10BIT 0x1000 /* start xfer in 10-bit mode */
|
||||
#define IG4_TAR_SPECIAL 0x0800 /* Perform special command */
|
||||
#define IG4_TAR_GC_OR_START 0x0400 /* General Call or Start */
|
||||
#define IG4_TAR_ADDR_MASK 0x03FF /* Target address */
|
||||
|
||||
/*
|
||||
* TAR_DATA_CMD - Data Buffer and Command Register 22.2.3
|
||||
*
|
||||
* RESTART - RW This bit controls whether a forced RESTART is
|
||||
* issued before the byte is sent or received.
|
||||
*
|
||||
* 0 If not set a RESTART is only issued if the tranfer
|
||||
* direction is changing from the previous command.
|
||||
*
|
||||
* 1 A RESTART is issued before the byte is sent or
|
||||
* received, regardless of whether or not the transfer
|
||||
* direction is changing from the previous command.
|
||||
*
|
||||
* STOP - RW This bit controls whether a STOP is issued after
|
||||
* the byte is sent or received.
|
||||
*
|
||||
* 0 STOP is not issued after this byte, regardless
|
||||
* of whether or not the Tx FIFO is empty.
|
||||
*
|
||||
* 1 STOP is issued after this byte, regardless of
|
||||
* whether or not the Tx FIFO is empty. If the
|
||||
* Tx FIFO is not empty the master immediately tries
|
||||
* to start a new transfer by issuing a START and
|
||||
* arbitrating for the bus.
|
||||
*
|
||||
* i.e. the STOP is issued along with this byte,
|
||||
* within the write stream.
|
||||
*
|
||||
* COMMAND - RW Control whether a read or write is performed.
|
||||
*
|
||||
* 0 WRITE
|
||||
*
|
||||
* 1 READ
|
||||
*
|
||||
* DATA (7:0) - RW Contains the data to be transmitted or received
|
||||
* on the I2C bus.
|
||||
*
|
||||
* NOTE: Writing to this register causes a START + slave + RW to be
|
||||
* issued if the direction has changed or the last data byte was
|
||||
* sent with a STOP.
|
||||
*
|
||||
* NOTE: We control termination? so this register must be written
|
||||
* for each byte we wish to receive. We can then drain the
|
||||
* receive FIFO.
|
||||
*/
|
||||
|
||||
#define IG4_DATA_RESTART 0x0400 /* Force RESTART */
|
||||
#define IG4_DATA_STOP 0x0200 /* Force STOP[+START] */
|
||||
#define IG4_DATA_COMMAND_RD 0x0100 /* bus direction 0=write 1=read */
|
||||
#define IG4_DATA_MASK 0x00FF
|
||||
|
||||
/*
|
||||
* SS_SCL_HCNT - Standard Speed Clock High Count Register 22.2.4
|
||||
* SS_SCL_LCNT - Standard Speed Clock Low Count Register 22.2.5
|
||||
* FS_SCL_HCNT - Fast Speed Clock High Count Register 22.2.6
|
||||
* FS_SCL_LCNT - Fast Speed Clock Low Count Register 22.2.7
|
||||
*
|
||||
* COUNT (15:0) - Set the period count to a value between 6 and
|
||||
* 65525.
|
||||
*/
|
||||
#define IG4_SCL_CLOCK_MASK 0xFFFFU /* count bits in register */
|
||||
|
||||
/*
|
||||
* INTR_STAT - (RO) Interrupt Status Register 22.2.8
|
||||
* INTR_MASK - (RW) Interrupt Mask Register 22.2.9
|
||||
* RAW_INTR_STAT- (RO) Raw Interrupt Status Register 22.2.10
|
||||
*
|
||||
* GEN_CALL Set only when a general call (broadcast) address
|
||||
* is received and acknowleged, stays set until
|
||||
* cleared by reading CLR_GEN_CALL.
|
||||
*
|
||||
* START_DET Set when a START or RESTART condition has occurred
|
||||
* on the interface.
|
||||
*
|
||||
* STOP_DET Set when a STOP condition has occurred on the
|
||||
* interface.
|
||||
*
|
||||
* ACTIVITY Set by any activity on the interface. Cleared
|
||||
* by reading CLR_ACTIVITY or CLR_INTR.
|
||||
*
|
||||
* TX_ABRT Indicates the controller as a transmitter is
|
||||
* unable to complete the intended action. When set,
|
||||
* the controller will hold the TX FIFO in a reset
|
||||
* state (flushed) until CLR_TX_ABORT is read to
|
||||
* clear the condition. Once cleared, the TX FIFO
|
||||
* will be available again.
|
||||
*
|
||||
* TX_EMPTY Indicates that the transmitter is at or below
|
||||
* the specified TX_TL threshold. Automatically
|
||||
* cleared by HW when the buffer level goes above
|
||||
* the threshold.
|
||||
*
|
||||
* TX_OVER Indicates that the processer attempted to write
|
||||
* to the TX FIFO while the TX FIFO was full. Cleared
|
||||
* by reading CLR_TX_OVER.
|
||||
*
|
||||
* RX_FULL Indicates that the receive FIFO has reached or
|
||||
* exceeded the specified RX_TL threshold. Cleared
|
||||
* by HW when the cpu drains the FIFO to below the
|
||||
* threshold.
|
||||
*
|
||||
* RX_OVER Indicates that the receive FIFO was unable to
|
||||
* accept new data and data was lost. Cleared by
|
||||
* reading CLR_RX_OVER.
|
||||
*
|
||||
* RX_UNDER Indicates that the cpu attempted to read data
|
||||
* from the receive buffer while the RX FIFO was
|
||||
* empty. Cleared by reading CLR_RX_UNDER.
|
||||
*
|
||||
* NOTES ON RAW_INTR_STAT:
|
||||
*
|
||||
* This register can be used to monitor the GEN_CALL, START_DET,
|
||||
* STOP_DET, ACTIVITY, TX_ABRT, TX_EMPTY, TX_OVER, RX_FULL, RX_OVER,
|
||||
* and RX_UNDER bits. The documentation is a bit unclear but presumably
|
||||
* this is the unlatched version.
|
||||
*
|
||||
* Code should test FIFO conditions using the I2C_STA (status) register,
|
||||
* not the interrupt status registers.
|
||||
*/
|
||||
|
||||
#define IG4_INTR_GEN_CALL 0x0800
|
||||
#define IG4_INTR_START_DET 0x0400
|
||||
#define IG4_INTR_STOP_DET 0x0200
|
||||
#define IG4_INTR_ACTIVITY 0x0100
|
||||
#define IG4_INTR_TX_ABRT 0x0040
|
||||
#define IG4_INTR_TX_EMPTY 0x0010
|
||||
#define IG4_INTR_TX_OVER 0x0008
|
||||
#define IG4_INTR_RX_FULL 0x0004
|
||||
#define IG4_INTR_RX_OVER 0x0002
|
||||
#define IG4_INTR_RX_UNDER 0x0001
|
||||
|
||||
/*
|
||||
* RX_TL - (RW) Receive FIFO Threshold Register 22.2.11
|
||||
* TX_TL - (RW) Transmit FIFO Threshold Register 22.2.12
|
||||
*
|
||||
* Specify the receive and transmit FIFO threshold register. The
|
||||
* FIFOs have 16 elements. The valid range is 0-15. Setting a
|
||||
* value greater than 15 causes the actual value to be the maximum
|
||||
* depth of the FIFO.
|
||||
*
|
||||
* Generally speaking since everything is messaged, we can use a
|
||||
* mid-level setting for both parameters and (e.g.) fully drain the
|
||||
* receive FIFO on the STOP_DET condition to handle loose ends.
|
||||
*/
|
||||
#define IG4_FIFO_MASK 0x00FF
|
||||
#define IG4_FIFO_LIMIT 16
|
||||
|
||||
/*
|
||||
* CLR_INTR - (RO) Clear Interrupt Register 22.2.13
|
||||
* CLR_RX_UNDER - (RO) Clear Interrupt Register (specific) 22.2.14
|
||||
* CLR_RX_OVER - (RO) Clear Interrupt Register (specific) 22.2.15
|
||||
* CLR_TX_OVER - (RO) Clear Interrupt Register (specific) 22.2.16
|
||||
* CLR_TX_ABORT - (RO) Clear Interrupt Register (specific) 22.2.17
|
||||
* CLR_ACTIVITY - (RO) Clear Interrupt Register (specific) 22.2.18
|
||||
* CLR_STOP_DET - (RO) Clear Interrupt Register (specific) 22.2.19
|
||||
* CLR_START_DET- (RO) Clear Interrupt Register (specific) 22.2.20
|
||||
* CLR_GEN_CALL - (RO) Clear Interrupt Register (specific) 22.2.21
|
||||
*
|
||||
* CLR_* specific operations clear the appropriate bit in the
|
||||
* RAW_INTR_STAT register. Intel does not really document whether
|
||||
* these operations clear the normal interrupt status register.
|
||||
*
|
||||
* CLR_INTR clears bits in the normal interrupt status register and
|
||||
* presumably also the raw(?) register? Intel is again unclear.
|
||||
*
|
||||
* NOTE: CLR_INTR only clears software-clearable interrupts. Hardware
|
||||
* clearable interrupts are controlled entirely by the hardware.
|
||||
* CLR_INTR also clears the TX_ABRT_SOURCE register.
|
||||
*
|
||||
* NOTE: CLR_TX_ABORT also clears the TX_ABRT_SOURCE register and releases
|
||||
* the TX FIFO from its flushed/reset state, allowing more writes
|
||||
* to the TX FIFO.
|
||||
*
|
||||
* NOTE: CLR_ACTIVITY has no effect if the I2C bus is still active.
|
||||
* Intel documents that the bit is automatically cleared when
|
||||
* there is no further activity on the bus.
|
||||
*/
|
||||
#define IG4_CLR_BIT 0x0001 /* Reflects source */
|
||||
|
||||
/*
|
||||
* I2C_EN - (RW) I2C Enable Register 22.2.22
|
||||
*
|
||||
* ABORT Software can abort an I2C transfer by setting this
|
||||
* bit. Hardware will clear the bit once the STOP has
|
||||
* been detected. This bit can only be set while the
|
||||
* I2C interface is enabled.
|
||||
*
|
||||
* I2C_ENABLE Enable the controller, else disable it.
|
||||
* (Use I2C_ENABLE_STATUS to poll enable status
|
||||
* & wait for changes)
|
||||
*/
|
||||
#define IG4_I2C_ABORT 0x0002
|
||||
#define IG4_I2C_ENABLE 0x0001
|
||||
|
||||
/*
|
||||
* I2C_STA - (RO) I2C Status Register 22.2.23
|
||||
*/
|
||||
#define IG4_STATUS_ACTIVITY 0x0020 /* Controller is active */
|
||||
#define IG4_STATUS_RX_FULL 0x0010 /* RX FIFO completely full */
|
||||
#define IG4_STATUS_RX_NOTEMPTY 0x0008 /* RX FIFO not empty */
|
||||
#define IG4_STATUS_TX_EMPTY 0x0004 /* TX FIFO completely empty */
|
||||
#define IG4_STATUS_TX_NOTFULL 0x0002 /* TX FIFO not full */
|
||||
#define IG4_STATUS_I2C_ACTIVE 0x0001 /* I2C bus is active */
|
||||
|
||||
/*
|
||||
* TXFLR - (RO) Transmit FIFO Level Register 22.2.24
|
||||
* RXFLR - (RO) Receive FIFO Level Register 22.2.25
|
||||
*
|
||||
* Read the number of entries currently in the Transmit or Receive
|
||||
* FIFOs. Note that for some reason the mask is 9 bits instead of
|
||||
* the 8 bits the fill level controls.
|
||||
*/
|
||||
#define IG4_FIFOLVL_MASK 0x001F
|
||||
|
||||
/*
|
||||
* SDA_HOLD - (RW) SDA Hold Time Length Register 22.2.26
|
||||
*
|
||||
* Set the SDA hold time length register in I2C clocks.
|
||||
*/
|
||||
#define IG4_SDA_HOLD_MASK 0x00FF
|
||||
|
||||
/*
|
||||
* TX_ABRT_SOURCE- (RO) Transmit Abort Source Register 22.2.27
|
||||
*
|
||||
* Indicates the cause of a transmit abort. This can indicate a
|
||||
* software programming error or a device expected address width
|
||||
* mismatch or other issues. The NORESTART conditions and GENCALL_NOACK
|
||||
* can only occur if a programming error was made in the driver software.
|
||||
*
|
||||
* In particular, it should be possible to detect whether any devices
|
||||
* are on the bus by observing the GENCALL_READ status, and it might
|
||||
* be possible to detect ADDR7 vs ADDR10 mismatches.
|
||||
*/
|
||||
#define IG4_ABRTSRC_TRANSFER 0x00010000 /* Abort initiated by user */
|
||||
#define IG4_ABRTSRC_ARBLOST 0x00001000 /* Arbitration lost */
|
||||
#define IG4_ABRTSRC_NORESTART_10 0x00000400 /* RESTART disabled */
|
||||
#define IG4_ABRTSRC_NORESTART_START 0x00000200 /* RESTART disabled */
|
||||
#define IG4_ABRTSRC_ACKED_START 0x00000080 /* Improper acked START */
|
||||
#define IG4_ABRTSRC_GENCALL_NOACK 0x00000020 /* Improper GENCALL */
|
||||
#define IG4_ABRTSRC_GENCALL_READ 0x00000010 /* Nobody acked GENCALL */
|
||||
#define IG4_ABRTSRC_TXNOACK_DATA 0x00000008 /* data phase no ACK */
|
||||
#define IG4_ABRTSRC_TXNOACK_ADDR10_2 0x00000004 /* addr10/1 phase no ACK */
|
||||
#define IG4_ABRTSRC_TXNOACK_ADDR10_1 0x00000002 /* addr10/2 phase no ACK */
|
||||
#define IG4_ABRTSRC_TXNOACK_ADDR7 0x00000001 /* addr7 phase no ACK */
|
||||
|
||||
/*
|
||||
* SLV_DATA_NACK - (RW) Generate Slave DATA NACK Register 22.2.28
|
||||
*
|
||||
* When the controller is a receiver a NACK can be generated on
|
||||
* receipt of data.
|
||||
*
|
||||
* NACK_GENERATE Set to 0 for normal NACK/ACK generation.
|
||||
* Set to 1 to generate a NACK after next data
|
||||
* byte received.
|
||||
*
|
||||
*/
|
||||
#define IG4_NACK_GENERATE 0x0001
|
||||
|
||||
/*
|
||||
* DMA_CTRL - (RW) DMA Control Register 22.2.29
|
||||
*
|
||||
* Enables DMA on the transmit and/or receive DMA channel.
|
||||
*/
|
||||
#define IG4_TX_DMA_ENABLE 0x0002
|
||||
#define IG4_RX_DMA_ENABLE 0x0001
|
||||
|
||||
/*
|
||||
* DMA_TDLR - (RW) DMA Transmit Data Level Register 22.2.30
|
||||
* DMA_RDLR - (RW) DMA Receive Data Level Register 22.2.31
|
||||
*
|
||||
* Similar to RX_TL and TX_TL but controls when a DMA burst occurs
|
||||
* to empty or fill the FIFOs. Use the same IG4_FIFO_MASK and
|
||||
* IG4_FIFO_LIMIT defines for RX_RL and TX_TL.
|
||||
*/
|
||||
/* empty */
|
||||
|
||||
/*
|
||||
* SDA_SETUP - (RW) SDA Setup Time Length Register 22.2.32
|
||||
*
|
||||
* Set the SDA setup time length register in I2C clocks.
|
||||
* The register must be programmed with a value >=2.
|
||||
* (Defaults to 0x64).
|
||||
*/
|
||||
#define IG4_SDA_SETUP_MASK 0x00FF
|
||||
|
||||
/*
|
||||
* ACK_GEN_CALL - (RW) ACK General Call Register 22.2.33
|
||||
*
|
||||
* Control whether the controller responds with a ACK or NACK when
|
||||
* it receives an I2C General Call address.
|
||||
*
|
||||
* If set to 0 a NACK is generated and a General Call interrupt is
|
||||
* NOT generated. Otherwise an ACK + interrupt is generated.
|
||||
*/
|
||||
#define IG4_ACKGC_ACK 0x0001
|
||||
|
||||
/*
|
||||
* ENABLE_STATUS - (RO) Enable Status Registger 22.2.34
|
||||
*
|
||||
* DATA_LOST - Indicates that a slave receiver operation has
|
||||
* been aborted with at least one data byte received
|
||||
* from a transfer due to the I2C controller being
|
||||
* disabled (IG4_I2C_ENABLE -> 0)
|
||||
*
|
||||
* ENABLED - Intel documentation is lacking but I assume this
|
||||
* is a reflection of the IG4_I2C_ENABLE bit in the
|
||||
* I2C_EN register.
|
||||
*
|
||||
*/
|
||||
#define IG4_ENASTAT_DATA_LOST 0x0004
|
||||
#define IG4_ENASTAT_ENABLED 0x0001
|
||||
|
||||
/*
|
||||
* COMP_PARAM1 - (RO) Component Parameter Register 22.2.35
|
||||
* Default Value 0x00FFFF6E
|
||||
*
|
||||
* VALID - Intel documentation is unclear but I believe this
|
||||
* must be read as a 1 to indicate that the rest of
|
||||
* the bits in the register are valid.
|
||||
*
|
||||
* HASDMA - Indicates that the chip is DMA-capable. Presumably
|
||||
* in certain virtualization cases the chip might be
|
||||
* set to not be DMA-capable.
|
||||
*
|
||||
* INTR_IO - Indicates that all interrupts are combined to
|
||||
* generate one interrupt. If not set, interrupts
|
||||
* are individual (more virtualization stuff?)
|
||||
*
|
||||
* HCCNT_RO - Indicates that the clock timing registers are
|
||||
* RW. If not set, the registers are RO.
|
||||
* (more virtualization stuff).
|
||||
*
|
||||
* MAXSPEED - Indicates the maximum speed supported.
|
||||
*
|
||||
* DATAW - Indicates the internal bus width in bits.
|
||||
*/
|
||||
#define IG4_PARAM1_TXFIFO_DEPTH(v) (((v) >> 16) & 0xFF)
|
||||
#define IG4_PARAM1_RXFIFO_DEPTH(v) (((v) >> 8) & 0xFF)
|
||||
#define IG4_PARAM1_CONFIG_VALID 0x00000080
|
||||
#define IG4_PARAM1_CONFIG_HASDMA 0x00000040
|
||||
#define IG4_PARAM1_CONFIG_INTR_IO 0x00000020
|
||||
#define IG4_PARAM1_CONFIG_HCCNT_RO 0x00000010
|
||||
#define IG4_PARAM1_CONFIG_MAXSPEED_MASK 0x0000000C
|
||||
#define IG4_PARAM1_CONFIG_DATAW_MASK 0x00000003
|
||||
|
||||
#define IG4_CONFIG_MAXSPEED_RESERVED00 0x00000000
|
||||
#define IG4_CONFIG_MAXSPEED_STANDARD 0x00000004
|
||||
#define IG4_CONFIG_MAXSPEED_FAST 0x00000008
|
||||
#define IG4_CONFIG_MAXSPEED_HIGH 0x0000000C
|
||||
|
||||
#define IG4_CONFIG_DATAW_8 0x00000000
|
||||
#define IG4_CONFIG_DATAW_16 0x00000001
|
||||
#define IG4_CONFIG_DATAW_32 0x00000002
|
||||
#define IG4_CONFIG_DATAW_RESERVED11 0x00000003
|
||||
|
||||
/*
|
||||
* COMP_VER - (RO) Component Version Register 22.2.36
|
||||
* Default Value 0x3131352A
|
||||
*
|
||||
* Contains the chip version number. All 32 bits.
|
||||
*/
|
||||
#define IG4_COMP_VER 0x3131352A
|
||||
|
||||
/*
|
||||
* COMP_TYPE - (RO) (linux) Endian and bus width probe
|
||||
*
|
||||
* Read32 from this register and test against IG4_COMP_TYPE
|
||||
* to determine the bus width. e.g. 01404457 = endian-reversed,
|
||||
* and 00000140 or 00004457 means internal 16-bit bus (?).
|
||||
*
|
||||
* This register is not in the intel documentation, I pulled it
|
||||
* from the linux driver i2c-designware-core.c.
|
||||
*/
|
||||
#define IG4_COMP_TYPE 0x44570140
|
||||
|
||||
/*
|
||||
* RESETS - (RW) Resets Register 22.2.37
|
||||
*
|
||||
* Used to reset the I2C host controller by SW. There is no timing
|
||||
* requirement, software can assert and de-assert in back-to-back
|
||||
* transactions.
|
||||
*
|
||||
* 00 I2C host controller is NOT in reset.
|
||||
* 01 (reserved)
|
||||
* 10 (reserved)
|
||||
* 11 I2C host controller is in reset.
|
||||
*/
|
||||
#define IG4_RESETS_ASSERT 0x0003
|
||||
#define IG4_RESETS_DEASSERT 0x0000
|
||||
|
||||
/*
|
||||
* GENERAL - (RW) General Reigster 22.2.38
|
||||
*
|
||||
* IOVOLT 0=1.8V 1=3.3V
|
||||
*
|
||||
* LTR 0=Auto 1=SW
|
||||
*
|
||||
* In Auto mode the BIOS will write to the host controller's
|
||||
* AUTO LTR Value register (offset 0x0814) with the active
|
||||
* state LTR value, and will write to the SW LTR Value register
|
||||
* (offset 0x0810) with the idle state LTR value.
|
||||
*
|
||||
* In SW mode the SW will write to the host controller SW LTR
|
||||
* value (offset 0x0810). It is the SW responsibility to update
|
||||
* the LTR with the appropriate value.
|
||||
*/
|
||||
#define IG4_GENERAL_IOVOLT3_3 0x0008
|
||||
#define IG4_GENERAL_SWMODE 0x0004
|
||||
|
||||
/*
|
||||
* SW_LTR_VALUE - (RW) SW LTR Value Register 22.2.39
|
||||
* AUTO_LTR_VALUE - (RW) SW LTR Value Register 22.2.40
|
||||
*
|
||||
* Default value is 0x00000800 which means the best possible
|
||||
* service/response time.
|
||||
*
|
||||
* It isn't quite clear how the snooping works. There are two scale
|
||||
* bits for both sets but two of the four codes are reserved. The
|
||||
* *SNOOP_VALUE() is specified as a 10-bit latency value. If 0, it
|
||||
* indicates that the device cannot tolerate any delay and needs the
|
||||
* best possible service/response time.
|
||||
*
|
||||
* I think this is for snooping (testing) the I2C bus. The lowest
|
||||
* delay (0) probably runs the controller polling at a high, power hungry
|
||||
* rate. But I dunno.
|
||||
*/
|
||||
#define IG4_SWLTR_NSNOOP_REQ 0x80000000 /* (ro) */
|
||||
#define IG4_SWLTR_NSNOOP_SCALE_MASK 0x1C000000 /* (ro) */
|
||||
#define IG4_SWLTR_NSNOOP_SCALE_1US 0x08000000 /* (ro) */
|
||||
#define IG4_SWLTR_NSNOOP_SCALE_32US 0x0C000000 /* (ro) */
|
||||
#define IG4_SWLTR_NSNOOP_VALUE_DECODE(v) (((v) >> 16) & 0x3F)
|
||||
#define IG4_SWLTR_NSNOOP_VALUE_ENCODE(v) (((v) & 0x3F) << 16)
|
||||
|
||||
#define IG4_SWLTR_SNOOP_REQ 0x00008000 /* (rw) */
|
||||
#define IG4_SWLTR_SNOOP_SCALE_MASK 0x00001C00 /* (rw) */
|
||||
#define IG4_SWLTR_SNOOP_SCALE_1US 0x00000800 /* (rw) */
|
||||
#define IG4_SWLTR_SNOOP_SCALE_32US 0x00000C00 /* (rw) */
|
||||
#define IG4_SWLTR_SNOOP_VALUE_DECODE(v) ((v) & 0x3F)
|
||||
#define IG4_SWLTR_SNOOP_VALUE_ENCODE(v) ((v) & 0x3F)
|
||||
|
||||
#endif
|
96
sys/dev/ichiic/ig4_var.h
Normal file
96
sys/dev/ichiic/ig4_var.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The DragonFly Project. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The DragonFly Project
|
||||
* by Matthew Dillon <dillon@backplane.com> and was subsequently ported
|
||||
* to FreeBSD by Michael Gmelin <freebsd@grem.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name of The DragonFly Project nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific, prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BUS_SMBUS_INTELGEN4_IG4_VAR_H_
|
||||
#define _BUS_SMBUS_INTELGEN4_IG4_VAR_H_
|
||||
|
||||
#include "bus_if.h"
|
||||
#include "device_if.h"
|
||||
#include "pci_if.h"
|
||||
#include "smbus_if.h"
|
||||
|
||||
#define IG4_RBUFSIZE 128
|
||||
#define IG4_RBUFMASK (IG4_RBUFSIZE - 1)
|
||||
|
||||
enum ig4_op { IG4_IDLE, IG4_READ, IG4_WRITE };
|
||||
|
||||
struct ig4iic_softc {
|
||||
device_t dev;
|
||||
struct intr_config_hook enum_hook;
|
||||
device_t smb;
|
||||
struct resource *regs_res;
|
||||
int regs_rid;
|
||||
struct resource *intr_res;
|
||||
int intr_rid;
|
||||
void *intr_handle;
|
||||
int intr_type;
|
||||
enum ig4_op op;
|
||||
int cmd;
|
||||
int rnext;
|
||||
int rpos;
|
||||
char rbuf[IG4_RBUFSIZE];
|
||||
int error;
|
||||
uint8_t last_slave;
|
||||
int pci_attached : 1;
|
||||
int use_10bit : 1;
|
||||
int slave_valid : 1;
|
||||
int read_started : 1;
|
||||
int write_started : 1;
|
||||
struct mtx mutex;
|
||||
};
|
||||
|
||||
typedef struct ig4iic_softc ig4iic_softc_t;
|
||||
|
||||
/* Attach/Detach called from ig4iic_pci_*() */
|
||||
int ig4iic_attach(ig4iic_softc_t *sc);
|
||||
int ig4iic_detach(ig4iic_softc_t *sc);
|
||||
|
||||
/* SMBus methods */
|
||||
extern smbus_callback_t ig4iic_smb_callback;
|
||||
extern smbus_quick_t ig4iic_smb_quick;
|
||||
extern smbus_sendb_t ig4iic_smb_sendb;
|
||||
extern smbus_recvb_t ig4iic_smb_recvb;
|
||||
extern smbus_writeb_t ig4iic_smb_writeb;
|
||||
extern smbus_writew_t ig4iic_smb_writew;
|
||||
extern smbus_readb_t ig4iic_smb_readb;
|
||||
extern smbus_readw_t ig4iic_smb_readw;
|
||||
extern smbus_pcall_t ig4iic_smb_pcall;
|
||||
extern smbus_bwrite_t ig4iic_smb_bwrite;
|
||||
extern smbus_bread_t ig4iic_smb_bread;
|
||||
extern smbus_trans_t ig4iic_smb_trans;
|
||||
|
||||
#endif
|
@ -199,8 +199,8 @@ static int ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS);
|
||||
#ifdef PCI_IOV
|
||||
static int ixl_adminq_err_to_errno(enum i40e_admin_queue_err err);
|
||||
|
||||
static int ixl_init_iov(device_t dev, uint16_t num_vfs, const nvlist_t*);
|
||||
static void ixl_uninit_iov(device_t dev);
|
||||
static int ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t*);
|
||||
static void ixl_iov_uninit(device_t dev);
|
||||
static int ixl_add_vf(device_t dev, uint16_t vfnum, const nvlist_t*);
|
||||
|
||||
static void ixl_handle_vf_msg(struct ixl_pf *,
|
||||
@ -222,9 +222,9 @@ static device_method_t ixl_methods[] = {
|
||||
DEVMETHOD(device_detach, ixl_detach),
|
||||
DEVMETHOD(device_shutdown, ixl_shutdown),
|
||||
#ifdef PCI_IOV
|
||||
DEVMETHOD(pci_init_iov, ixl_init_iov),
|
||||
DEVMETHOD(pci_uninit_iov, ixl_uninit_iov),
|
||||
DEVMETHOD(pci_add_vf, ixl_add_vf),
|
||||
DEVMETHOD(pci_iov_init, ixl_iov_init),
|
||||
DEVMETHOD(pci_iov_uninit, ixl_iov_uninit),
|
||||
DEVMETHOD(pci_iov_add_vf, ixl_add_vf),
|
||||
#endif
|
||||
{0, 0}
|
||||
};
|
||||
@ -6456,7 +6456,7 @@ ixl_adminq_err_to_errno(enum i40e_admin_queue_err err)
|
||||
}
|
||||
|
||||
static int
|
||||
ixl_init_iov(device_t dev, uint16_t num_vfs, const nvlist_t *params)
|
||||
ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *params)
|
||||
{
|
||||
struct ixl_pf *pf;
|
||||
struct i40e_hw *hw;
|
||||
@ -6504,7 +6504,7 @@ fail:
|
||||
}
|
||||
|
||||
static void
|
||||
ixl_uninit_iov(device_t dev)
|
||||
ixl_iov_uninit(device_t dev)
|
||||
{
|
||||
struct ixl_pf *pf;
|
||||
struct i40e_hw *hw;
|
||||
|
@ -93,6 +93,7 @@
|
||||
#ifdef PCI_IOV
|
||||
#include <sys/nv.h>
|
||||
#include <sys/iov_schema.h>
|
||||
#include <dev/pci/pci_iov.h>
|
||||
#endif
|
||||
|
||||
#include "i40e_type.h"
|
||||
|
@ -163,33 +163,10 @@ mmcsd_attach(device_t dev)
|
||||
d->d_sectorsize = mmc_get_sector_size(dev);
|
||||
d->d_maxsize = mmc_get_max_data(dev) * d->d_sectorsize;
|
||||
d->d_mediasize = (off_t)mmc_get_media_size(dev) * d->d_sectorsize;
|
||||
d->d_stripeoffset = 0;
|
||||
d->d_stripesize = mmc_get_erase_sector(dev) * d->d_sectorsize;
|
||||
d->d_unit = device_get_unit(dev);
|
||||
d->d_flags = DISKFLAG_CANDELETE;
|
||||
d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize * 1; /* conservative */
|
||||
/*
|
||||
* The d_fw* values are fake. However, layout is aided by making the
|
||||
* number of fwsectors equal to the erase sectors from the drive since
|
||||
* we set the stripe size equal to that. We set fwheads such that there
|
||||
* are ~20 cylinder groups since all values are somewhat arbitrary here
|
||||
* and this gives good behavior with ffs without wasting too much
|
||||
* space. Sadly, geom_part wants to round partitions to these
|
||||
* values. While not bad, in and of itself, the values we present here
|
||||
* will almost certainly be different then the values that USB SD
|
||||
* adapters use and there's too much variation between brands to just
|
||||
* use those values here. Also SD to ATA adapters favor traditional
|
||||
* ata sizes, which are different again from the USB adapters (which
|
||||
* favor SCSI values). This rounding leads to a loss of up to 5% of the
|
||||
* usable space (usually much less, but that's why 20 was selected: to
|
||||
* limit this effect at a few percent). gpart needs a way to override
|
||||
* this behavior for situations like this, but doesn't provide
|
||||
* one. Perhaps this behavior should be tunable as well, but maybe that
|
||||
* belongs in the disk layer. These values will be much better than
|
||||
* the default ones.
|
||||
*/
|
||||
d->d_fwsectors = mmc_get_erase_sector(dev);
|
||||
d->d_fwheads = mmc_get_media_size(dev) / (d->d_fwsectors * 20);
|
||||
d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize;
|
||||
strlcpy(d->d_ident, mmc_get_card_sn_string(dev), sizeof(d->d_ident));
|
||||
strlcpy(d->d_descr, mmc_get_card_id_string(dev), sizeof(d->d_descr));
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,13 +27,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-2013 LSI Corporation.
|
||||
* Copyright (c) 2000-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,13 +27,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-2013 LSI Corporation.
|
||||
* Copyright (c) 2000-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_cnfg.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,13 +27,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-2011 LSI Corporation.
|
||||
* Copyright (c) 2009-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_hbd.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,7 +27,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,8 @@
|
||||
Fusion-MPT MPI 2.0 / 2.5 Header File Change History
|
||||
==============================
|
||||
|
||||
Copyright (c) 2000-2013 LSI Corporation.
|
||||
Copyright (c) 2000-2015 LSI Corporation.
|
||||
Copyright (c) 2013-2015 Avago Technologies
|
||||
|
||||
---------------------------------------
|
||||
Header Set Release Version: 02.00.33
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,13 +27,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-2013 LSI Corporation.
|
||||
* Copyright (c) 2000-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_init.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,13 +27,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-2013 LSI Corporation.
|
||||
* Copyright (c) 2000-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_ioc.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,13 +27,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 LSI Corporation.
|
||||
* Copyright (c) 2012-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_ra.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,13 +27,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-2013 LSI Corporation.
|
||||
* Copyright (c) 2000-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_raid.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,13 +27,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-2013 LSI Corporation.
|
||||
* Copyright (c) 2000-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_sas.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,13 +27,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) 2000-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_targ.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,13 +27,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-2013 LSI Corporation.
|
||||
* Copyright (c) 2000-2015 LSI Corporation.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
*
|
||||
*
|
||||
* Name: mpi2_tool.h
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 LSI Corp.
|
||||
* Copyright (c) 2012-2015 LSI Corp.
|
||||
* Copyright (c) 2013-2015 Avago Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,13 +27,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-2007 LSI Corporation.
|
||||
* Copyright (c) 2000-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-2014 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,12 +25,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* 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) MPT3 */
|
||||
|
||||
/* TODO Move headers to mprvar */
|
||||
#include <sys/types.h>
|
||||
@ -72,7 +75,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/mpr/mpr_ioctl.h>
|
||||
#include <dev/mpr/mprvar.h>
|
||||
#include <dev/mpr/mpr_table.h>
|
||||
#include <dev/mpr/mpr_sas.h>
|
||||
|
||||
static int mpr_diag_reset(struct mpr_softc *sc, int sleep_flag);
|
||||
static int mpr_init_queues(struct mpr_softc *sc);
|
||||
@ -352,11 +354,9 @@ mpr_transition_operational(struct mpr_softc *sc)
|
||||
static int
|
||||
mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching)
|
||||
{
|
||||
int error, i;
|
||||
int error;
|
||||
Mpi2IOCFactsReply_t saved_facts;
|
||||
uint8_t saved_mode, reallocating;
|
||||
struct mprsas_lun *lun, *lun_tmp;
|
||||
struct mprsas_target *targ;
|
||||
|
||||
mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
|
||||
|
||||
@ -513,27 +513,7 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching)
|
||||
*/
|
||||
if (reallocating) {
|
||||
mpr_iocfacts_free(sc);
|
||||
|
||||
/*
|
||||
* The number of targets is based on IOC Facts, so free all of
|
||||
* the allocated LUNs for each target and then the target buffer
|
||||
* itself.
|
||||
*/
|
||||
for (i=0; i< saved_facts.MaxTargets; i++) {
|
||||
targ = &sc->sassc->targets[i];
|
||||
SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link,
|
||||
lun_tmp) {
|
||||
free(lun, M_MPR);
|
||||
}
|
||||
}
|
||||
free(sc->sassc->targets, M_MPR);
|
||||
|
||||
sc->sassc->targets = malloc(sizeof(struct mprsas_target) *
|
||||
sc->facts->MaxTargets, M_MPR, M_WAITOK|M_ZERO);
|
||||
if (!sc->sassc->targets) {
|
||||
panic("%s failed to alloc targets with error %d\n",
|
||||
__func__, ENOMEM);
|
||||
}
|
||||
mprsas_realloc_targets(sc, saved_facts.MaxTargets);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -775,7 +755,7 @@ mpr_reinit(struct mpr_softc *sc)
|
||||
/* the end of discovery will release the simq, so we're done. */
|
||||
mpr_dprint(sc, MPR_INFO, "%s finished sc %p post %u free %u\n",
|
||||
__func__, sc, sc->replypostindex, sc->replyfreeindex);
|
||||
mprsas_release_simq_reinit(sassc);
|
||||
mprsas_release_simq_reinit(sassc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -816,7 +796,8 @@ mpr_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag)
|
||||
* 0.5 milisecond
|
||||
*/
|
||||
if (mtx_owned(&sc->mpr_mtx) && sleep_flag == CAN_SLEEP)
|
||||
msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba", hz/1000);
|
||||
msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba",
|
||||
hz/1000);
|
||||
else if (sleep_flag == CAN_SLEEP)
|
||||
pause("mprdba", hz/1000);
|
||||
else
|
||||
@ -982,7 +963,7 @@ mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
reply_descriptor rd;
|
||||
|
||||
MPR_FUNCTRACE(sc);
|
||||
mpr_dprint(sc, MPR_TRACE, "%s SMID %u cm %p ccb %p\n", __func__,
|
||||
mpr_dprint(sc, MPR_TRACE, "SMID %u cm %p ccb %p\n",
|
||||
cm->cm_desc.Default.SMID, cm, cm->cm_ccb);
|
||||
|
||||
if (sc->mpr_flags & MPR_FLAGS_ATTACH_DONE && !(sc->mpr_flags &
|
||||
@ -1372,6 +1353,8 @@ mpr_get_tunables(struct mpr_softc *sc)
|
||||
sc->disable_msix = 0;
|
||||
sc->disable_msi = 0;
|
||||
sc->max_chains = MPR_CHAIN_FRAMES;
|
||||
sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD;
|
||||
sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
|
||||
|
||||
/*
|
||||
* Grab the global variables.
|
||||
@ -1380,6 +1363,8 @@ mpr_get_tunables(struct mpr_softc *sc)
|
||||
TUNABLE_INT_FETCH("hw.mpr.disable_msix", &sc->disable_msix);
|
||||
TUNABLE_INT_FETCH("hw.mpr.disable_msi", &sc->disable_msi);
|
||||
TUNABLE_INT_FETCH("hw.mpr.max_chains", &sc->max_chains);
|
||||
TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu);
|
||||
TUNABLE_INT_FETCH("hw.mpr.spinup_wait_time", &sc->spinup_wait_time);
|
||||
|
||||
/* Grab the unit-instance variables */
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level",
|
||||
@ -1402,6 +1387,14 @@ mpr_get_tunables(struct mpr_softc *sc)
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.exclude_ids",
|
||||
device_get_unit(sc->mpr_dev));
|
||||
TUNABLE_STR_FETCH(tmpstr, sc->exclude_ids, sizeof(sc->exclude_ids));
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.enable_ssu",
|
||||
device_get_unit(sc->mpr_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->enable_ssu);
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.spinup_wait_time",
|
||||
device_get_unit(sc->mpr_dev));
|
||||
TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1474,11 +1467,20 @@ mpr_setup_sysctl(struct mpr_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
|
||||
@ -2096,7 +2098,7 @@ mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle,
|
||||
(reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
|
||||
error = ENXIO;
|
||||
|
||||
if(reply)
|
||||
if (reply)
|
||||
mpr_print_event(sc, reply);
|
||||
|
||||
mpr_dprint(sc, MPR_TRACE, "%s finished error %d\n", __func__, error);
|
||||
@ -2163,8 +2165,8 @@ mpr_deregister_events(struct mpr_softc *sc, struct mpr_event_handle *handle)
|
||||
* Add a chain element as the next SGE for the specified command.
|
||||
* Reset cm_sge and cm_sgesize to indicate all the available space. Chains are
|
||||
* only required for IEEE commands. Therefore there is no code for commands
|
||||
* that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands shouldn't
|
||||
* be requesting chains).
|
||||
* that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands
|
||||
* shouldn't be requesting chains).
|
||||
*/
|
||||
static int
|
||||
mpr_add_chain(struct mpr_command *cm, int segsleft)
|
||||
@ -2246,9 +2248,9 @@ mpr_add_chain(struct mpr_command *cm, int segsleft)
|
||||
|
||||
/*
|
||||
* Add one scatter-gather element to the scatter-gather list for a command.
|
||||
* Maintain cm_sglsize and cm_sge as the remaining size and pointer to the next
|
||||
* SGE to fill in, respectively. In Gen3, the MPI SGL does not have a chain,
|
||||
* so don't consider any chain additions.
|
||||
* Maintain cm_sglsize and cm_sge as the remaining size and pointer to the
|
||||
* next SGE to fill in, respectively. In Gen3, the MPI SGL does not have a
|
||||
* chain, so don't consider any chain additions.
|
||||
*/
|
||||
int
|
||||
mpr_push_sge(struct mpr_command *cm, MPI2_SGE_SIMPLE64 *sge, size_t len,
|
||||
@ -2660,7 +2662,7 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
}
|
||||
}
|
||||
|
||||
if(error) {
|
||||
if (error) {
|
||||
mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s\n", __func__);
|
||||
rc = mpr_reinit(sc);
|
||||
mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ?
|
||||
@ -2717,9 +2719,12 @@ mpr_read_config_page(struct mpr_softc *sc, struct mpr_config_params *params)
|
||||
|
||||
cm->cm_data = params->buffer;
|
||||
cm->cm_length = params->length;
|
||||
cm->cm_sge = &req->PageBufferSGE;
|
||||
cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
|
||||
cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
|
||||
if (cm->cm_data != NULL) {
|
||||
cm->cm_sge = &req->PageBufferSGE;
|
||||
cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
|
||||
cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
|
||||
} else
|
||||
cm->cm_sge = NULL;
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
|
||||
cm->cm_complete_data = params;
|
||||
@ -2776,9 +2781,12 @@ mpr_config_complete(struct mpr_softc *sc, struct mpr_command *cm)
|
||||
goto done;
|
||||
}
|
||||
params->status = reply->IOCStatus;
|
||||
if (params->hdr.Ext.ExtPageType != 0) {
|
||||
if (params->hdr.Struct.PageType == MPI2_CONFIG_PAGETYPE_EXTENDED) {
|
||||
params->hdr.Ext.ExtPageType = reply->ExtPageType;
|
||||
params->hdr.Ext.ExtPageLength = reply->ExtPageLength;
|
||||
params->hdr.Ext.PageType = reply->Header.PageType;
|
||||
params->hdr.Ext.PageNumber = reply->Header.PageNumber;
|
||||
params->hdr.Ext.PageVersion = reply->Header.PageVersion;
|
||||
} else {
|
||||
params->hdr.Struct.PageType = reply->Header.PageType;
|
||||
params->hdr.Struct.PageNumber = reply->Header.PageNumber;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011-2014 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-2014 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-2014 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>
|
||||
@ -326,11 +327,13 @@ _mapping_get_high_missing_mt_idx(struct mpr_softc *sc)
|
||||
{
|
||||
u32 map_idx, high_idx = MPR_ENCTABLE_BAD_IDX;
|
||||
u8 high_missing_count = 0;
|
||||
u32 start_idx, end_idx, start_idx_ir = 0, end_idx_ir;
|
||||
u32 start_idx, end_idx, start_idx_ir, end_idx_ir;
|
||||
struct dev_mapping_table *mt_entry;
|
||||
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
|
||||
|
||||
start_idx = 0;
|
||||
start_idx_ir = 0;
|
||||
end_idx_ir = 0;
|
||||
end_idx = sc->max_devices;
|
||||
if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
|
||||
start_idx = 1;
|
||||
@ -887,14 +890,14 @@ _mapping_get_dev_info(struct mpr_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];
|
||||
@ -908,41 +911,36 @@ _mapping_get_dev_info(struct mpr_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 = mprsas_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;
|
||||
}
|
||||
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 = mprsas_get_sas_address_for_sata_disk(sc,
|
||||
&sas_address, phy_change->dev_handle, device_info,
|
||||
&phy_change->is_SATA_SSD);
|
||||
if (rc) {
|
||||
mpr_dprint(sc, MPR_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 {
|
||||
mpr_dprint(sc, MPR_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;
|
||||
}
|
||||
} 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) {
|
||||
@ -950,10 +948,10 @@ _mapping_get_dev_info(struct mpr_softc *sc,
|
||||
topo_change->enc_handle);
|
||||
if (enc_idx == MPR_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);
|
||||
mpr_dprint(sc, MPR_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-2014 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
|
||||
mprsas_get_sas_address_for_sata_disk(struct mpr_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) MPT3 controllers */
|
||||
|
||||
/* TODO Move headers to mprvar */
|
||||
#include <sys/types.h>
|
||||
@ -99,17 +99,17 @@ struct mpr_ident {
|
||||
const char *desc;
|
||||
} mpr_identifiers[] = {
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
|
||||
0xffff, 0xffff, 0, "LSI SAS3004" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3004" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008,
|
||||
0xffff, 0xffff, 0, "LSI SAS3008" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3008" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1,
|
||||
0xffff, 0xffff, 0, "LSI SAS3108_1" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_1" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2,
|
||||
0xffff, 0xffff, 0, "LSI SAS3108_2" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_2" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5,
|
||||
0xffff, 0xffff, 0, "LSI SAS3108_5" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_5" },
|
||||
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
|
||||
0xffff, 0xffff, 0, "LSI SAS3108_6" },
|
||||
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_6" },
|
||||
{ 0, 0, 0, 0, 0, NULL }
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011-2014 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 mprsas_lun {
|
||||
lun_id_t lun_id;
|
||||
uint8_t eedp_formatted;
|
||||
uint32_t eedp_block_size;
|
||||
uint8_t stop_at_shutdown;
|
||||
};
|
||||
|
||||
struct mprsas_target {
|
||||
@ -55,11 +55,10 @@ struct mprsas_target {
|
||||
#define MPRSAS_TARGET_INREMOVAL (1 << 3)
|
||||
#define MPR_TARGET_FLAGS_RAID_COMPONENT (1 << 4)
|
||||
#define MPR_TARGET_FLAGS_VOLUME (1 << 5)
|
||||
#define MPR_TARGET_IS_SATA_SSD (1 << 6)
|
||||
#define MPRSAS_TARGET_INRECOVERY (MPRSAS_TARGET_INABORT | \
|
||||
MPRSAS_TARGET_INRESET | MPRSAS_TARGET_INCHIPRESET)
|
||||
|
||||
#define MPRSAS_TARGET_ADD (1 << 29)
|
||||
#define MPRSAS_TARGET_REMOVE (1 << 30)
|
||||
uint16_t tid;
|
||||
SLIST_HEAD(, mprsas_lun) luns;
|
||||
TAILQ_HEAD(, mpr_command) commands;
|
||||
@ -82,6 +81,8 @@ struct mprsas_target {
|
||||
unsigned int logical_unit_resets;
|
||||
unsigned int target_resets;
|
||||
uint8_t scsi_req_desc_type;
|
||||
uint8_t stop_at_shutdown;
|
||||
uint8_t supports_SSU;
|
||||
};
|
||||
|
||||
struct mprsas_softc {
|
||||
@ -92,7 +93,6 @@ struct mprsas_softc {
|
||||
#define MPRSAS_DISCOVERY_TIMEOUT_PENDING (1 << 2)
|
||||
#define MPRSAS_QUEUE_FROZEN (1 << 3)
|
||||
#define MPRSAS_SHUTDOWN (1 << 4)
|
||||
#define MPRSAS_SCANTHREAD (1 << 5)
|
||||
u_int maxtargets;
|
||||
struct mprsas_target *targets;
|
||||
struct cam_devq *devq;
|
||||
@ -103,7 +103,6 @@ struct mprsas_softc {
|
||||
struct mpr_event_handle *mprsas_eh;
|
||||
|
||||
u_int startup_refcount;
|
||||
u_int tm_count;
|
||||
struct proc *sysctl_proc;
|
||||
|
||||
struct taskqueue *ev_tq;
|
||||
@ -150,6 +149,19 @@ mprsas_set_lun(uint8_t *lun, u_int ccblun)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
mprsas_set_ccbstatus(union ccb *ccb, int status)
|
||||
{
|
||||
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
|
||||
ccb->ccb_h.status |= status;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
mprsas_get_ccbstatus(union ccb *ccb)
|
||||
{
|
||||
return (ccb->ccb_h.status & CAM_STATUS_MASK);
|
||||
}
|
||||
|
||||
#define MPR_SET_SINGLE_LUN(req, lun) \
|
||||
do { \
|
||||
bzero((req)->LUN, 8); \
|
||||
@ -158,11 +170,10 @@ do { \
|
||||
|
||||
void mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ);
|
||||
void mprsas_discovery_end(struct mprsas_softc *sassc);
|
||||
void mprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm,
|
||||
struct mprsas_target *target, lun_id_t lun_id);
|
||||
void mprsas_startup_increment(struct mprsas_softc *sassc);
|
||||
void mprsas_startup_decrement(struct mprsas_softc *sassc);
|
||||
void mprsas_release_simq_reinit(struct mprsas_softc *sassc);
|
||||
|
||||
struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc);
|
||||
void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm);
|
||||
void mprsas_firmware_event_work(void *arg, int pending);
|
||||
int mprsas_check_id(struct mprsas_softc *sassc, int id);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2011-2014 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 LSI MPT3 */
|
||||
|
||||
/* TODO Move headers to mprvar */
|
||||
#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 mprsas_fw_work(struct mpr_softc *sc,
|
||||
@ -116,8 +119,9 @@ static int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate);
|
||||
static int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle,
|
||||
Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
|
||||
u32 devinfo);
|
||||
static void mprsas_ata_id_timeout(void *data);
|
||||
int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc,
|
||||
u64 *sas_address, u16 handle, u32 device_info);
|
||||
u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD);
|
||||
static int mprsas_volume_add(struct mpr_softc *sc,
|
||||
u16 handle);
|
||||
static void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc);
|
||||
@ -325,7 +329,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
|
||||
return;
|
||||
}
|
||||
|
||||
mpr_dprint(sc, MPR_INFO, "Sending FP action "
|
||||
mpr_dprint(sc, MPR_EVENT, "Sending FP action "
|
||||
"from "
|
||||
"MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST "
|
||||
":\n");
|
||||
@ -350,9 +354,9 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
|
||||
if (reply && (le16toh(reply->IOCStatus) &
|
||||
MPI2_IOCSTATUS_MASK) !=
|
||||
MPI2_IOCSTATUS_SUCCESS) {
|
||||
mpr_dprint(sc, MPR_INFO, "%s: error "
|
||||
"sending RaidActionPage; iocstatus "
|
||||
"= 0x%x\n", __func__,
|
||||
mpr_dprint(sc, MPR_ERROR, "%s: error "
|
||||
"sending RaidActionPage; "
|
||||
"iocstatus = 0x%x\n", __func__,
|
||||
le16toh(reply->IOCStatus));
|
||||
}
|
||||
|
||||
@ -360,7 +364,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
|
||||
mpr_free_command(sc, cm);
|
||||
}
|
||||
skip_fp_send:
|
||||
mpr_dprint(sc, MPR_INFO, "Received "
|
||||
mpr_dprint(sc, MPR_EVENT, "Received "
|
||||
"MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST Reason "
|
||||
"code %x:\n", element->ReasonCode);
|
||||
switch (element->ReasonCode) {
|
||||
@ -421,7 +425,6 @@ skip_fp_send:
|
||||
break;
|
||||
targ->flags |= MPR_TARGET_FLAGS_RAID_COMPONENT;
|
||||
mprsas_rescan_target(sc, targ);
|
||||
|
||||
break;
|
||||
case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
|
||||
/*
|
||||
@ -678,14 +681,13 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
|
||||
struct mprsas_target *targ;
|
||||
Mpi2ConfigReply_t mpi_reply;
|
||||
Mpi2SasDevicePage0_t config_page;
|
||||
uint64_t sas_address, sata_sas_address;
|
||||
uint64_t parent_sas_address = 0;
|
||||
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
|
||||
uint64_t sas_address, parent_sas_address = 0;
|
||||
u32 device_info, parent_devinfo = 0;
|
||||
unsigned int id;
|
||||
int ret;
|
||||
int error = 0;
|
||||
int ret = 1, error = 0, i;
|
||||
struct mprsas_lun *lun;
|
||||
u8 is_SATA_SSD = 0;
|
||||
struct mpr_command *cm;
|
||||
|
||||
sassc = sc->sassc;
|
||||
mprsas_startup_increment(sassc);
|
||||
@ -717,26 +719,29 @@ mprsas_add_device(struct mpr_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;
|
||||
mpr_dprint(sc, MPR_INFO, "SAS Address from SAS device page0 = %jx\n",
|
||||
sas_address);
|
||||
|
||||
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 = mprsas_get_sas_address_for_sata_disk(sc,
|
||||
&sata_sas_address, handle, device_info);
|
||||
if (!ret)
|
||||
id = mpr_mapping_get_sas_id(sc,
|
||||
sata_sas_address, handle);
|
||||
else
|
||||
id = mpr_mapping_get_sas_id(sc,
|
||||
sas_address, handle);
|
||||
} else
|
||||
id = mpr_mapping_get_sas_id(sc, sas_address,
|
||||
handle);
|
||||
} else
|
||||
id = mpr_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 = mprsas_get_sas_address_for_sata_disk(sc, &sas_address,
|
||||
handle, device_info, &is_SATA_SSD);
|
||||
if (ret) {
|
||||
mpr_dprint(sc, MPR_ERROR, "%s: failed to get disk type "
|
||||
"(SSD or HDD) for SATA device with handle 0x%04x\n",
|
||||
__func__, handle);
|
||||
} else {
|
||||
mpr_dprint(sc, MPR_INFO, "SAS Address from SATA "
|
||||
"device = %jx\n", sas_address);
|
||||
}
|
||||
}
|
||||
|
||||
id = mpr_mapping_get_sas_id(sc, sas_address, handle);
|
||||
if (id == MPR_MAP_BAD_ID) {
|
||||
printf("failure at %s:%d/%s()! Could not get ID for device "
|
||||
"with handle 0x%04x\n", __FILE__, __LINE__, __func__,
|
||||
@ -750,7 +755,7 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n",
|
||||
sas_address);
|
||||
targ = &sassc->targets[id];
|
||||
@ -773,6 +778,9 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
|
||||
targ->tid = id;
|
||||
targ->linkrate = (linkrate>>4);
|
||||
targ->flags = 0;
|
||||
if (is_SATA_SSD) {
|
||||
targ->flags = MPR_TARGET_IS_SATA_SSD;
|
||||
}
|
||||
if (le16toh(config_page.Flags) &
|
||||
MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) {
|
||||
targ->scsi_req_desc_type =
|
||||
@ -792,12 +800,12 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
|
||||
SLIST_INIT(&targ->luns);
|
||||
|
||||
mpr_describe_devinfo(targ->devinfo, devstring, 80);
|
||||
mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "Found device <%s> <%s> "
|
||||
mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found device <%s> <%s> "
|
||||
"handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring,
|
||||
mpr_describe_table(mpr_linkrate_names, targ->linkrate),
|
||||
targ->handle, targ->encl_handle, targ->encl_slot);
|
||||
if (targ->encl_level_valid) {
|
||||
mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "At enclosure level %d "
|
||||
mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d "
|
||||
"and connector name (%4s)\n", targ->encl_level,
|
||||
targ->connector_name);
|
||||
}
|
||||
@ -807,15 +815,57 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
|
||||
#endif
|
||||
mprsas_rescan_target(sc, targ);
|
||||
mpr_dprint(sc, MPR_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 & MPR_CM_FLAGS_SATA_ID_TIMEOUT) {
|
||||
targ->timeouts++;
|
||||
cm->cm_state = MPR_CM_STATE_TIMEDOUT;
|
||||
|
||||
if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) {
|
||||
mpr_dprint(sc, MPR_INFO, "%s: sending Target "
|
||||
"Reset for stuck SATA identify command "
|
||||
"(cm = %p)\n", __func__, cm);
|
||||
targ->tm->cm_targ = targ;
|
||||
mprsas_send_reset(sc, targ->tm,
|
||||
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
|
||||
} else {
|
||||
mpr_dprint(sc, MPR_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 & MPR_CM_FLAGS_SATA_ID_TIMEOUT) {
|
||||
mpr_free_command(sc, cm);
|
||||
}
|
||||
}
|
||||
mprsas_startup_decrement(sassc);
|
||||
return (error);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
mprsas_get_sas_address_for_sata_disk(struct mpr_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;
|
||||
@ -835,7 +885,16 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_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) {
|
||||
mpr_dprint(sc, MPR_INFO, "Sleeping %d seconds "
|
||||
"after SATA ID error to wait for spinup\n",
|
||||
sc->spinup_wait_time);
|
||||
msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0,
|
||||
"mprid", sc->spinup_wait_time * hz);
|
||||
}
|
||||
}
|
||||
} while (((rc && (rc != EWOULDBLOCK)) || ioc_status || sas_status) &&
|
||||
(try_count < 5));
|
||||
|
||||
if (rc == 0 && !ioc_status && !sas_status) {
|
||||
@ -884,6 +943,10 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_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;
|
||||
}
|
||||
|
||||
@ -923,14 +986,29 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle,
|
||||
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
|
||||
cm->cm_data = buffer;
|
||||
cm->cm_length = htole32(sz);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
mpr_dprint(sc, MPR_XINFO, "%s start timeout counter for SATA ID "
|
||||
"command\n", __func__);
|
||||
callout_reset(&cm->cm_callout, MPR_ATA_ID_TIMEOUT * hz,
|
||||
mprsas_ata_id_timeout, cm);
|
||||
error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
|
||||
mpr_dprint(sc, MPR_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 */
|
||||
/*
|
||||
* If the request returns an error then we need to do a diag
|
||||
* reset
|
||||
*/
|
||||
*/
|
||||
printf("%s: request for page completed with error %d",
|
||||
__func__, error);
|
||||
error = ENXIO;
|
||||
@ -946,11 +1024,66 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle,
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
mpr_free_command(sc, cm);
|
||||
free(buffer, M_MPR);
|
||||
/*
|
||||
* 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 & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0)
|
||||
mpr_free_command(sc, cm);
|
||||
else if (error == 0)
|
||||
error = EWOULDBLOCK;
|
||||
free(buffer, M_MPR);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
mprsas_ata_id_timeout(void *data)
|
||||
{
|
||||
struct mpr_softc *sc;
|
||||
struct mpr_command *cm;
|
||||
|
||||
cm = (struct mpr_command *)data;
|
||||
sc = cm->cm_sc;
|
||||
mtx_assert(&sc->mpr_mtx, MA_OWNED);
|
||||
|
||||
mpr_dprint(sc, MPR_INFO, "%s checking ATA ID command %p sc %p\n",
|
||||
__func__, cm, sc);
|
||||
if ((callout_pending(&cm->cm_callout)) ||
|
||||
(!callout_active(&cm->cm_callout))) {
|
||||
mpr_dprint(sc, MPR_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.
|
||||
*/
|
||||
mpr_intr_locked(sc);
|
||||
if (cm->cm_state == MPR_CM_STATE_FREE) {
|
||||
mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed "
|
||||
"out\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
mpr_dprint(sc, MPR_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 |= MPR_CM_FLAGS_SATA_ID_TIMEOUT;
|
||||
wakeup(cm);
|
||||
}
|
||||
|
||||
static int
|
||||
mprsas_volume_add(struct mpr_softc *sc, u16 handle)
|
||||
{
|
||||
@ -1024,15 +1157,13 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc)
|
||||
path_id_t pathid = cam_sim_path(sassc->sim);
|
||||
target_id_t targetid;
|
||||
struct mprsas_target *target;
|
||||
struct mprsas_lun *lun;
|
||||
char path_str[64];
|
||||
struct timeval cur_time, start_time;
|
||||
|
||||
mpr_lock(sc);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
@ -1042,59 +1173,52 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc)
|
||||
continue;
|
||||
}
|
||||
|
||||
SLIST_FOREACH(lun, &target->luns, lun_link) {
|
||||
ccb = xpt_alloc_ccb_nowait();
|
||||
if (ccb == NULL) {
|
||||
mpr_unlock(sc);
|
||||
mpr_dprint(sc, MPR_FAULT, "Unable to alloc "
|
||||
"CCB to stop unit.\n");
|
||||
ccb = xpt_alloc_ccb_nowait();
|
||||
if (ccb == NULL) {
|
||||
mpr_dprint(sc, MPR_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) {
|
||||
mpr_dprint(sc, MPR_ERROR, "Unable to create "
|
||||
"path to stop unit.\n");
|
||||
xpt_free_ccb(ccb);
|
||||
return;
|
||||
}
|
||||
xpt_path_string(ccb->ccb_h.path, path_str,
|
||||
sizeof(path_str));
|
||||
|
||||
mpr_dprint(sc, MPR_INFO, "Sending StopUnit: path %s "
|
||||
"handle %d\n", path_str, target->handle);
|
||||
|
||||
/*
|
||||
* The stop_at_shutdown flag will be set if this LUN is
|
||||
* a SATA direct-access end device.
|
||||
* Issue a START STOP UNIT command for the target.
|
||||
* Increment the SSU counter to be used to count the
|
||||
* number of required replies.
|
||||
*/
|
||||
if (lun->stop_at_shutdown) {
|
||||
if (xpt_create_path(&ccb->ccb_h.path,
|
||||
xpt_periph, pathid, targetid,
|
||||
lun->lun_id) != CAM_REQ_CMP) {
|
||||
mpr_dprint(sc, MPR_FAULT, "Unable to "
|
||||
"create LUN path to stop unit.\n");
|
||||
xpt_free_ccb(ccb);
|
||||
mpr_unlock(sc);
|
||||
return;
|
||||
}
|
||||
xpt_path_string(ccb->ccb_h.path, path_str,
|
||||
sizeof(path_str));
|
||||
|
||||
mpr_dprint(sc, MPR_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.
|
||||
*/
|
||||
mpr_dprint(sc, MPR_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,
|
||||
mprsas_stop_unit_done,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
/*start*/FALSE,
|
||||
/*load/eject*/0,
|
||||
/*immediate*/FALSE,
|
||||
MPR_SENSE_LEN,
|
||||
/*timeout*/10000);
|
||||
xpt_action(ccb);
|
||||
}
|
||||
mpr_dprint(sc, MPR_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,
|
||||
mprsas_stop_unit_done,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
/*start*/FALSE,
|
||||
/*load/eject*/0,
|
||||
/*immediate*/FALSE,
|
||||
MPR_SENSE_LEN,
|
||||
/*timeout*/10000);
|
||||
xpt_action(ccb);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1102,7 +1226,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc)
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@ -1112,7 +1236,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc)
|
||||
|
||||
getmicrotime(&cur_time);
|
||||
if ((cur_time.tv_sec - start_time.tv_sec) > 60) {
|
||||
mpr_dprint(sc, MPR_FAULT, "Time has expired waiting "
|
||||
mpr_dprint(sc, MPR_ERROR, "Time has expired waiting "
|
||||
"for SSU commands to complete.\n");
|
||||
break;
|
||||
}
|
||||
@ -1162,6 +1286,8 @@ mprsas_ir_shutdown(struct mpr_softc *sc)
|
||||
unsigned int id, found_volume = 0;
|
||||
struct mpr_command *cm;
|
||||
Mpi2RaidActionRequest_t *action;
|
||||
target_id_t targetid;
|
||||
struct mprsas_target *target;
|
||||
|
||||
mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
|
||||
|
||||
@ -1214,5 +1340,47 @@ mprsas_ir_shutdown(struct mpr_softc *sc)
|
||||
mpr_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 MPR_SSU_DISABLE_SSD_DISABLE_HDD:
|
||||
target->stop_at_shutdown = FALSE;
|
||||
break;
|
||||
case MPR_SSU_DISABLE_SSD_ENABLE_HDD:
|
||||
target->stop_at_shutdown = TRUE;
|
||||
if (target->flags & MPR_TARGET_IS_SATA_SSD) {
|
||||
target->stop_at_shutdown = FALSE;
|
||||
}
|
||||
break;
|
||||
case MPR_SSU_ENABLE_SSD_ENABLE_HDD:
|
||||
target->stop_at_shutdown = TRUE;
|
||||
break;
|
||||
case MPR_SSU_ENABLE_SSD_DISABLE_HDD:
|
||||
default:
|
||||
target->stop_at_shutdown = TRUE;
|
||||
if ((target->flags &
|
||||
MPR_TARGET_IS_SATA_SSD) == 0) {
|
||||
target->stop_at_shutdown = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mprsas_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-2014 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,7 +91,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
|
||||
#include <dev/mpr/mpi/mpi2_type.h>
|
||||
#include <dev/mpr/mpi/mpi2.h>
|
||||
@ -284,8 +285,7 @@ mpr_user_read_cfg_header(struct mpr_softc *sc,
|
||||
|
||||
static int
|
||||
mpr_user_read_cfg_page(struct mpr_softc *sc,
|
||||
struct mpr_cfg_page_req *page_req,
|
||||
void *buf)
|
||||
struct mpr_cfg_page_req *page_req, void *buf)
|
||||
{
|
||||
MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
|
||||
struct mpr_config_params params;
|
||||
@ -328,6 +328,10 @@ mpr_user_read_extcfg_header(struct mpr_softc *sc,
|
||||
hdr->PageNumber = ext_page_req->header.PageNumber;
|
||||
hdr->ExtPageType = ext_page_req->header.ExtPageType;
|
||||
params.page_address = le32toh(ext_page_req->page_address);
|
||||
params.buffer = NULL;
|
||||
params.length = 0;
|
||||
params.callback = NULL;
|
||||
|
||||
if ((error = mpr_read_config_page(sc, ¶ms)) != 0) {
|
||||
/*
|
||||
* Leave the request. Without resetting the chip, it's
|
||||
@ -365,8 +369,8 @@ mpr_user_read_extcfg_page(struct mpr_softc *sc,
|
||||
params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
|
||||
params.page_address = le32toh(ext_page_req->page_address);
|
||||
hdr->PageVersion = reqhdr->PageVersion;
|
||||
hdr->PageNumber = reqhdr->PageNumber;
|
||||
hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
|
||||
hdr->PageNumber = reqhdr->PageNumber;
|
||||
hdr->ExtPageType = reqhdr->ExtPageType;
|
||||
hdr->ExtPageLength = reqhdr->ExtPageLength;
|
||||
params.buffer = buf;
|
||||
@ -541,6 +545,8 @@ mpi_pre_fw_upload(struct mpr_command *cm, struct mpr_usr_command *cmd)
|
||||
req->ImageOffset = 0;
|
||||
req->ImageSize = cmd->len;
|
||||
|
||||
cm->cm_flags |= MPR_CM_FLAGS_DATAIN;
|
||||
|
||||
return (mpr_push_ieee_sge(cm, &req->SGL, 0));
|
||||
}
|
||||
|
||||
@ -834,11 +840,22 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_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 = mpr_wait_command(sc, cm, 30, CAN_SLEEP);
|
||||
targ = mprsas_find_target_by_handle(sc->sassc, 0,
|
||||
task->DevHandle);
|
||||
if (targ == NULL) {
|
||||
mpr_dprint(sc, MPR_INFO,
|
||||
"%s %d : invalid handle for requested TM 0x%x \n",
|
||||
__func__, __LINE__, task->DevHandle);
|
||||
err = 1;
|
||||
} else {
|
||||
mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
|
||||
err = mpr_wait_command(sc, cm, 30, CAN_SLEEP);
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
err = EIO;
|
||||
@ -1029,7 +1046,7 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
|
||||
if (cm->cm_flags & MPR_CM_FLAGS_DATAIN)
|
||||
dir = BUS_DMASYNC_POSTREAD;
|
||||
else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT)
|
||||
dir = BUS_DMASYNC_POSTWRITE;;
|
||||
dir = BUS_DMASYNC_POSTWRITE;
|
||||
bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir);
|
||||
bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap);
|
||||
|
||||
@ -1351,8 +1368,8 @@ done:
|
||||
}
|
||||
|
||||
static int
|
||||
mpr_diag_register(struct mpr_softc *sc,
|
||||
mpr_fw_diag_register_t *diag_register, uint32_t *return_code)
|
||||
mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register,
|
||||
uint32_t *return_code)
|
||||
{
|
||||
mpr_fw_diagnostic_buffer_t *pBuffer;
|
||||
uint8_t extended_type, buffer_type, i;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Yahoo! Inc.
|
||||
* Copyright (c) 2011-2014 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,13 +25,15 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MPRVAR_H
|
||||
#define _MPRVAR_H
|
||||
|
||||
#define MPR_DRIVER_VERSION "05.255.05.00-fbsd"
|
||||
#define MPR_DRIVER_VERSION "09.255.01.00-fbsd"
|
||||
|
||||
#define MPR_DB_MAX_WAIT 2500
|
||||
|
||||
@ -47,16 +50,19 @@
|
||||
#define MPR_FUNCTRACE(sc) \
|
||||
mpr_dprint((sc), MPR_TRACE, "%s\n", __func__)
|
||||
|
||||
#define CAN_SLEEP 1
|
||||
#define NO_SLEEP 0
|
||||
#define CAN_SLEEP 1
|
||||
#define NO_SLEEP 0
|
||||
|
||||
#define MPR_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */
|
||||
#define MPR_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */
|
||||
|
||||
#define IFAULT_IOP_OVER_TEMP_THRESHOLD_EXCEEDED 0x2810
|
||||
|
||||
#define MPR_SCSI_RI_INVALID_FRAME (0x00000002)
|
||||
#define MPR_STRING_LENGTH 64
|
||||
|
||||
#define DEFAULT_SPINUP_WAIT 3 /* seconds to wait for spinup */
|
||||
|
||||
#include <sys/endian.h>
|
||||
|
||||
/*
|
||||
@ -213,13 +219,14 @@ struct mpr_command {
|
||||
#define MPR_CM_FLAGS_CHAIN_FAILED (1 << 8)
|
||||
#define MPR_CM_FLAGS_ERROR_MASK MPR_CM_FLAGS_CHAIN_FAILED
|
||||
#define MPR_CM_FLAGS_USE_CCB (1 << 9)
|
||||
#define MPR_CM_FLAGS_SATA_ID_TIMEOUT (1 << 10)
|
||||
u_int cm_state;
|
||||
#define MPR_CM_STATE_FREE 0
|
||||
#define MPR_CM_STATE_BUSY 1
|
||||
#define MPR_CM_STATE_TIMEDOUT 2
|
||||
bus_dmamap_t cm_dmamap;
|
||||
struct scsi_sense_data *cm_sense;
|
||||
TAILQ_HEAD(, mpr_chain) cm_chain_list;
|
||||
TAILQ_HEAD(, mpr_chain) cm_chain_list;
|
||||
uint32_t cm_req_busaddr;
|
||||
uint32_t cm_sense_busaddr;
|
||||
struct callout cm_callout;
|
||||
@ -256,6 +263,8 @@ struct mpr_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
|
||||
@ -270,7 +279,7 @@ struct mpr_softc {
|
||||
char tmp_string[MPR_STRING_LENGTH];
|
||||
TAILQ_HEAD(, mpr_command) req_list;
|
||||
TAILQ_HEAD(, mpr_command) high_priority_req_list;
|
||||
TAILQ_HEAD(, mpr_chain) chain_list;
|
||||
TAILQ_HEAD(, mpr_chain) chain_list;
|
||||
TAILQ_HEAD(, mpr_command) tm_list;
|
||||
int replypostindex;
|
||||
int replyfreeindex;
|
||||
@ -291,7 +300,7 @@ struct mpr_softc {
|
||||
|
||||
uint8_t event_mask[16];
|
||||
TAILQ_HEAD(, mpr_event_handle) event_list;
|
||||
struct mpr_event_handle *mpr_log_eh;
|
||||
struct mpr_event_handle *mpr_log_eh;
|
||||
|
||||
struct mtx mpr_mtx;
|
||||
struct intr_config_hook mpr_ich;
|
||||
@ -565,6 +574,11 @@ mpr_unlock(struct mpr_softc *sc)
|
||||
#define MPR_MAPPING (1 << 9) /* Trace device mappings */
|
||||
#define MPR_TRACE (1 << 10) /* Function-by-function trace */
|
||||
|
||||
#define MPR_SSU_DISABLE_SSD_DISABLE_HDD 0
|
||||
#define MPR_SSU_ENABLE_SSD_DISABLE_HDD 1
|
||||
#define MPR_SSU_DISABLE_SSD_ENABLE_HDD 2
|
||||
#define MPR_SSU_ENABLE_SSD_ENABLE_HDD 3
|
||||
|
||||
#define mpr_printf(sc, args...) \
|
||||
device_printf((sc)->mpr_dev, ##args)
|
||||
|
||||
@ -600,9 +614,6 @@ do { \
|
||||
#define MPR_EVENTFIELD(sc, facts, attr, fmt) \
|
||||
mpr_dprint_field((sc), MPR_EVENT, #attr ": " #fmt "\n", (facts)->attr)
|
||||
|
||||
#define CAN_SLEEP 1
|
||||
#define NO_SLEEP 0
|
||||
|
||||
static __inline void
|
||||
mpr_from_u64(uint64_t data, U64 *mpr)
|
||||
{
|
||||
@ -613,7 +624,6 @@ mpr_from_u64(uint64_t data, U64 *mpr)
|
||||
static __inline uint64_t
|
||||
mpr_to_u64(U64 *data)
|
||||
{
|
||||
|
||||
return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low));
|
||||
}
|
||||
|
||||
@ -727,6 +737,12 @@ void mprsas_prepare_volume_remove(struct mprsas_softc *sassc,
|
||||
int mprsas_startup(struct mpr_softc *sc);
|
||||
struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *,
|
||||
int, uint16_t);
|
||||
void mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets);
|
||||
struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc);
|
||||
void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm);
|
||||
void mprsas_release_simq_reinit(struct mprsas_softc *sassc);
|
||||
int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm,
|
||||
uint8_t type);
|
||||
|
||||
SYSCTL_DECL(_hw_mpr);
|
||||
|
||||
|
@ -2389,7 +2389,7 @@ pci_set_powerstate_method(device_t dev, device_t child, int state)
|
||||
struct pci_devinfo *dinfo = device_get_ivars(child);
|
||||
pcicfgregs *cfg = &dinfo->cfg;
|
||||
uint16_t status;
|
||||
int result, oldstate, highest, delay;
|
||||
int oldstate, highest, delay;
|
||||
|
||||
if (cfg->pp.pp_cap == 0)
|
||||
return (EOPNOTSUPP);
|
||||
@ -2424,7 +2424,6 @@ pci_set_powerstate_method(device_t dev, device_t child, int state)
|
||||
delay = 0;
|
||||
status = PCI_READ_CONFIG(dev, child, cfg->pp.pp_status, 2)
|
||||
& ~PCIM_PSTAT_DMASK;
|
||||
result = 0;
|
||||
switch (state) {
|
||||
case PCI_POWERSTATE_D0:
|
||||
status |= PCIM_PSTAT_D0;
|
||||
@ -2989,7 +2988,6 @@ static void
|
||||
pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force,
|
||||
uint32_t prefetchmask)
|
||||
{
|
||||
struct resource *r;
|
||||
int rid, type, progif;
|
||||
#if 0
|
||||
/* if this device supports PCI native addressing use it */
|
||||
@ -3012,11 +3010,11 @@ pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force,
|
||||
} else {
|
||||
rid = PCIR_BAR(0);
|
||||
resource_list_add(rl, type, rid, 0x1f0, 0x1f7, 8);
|
||||
r = resource_list_reserve(rl, bus, dev, type, &rid, 0x1f0,
|
||||
(void)resource_list_reserve(rl, bus, dev, type, &rid, 0x1f0,
|
||||
0x1f7, 8, 0);
|
||||
rid = PCIR_BAR(1);
|
||||
resource_list_add(rl, type, rid, 0x3f6, 0x3f6, 1);
|
||||
r = resource_list_reserve(rl, bus, dev, type, &rid, 0x3f6,
|
||||
(void)resource_list_reserve(rl, bus, dev, type, &rid, 0x3f6,
|
||||
0x3f6, 1, 0);
|
||||
}
|
||||
if (progif & PCIP_STORAGE_IDE_MODESEC) {
|
||||
@ -3027,11 +3025,11 @@ pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force,
|
||||
} else {
|
||||
rid = PCIR_BAR(2);
|
||||
resource_list_add(rl, type, rid, 0x170, 0x177, 8);
|
||||
r = resource_list_reserve(rl, bus, dev, type, &rid, 0x170,
|
||||
(void)resource_list_reserve(rl, bus, dev, type, &rid, 0x170,
|
||||
0x177, 8, 0);
|
||||
rid = PCIR_BAR(3);
|
||||
resource_list_add(rl, type, rid, 0x376, 0x376, 1);
|
||||
r = resource_list_reserve(rl, bus, dev, type, &rid, 0x376,
|
||||
(void)resource_list_reserve(rl, bus, dev, type, &rid, 0x376,
|
||||
0x376, 1, 0);
|
||||
}
|
||||
pci_add_map(bus, dev, PCIR_BAR(4), rl, force,
|
||||
@ -3727,7 +3725,6 @@ pci_detach(device_t dev)
|
||||
static void
|
||||
pci_set_power_child(device_t dev, device_t child, int state)
|
||||
{
|
||||
struct pci_devinfo *dinfo;
|
||||
device_t pcib;
|
||||
int dstate;
|
||||
|
||||
@ -3739,7 +3736,6 @@ pci_set_power_child(device_t dev, device_t child, int state)
|
||||
* are handled separately.
|
||||
*/
|
||||
pcib = device_get_parent(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
dstate = state;
|
||||
if (device_is_attached(child) &&
|
||||
PCIB_POWER_FOR_SLEEP(pcib, child, &dstate) == 0)
|
||||
|
@ -214,22 +214,6 @@ METHOD int iov_detach {
|
||||
device_t child;
|
||||
};
|
||||
|
||||
METHOD int init_iov {
|
||||
device_t dev;
|
||||
uint16_t num_vfs;
|
||||
const struct nvlist *config;
|
||||
};
|
||||
|
||||
METHOD void uninit_iov {
|
||||
device_t dev;
|
||||
};
|
||||
|
||||
METHOD int add_vf {
|
||||
device_t dev;
|
||||
uint16_t vfnum;
|
||||
const struct nvlist *config;
|
||||
};
|
||||
|
||||
METHOD device_t create_iov_child {
|
||||
device_t bus;
|
||||
device_t pf;
|
||||
@ -237,4 +221,3 @@ METHOD device_t create_iov_child {
|
||||
uint16_t vid;
|
||||
uint16_t did;
|
||||
} DEFAULT null_create_iov_child;
|
||||
|
||||
|
@ -53,11 +53,11 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pci_iov.h>
|
||||
#include <dev/pci/pci_private.h>
|
||||
#include <dev/pci/pci_iov_private.h>
|
||||
#include <dev/pci/schema_private.h>
|
||||
|
||||
#include "pci_if.h"
|
||||
#include "pcib_if.h"
|
||||
|
||||
static MALLOC_DEFINE(M_SRIOV, "sr_iov", "PCI SR-IOV allocations");
|
||||
@ -483,13 +483,13 @@ pci_iov_config_page_size(struct pci_devinfo *dinfo)
|
||||
}
|
||||
|
||||
static int
|
||||
pci_init_iov(device_t dev, uint16_t num_vfs, const nvlist_t *config)
|
||||
pci_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *config)
|
||||
{
|
||||
const nvlist_t *device, *driver_config;
|
||||
|
||||
device = nvlist_get_nvlist(config, PF_CONFIG_NAME);
|
||||
driver_config = nvlist_get_nvlist(device, DRIVER_CONFIG_NAME);
|
||||
return (PCI_INIT_IOV(dev, num_vfs, driver_config));
|
||||
return (PCI_IOV_INIT(dev, num_vfs, driver_config));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -595,7 +595,7 @@ pci_iov_enumerate_vfs(struct pci_devinfo *dinfo, const nvlist_t *config,
|
||||
|
||||
pci_iov_add_bars(iov, vfinfo);
|
||||
|
||||
error = PCI_ADD_VF(dev, i, driver_config);
|
||||
error = PCI_IOV_ADD_VF(dev, i, driver_config);
|
||||
if (error != 0) {
|
||||
device_printf(dev, "Failed to add VF %d\n", i);
|
||||
pci_delete_child(bus, vf);
|
||||
@ -652,7 +652,7 @@ pci_iov_config(struct cdev *cdev, struct pci_iov_arg *arg)
|
||||
if (error != 0)
|
||||
goto out;
|
||||
|
||||
error = pci_init_iov(dev, num_vfs, config);
|
||||
error = pci_iov_init(dev, num_vfs, config);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
iov_inited = 1;
|
||||
@ -700,7 +700,7 @@ pci_iov_config(struct cdev *cdev, struct pci_iov_arg *arg)
|
||||
return (0);
|
||||
out:
|
||||
if (iov_inited)
|
||||
PCI_UNINIT_IOV(dev);
|
||||
PCI_IOV_UNINIT(dev);
|
||||
|
||||
for (i = 0; i <= PCIR_MAX_BAR_0; i++) {
|
||||
if (iov->iov_bar[i].res != NULL) {
|
||||
@ -793,7 +793,7 @@ pci_iov_delete(struct cdev *cdev)
|
||||
if (pci_iov_is_child_vf(iov, vf))
|
||||
pci_delete_child(bus, vf);
|
||||
}
|
||||
PCI_UNINIT_IOV(dev);
|
||||
PCI_IOV_UNINIT(dev);
|
||||
|
||||
iov_ctl = IOV_READ(dinfo, PCIR_SRIOV_CTL, 2);
|
||||
iov_ctl &= ~(PCIM_SRIOV_VF_EN | PCIM_SRIOV_VF_MSE);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user