Merge ^/head r305687 through r305890.
This commit is contained in:
commit
93badfa1f2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/clang390-import/; revision=305891
@ -133,6 +133,8 @@ OLD_DIRS+=usr/lib/clang/3.8.0
|
||||
# 20160906: libkqueue tests moved to /usr/tests/sys/kqueue/libkqueue
|
||||
OLD_FILES+=usr/tests/sys/kqueue/kqtest
|
||||
OLD_FILES+=usr/tests/sys/kqueue/kqueue_test
|
||||
# 20160903: idle page zeroing support removed
|
||||
OLD_FILES+=usr/share/man/man9/pmap_zero_idle.9.gz
|
||||
# 20160901: Remove digi(4)
|
||||
OLD_FILES+=usr/share/man/man4/digi.4.gz
|
||||
# 20160819: Remove ie(4)
|
||||
@ -151,6 +153,8 @@ OLD_FILES+=usr/share/man/man8/sicontrol.8.gz
|
||||
OLD_FILES+=usr/share/man/man4/scd.4.gz
|
||||
# 20160815: Remove mcd(4)
|
||||
OLD_FILES+=usr/share/man/man4/mcd.4.gz
|
||||
# 20160805: lockmgr_waiters(9) removed
|
||||
OLD_FILES+=usr/share/man/man9/lockmgr_waiters.9.gz
|
||||
# 20160703: POSIXify locales with variants
|
||||
OLD_FILES+=usr/share/locale/zh_Hant_TW.UTF-8/LC_COLLATE
|
||||
OLD_FILES+=usr/share/locale/zh_Hant_TW.UTF-8/LC_CTYPE
|
||||
@ -305,18 +309,23 @@ OLD_LIBS+=usr/lib32/pam_unix.so.5
|
||||
OLD_FILES+=usr/include/altq/altq_codel.h
|
||||
OLD_FILES+=usr/include/altq/altq_fairq.h
|
||||
# 20160519: remove DTrace Toolkit from base
|
||||
OLD_FILES+=usr/sbin/dtruss
|
||||
OLD_FILES+=usr/share/dtrace/toolkit/execsnoop
|
||||
OLD_FILES+=usr/share/dtrace/toolkit/hotkernel
|
||||
OLD_FILES+=usr/share/dtrace/toolkit/hotuser
|
||||
OLD_FILES+=usr/share/dtrace/toolkit/opensnoop
|
||||
OLD_FILES+=usr/share/dtrace/toolkit/procsystime
|
||||
OLD_DIRS+=usr/share/dtrace/toolkit
|
||||
OLD_FILES+=usr/share/man/man1/dtruss.1.gz
|
||||
# 20160519: stale MLINK removed
|
||||
OLD_FILES+=usr/share/man/man9/rman_await_resource.9.gz
|
||||
# 20160517: ReiserFS removed
|
||||
OLD_FILES+=usr/share/man/man5/reiserfs.5.gz
|
||||
# 20160504: tests rework
|
||||
OLD_FILES+=usr/tests/lib/libc/regex/data/README
|
||||
# 20160430: kvm_getfiles(3) removed from kvm(3)
|
||||
OLD_LIBS+=lib/libkvm.so.6
|
||||
OLD_LIBS+=usr/lib32/libkvm.so.6
|
||||
OLD_FILES+=usr/share/man/man3/kvm_getfiles.3.gz
|
||||
# 20160423: remove mroute6d
|
||||
OLD_FILES+=etc/rc.d/mroute6d
|
||||
@ -464,12 +473,18 @@ OLD_LIBS+=usr/lib32/libcapsicum.so.0
|
||||
OLD_FILES+=usr/lib32/libcapsicum_p.a
|
||||
# 20160223: functionality from mkulzma(1) merged into mkuzip(1)
|
||||
OLD_FILES+=usr/bin/mkulzma
|
||||
OLD_FILES+=usr/share/man/man4/geom_uncompress.4.gz
|
||||
OLD_FILES+=usr/share/man/man8/mkulzma.8.gz
|
||||
# 20160211: Remove obsolete unbound-control-setup
|
||||
OLD_FILES+=usr/sbin/unbound-control-setup
|
||||
# 20160121: cc.h moved
|
||||
OLD_FILES+=usr/include/netinet/cc.h
|
||||
# 20160116: Update mandoc to cvs snapshot 20160116
|
||||
OLD_FILES+=usr/share/mdocml/example.style.css
|
||||
OLD_FILES+=usr/share/mdocml/style.css
|
||||
OLD_DIRS+=usr/share/mdocml
|
||||
# 20160114: SA-16:06.snmpd
|
||||
OLD_FILES+=usr/share/examples/etc/snmpd.config
|
||||
# 20151225: new clang import which bumps version from 3.7.0 to 3.7.1.
|
||||
OLD_FILES+=usr/lib/clang/3.7.0/include/sanitizer/allocator_interface.h
|
||||
OLD_FILES+=usr/lib/clang/3.7.0/include/sanitizer/asan_interface.h
|
||||
@ -554,6 +569,9 @@ OLD_FILES+=usr/lib/clang/3.7.0/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_
|
||||
OLD_DIRS+=usr/lib/clang/3.7.0/lib/freebsd
|
||||
OLD_DIRS+=usr/lib/clang/3.7.0/lib
|
||||
OLD_DIRS+=usr/lib/clang/3.7.0
|
||||
# 20151201: mqueue tests 3 and 4 disabled
|
||||
OLD_FILES+=usr/tests/sys/mqueue/mqtest3
|
||||
OLD_FILES+=usr/tests/sys/mqueue/mqtest4
|
||||
# 20151130: libelf moved from /usr/lib to /lib (libkvm dependency in r291406)
|
||||
OLD_LIBS+=usr/lib/libelf.so.2
|
||||
# 20151115: Fox bad upgrade scheme
|
||||
@ -688,6 +706,8 @@ OLD_LIBS+=lib/libcrypto.so.7
|
||||
OLD_LIBS+=usr/lib/libssl.so.7
|
||||
OLD_LIBS+=usr/lib32/libcrypto.so.7
|
||||
OLD_LIBS+=usr/lib32/libssl.so.7
|
||||
# 20151029: LinuxKPI moved to sys/compat/linuxkpi
|
||||
OLD_FILES+=usr/include/dev/usb/usb_compat_linux.h
|
||||
# 20151015: test symbols moved to /usr/lib/debug
|
||||
OLD_DIRS+=usr/tests/lib/atf/libatf-c++/.debug
|
||||
OLD_FILES+=usr/tests/lib/atf/libatf-c++/.debug/atf_c++_test.debug
|
||||
|
@ -64,6 +64,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
|
||||
static int bflag, eflag, lflag, nflag, sflag, tflag, vflag;
|
||||
static int rval;
|
||||
@ -207,6 +209,7 @@ static void
|
||||
cook_cat(FILE *fp)
|
||||
{
|
||||
int ch, gobble, line, prev;
|
||||
wint_t wch;
|
||||
|
||||
/* Reset EOF condition on stdin. */
|
||||
if (fp == stdin && feof(stdin))
|
||||
@ -239,18 +242,40 @@ cook_cat(FILE *fp)
|
||||
continue;
|
||||
}
|
||||
} else if (vflag) {
|
||||
if (!isascii(ch) && !isprint(ch)) {
|
||||
(void)ungetc(ch, fp);
|
||||
/*
|
||||
* Our getwc(3) doesn't change file position
|
||||
* on error.
|
||||
*/
|
||||
if ((wch = getwc(fp)) == WEOF) {
|
||||
if (ferror(fp) && errno == EILSEQ) {
|
||||
clearerr(fp);
|
||||
/* Resync attempt. */
|
||||
memset(&fp->_mbstate, 0, sizeof(mbstate_t));
|
||||
if ((ch = getc(fp)) == EOF)
|
||||
break;
|
||||
wch = ch;
|
||||
goto ilseq;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (!iswascii(wch) && !iswprint(wch)) {
|
||||
ilseq:
|
||||
if (putchar('M') == EOF || putchar('-') == EOF)
|
||||
break;
|
||||
ch = toascii(ch);
|
||||
wch = toascii(wch);
|
||||
}
|
||||
if (iscntrl(ch)) {
|
||||
if (putchar('^') == EOF ||
|
||||
putchar(ch == '\177' ? '?' :
|
||||
ch | 0100) == EOF)
|
||||
if (iswcntrl(wch)) {
|
||||
ch = toascii(wch);
|
||||
ch = (ch == '\177') ? '?' : (ch | 0100);
|
||||
if (putchar('^') == EOF || putchar(ch) == EOF)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (putwchar(wch) == WEOF)
|
||||
break;
|
||||
ch = -1;
|
||||
continue;
|
||||
}
|
||||
if (putchar(ch) == EOF)
|
||||
break;
|
||||
|
@ -159,6 +159,15 @@
|
||||
#define CAN_RESTORE_METADATA_FD
|
||||
#endif
|
||||
|
||||
/*
|
||||
* glibc 2.24 deprecates readdir_r
|
||||
*/
|
||||
#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24))
|
||||
#define USE_READDIR_R 1
|
||||
#else
|
||||
#undef USE_READDIR_R
|
||||
#endif
|
||||
|
||||
/* Set up defaults for internal error codes. */
|
||||
#ifndef ARCHIVE_ERRNO_FILE_FORMAT
|
||||
#if HAVE_EFTYPE
|
||||
|
@ -411,9 +411,7 @@ setup_acls(struct archive_read_disk *a,
|
||||
{
|
||||
const char *accpath;
|
||||
acl_t acl;
|
||||
#if HAVE_ACL_IS_TRIVIAL_NP
|
||||
int r;
|
||||
#endif
|
||||
|
||||
accpath = archive_entry_sourcepath(entry);
|
||||
if (accpath == NULL)
|
||||
@ -473,9 +471,13 @@ setup_acls(struct archive_read_disk *a,
|
||||
}
|
||||
#endif
|
||||
if (acl != NULL) {
|
||||
translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
|
||||
r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
|
||||
acl_free(acl);
|
||||
return (ARCHIVE_OK);
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Couldn't translate NFSv4 ACLs: %s", accpath);
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
#endif /* ACL_TYPE_NFS4 */
|
||||
|
||||
@ -506,19 +508,30 @@ setup_acls(struct archive_read_disk *a,
|
||||
#endif
|
||||
|
||||
if (acl != NULL) {
|
||||
translate_acl(a, entry, acl,
|
||||
r = translate_acl(a, entry, acl,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
|
||||
acl_free(acl);
|
||||
acl = NULL;
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Couldn't translate access ACLs: %s", accpath);
|
||||
return (r);
|
||||
}
|
||||
}
|
||||
|
||||
/* Only directories can have default ACLs. */
|
||||
if (S_ISDIR(archive_entry_mode(entry))) {
|
||||
acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
|
||||
if (acl != NULL) {
|
||||
translate_acl(a, entry, acl,
|
||||
r = translate_acl(a, entry, acl,
|
||||
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
|
||||
acl_free(acl);
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Couldn't translate default ACLs: %s",
|
||||
accpath);
|
||||
return (r);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
@ -574,19 +587,23 @@ translate_acl(struct archive_read_disk *a,
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
acl_entry_type_t acl_type;
|
||||
acl_flagset_t acl_flagset;
|
||||
int brand, r;
|
||||
int brand;
|
||||
#endif
|
||||
acl_entry_t acl_entry;
|
||||
acl_permset_t acl_permset;
|
||||
int i, entry_acl_type;
|
||||
int s, ae_id, ae_tag, ae_perm;
|
||||
int r, s, ae_id, ae_tag, ae_perm;
|
||||
const char *ae_name;
|
||||
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
|
||||
// Make sure the "brand" on this ACL is consistent
|
||||
// with the default_entry_acl_type bits provided.
|
||||
acl_get_brand_np(acl, &brand);
|
||||
if (acl_get_brand_np(acl, &brand) != 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Failed to read ACL brand");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
switch (brand) {
|
||||
case ACL_BRAND_POSIX:
|
||||
switch (default_entry_acl_type) {
|
||||
@ -594,31 +611,43 @@ translate_acl(struct archive_read_disk *a,
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
|
||||
break;
|
||||
default:
|
||||
// XXX set warning message?
|
||||
return ARCHIVE_FAILED;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid ACL entry type for POSIX.1e ACL");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
break;
|
||||
case ACL_BRAND_NFS4:
|
||||
if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
|
||||
// XXX set warning message?
|
||||
return ARCHIVE_FAILED;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid ACL entry type for NFSv4 ACL");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// XXX set warning message?
|
||||
return ARCHIVE_FAILED;
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Unknown ACL brand");
|
||||
return (ARCHIVE_WARN);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
|
||||
if (s == -1) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Failed to get first ACL entry");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
while (s == 1) {
|
||||
ae_id = -1;
|
||||
ae_name = NULL;
|
||||
ae_perm = 0;
|
||||
|
||||
acl_get_tag_type(acl_entry, &acl_tag);
|
||||
if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Failed to get ACL tag type");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
switch (acl_tag) {
|
||||
case ACL_USER:
|
||||
ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
|
||||
@ -653,13 +682,18 @@ translate_acl(struct archive_read_disk *a,
|
||||
continue;
|
||||
}
|
||||
|
||||
// XXX acl type maps to allow/deny/audit/YYYY bits
|
||||
// XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
|
||||
// non-NFSv4 ACLs
|
||||
// XXX acl_type maps to allow/deny/audit/YYYY bits
|
||||
entry_acl_type = default_entry_acl_type;
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
r = acl_get_entry_type_np(acl_entry, &acl_type);
|
||||
if (r == 0) {
|
||||
if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
|
||||
/*
|
||||
* acl_get_entry_type_np() falis with non-NFSv4 ACLs
|
||||
*/
|
||||
if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
|
||||
archive_set_error(&a->archive, errno, "Failed "
|
||||
"to get ACL type from a NFSv4 ACL entry");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
switch (acl_type) {
|
||||
case ACL_ENTRY_TYPE_ALLOW:
|
||||
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
|
||||
@ -673,32 +707,53 @@ translate_acl(struct archive_read_disk *a,
|
||||
case ACL_ENTRY_TYPE_ALARM:
|
||||
entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
|
||||
break;
|
||||
default:
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Invalid NFSv4 ACL entry type");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Libarchive stores "flag" (NFSv4 inheritance bits)
|
||||
* in the ae_perm bitmap.
|
||||
*/
|
||||
// XXX acl_get_flagset_np on FreeBSD returns EINVAL for
|
||||
// non-NFSv4 ACLs
|
||||
r = acl_get_flagset_np(acl_entry, &acl_flagset);
|
||||
if (r == 0) {
|
||||
/*
|
||||
* Libarchive stores "flag" (NFSv4 inheritance bits)
|
||||
* in the ae_perm bitmap.
|
||||
*
|
||||
* acl_get_flagset_np() fails with non-NFSv4 ACLs
|
||||
*/
|
||||
if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Failed to get flagset from a NFSv4 ACL entry");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
|
||||
if (acl_get_flag_np(acl_flagset,
|
||||
acl_inherit_map[i].platform_inherit))
|
||||
r = acl_get_flag_np(acl_flagset,
|
||||
acl_inherit_map[i].platform_inherit);
|
||||
if (r == -1) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Failed to check flag in a NFSv4 "
|
||||
"ACL flagset");
|
||||
return (ARCHIVE_WARN);
|
||||
} else if (r)
|
||||
ae_perm |= acl_inherit_map[i].archive_inherit;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
acl_get_permset(acl_entry, &acl_permset);
|
||||
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Failed to get ACL permission set");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
|
||||
/*
|
||||
* acl_get_perm() is spelled differently on different
|
||||
* platforms; see above.
|
||||
*/
|
||||
if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
|
||||
r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm);
|
||||
if (r == -1) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Failed to check permission in an ACL permission set");
|
||||
return (ARCHIVE_WARN);
|
||||
} else if (r)
|
||||
ae_perm |= acl_perm_map[i].archive_perm;
|
||||
}
|
||||
|
||||
@ -707,6 +762,11 @@ translate_acl(struct archive_read_disk *a,
|
||||
ae_id, ae_name);
|
||||
|
||||
s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
|
||||
if (s == -1) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Failed to get next ACL entry");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ struct filesystem {
|
||||
int synthetic;
|
||||
int remote;
|
||||
int noatime;
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
size_t name_max;
|
||||
#endif
|
||||
long incr_xfer_size;
|
||||
@ -200,7 +200,7 @@ struct tree {
|
||||
DIR *d;
|
||||
#define INVALID_DIR_HANDLE NULL
|
||||
struct dirent *de;
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
struct dirent *dirent;
|
||||
size_t dirent_allocated;
|
||||
#endif
|
||||
@ -1592,7 +1592,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
#endif
|
||||
t->current_filesystem->noatime = 0;
|
||||
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
/* Set maximum filename length. */
|
||||
#if defined(HAVE_STRUCT_STATFS_F_NAMEMAX)
|
||||
t->current_filesystem->name_max = sfs.f_namemax;
|
||||
@ -1615,7 +1615,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
else
|
||||
t->current_filesystem->name_max = nm;
|
||||
#endif
|
||||
#endif /* HAVE_READDIR_R */
|
||||
#endif /* USE_READDIR_R */
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -1817,7 +1817,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
#endif
|
||||
t->current_filesystem->noatime = 0;
|
||||
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
/* Set maximum filename length. */
|
||||
t->current_filesystem->name_max = sfs.f_namelen;
|
||||
#endif
|
||||
@ -1901,7 +1901,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
#endif
|
||||
t->current_filesystem->noatime = 0;
|
||||
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
/* Set maximum filename length. */
|
||||
t->current_filesystem->name_max = sfs.f_namemax;
|
||||
#endif
|
||||
@ -1918,7 +1918,7 @@ static int
|
||||
setup_current_filesystem(struct archive_read_disk *a)
|
||||
{
|
||||
struct tree *t = a->tree;
|
||||
#if defined(_PC_NAME_MAX) && defined(HAVE_READDIR_R)
|
||||
#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R)
|
||||
long nm;
|
||||
#endif
|
||||
t->current_filesystem->synthetic = -1;/* Not supported */
|
||||
@ -1930,7 +1930,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
t->current_filesystem->min_xfer_size = -1;
|
||||
t->current_filesystem->incr_xfer_size = -1;
|
||||
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
/* Set maximum filename length. */
|
||||
# if defined(_PC_NAME_MAX)
|
||||
if (tree_current_is_symblic_link_target(t)) {
|
||||
@ -1958,7 +1958,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
||||
else
|
||||
t->current_filesystem->name_max = nm;
|
||||
# endif /* _PC_NAME_MAX */
|
||||
#endif /* HAVE_READDIR_R */
|
||||
#endif /* USE_READDIR_R */
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -2366,7 +2366,7 @@ tree_dir_next_posix(struct tree *t)
|
||||
size_t namelen;
|
||||
|
||||
if (t->d == NULL) {
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
size_t dirent_size;
|
||||
#endif
|
||||
|
||||
@ -2387,7 +2387,7 @@ tree_dir_next_posix(struct tree *t)
|
||||
t->visit_type = r != 0 ? r : TREE_ERROR_DIR;
|
||||
return (t->visit_type);
|
||||
}
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
dirent_size = offsetof(struct dirent, d_name) +
|
||||
t->filesystem_table[t->current->filesystem_id].name_max + 1;
|
||||
if (t->dirent == NULL || t->dirent_allocated < dirent_size) {
|
||||
@ -2404,11 +2404,11 @@ tree_dir_next_posix(struct tree *t)
|
||||
}
|
||||
t->dirent_allocated = dirent_size;
|
||||
}
|
||||
#endif /* HAVE_READDIR_R */
|
||||
#endif /* USE_READDIR_R */
|
||||
}
|
||||
for (;;) {
|
||||
errno = 0;
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
r = readdir_r(t->d, t->dirent, &t->de);
|
||||
#ifdef _AIX
|
||||
/* Note: According to the man page, return value 9 indicates
|
||||
@ -2660,7 +2660,7 @@ tree_free(struct tree *t)
|
||||
if (t == NULL)
|
||||
return;
|
||||
archive_string_free(&t->path);
|
||||
#if defined(HAVE_READDIR_R)
|
||||
#if defined(USE_READDIR_R)
|
||||
free(t->dirent);
|
||||
#endif
|
||||
free(t->sparse_list);
|
||||
|
@ -136,6 +136,7 @@ struct tar {
|
||||
int64_t entry_padding;
|
||||
int64_t entry_bytes_unconsumed;
|
||||
int64_t realsize;
|
||||
int sparse_allowed;
|
||||
struct sparse_block *sparse_list;
|
||||
struct sparse_block *sparse_last;
|
||||
int64_t sparse_offset;
|
||||
@ -1271,6 +1272,14 @@ header_common(struct archive_read *a, struct tar *tar,
|
||||
* sparse information in the extended area.
|
||||
*/
|
||||
/* FALLTHROUGH */
|
||||
case '0':
|
||||
/*
|
||||
* Enable sparse file "read" support only for regular
|
||||
* files and explicit GNU sparse files. However, we
|
||||
* don't allow non-standard file types to be sparse.
|
||||
*/
|
||||
tar->sparse_allowed = 1;
|
||||
/* FALLTHROUGH */
|
||||
default: /* Regular file and non-standard types */
|
||||
/*
|
||||
* Per POSIX: non-recognized types should always be
|
||||
@ -1730,6 +1739,14 @@ pax_attribute(struct archive_read *a, struct tar *tar,
|
||||
#endif
|
||||
switch (key[0]) {
|
||||
case 'G':
|
||||
/* Reject GNU.sparse.* headers on non-regular files. */
|
||||
if (strncmp(key, "GNU.sparse", 10) == 0 &&
|
||||
!tar->sparse_allowed) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Non-regular file cannot be sparse");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* GNU "0.0" sparse pax format. */
|
||||
if (strcmp(key, "GNU.sparse.numblocks") == 0) {
|
||||
tar->sparse_offset = -1;
|
||||
|
@ -153,9 +153,19 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
if (entries == 0)
|
||||
return (ARCHIVE_OK);
|
||||
acl = acl_init(entries);
|
||||
if (acl == (acl_t)NULL) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to initialize ACL working storage");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
|
||||
&ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
|
||||
acl_create_entry(&acl, &acl_entry);
|
||||
if (acl_create_entry(&acl, &acl_entry) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to create a new ACL entry");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
switch (ae_tag) {
|
||||
case ARCHIVE_ENTRY_ACL_USER:
|
||||
@ -186,53 +196,96 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* XXX */
|
||||
break;
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Unknown ACL tag");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
r = 0;
|
||||
switch (ae_type) {
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
|
||||
acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
|
||||
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DENY:
|
||||
acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
|
||||
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
|
||||
acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
|
||||
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
|
||||
acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
|
||||
r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
|
||||
break;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
|
||||
// These don't translate directly into the system ACL.
|
||||
break;
|
||||
default:
|
||||
// XXX error handling here.
|
||||
break;
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
"Unknown ACL entry type");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
if (r != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to set ACL entry type");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
#endif
|
||||
|
||||
acl_get_permset(acl_entry, &acl_permset);
|
||||
acl_clear_perms(acl_permset);
|
||||
if (acl_get_permset(acl_entry, &acl_permset) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to get ACL permission set");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
if (acl_clear_perms(acl_permset) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to clear ACL permissions");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
|
||||
if (ae_permset & acl_perm_map[i].archive_perm)
|
||||
acl_add_perm(acl_permset,
|
||||
acl_perm_map[i].platform_perm);
|
||||
if (acl_add_perm(acl_permset,
|
||||
acl_perm_map[i].platform_perm) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to add ACL permission");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ACL_TYPE_NFS4
|
||||
// XXX acl_get_flagset_np on FreeBSD returns EINVAL for
|
||||
// non-NFSv4 ACLs
|
||||
r = acl_get_flagset_np(acl_entry, &acl_flagset);
|
||||
if (r == 0) {
|
||||
acl_clear_flags_np(acl_flagset);
|
||||
if (acl_type == ACL_TYPE_NFS4) {
|
||||
/*
|
||||
* acl_get_flagset_np() fails with non-NFSv4 ACLs
|
||||
*/
|
||||
if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to get flagset from an NFSv4 ACL entry");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
if (acl_clear_flags_np(acl_flagset) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to clear flags from an NFSv4 ACL flagset");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
|
||||
if (ae_permset & acl_inherit_map[i].archive_inherit)
|
||||
acl_add_flag_np(acl_flagset,
|
||||
acl_inherit_map[i].platform_inherit);
|
||||
if (ae_permset & acl_inherit_map[i].archive_inherit) {
|
||||
if (acl_add_flag_np(acl_flagset,
|
||||
acl_inherit_map[i].platform_inherit) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to add flag to NFSv4 ACL flagset");
|
||||
ret = ARCHIVE_FAILED;
|
||||
goto exit_free;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -262,6 +315,7 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
#endif
|
||||
exit_free:
|
||||
acl_free(acl);
|
||||
return (ret);
|
||||
}
|
||||
|
@ -140,7 +140,17 @@ __FBSDID("$FreeBSD$");
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
/* Ignore non-int O_NOFOLLOW constant. */
|
||||
/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */
|
||||
#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
|
||||
#undef O_NOFOLLOW
|
||||
#endif
|
||||
|
||||
#ifndef O_NOFOLLOW
|
||||
#define O_NOFOLLOW 0
|
||||
#endif
|
||||
|
||||
struct fixup_entry {
|
||||
@ -326,12 +336,14 @@ struct archive_write_disk {
|
||||
|
||||
#define HFS_BLOCKS(s) ((s) >> 12)
|
||||
|
||||
static int check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags);
|
||||
static int check_symlinks(struct archive_write_disk *);
|
||||
static int create_filesystem_object(struct archive_write_disk *);
|
||||
static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname);
|
||||
#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
|
||||
static void edit_deep_directories(struct archive_write_disk *ad);
|
||||
#endif
|
||||
static int cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags);
|
||||
static int cleanup_pathname(struct archive_write_disk *);
|
||||
static int create_dir(struct archive_write_disk *, char *);
|
||||
static int create_parent_dir(struct archive_write_disk *, char *);
|
||||
@ -2014,6 +2026,10 @@ create_filesystem_object(struct archive_write_disk *a)
|
||||
const char *linkname;
|
||||
mode_t final_mode, mode;
|
||||
int r;
|
||||
/* these for check_symlinks_fsobj */
|
||||
char *linkname_copy; /* non-const copy of linkname */
|
||||
struct archive_string error_string;
|
||||
int error_number;
|
||||
|
||||
/* We identify hard/symlinks according to the link names. */
|
||||
/* Since link(2) and symlink(2) don't handle modes, we're done here. */
|
||||
@ -2022,6 +2038,27 @@ create_filesystem_object(struct archive_write_disk *a)
|
||||
#if !HAVE_LINK
|
||||
return (EPERM);
|
||||
#else
|
||||
archive_string_init(&error_string);
|
||||
linkname_copy = strdup(linkname);
|
||||
if (linkname_copy == NULL) {
|
||||
return (EPERM);
|
||||
}
|
||||
/* TODO: consider using the cleaned-up path as the link target? */
|
||||
r = cleanup_pathname_fsobj(linkname_copy, &error_number, &error_string, a->flags);
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s", error_string.s);
|
||||
free(linkname_copy);
|
||||
/* EPERM is more appropriate than error_number for our callers */
|
||||
return (EPERM);
|
||||
}
|
||||
r = check_symlinks_fsobj(linkname_copy, &error_number, &error_string, a->flags);
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s", error_string.s);
|
||||
free(linkname_copy);
|
||||
/* EPERM is more appropriate than error_number for our callers */
|
||||
return (EPERM);
|
||||
}
|
||||
free(linkname_copy);
|
||||
r = link(linkname, a->name) ? errno : 0;
|
||||
/*
|
||||
* New cpio and pax formats allow hardlink entries
|
||||
@ -2040,7 +2077,7 @@ create_filesystem_object(struct archive_write_disk *a)
|
||||
a->deferred = 0;
|
||||
} else if (r == 0 && a->filesize > 0) {
|
||||
a->fd = open(a->name,
|
||||
O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC);
|
||||
O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC | O_NOFOLLOW);
|
||||
__archive_ensure_cloexec_flag(a->fd);
|
||||
if (a->fd < 0)
|
||||
r = errno;
|
||||
@ -2351,126 +2388,233 @@ current_fixup(struct archive_write_disk *a, const char *pathname)
|
||||
return (a->current_fixup);
|
||||
}
|
||||
|
||||
/* TODO: Make this work. */
|
||||
/*
|
||||
* TODO: The deep-directory support bypasses this; disable deep directory
|
||||
* support if we're doing symlink checks.
|
||||
*/
|
||||
/*
|
||||
* TODO: Someday, integrate this with the deep dir support; they both
|
||||
* scan the path and both can be optimized by comparing against other
|
||||
* recent paths.
|
||||
*/
|
||||
/* TODO: Extend this to support symlinks on Windows Vista and later. */
|
||||
|
||||
/*
|
||||
* Checks the given path to see if any elements along it are symlinks. Returns
|
||||
* ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
|
||||
*/
|
||||
static int
|
||||
check_symlinks(struct archive_write_disk *a)
|
||||
check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags)
|
||||
{
|
||||
#if !defined(HAVE_LSTAT)
|
||||
/* Platform doesn't have lstat, so we can't look for symlinks. */
|
||||
(void)a; /* UNUSED */
|
||||
(void)path; /* UNUSED */
|
||||
(void)error_number; /* UNUSED */
|
||||
(void)error_string; /* UNUSED */
|
||||
(void)flags; /* UNUSED */
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
char *pn;
|
||||
int res = ARCHIVE_OK;
|
||||
char *tail;
|
||||
char *head;
|
||||
int last;
|
||||
char c;
|
||||
int r;
|
||||
struct stat st;
|
||||
int restore_pwd;
|
||||
|
||||
/* Nothing to do here if name is empty */
|
||||
if(path[0] == '\0')
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
/*
|
||||
* Guard against symlink tricks. Reject any archive entry whose
|
||||
* destination would be altered by a symlink.
|
||||
*
|
||||
* Walk the filename in chunks separated by '/'. For each segment:
|
||||
* - if it doesn't exist, continue
|
||||
* - if it's symlink, abort or remove it
|
||||
* - if it's a directory and it's not the last chunk, cd into it
|
||||
* As we go:
|
||||
* head points to the current (relative) path
|
||||
* tail points to the temporary \0 terminating the segment we're currently examining
|
||||
* c holds what used to be in *tail
|
||||
* last is 1 if this is the last tail
|
||||
*/
|
||||
/* Whatever we checked last time doesn't need to be re-checked. */
|
||||
pn = a->name;
|
||||
if (archive_strlen(&(a->path_safe)) > 0) {
|
||||
char *p = a->path_safe.s;
|
||||
while ((*pn != '\0') && (*p == *pn))
|
||||
++p, ++pn;
|
||||
}
|
||||
restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC);
|
||||
__archive_ensure_cloexec_flag(restore_pwd);
|
||||
if (restore_pwd < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
head = path;
|
||||
tail = path;
|
||||
last = 0;
|
||||
/* TODO: reintroduce a safe cache here? */
|
||||
/* Skip the root directory if the path is absolute. */
|
||||
if(pn == a->name && pn[0] == '/')
|
||||
++pn;
|
||||
c = pn[0];
|
||||
/* Keep going until we've checked the entire name. */
|
||||
while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) {
|
||||
if(tail == path && tail[0] == '/')
|
||||
++tail;
|
||||
/* Keep going until we've checked the entire name.
|
||||
* head, tail, path all alias the same string, which is
|
||||
* temporarily zeroed at tail, so be careful restoring the
|
||||
* stashed (c=tail[0]) for error messages.
|
||||
* Exiting the loop with break is okay; continue is not.
|
||||
*/
|
||||
while (!last) {
|
||||
/* Skip the separator we just consumed, plus any adjacent ones */
|
||||
while (*tail == '/')
|
||||
++tail;
|
||||
/* Skip the next path element. */
|
||||
while (*pn != '\0' && *pn != '/')
|
||||
++pn;
|
||||
c = pn[0];
|
||||
pn[0] = '\0';
|
||||
while (*tail != '\0' && *tail != '/')
|
||||
++tail;
|
||||
/* is this the last path component? */
|
||||
last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0');
|
||||
/* temporarily truncate the string here */
|
||||
c = tail[0];
|
||||
tail[0] = '\0';
|
||||
/* Check that we haven't hit a symlink. */
|
||||
r = lstat(a->name, &st);
|
||||
r = lstat(head, &st);
|
||||
if (r != 0) {
|
||||
tail[0] = c;
|
||||
/* We've hit a dir that doesn't exist; stop now. */
|
||||
if (errno == ENOENT) {
|
||||
break;
|
||||
} else {
|
||||
/* Note: This effectively disables deep directory
|
||||
/* Treat any other error as fatal - best to be paranoid here
|
||||
* Note: This effectively disables deep directory
|
||||
* support when security checks are enabled.
|
||||
* Otherwise, very long pathnames that trigger
|
||||
* an error here could evade the sandbox.
|
||||
* TODO: We could do better, but it would probably
|
||||
* require merging the symlink checks with the
|
||||
* deep-directory editing. */
|
||||
return (ARCHIVE_FAILED);
|
||||
if (error_number) *error_number = errno;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Could not stat %s",
|
||||
path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
} else if (S_ISDIR(st.st_mode)) {
|
||||
if (!last) {
|
||||
if (chdir(head) != 0) {
|
||||
tail[0] = c;
|
||||
if (error_number) *error_number = errno;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Could not chdir %s",
|
||||
path);
|
||||
res = (ARCHIVE_FATAL);
|
||||
break;
|
||||
}
|
||||
/* Our view is now from inside this dir: */
|
||||
head = tail + 1;
|
||||
}
|
||||
} else if (S_ISLNK(st.st_mode)) {
|
||||
if (c == '\0') {
|
||||
if (last) {
|
||||
/*
|
||||
* Last element is symlink; remove it
|
||||
* so we can overwrite it with the
|
||||
* item being extracted.
|
||||
*/
|
||||
if (unlink(a->name)) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Could not remove symlink %s",
|
||||
a->name);
|
||||
pn[0] = c;
|
||||
return (ARCHIVE_FAILED);
|
||||
if (unlink(head)) {
|
||||
tail[0] = c;
|
||||
if (error_number) *error_number = errno;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Could not remove symlink %s",
|
||||
path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
a->pst = NULL;
|
||||
/*
|
||||
* Even if we did remove it, a warning
|
||||
* is in order. The warning is silly,
|
||||
* though, if we're just replacing one
|
||||
* symlink with another symlink.
|
||||
*/
|
||||
if (!S_ISLNK(a->mode)) {
|
||||
archive_set_error(&a->archive, 0,
|
||||
"Removing symlink %s",
|
||||
a->name);
|
||||
tail[0] = c;
|
||||
/* FIXME: not sure how important this is to restore
|
||||
if (!S_ISLNK(path)) {
|
||||
if (error_number) *error_number = 0;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Removing symlink %s",
|
||||
path);
|
||||
}
|
||||
*/
|
||||
/* Symlink gone. No more problem! */
|
||||
pn[0] = c;
|
||||
return (0);
|
||||
} else if (a->flags & ARCHIVE_EXTRACT_UNLINK) {
|
||||
res = ARCHIVE_OK;
|
||||
break;
|
||||
} else if (flags & ARCHIVE_EXTRACT_UNLINK) {
|
||||
/* User asked us to remove problems. */
|
||||
if (unlink(a->name) != 0) {
|
||||
archive_set_error(&a->archive, 0,
|
||||
"Cannot remove intervening symlink %s",
|
||||
a->name);
|
||||
pn[0] = c;
|
||||
return (ARCHIVE_FAILED);
|
||||
if (unlink(head) != 0) {
|
||||
tail[0] = c;
|
||||
if (error_number) *error_number = 0;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Cannot remove intervening symlink %s",
|
||||
path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
a->pst = NULL;
|
||||
tail[0] = c;
|
||||
} else {
|
||||
archive_set_error(&a->archive, 0,
|
||||
"Cannot extract through symlink %s",
|
||||
a->name);
|
||||
pn[0] = c;
|
||||
return (ARCHIVE_FAILED);
|
||||
tail[0] = c;
|
||||
if (error_number) *error_number = 0;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Cannot extract through symlink %s",
|
||||
path);
|
||||
res = ARCHIVE_FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pn[0] = c;
|
||||
if (pn[0] != '\0')
|
||||
pn++; /* Advance to the next segment. */
|
||||
/* be sure to always maintain this */
|
||||
tail[0] = c;
|
||||
if (tail[0] != '\0')
|
||||
tail++; /* Advance to the next segment. */
|
||||
}
|
||||
pn[0] = c;
|
||||
/* We've checked and/or cleaned the whole path, so remember it. */
|
||||
archive_strcpy(&a->path_safe, a->name);
|
||||
return (ARCHIVE_OK);
|
||||
/* Catches loop exits via break */
|
||||
tail[0] = c;
|
||||
#ifdef HAVE_FCHDIR
|
||||
/* If we changed directory above, restore it here. */
|
||||
if (restore_pwd >= 0) {
|
||||
r = fchdir(restore_pwd);
|
||||
if (r != 0) {
|
||||
if(error_number) *error_number = errno;
|
||||
if(error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"chdir() failure");
|
||||
}
|
||||
close(restore_pwd);
|
||||
restore_pwd = -1;
|
||||
if (r != 0) {
|
||||
res = (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* TODO: reintroduce a safe cache here? */
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise
|
||||
* calls archive_set_error and returns ARCHIVE_{FATAL,FAILED}
|
||||
*/
|
||||
static int
|
||||
check_symlinks(struct archive_write_disk *a)
|
||||
{
|
||||
struct archive_string error_string;
|
||||
int error_number;
|
||||
int rc;
|
||||
archive_string_init(&error_string);
|
||||
rc = check_symlinks_fsobj(a->name, &error_number, &error_string, a->flags);
|
||||
if (rc != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s", error_string.s);
|
||||
}
|
||||
archive_string_free(&error_string);
|
||||
a->pst = NULL; /* to be safe */
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
/*
|
||||
* 1. Convert a path separator from '\' to '/' .
|
||||
@ -2544,15 +2688,17 @@ cleanup_pathname_win(struct archive_write_disk *a)
|
||||
* is set) if the path is absolute.
|
||||
*/
|
||||
static int
|
||||
cleanup_pathname(struct archive_write_disk *a)
|
||||
cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags)
|
||||
{
|
||||
char *dest, *src;
|
||||
char separator = '\0';
|
||||
|
||||
dest = src = a->name;
|
||||
dest = src = path;
|
||||
if (*src == '\0') {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid empty pathname");
|
||||
if (error_number) *error_number = ARCHIVE_ERRNO_MISC;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Invalid empty pathname");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
@ -2561,9 +2707,11 @@ cleanup_pathname(struct archive_write_disk *a)
|
||||
#endif
|
||||
/* Skip leading '/'. */
|
||||
if (*src == '/') {
|
||||
if (a->flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Path is absolute");
|
||||
if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
|
||||
if (error_number) *error_number = ARCHIVE_ERRNO_MISC;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Path is absolute");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
@ -2590,10 +2738,11 @@ cleanup_pathname(struct archive_write_disk *a)
|
||||
} else if (src[1] == '.') {
|
||||
if (src[2] == '/' || src[2] == '\0') {
|
||||
/* Conditionally warn about '..' */
|
||||
if (a->flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Path contains '..'");
|
||||
if (flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
|
||||
if (error_number) *error_number = ARCHIVE_ERRNO_MISC;
|
||||
if (error_string)
|
||||
archive_string_sprintf(error_string,
|
||||
"Path contains '..'");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
}
|
||||
@ -2624,7 +2773,7 @@ cleanup_pathname(struct archive_write_disk *a)
|
||||
* We've just copied zero or more path elements, not including the
|
||||
* final '/'.
|
||||
*/
|
||||
if (dest == a->name) {
|
||||
if (dest == path) {
|
||||
/*
|
||||
* Nothing got copied. The path must have been something
|
||||
* like '.' or '/' or './' or '/././././/./'.
|
||||
@ -2639,6 +2788,21 @@ cleanup_pathname(struct archive_write_disk *a)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
cleanup_pathname(struct archive_write_disk *a)
|
||||
{
|
||||
struct archive_string error_string;
|
||||
int error_number;
|
||||
int rc;
|
||||
archive_string_init(&error_string);
|
||||
rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string, a->flags);
|
||||
if (rc != ARCHIVE_OK) {
|
||||
archive_set_error(&a->archive, error_number, "%s", error_string.s);
|
||||
}
|
||||
archive_string_free(&error_string);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the parent directory of the specified path, assuming path
|
||||
* is already in mutable storage.
|
||||
|
@ -58,7 +58,7 @@ DEFINE_TEST(test_write_disk_secure745)
|
||||
/* Create a symlink pointing to the target directory */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "sym");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0777);
|
||||
archive_entry_set_mode(ae, AE_IFLNK | 0777);
|
||||
archive_entry_copy_symlink(ae, "../target");
|
||||
assert(0 == archive_write_header(a, ae));
|
||||
archive_entry_free(ae);
|
||||
@ -72,5 +72,8 @@ DEFINE_TEST(test_write_disk_secure745)
|
||||
|
||||
/* Permission of target dir should not have changed. */
|
||||
assertFileMode("../target", 0700);
|
||||
|
||||
assert(0 == archive_write_close(a));
|
||||
archive_write_free(a);
|
||||
#endif
|
||||
}
|
||||
|
@ -63,11 +63,11 @@ DEFINE_TEST(test_write_disk_secure746a)
|
||||
/* Attempt to hardlink to the target directory. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "bar");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0777);
|
||||
archive_entry_set_mode(ae, AE_IFREG | 0777);
|
||||
archive_entry_set_size(ae, 8);
|
||||
archive_entry_copy_hardlink(ae, "../target/foo");
|
||||
assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
|
||||
assertEqualInt(ARCHIVE_FAILED, archive_write_data(a, "modified", 8));
|
||||
assertEqualInt(ARCHIVE_FATAL, archive_write_data(a, "modified", 8));
|
||||
archive_entry_free(ae);
|
||||
|
||||
/* Verify that target file contents are unchanged. */
|
||||
@ -105,21 +105,25 @@ DEFINE_TEST(test_write_disk_secure746b)
|
||||
/* Create a symlink to the target directory. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "symlink");
|
||||
archive_entry_set_mode(ae, AE_IFLNK | 0777);
|
||||
archive_entry_copy_symlink(ae, "../target");
|
||||
assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
|
||||
archive_entry_free(ae);
|
||||
|
||||
/* Attempt to hardlink to the target directory via the symlink. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_copy_pathname(ae, "bar");
|
||||
archive_entry_set_mode(ae, S_IFREG | 0777);
|
||||
archive_entry_set_mode(ae, AE_IFREG | 0777);
|
||||
archive_entry_set_size(ae, 8);
|
||||
archive_entry_copy_hardlink(ae, "symlink/foo");
|
||||
assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
|
||||
assertEqualInt(ARCHIVE_FAILED, archive_write_data(a, "modified", 8));
|
||||
assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
|
||||
assertEqualIntA(a, ARCHIVE_FATAL, archive_write_data(a, "modified", 8));
|
||||
archive_entry_free(ae);
|
||||
|
||||
/* Verify that target file contents are unchanged. */
|
||||
assertTextFileContents("unmodified", "../target/foo");
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_FATAL, archive_write_close(a));
|
||||
archive_write_free(a);
|
||||
#endif
|
||||
}
|
||||
|
@ -100,6 +100,10 @@ DEFINE_TEST(test_write_format_gnutar_linknames)
|
||||
size_t used;
|
||||
int i;
|
||||
|
||||
#ifdef S_IFLNK
|
||||
assertEqualInt(S_IFLNK, AE_IFLNK);
|
||||
#endif
|
||||
|
||||
buff = malloc(buffsize); /* million bytes of work area */
|
||||
assert(buff != NULL);
|
||||
|
||||
@ -109,7 +113,7 @@ DEFINE_TEST(test_write_format_gnutar_linknames)
|
||||
archive_entry_set_birthtime(template, 3, 30);
|
||||
archive_entry_set_ctime(template, 4, 40);
|
||||
archive_entry_set_mtime(template, 5, 50);
|
||||
archive_entry_set_mode(template, S_IFLNK | 0755);
|
||||
archive_entry_set_mode(template, AE_IFLNK | 0755);
|
||||
archive_entry_copy_pathname(template, "link");
|
||||
|
||||
for (i = 0; i < 2000; ++i) {
|
||||
|
@ -110,6 +110,8 @@
|
||||
..
|
||||
ciss
|
||||
..
|
||||
evdev
|
||||
..
|
||||
filemon
|
||||
..
|
||||
firewire
|
||||
|
@ -154,7 +154,7 @@ copies: .PHONY .META
|
||||
done; \
|
||||
fi
|
||||
.endfor
|
||||
.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/nand:Ndev/pci} ${LSUBSUBDIRS}
|
||||
.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/nand:Ndev/pci} ${LSUBSUBDIRS}
|
||||
cd ${.CURDIR}/../sys; \
|
||||
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \
|
||||
${DESTDIR}${INCLUDEDIR}/$i
|
||||
@ -177,6 +177,13 @@ copies: .PHONY .META
|
||||
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 nand_dev.h \
|
||||
${DESTDIR}${INCLUDEDIR}/dev/nand
|
||||
.endif
|
||||
cd ${.CURDIR}/../sys/dev/evdev; \
|
||||
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 input.h \
|
||||
${DESTDIR}${INCLUDEDIR}/dev/evdev; \
|
||||
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 input-event-codes.h \
|
||||
${DESTDIR}${INCLUDEDIR}/dev/evdev; \
|
||||
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 uinput.h \
|
||||
${DESTDIR}${INCLUDEDIR}/dev/evdev
|
||||
cd ${.CURDIR}/../sys/dev/pci; \
|
||||
${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 pcireg.h \
|
||||
${DESTDIR}${INCLUDEDIR}/dev/pci
|
||||
@ -238,7 +245,7 @@ symlinks: .PHONY .META
|
||||
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \
|
||||
done
|
||||
.endfor
|
||||
.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/nand:Ndev/pci}
|
||||
.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/nand:Ndev/pci}
|
||||
cd ${.CURDIR}/../sys/$i; \
|
||||
for h in *.h; do \
|
||||
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/$i/$$h ${DESTDIR}${INCLUDEDIR}/$i; \
|
||||
@ -266,6 +273,11 @@ symlinks: .PHONY .META
|
||||
${DESTDIR}${INCLUDEDIR}/dev/nand; \
|
||||
done
|
||||
.endif
|
||||
cd ${.CURDIR}/../sys/dev/evdev; \
|
||||
for h in input.h input-event-codes.h uinput.h; do \
|
||||
ln -fs ../../../../sys/dev/evdev/$$h \
|
||||
${DESTDIR}${INCLUDEDIR}/dev/evdev; \
|
||||
done
|
||||
cd ${.CURDIR}/../sys/dev/pci; \
|
||||
for h in pcireg.h; do \
|
||||
${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/pci/$$h \
|
||||
|
@ -211,6 +211,8 @@ TESTS_SRCS= \
|
||||
test_write_disk_perms.c \
|
||||
test_write_disk_secure.c \
|
||||
test_write_disk_secure744.c \
|
||||
test_write_disk_secure745.c \
|
||||
test_write_disk_secure746.c \
|
||||
test_write_disk_sparse.c \
|
||||
test_write_disk_symlink.c \
|
||||
test_write_disk_times.c \
|
||||
|
@ -4,7 +4,7 @@
|
||||
# machine-independent stdlib sources
|
||||
.PATH: ${LIBC_SRCTOP}/${LIBC_ARCH}/stdlib ${LIBC_SRCTOP}/stdlib
|
||||
|
||||
MISRCS+=_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
|
||||
MISRCS+=C99_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
|
||||
bsearch.c cxa_thread_atexit.c div.c exit.c getenv.c getopt.c getopt_long.c \
|
||||
getsubopt.c hcreate.c hcreate_r.c hdestroy_r.c heapsort.c heapsort_b.c \
|
||||
hsearch_r.c imaxabs.c imaxdiv.c \
|
||||
@ -16,6 +16,13 @@ MISRCS+=_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
|
||||
strtol.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c \
|
||||
strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
|
||||
|
||||
# Work around an issue on case-insensitive file systems.
|
||||
# libc has both _Exit.c and _exit.s and they both yield
|
||||
# _exit.o (case insensitively speaking).
|
||||
CLEANFILES+=C99_Exit.c
|
||||
C99_Exit.c: ${LIBC_SRCTOP}/stdlib/_Exit.c .NOMETA
|
||||
ln -sf ${.ALLSRC} ${.TARGET}
|
||||
|
||||
SYM_MAPS+= ${LIBC_SRCTOP}/stdlib/Symbol.map
|
||||
|
||||
# machine-dependent stdlib sources
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 27, 2014
|
||||
.Dd September 10, 2016
|
||||
.Dt CAP_ENTER 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -84,6 +84,11 @@ to create a runtime environment inside the sandbox that has as few implicitly
|
||||
acquired rights as possible.
|
||||
.Sh RETURN VALUES
|
||||
.Rv -std cap_enter cap_getmode
|
||||
.Pp
|
||||
When the process is in capability mode,
|
||||
.Fn cap_getmode
|
||||
sets the flag to a non-zero value.
|
||||
A zero value means the process is not in capability mode.
|
||||
.Sh ERRORS
|
||||
The
|
||||
.Fn cap_enter
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
PACKAGE= lib${LIB}
|
||||
LIB= ifconfig
|
||||
PRIVATELIB= true
|
||||
# Don't build shared library, for now.
|
||||
NO_PIC=
|
||||
|
||||
|
@ -130,4 +130,4 @@ n_long inet_addr(char *);
|
||||
|
||||
/* Machine-dependent functions: */
|
||||
time_t getsecs(void);
|
||||
#endif
|
||||
#endif /* ! _STAND_NET_H */
|
||||
|
@ -7,7 +7,7 @@ EMBEDDEDBUILD=1
|
||||
EMBEDDED_TARGET="arm"
|
||||
EMBEDDED_TARGET_ARCH="armv6"
|
||||
EMBEDDEDPORTS="sysutils/u-boot-cubieboard"
|
||||
KERNEL="CUBIEBOARD"
|
||||
KERNEL="ALLWINNER_UP"
|
||||
WORLD_FLAGS="${WORLD_FLAGS} UBLDR_LOADADDR=0x42000000"
|
||||
IMAGE_SIZE="1G"
|
||||
PART_SCHEME="MBR"
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 18, 2015
|
||||
.Dd September 8, 2016
|
||||
.Dt GMULTIPATH 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -255,12 +255,11 @@ When this occurs, that path is marked FAIL, the next path
|
||||
in a list is selected as active and the failed I/O reissued.
|
||||
In Active/Active mode all paths not marked FAIL may handle I/O at the same time.
|
||||
Requests are distributed between paths to equalize load.
|
||||
For capable devices it allows to utilize the bandwidth of all paths.
|
||||
For capable devices it allows the utilisation of the bandwidth available on all paths.
|
||||
In Active/Read mode all paths not marked FAIL may handle reads at the same time,
|
||||
but unlike in Active/Active mode only one path handles write requests at any
|
||||
point in time.
|
||||
It allows to closer follow the original write request order if the layer above
|
||||
needs it for data consistency (not waiting for requisite write completion
|
||||
point in time; closely following the original write request order if the layer
|
||||
above needs it for data consistency (not waiting for requisite write completion
|
||||
before sending dependent write).
|
||||
.Pp
|
||||
When new devices are added to the system the
|
||||
@ -368,6 +367,11 @@ geom_multipath_load="YES"
|
||||
.Xr mount 8 ,
|
||||
.Xr newfs 8 ,
|
||||
.Xr sysctl 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Fx 7.0
|
||||
.Sh AUTHORS
|
||||
.An Matthew Jacob Aq Mt mjacob@FreeBSD.org
|
||||
.An Alexander Motin Aq Mt mav@FreeBSD.org
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 25, 2016
|
||||
.Dd September 8, 2016
|
||||
.Dt GGATEC 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -173,6 +173,11 @@ client# mount_cd9660 /dev/ggate0 /cdrom
|
||||
.Xr ggated 8 ,
|
||||
.Xr ggatel 8 ,
|
||||
.Xr mount_cd9660 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Fx 5.3 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 25, 2016
|
||||
.Dd September 8, 2016
|
||||
.Dt GGATED 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -116,6 +116,11 @@ Export CD-ROM device and a file:
|
||||
.Xr geom 4 ,
|
||||
.Xr ggatec 8 ,
|
||||
.Xr ggatel 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Fx 5.3 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 14, 2015
|
||||
.Dd September 8, 2016
|
||||
.Dt GGATEL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -80,7 +80,8 @@ List
|
||||
providers.
|
||||
.It Cm rescue
|
||||
Take over a previously created provider and handle pending and future
|
||||
requests. This is useful if the initial
|
||||
requests.
|
||||
This is useful if the initial
|
||||
.Nm
|
||||
process died.
|
||||
To prevent data loss, the given path must lead to the
|
||||
@ -151,6 +152,11 @@ ggatel destroy -u 5
|
||||
.Xr ggated 8 ,
|
||||
.Xr mount 8 ,
|
||||
.Xr newfs 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Fx 5.3 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
|
@ -27,7 +27,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 14, 2013
|
||||
.Dd September 8, 2016
|
||||
.Dt HASTCTL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -220,6 +220,11 @@ nodeB# application_start
|
||||
.Xr hastd 8 ,
|
||||
.Xr mount 8 ,
|
||||
.Xr newfs 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Fx 8.1 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
|
@ -27,7 +27,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 1, 2010
|
||||
.Dd September 8, 2016
|
||||
.Dt HASTD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -44,8 +44,8 @@ The
|
||||
daemon is responsible for managing highly available GEOM providers.
|
||||
.Pp
|
||||
.Nm
|
||||
allows to transparently store data on two physically separated machines
|
||||
connected over the TCP/IP network.
|
||||
allows the transpaent storage of data on two physically separated machines
|
||||
connected over a TCP/IP network.
|
||||
Only one machine (cluster node) can actively use storage provided by
|
||||
.Nm .
|
||||
This machine is called primary.
|
||||
@ -224,6 +224,11 @@ nodeA# mount -o noatime /dev/hast/shared /shared
|
||||
.Xr mount 8 ,
|
||||
.Xr newfs 8 ,
|
||||
.Xr g_bio 9
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Fx 8.1 .
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
|
@ -90,13 +90,23 @@ link_getaddr(const char *addr, int which)
|
||||
|
||||
if (which != ADDR)
|
||||
errx(1, "can't set link-level netmask or broadcast");
|
||||
if ((temp = malloc(strlen(addr) + 2)) == NULL)
|
||||
errx(1, "malloc failed");
|
||||
temp[0] = ':';
|
||||
strcpy(temp + 1, addr);
|
||||
sdl.sdl_len = sizeof(sdl);
|
||||
link_addr(temp, &sdl);
|
||||
free(temp);
|
||||
if (!strcmp(addr, "random")) {
|
||||
sdl.sdl_len = sizeof(sdl);
|
||||
sdl.sdl_alen = ETHER_ADDR_LEN;
|
||||
sdl.sdl_nlen = 0;
|
||||
sdl.sdl_family = AF_LINK;
|
||||
arc4random_buf(&sdl.sdl_data, ETHER_ADDR_LEN);
|
||||
/* Non-multicast and claim it is a hardware address */
|
||||
sdl.sdl_data[0] &= 0xfc;
|
||||
} else {
|
||||
if ((temp = malloc(strlen(addr) + 2)) == NULL)
|
||||
errx(1, "malloc failed");
|
||||
temp[0] = ':';
|
||||
strcpy(temp + 1, addr);
|
||||
sdl.sdl_len = sizeof(sdl);
|
||||
link_addr(temp, &sdl);
|
||||
free(temp);
|
||||
}
|
||||
if (sdl.sdl_alen > sizeof(sa->sa_data))
|
||||
errx(1, "malformed link-level address");
|
||||
sa->sa_family = AF_LINK;
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 8, 2016
|
||||
.Dd September 17, 2016
|
||||
.Dt IFCONFIG 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -145,6 +145,12 @@ is specified as a series of colon-separated hex digits.
|
||||
This can be used to, for example,
|
||||
set a new MAC address on an Ethernet interface, though the
|
||||
mechanism used is not Ethernet specific.
|
||||
Use the
|
||||
.Pq Dq random
|
||||
keyword to set a randomly generated MAC address.
|
||||
A randomly-generated MAC address might be the same as one already in use
|
||||
in the network.
|
||||
Such duplications are extremely unlikely.
|
||||
If the interface is already
|
||||
up when this option is used, it will be briefly brought down and
|
||||
then brought back up again in order to ensure that the receive
|
||||
@ -254,7 +260,7 @@ Display subnet masks in dotted quad notation, for example:
|
||||
.br
|
||||
255.255.0.0 or 255.255.255.192
|
||||
.It Sy hex
|
||||
Display subnet masks in hexidecimal, for example:
|
||||
Display subnet masks in hexadecimal, for example:
|
||||
.br
|
||||
0xffff0000 or 0xffffffc0
|
||||
.El
|
||||
@ -2615,13 +2621,13 @@ and
|
||||
.Cm vlandev
|
||||
must both be set at the same time.
|
||||
.It Cm vlanpcp Ar priority_code_point
|
||||
Priority code point
|
||||
Priority code point
|
||||
.Pq Dv PCP
|
||||
is an 3-bit field which refers to the IEEE 802.1p
|
||||
class of service and maps to the frame priority level.
|
||||
.Pp
|
||||
Values in order of priority are:
|
||||
.Cm 1
|
||||
.Cm 1
|
||||
.Pq Dv Background (lowest) ,
|
||||
.Cm 0
|
||||
.Pq Dv Best effort (default) ,
|
||||
@ -2759,7 +2765,7 @@ interface to send the frame directly to the remote host instead of
|
||||
broadcasting the frame to the multicast group.
|
||||
This is the default.
|
||||
.It Fl vxlanlearn
|
||||
The forwarding table is not populated by recevied packets.
|
||||
The forwarding table is not populated by received packets.
|
||||
.It Cm vxlanflush
|
||||
Delete all dynamically-learned addresses from the forwarding table.
|
||||
.It Cm vxlanflushall
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 9, 2014
|
||||
.Dd September 9, 2016
|
||||
.Dt ISCONTROL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -125,7 +125,11 @@ whatever options are specified, and start an iscsi-session.
|
||||
.Xr iscsictl 8
|
||||
.Sh STANDARDS
|
||||
RFC 3720
|
||||
.\"Sh HISTORY
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
Fx 7.0 .
|
||||
.Sh BUGS
|
||||
.Nm
|
||||
should probably load the iscsi_initiator module if needed.
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 9, 2016
|
||||
.Dd September 9, 2016
|
||||
.Dt MDMFS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -127,7 +127,8 @@ to try to detach the unit before attaching it.
|
||||
.It Fl d Ar max-extent-size
|
||||
The file system may choose to store large files using extents.
|
||||
This parameter specifies the largest extent size that may be
|
||||
used. It is presently limited to its default value which is 16
|
||||
used.
|
||||
It is presently limited to its default value which is 16
|
||||
times the file system blocksize.
|
||||
.It Fl E Ar path-mdconfig
|
||||
Use
|
||||
@ -311,8 +312,8 @@ option is passed to
|
||||
.Xr mount 8
|
||||
as
|
||||
.Fl t .
|
||||
See the programs that the options are passed to for more information
|
||||
on their semantics.
|
||||
For information on semantics, refer to the documentation of the programs
|
||||
that the options are passed to.
|
||||
.Sh EXAMPLES
|
||||
Create and mount a 32 megabyte swap-backed file system on
|
||||
.Pa /tmp :
|
||||
@ -394,5 +395,10 @@ was given on the command line.
|
||||
.Xr mdconfig 8 ,
|
||||
.Xr mount 8 ,
|
||||
.Xr newfs 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Fx 5.0 .
|
||||
.Sh AUTHORS
|
||||
.An Dima Dorfman
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\" @(#)mount_nfs.8 8.3 (Berkeley) 3/29/95
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 30, 2014
|
||||
.Dd September 10, 2016
|
||||
.Dt MOUNT_NFS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -183,8 +183,8 @@ for positive name cache entries.
|
||||
If this is set to 0 it disables positive name caching for the mount point.
|
||||
.It Cm negnametimeo Ns = Ns Aq Ar value
|
||||
Override the default of NFS_DEFAULT_NEGNAMETIMEO for the timeout (in seconds)
|
||||
for negative name cache entries. If this is set to 0 it disables negative
|
||||
name caching for the mount point.
|
||||
for negative name cache entries.
|
||||
If this is set to 0 it disables negative name caching for the mount point.
|
||||
.It Cm nfsv2
|
||||
Use the NFS Version 2 protocol (the default is to try version 3 first
|
||||
then version 2).
|
||||
@ -262,7 +262,7 @@ such that the dirty byte range becomes a superset of the bytes
|
||||
that are dirty.
|
||||
This reduces the number of writes significantly for software
|
||||
builds.
|
||||
The merging of byte ranges isn't done if the file has been file
|
||||
The merging of byte ranges is not done if the file has been file
|
||||
locked, since most applications modifying a file from multiple
|
||||
clients will use file locking.
|
||||
As such, this option could result in a corrupted file for the
|
||||
@ -271,8 +271,9 @@ clients concurrently without using file locking.
|
||||
.It Cm principal
|
||||
For the RPCSEC_GSS security flavors, such as krb5, krb5i and krb5p,
|
||||
this option sets the name of the host based principal name expected
|
||||
by the server. This option overrides the default, which will be
|
||||
``nfs@<server-fqdn>'' and should normally be sufficient.
|
||||
by the server.
|
||||
This option overrides the default, which will be ``nfs@<server-fqdn>''
|
||||
and should normally be sufficient.
|
||||
.It Cm noresvport
|
||||
Do
|
||||
.Em not
|
||||
@ -515,6 +516,11 @@ Same as
|
||||
.Xr nfsd 8 ,
|
||||
.Xr nfsiod 8 ,
|
||||
.Xr showmount 8
|
||||
.Sh HISTORY
|
||||
A version of the
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Bx 4.4 .
|
||||
.Sh BUGS
|
||||
Since nfsv4 performs open/lock operations that have their ordering strictly
|
||||
enforced by the server, the options
|
||||
|
@ -29,7 +29,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 28, 2012
|
||||
.Dd September 10, 2016
|
||||
.Dt NANDFS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -48,7 +48,7 @@
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility allows to manage snapshots of a mounted NAND FS.
|
||||
utility allows the management of snapshots on a mounted NAND FS.
|
||||
.Sh EXAMPLES
|
||||
Create a snapshot of filesystem mounted on
|
||||
.Em /nand .
|
||||
@ -69,6 +69,11 @@ Remove snapshot 1 of filesystem mounted on
|
||||
.Bd -literal -offset 2n
|
||||
.Li # Ic nandfs rmsnap 1 /nand
|
||||
.Ed
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Fx 10.0 .
|
||||
.Sh AUTHORS
|
||||
This utility and manual page were written by
|
||||
.An Mateusz Guzik .
|
||||
|
@ -2006,7 +2006,7 @@ NewInstance(const char *name)
|
||||
}
|
||||
}
|
||||
ninstance++;
|
||||
ip = calloc(sizeof *ip, 1);
|
||||
ip = calloc(1, sizeof(*ip));
|
||||
ip->name = strdup(name);
|
||||
ip->la = LibAliasInit (ip->la);
|
||||
ip->assignAliasAddr = 0;
|
||||
|
@ -33,7 +33,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 26, 2013
|
||||
.Dd September 10, 2016
|
||||
.Dt NVMECONTROL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -94,9 +94,9 @@ Display an hexadecimal dump of the nvme0 IDENTIFY_NAMESPACE data for namespace
|
||||
.Pp
|
||||
.Dl nvmecontrol perftest -n 32 -o read -s 512 -t 30 nvme0ns1
|
||||
.Pp
|
||||
Run a performance test on nvme0ns1 using 32 kernel threads for 30 seconds. Each
|
||||
thread will issue a single 512 byte read command. Results are printed to
|
||||
stdout when 30 seconds expires.
|
||||
Run a performance test on nvme0ns1 using 32 kernel threads for 30 seconds.
|
||||
Each thread will issue a single 512 byte read command.
|
||||
Results are printed to stdout when 30 seconds expires.
|
||||
.Pp
|
||||
.Dl nvmecontrol reset nvme0
|
||||
.Pp
|
||||
@ -137,6 +137,11 @@ Set the current power mode.
|
||||
.Dl nvmecontrol power nvme0
|
||||
.Pp
|
||||
Get the current power mode.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility appeared in
|
||||
.Fx 9.2 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
.Nm
|
||||
|
@ -1,7 +1,7 @@
|
||||
.\" $NetBSD: rcorder.8,v 1.3 2000/07/17 14:16:22 mrg Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1998
|
||||
.\" Perry E. Metzger. All rights reserved.
|
||||
.\" Perry E. Metzger. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
@ -31,7 +31,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 5, 2011
|
||||
.Dd September 10, 2016
|
||||
.Dt RCORDER 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -160,8 +160,11 @@ processing the stated file.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
utility first appeared in
|
||||
utility appeared in
|
||||
.Nx 1.5 .
|
||||
.Nm
|
||||
utility first appeared in
|
||||
.Fx 5.0 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
Written by
|
||||
@ -172,7 +175,7 @@ and
|
||||
The
|
||||
.Dq Li REQUIRE
|
||||
keyword is misleading:
|
||||
It doesn't describe which daemons have to be running before a script
|
||||
It does not describe which daemons have to be running before a script
|
||||
will be started.
|
||||
It describes which scripts must be placed before it in
|
||||
the dependency ordering.
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\" @(#)reboot.8 8.1 (Berkeley) 6/9/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd Dec 12, 2015
|
||||
.Dd September 10, 2016
|
||||
.Dt REBOOT 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -165,4 +165,4 @@ reboot -r
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v6 .
|
||||
.Bx 4.0 .
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\" @(#)umount.8 8.2 (Berkeley) 5/8/95
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 7, 2016
|
||||
.Dd September 10, 2016
|
||||
.Dt UMOUNT 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -158,4 +158,4 @@ file system table
|
||||
A
|
||||
.Nm
|
||||
utility appeared in
|
||||
.At v6 .
|
||||
.At v1 .
|
||||
|
@ -28,7 +28,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 21, 1999
|
||||
.Dd September 12, 2016
|
||||
.Dt DEVICE_QUIET 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -49,16 +49,18 @@
|
||||
Each device has a quiet flag associated with it.
|
||||
A device is
|
||||
verbose by default when it is created but may be quieted to prevent
|
||||
the device identification string to be printed during probe.
|
||||
printing of the device identification string during attach
|
||||
and printing of a message during detach.
|
||||
To quiet a device, call
|
||||
.Fn device_quiet ,
|
||||
to re-enable to probe message (to make the message appear again, for
|
||||
example after a
|
||||
.Xr device_detach 9 )
|
||||
.Fn device_quiet
|
||||
during a device driver probe routine.
|
||||
To re-enable probe messages,
|
||||
call
|
||||
.Fn device_verbose .
|
||||
To test to see if a device is quieted, call
|
||||
.Fn device_is_quiet .
|
||||
.Pp
|
||||
Devices are implicitly marked verbose after a driver detaches.
|
||||
.Sh SEE ALSO
|
||||
.Xr device 9
|
||||
.Sh AUTHORS
|
||||
|
@ -120,6 +120,16 @@ could be used from both kernel thread and syscall contexts.
|
||||
The
|
||||
.Fn fpu_kern_leave
|
||||
function correctly handles such contexts.
|
||||
.It Dv FPU_KERN_NOCTX
|
||||
Avoid nesting save area.
|
||||
If the flag is specified, the
|
||||
.Fa ctx
|
||||
must be passed as
|
||||
.Va NULL .
|
||||
The flag should only be used for really short code blocks
|
||||
which can be executed in a critical section.
|
||||
It avoids the need to allocate the FPU context by the cost
|
||||
of increased system latency.
|
||||
.El
|
||||
.El
|
||||
.Pp
|
||||
|
@ -114,16 +114,13 @@ _metaError: .NOMETA .NOTMAIN
|
||||
|
||||
.endif
|
||||
|
||||
META_COOKIE_TOUCH=
|
||||
# some targets need to be .PHONY in non-meta mode
|
||||
META_NOPHONY= .PHONY
|
||||
# Are we, after all, in meta mode?
|
||||
.if ${.MAKE.MODE:Uno:Mmeta*} != ""
|
||||
MKDEP_MK = meta.autodep.mk
|
||||
|
||||
# we can afford to use cookies to prevent some targets
|
||||
# re-running needlessly
|
||||
META_COOKIE_TOUCH= touch ${COOKIE.${.TARGET}:U${.OBJDIR}/${.TARGET:T}}
|
||||
META_COOKIE_TOUCH?= touch ${COOKIE.${.TARGET}:U${.OBJDIR}/${.TARGET:T}}
|
||||
META_NOPHONY=
|
||||
|
||||
# some targets involve old pre-built targets
|
||||
@ -159,5 +156,9 @@ BUILD_AT_LEVEL0 ?= no
|
||||
.endif
|
||||
|
||||
.endif
|
||||
.else
|
||||
META_COOKIE_TOUCH=
|
||||
# some targets need to be .PHONY in non-meta mode
|
||||
META_NOPHONY= .PHONY
|
||||
.endif
|
||||
.endif
|
||||
|
@ -633,6 +633,8 @@ fpudna(void)
|
||||
*/
|
||||
critical_enter();
|
||||
|
||||
KASSERT((curpcb->pcb_flags & PCB_FPUNOSAVE) == 0,
|
||||
("fpudna while in fpu_kern_enter(FPU_KERN_NOCTX)"));
|
||||
if (PCPU_GET(fpcurthread) == curthread) {
|
||||
printf("fpudna: fpcurthread == curthread\n");
|
||||
stop_emulating();
|
||||
@ -964,13 +966,39 @@ fpu_kern_enter(struct thread *td, struct fpu_kern_ctx *ctx, u_int flags)
|
||||
{
|
||||
struct pcb *pcb;
|
||||
|
||||
KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) == 0, ("using inuse ctx"));
|
||||
pcb = td->td_pcb;
|
||||
KASSERT((flags & FPU_KERN_NOCTX) != 0 || ctx != NULL,
|
||||
("ctx is required when !FPU_KERN_NOCTX"));
|
||||
KASSERT(ctx == NULL || (ctx->flags & FPU_KERN_CTX_INUSE) == 0,
|
||||
("using inuse ctx"));
|
||||
KASSERT((pcb->pcb_flags & PCB_FPUNOSAVE) == 0,
|
||||
("recursive fpu_kern_enter while in PCB_FPUNOSAVE state"));
|
||||
|
||||
if ((flags & FPU_KERN_NOCTX) != 0) {
|
||||
critical_enter();
|
||||
stop_emulating();
|
||||
if (curthread == PCPU_GET(fpcurthread)) {
|
||||
fpusave(curpcb->pcb_save);
|
||||
PCPU_SET(fpcurthread, NULL);
|
||||
} else {
|
||||
KASSERT(PCPU_GET(fpcurthread) == NULL,
|
||||
("invalid fpcurthread"));
|
||||
}
|
||||
|
||||
/*
|
||||
* This breaks XSAVEOPT tracker, but
|
||||
* PCB_FPUNOSAVE state is supposed to never need to
|
||||
* save FPU context at all.
|
||||
*/
|
||||
fpurestore(fpu_initialstate);
|
||||
set_pcb_flags(pcb, PCB_KERNFPU | PCB_FPUNOSAVE |
|
||||
PCB_FPUINITDONE);
|
||||
return (0);
|
||||
}
|
||||
if ((flags & FPU_KERN_KTHR) != 0 && is_fpu_kern_thread(0)) {
|
||||
ctx->flags = FPU_KERN_CTX_DUMMY | FPU_KERN_CTX_INUSE;
|
||||
return (0);
|
||||
}
|
||||
pcb = td->td_pcb;
|
||||
KASSERT(!PCB_USER_FPU(pcb) || pcb->pcb_save ==
|
||||
get_pcb_user_save_pcb(pcb), ("mangled pcb_save"));
|
||||
ctx->flags = FPU_KERN_CTX_INUSE;
|
||||
@ -989,19 +1017,34 @@ fpu_kern_leave(struct thread *td, struct fpu_kern_ctx *ctx)
|
||||
{
|
||||
struct pcb *pcb;
|
||||
|
||||
KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) != 0,
|
||||
("leaving not inuse ctx"));
|
||||
ctx->flags &= ~FPU_KERN_CTX_INUSE;
|
||||
|
||||
if (is_fpu_kern_thread(0) && (ctx->flags & FPU_KERN_CTX_DUMMY) != 0)
|
||||
return (0);
|
||||
KASSERT((ctx->flags & FPU_KERN_CTX_DUMMY) == 0, ("dummy ctx"));
|
||||
pcb = td->td_pcb;
|
||||
critical_enter();
|
||||
if (curthread == PCPU_GET(fpcurthread))
|
||||
fpudrop();
|
||||
critical_exit();
|
||||
pcb->pcb_save = ctx->prev;
|
||||
|
||||
if ((pcb->pcb_flags & PCB_FPUNOSAVE) != 0) {
|
||||
KASSERT(ctx == NULL, ("non-null ctx after FPU_KERN_NOCTX"));
|
||||
KASSERT(PCPU_GET(fpcurthread) == NULL,
|
||||
("non-NULL fpcurthread for PCB_FPUNOSAVE"));
|
||||
CRITICAL_ASSERT(td);
|
||||
|
||||
clear_pcb_flags(pcb, PCB_FPUNOSAVE | PCB_FPUINITDONE);
|
||||
start_emulating();
|
||||
critical_exit();
|
||||
} else {
|
||||
KASSERT((ctx->flags & FPU_KERN_CTX_INUSE) != 0,
|
||||
("leaving not inuse ctx"));
|
||||
ctx->flags &= ~FPU_KERN_CTX_INUSE;
|
||||
|
||||
if (is_fpu_kern_thread(0) &&
|
||||
(ctx->flags & FPU_KERN_CTX_DUMMY) != 0)
|
||||
return (0);
|
||||
KASSERT((ctx->flags & FPU_KERN_CTX_DUMMY) == 0,
|
||||
("dummy ctx"));
|
||||
critical_enter();
|
||||
if (curthread == PCPU_GET(fpcurthread))
|
||||
fpudrop();
|
||||
critical_exit();
|
||||
pcb->pcb_save = ctx->prev;
|
||||
}
|
||||
|
||||
if (pcb->pcb_save == get_pcb_user_save_pcb(pcb)) {
|
||||
if ((pcb->pcb_flags & PCB_USERFPUINITDONE) != 0) {
|
||||
set_pcb_flags(pcb, PCB_FPUINITDONE);
|
||||
|
@ -269,7 +269,6 @@ cpu_startup(dummy)
|
||||
*/
|
||||
startrtclock();
|
||||
printcpuinfo();
|
||||
panicifcpuunsupported();
|
||||
|
||||
/*
|
||||
* Display physical memory if SMBIOS reports reasonable amount.
|
||||
|
@ -176,7 +176,10 @@ trap(struct trapframe *frame)
|
||||
#endif
|
||||
struct thread *td = curthread;
|
||||
struct proc *p = td->td_proc;
|
||||
int i = 0, ucode = 0, code;
|
||||
#ifdef KDB
|
||||
register_t dr6;
|
||||
#endif
|
||||
int i = 0, ucode = 0;
|
||||
u_int type;
|
||||
register_t addr = 0;
|
||||
ksiginfo_t ksi;
|
||||
@ -236,7 +239,7 @@ trap(struct trapframe *frame)
|
||||
* interrupts disabled until they are accidentally
|
||||
* enabled later.
|
||||
*/
|
||||
if (ISPL(frame->tf_cs) == SEL_UPL)
|
||||
if (TRAPF_USERMODE(frame))
|
||||
uprintf(
|
||||
"pid %ld (%s): trap %d with interrupts disabled\n",
|
||||
(long)curproc->p_pid, curthread->td_name, type);
|
||||
@ -258,9 +261,7 @@ trap(struct trapframe *frame)
|
||||
}
|
||||
}
|
||||
|
||||
code = frame->tf_err;
|
||||
|
||||
if (ISPL(frame->tf_cs) == SEL_UPL) {
|
||||
if (TRAPF_USERMODE(frame)) {
|
||||
/* user trap */
|
||||
|
||||
td->td_pticks = 0;
|
||||
@ -377,7 +378,7 @@ trap(struct trapframe *frame)
|
||||
#ifdef DEV_ISA
|
||||
case T_NMI:
|
||||
/* machine/parity/power fail/"kitchen sink" faults */
|
||||
if (isa_nmi(code) == 0) {
|
||||
if (isa_nmi(frame->tf_err) == 0) {
|
||||
#ifdef KDB
|
||||
/*
|
||||
* NMI can be hooked up to a pushbutton
|
||||
@ -540,8 +541,7 @@ trap(struct trapframe *frame)
|
||||
* Reset breakpoint bits because the
|
||||
* processor doesn't
|
||||
*/
|
||||
/* XXX check upper bits here */
|
||||
load_dr6(rdr6() & 0xfffffff0);
|
||||
load_dr6(rdr6() & ~0xf);
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
@ -553,7 +553,10 @@ trap(struct trapframe *frame)
|
||||
* Otherwise, debugger traps "can't happen".
|
||||
*/
|
||||
#ifdef KDB
|
||||
if (kdb_trap(type, 0, frame))
|
||||
/* XXX %dr6 is not quite reentrant. */
|
||||
dr6 = rdr6();
|
||||
load_dr6(dr6 & ~0x4000);
|
||||
if (kdb_trap(type, dr6, frame))
|
||||
goto out;
|
||||
#endif
|
||||
break;
|
||||
@ -561,7 +564,7 @@ trap(struct trapframe *frame)
|
||||
#ifdef DEV_ISA
|
||||
case T_NMI:
|
||||
/* machine/parity/power fail/"kitchen sink" faults */
|
||||
if (isa_nmi(code) == 0) {
|
||||
if (isa_nmi(frame->tf_err) == 0) {
|
||||
#ifdef KDB
|
||||
/*
|
||||
* NMI can be hooked up to a pushbutton
|
||||
@ -773,7 +776,6 @@ trap_fatal(frame, eva)
|
||||
{
|
||||
int code, ss;
|
||||
u_int type;
|
||||
long esp;
|
||||
struct soft_segment_descriptor softseg;
|
||||
char *msg;
|
||||
|
||||
@ -787,7 +789,7 @@ trap_fatal(frame, eva)
|
||||
else
|
||||
msg = "UNKNOWN";
|
||||
printf("\n\nFatal trap %d: %s while in %s mode\n", type, msg,
|
||||
ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel");
|
||||
TRAPF_USERMODE(frame) ? "user" : "kernel");
|
||||
#ifdef SMP
|
||||
/* two separate prints in case of a trap on an unmapped page */
|
||||
printf("cpuid = %d; ", PCPU_GET(cpuid));
|
||||
@ -804,14 +806,8 @@ trap_fatal(frame, eva)
|
||||
}
|
||||
printf("instruction pointer = 0x%lx:0x%lx\n",
|
||||
frame->tf_cs & 0xffff, frame->tf_rip);
|
||||
if (ISPL(frame->tf_cs) == SEL_UPL) {
|
||||
ss = frame->tf_ss & 0xffff;
|
||||
esp = frame->tf_rsp;
|
||||
} else {
|
||||
ss = GSEL(GDATA_SEL, SEL_KPL);
|
||||
esp = (long)&frame->tf_rsp;
|
||||
}
|
||||
printf("stack pointer = 0x%x:0x%lx\n", ss, esp);
|
||||
ss = frame->tf_ss & 0xffff;
|
||||
printf("stack pointer = 0x%x:0x%lx\n", ss, frame->tf_rsp);
|
||||
printf("frame pointer = 0x%x:0x%lx\n", ss, frame->tf_rbp);
|
||||
printf("code segment = base 0x%lx, limit 0x%lx, type 0x%x\n",
|
||||
softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type);
|
||||
@ -934,7 +930,7 @@ amd64_syscall(struct thread *td, int traced)
|
||||
ksiginfo_t ksi;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (ISPL(td->td_frame->tf_cs) != SEL_UPL) {
|
||||
if (!TRAPF_USERMODE(td->td_frame)) {
|
||||
panic("syscall");
|
||||
/* NOT REACHED */
|
||||
}
|
||||
|
@ -1,48 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1993 Christopher G. Demetriou
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
* This file is in the public domain.
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_CPUTYPES_H_
|
||||
#define _MACHINE_CPUTYPES_H_
|
||||
/* $FreeBSD$ */
|
||||
|
||||
#include <x86/cputypes.h>
|
||||
|
||||
/*
|
||||
* Classes of processor.
|
||||
*/
|
||||
#define CPUCLASS_X86 0 /* X86 */
|
||||
#define CPUCLASS_K8 1 /* K8 AMD64 class */
|
||||
|
||||
/*
|
||||
* Kinds of processor.
|
||||
*/
|
||||
#define CPU_X86 0 /* Intel */
|
||||
#define CPU_CLAWHAMMER 1 /* AMD Clawhammer */
|
||||
#define CPU_SLEDGEHAMMER 2 /* AMD Sledgehammer */
|
||||
|
||||
#endif /* !_MACHINE_CPUTYPES_H_ */
|
||||
|
@ -56,23 +56,28 @@ do { \
|
||||
#define db_clear_single_step kdb_cpu_clear_singlestep
|
||||
#define db_set_single_step kdb_cpu_set_singlestep
|
||||
|
||||
#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT)
|
||||
/*
|
||||
* Watchpoints are not supported. The debug exception type is in %dr6
|
||||
* and not yet in the args to this macro.
|
||||
* The debug exception type is copied from %dr6 to 'code' and used to
|
||||
* disambiguate single step traps. Watchpoints have no special support.
|
||||
* Our hardware breakpoints are not well integrated with ddb and are too
|
||||
* different from watchpoints. ddb treats them as unknown traps with
|
||||
* unknown addresses and doesn't turn them off while it is running.
|
||||
*/
|
||||
#define IS_WATCHPOINT_TRAP(type, code) 0
|
||||
#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT)
|
||||
#define IS_SSTEP_TRAP(type, code) ((type) == T_TRCTRAP && (code) & 0x4000)
|
||||
#define IS_WATCHPOINT_TRAP(type, code) 0
|
||||
|
||||
#define I_CALL 0xe8
|
||||
#define I_CALLI 0xff
|
||||
#define i_calli(ins) (((ins)&0xff) == I_CALLI && ((ins)&0x3800) == 0x1000)
|
||||
#define I_RET 0xc3
|
||||
#define I_IRET 0xcf
|
||||
#define i_rex(ins) (((ins) & 0xff) == 0x41 || ((ins) & 0xff) == 0x43)
|
||||
|
||||
#define inst_trap_return(ins) (((ins)&0xff) == I_IRET)
|
||||
#define inst_return(ins) (((ins)&0xff) == I_RET)
|
||||
#define inst_call(ins) (((ins)&0xff) == I_CALL || \
|
||||
(((ins)&0xff) == I_CALLI && \
|
||||
((ins)&0x3800) == 0x1000))
|
||||
#define inst_call(ins) (((ins)&0xff) == I_CALL || i_calli(ins) || \
|
||||
(i_calli((ins) >> 8) && i_rex(ins)))
|
||||
#define inst_load(ins) 0
|
||||
#define inst_store(ins) 0
|
||||
|
||||
|
@ -86,6 +86,7 @@ void fpu_save_area_reset(struct savefpu *fsa);
|
||||
#define FPU_KERN_NORMAL 0x0000
|
||||
#define FPU_KERN_NOWAIT 0x0001
|
||||
#define FPU_KERN_KTHR 0x0002
|
||||
#define FPU_KERN_NOCTX 0x0004
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -83,6 +83,7 @@ struct pcb {
|
||||
#define PCB_FPUINITDONE 0x08 /* fpu state is initialized */
|
||||
#define PCB_USERFPUINITDONE 0x10 /* fpu user state is initialized */
|
||||
#define PCB_32BIT 0x40 /* process has 32 bit context (segs etc) */
|
||||
#define PCB_FPUNOSAVE 0x80 /* no save area for current FPU ctx */
|
||||
|
||||
uint16_t pcb_initial_fpucw;
|
||||
|
||||
|
@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/mmc/mmcreg.h>
|
||||
#include <dev/mmc/mmcbrvar.h>
|
||||
|
||||
#include <arm/allwinner/aw_machdep.h>
|
||||
#include <arm/allwinner/a10_mmc.h>
|
||||
#include <dev/extres/clk/clk.h>
|
||||
#include <dev/extres/hwreset/hwreset.h>
|
||||
@ -56,16 +55,12 @@ __FBSDID("$FreeBSD$");
|
||||
#define A10_MMC_MEMRES 0
|
||||
#define A10_MMC_IRQRES 1
|
||||
#define A10_MMC_RESSZ 2
|
||||
#define A10_MMC_DMA_SEGS 16
|
||||
#define A10_MMC_DMA_SEGS ((MAXPHYS / PAGE_SIZE) + 1)
|
||||
#define A10_MMC_DMA_MAX_SIZE 0x2000
|
||||
#define A10_MMC_DMA_FTRGLEVEL 0x20070008
|
||||
|
||||
#define CARD_ID_FREQUENCY 400000
|
||||
|
||||
static int a10_mmc_pio_mode = 0;
|
||||
|
||||
TUNABLE_INT("hw.a10.mmc.pio_mode", &a10_mmc_pio_mode);
|
||||
|
||||
static struct ofw_compat_data compat_data[] = {
|
||||
{"allwinner,sun4i-a10-mmc", 1},
|
||||
{"allwinner,sun5i-a13-mmc", 1},
|
||||
@ -73,14 +68,11 @@ static struct ofw_compat_data compat_data[] = {
|
||||
};
|
||||
|
||||
struct a10_mmc_softc {
|
||||
bus_space_handle_t a10_bsh;
|
||||
bus_space_tag_t a10_bst;
|
||||
device_t a10_dev;
|
||||
clk_t a10_clk_ahb;
|
||||
clk_t a10_clk_mmc;
|
||||
hwreset_t a10_rst_ahb;
|
||||
int a10_bus_busy;
|
||||
int a10_id;
|
||||
int a10_resid;
|
||||
int a10_timeout;
|
||||
struct callout a10_timeoutc;
|
||||
@ -91,7 +83,6 @@ struct a10_mmc_softc {
|
||||
uint32_t a10_intr;
|
||||
uint32_t a10_intr_wait;
|
||||
void * a10_intrhand;
|
||||
bus_size_t a10_fifo_reg;
|
||||
|
||||
/* Fields required for DMA access. */
|
||||
bus_addr_t a10_dma_desc_phys;
|
||||
@ -100,7 +91,6 @@ struct a10_mmc_softc {
|
||||
void * a10_dma_desc;
|
||||
bus_dmamap_t a10_dma_buf_map;
|
||||
bus_dma_tag_t a10_dma_buf_tag;
|
||||
int a10_dma_inuse;
|
||||
int a10_dma_map_err;
|
||||
};
|
||||
|
||||
@ -116,7 +106,7 @@ static int a10_mmc_detach(device_t);
|
||||
static int a10_mmc_setup_dma(struct a10_mmc_softc *);
|
||||
static int a10_mmc_reset(struct a10_mmc_softc *);
|
||||
static void a10_mmc_intr(void *);
|
||||
static int a10_mmc_update_clock(struct a10_mmc_softc *);
|
||||
static int a10_mmc_update_clock(struct a10_mmc_softc *, uint32_t);
|
||||
|
||||
static int a10_mmc_update_ios(device_t, device_t);
|
||||
static int a10_mmc_request(device_t, device_t, struct mmc_request *);
|
||||
@ -127,9 +117,9 @@ static int a10_mmc_release_host(device_t, device_t);
|
||||
#define A10_MMC_LOCK(_sc) mtx_lock(&(_sc)->a10_mtx)
|
||||
#define A10_MMC_UNLOCK(_sc) mtx_unlock(&(_sc)->a10_mtx)
|
||||
#define A10_MMC_READ_4(_sc, _reg) \
|
||||
bus_space_read_4((_sc)->a10_bst, (_sc)->a10_bsh, _reg)
|
||||
bus_read_4((_sc)->a10_res[A10_MMC_MEMRES], _reg)
|
||||
#define A10_MMC_WRITE_4(_sc, _reg, _value) \
|
||||
bus_space_write_4((_sc)->a10_bst, (_sc)->a10_bsh, _reg, _value)
|
||||
bus_write_4((_sc)->a10_res[A10_MMC_MEMRES], _reg, _value)
|
||||
|
||||
static int
|
||||
a10_mmc_probe(device_t dev)
|
||||
@ -160,17 +150,10 @@ a10_mmc_attach(device_t dev)
|
||||
sc = device_get_softc(dev);
|
||||
sc->a10_dev = dev;
|
||||
sc->a10_req = NULL;
|
||||
sc->a10_id = device_get_unit(dev);
|
||||
if (sc->a10_id > 3) {
|
||||
device_printf(dev, "only 4 hosts are supported (0-3)\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
if (bus_alloc_resources(dev, a10_mmc_res_spec, sc->a10_res) != 0) {
|
||||
device_printf(dev, "cannot allocate device resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
sc->a10_bst = rman_get_bustag(sc->a10_res[A10_MMC_MEMRES]);
|
||||
sc->a10_bsh = rman_get_bushandle(sc->a10_res[A10_MMC_MEMRES]);
|
||||
if (bus_setup_intr(dev, sc->a10_res[A10_MMC_IRQRES],
|
||||
INTR_TYPE_MISC | INTR_MPSAFE, NULL, a10_mmc_intr, sc,
|
||||
&sc->a10_intrhand)) {
|
||||
@ -182,31 +165,12 @@ a10_mmc_attach(device_t dev)
|
||||
MTX_DEF);
|
||||
callout_init_mtx(&sc->a10_timeoutc, &sc->a10_mtx, 0);
|
||||
|
||||
#if defined(__arm__)
|
||||
/*
|
||||
* Later chips use a different FIFO offset. Unfortunately the FDT
|
||||
* uses the same compatible string for old and new implementations.
|
||||
*/
|
||||
switch (allwinner_soc_family()) {
|
||||
case ALLWINNERSOC_SUN4I:
|
||||
case ALLWINNERSOC_SUN5I:
|
||||
case ALLWINNERSOC_SUN7I:
|
||||
sc->a10_fifo_reg = A10_MMC_FIFO;
|
||||
break;
|
||||
default:
|
||||
sc->a10_fifo_reg = A31_MMC_FIFO;
|
||||
break;
|
||||
}
|
||||
#else /* __aarch64__ */
|
||||
sc->a10_fifo_reg = A31_MMC_FIFO;
|
||||
#endif
|
||||
|
||||
/* De-assert reset */
|
||||
if (hwreset_get_by_ofw_name(dev, 0, "ahb", &sc->a10_rst_ahb) == 0) {
|
||||
error = hwreset_deassert(sc->a10_rst_ahb);
|
||||
if (error != 0) {
|
||||
device_printf(dev, "cannot de-assert reset\n");
|
||||
return (error);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,19 +208,22 @@ a10_mmc_attach(device_t dev)
|
||||
SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "req_timeout", CTLFLAG_RW,
|
||||
&sc->a10_timeout, 0, "Request timeout in seconds");
|
||||
|
||||
/* Reset controller. */
|
||||
/* Hardware reset */
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_HWRST, 1);
|
||||
DELAY(100);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_HWRST, 0);
|
||||
DELAY(500);
|
||||
|
||||
/* Soft Reset controller. */
|
||||
if (a10_mmc_reset(sc) != 0) {
|
||||
device_printf(dev, "cannot reset the controller\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (a10_mmc_pio_mode == 0 && a10_mmc_setup_dma(sc) != 0) {
|
||||
if (a10_mmc_setup_dma(sc) != 0) {
|
||||
device_printf(sc->a10_dev, "Couldn't setup DMA!\n");
|
||||
a10_mmc_pio_mode = 1;
|
||||
goto fail;
|
||||
}
|
||||
if (bootverbose)
|
||||
device_printf(sc->a10_dev, "DMA status: %s\n",
|
||||
a10_mmc_pio_mode ? "disabled" : "enabled");
|
||||
|
||||
if (OF_getencprop(node, "bus-width", &bus_width, sizeof(uint32_t)) <= 0)
|
||||
bus_width = 4;
|
||||
@ -369,7 +336,6 @@ a10_dma_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int err)
|
||||
return;
|
||||
|
||||
dma_desc = sc->a10_dma_desc;
|
||||
/* Note nsegs is guaranteed to be zero if err is non-zero. */
|
||||
for (i = 0; i < nsegs; i++) {
|
||||
dma_desc[i].buf_size = segs[i].ds_len;
|
||||
dma_desc[i].buf_addr = segs[i].ds_addr;
|
||||
@ -386,7 +352,7 @@ a10_dma_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int err)
|
||||
A10_MMC_DMA_CONFIG_ER;
|
||||
dma_desc[i].next = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@ -401,13 +367,12 @@ a10_mmc_prepare_dma(struct a10_mmc_softc *sc)
|
||||
if (cmd->data->len > A10_MMC_DMA_MAX_SIZE * A10_MMC_DMA_SEGS)
|
||||
return (EFBIG);
|
||||
error = bus_dmamap_load(sc->a10_dma_buf_tag, sc->a10_dma_buf_map,
|
||||
cmd->data->data, cmd->data->len, a10_dma_cb, sc, BUS_DMA_NOWAIT);
|
||||
cmd->data->data, cmd->data->len, a10_dma_cb, sc, 0);
|
||||
if (error)
|
||||
return (error);
|
||||
if (sc->a10_dma_map_err)
|
||||
return (sc->a10_dma_map_err);
|
||||
|
||||
sc->a10_dma_inuse = 1;
|
||||
if (cmd->data->flags & MMC_DATA_WRITE)
|
||||
sync_op = BUS_DMASYNC_PREWRITE;
|
||||
else
|
||||
@ -415,27 +380,32 @@ a10_mmc_prepare_dma(struct a10_mmc_softc *sc)
|
||||
bus_dmamap_sync(sc->a10_dma_buf_tag, sc->a10_dma_buf_map, sync_op);
|
||||
bus_dmamap_sync(sc->a10_dma_tag, sc->a10_dma_map, BUS_DMASYNC_PREWRITE);
|
||||
|
||||
val = A10_MMC_READ_4(sc, A10_MMC_IMASK);
|
||||
val &= ~(A10_MMC_RX_DATA_REQ | A10_MMC_TX_DATA_REQ);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_IMASK, val);
|
||||
val = A10_MMC_READ_4(sc, A10_MMC_GCTRL);
|
||||
val &= ~A10_MMC_ACCESS_BY_AHB;
|
||||
val |= A10_MMC_DMA_ENABLE;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_GCTRL, val);
|
||||
val |= A10_MMC_DMA_RESET;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_GCTRL, val);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_DMAC, A10_MMC_IDMAC_SOFT_RST);
|
||||
/* Enable DMA */
|
||||
val = A10_MMC_READ_4(sc, A10_MMC_GCTL);
|
||||
val &= ~A10_MMC_CTRL_FIFO_AC_MOD;
|
||||
val |= A10_MMC_CTRL_DMA_ENB;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_GCTL, val);
|
||||
|
||||
/* Reset DMA */
|
||||
val |= A10_MMC_CTRL_DMA_RST;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_GCTL, val);
|
||||
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_DMAC, A10_MMC_DMAC_IDMAC_SOFT_RST);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_DMAC,
|
||||
A10_MMC_IDMAC_IDMA_ON | A10_MMC_IDMAC_FIX_BURST);
|
||||
val = A10_MMC_READ_4(sc, A10_MMC_IDIE);
|
||||
val &= ~(A10_MMC_IDMAC_RECEIVE_INT | A10_MMC_IDMAC_TRANSMIT_INT);
|
||||
A10_MMC_DMAC_IDMAC_IDMA_ON | A10_MMC_DMAC_IDMAC_FIX_BURST);
|
||||
|
||||
/* Enable RX or TX DMA interrupt */
|
||||
if (cmd->data->flags & MMC_DATA_WRITE)
|
||||
val |= A10_MMC_IDMAC_TRANSMIT_INT;
|
||||
val |= A10_MMC_IDST_TX_INT;
|
||||
else
|
||||
val |= A10_MMC_IDMAC_RECEIVE_INT;
|
||||
val |= A10_MMC_IDST_RX_INT;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_IDIE, val);
|
||||
|
||||
/* Set DMA descritptor list address */
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_DLBA, sc->a10_dma_desc_phys);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_FTRGL, A10_MMC_DMA_FTRGLEVEL);
|
||||
|
||||
/* FIFO trigger level */
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_FWLR, A10_MMC_DMA_FTRGLEVEL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -445,11 +415,10 @@ a10_mmc_reset(struct a10_mmc_softc *sc)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_GCTRL,
|
||||
A10_MMC_READ_4(sc, A10_MMC_GCTRL) | A10_MMC_RESET);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_GCTL, A10_MMC_RESET);
|
||||
timeout = 1000;
|
||||
while (--timeout > 0) {
|
||||
if ((A10_MMC_READ_4(sc, A10_MMC_GCTRL) & A10_MMC_RESET) == 0)
|
||||
if ((A10_MMC_READ_4(sc, A10_MMC_GCTL) & A10_MMC_RESET) == 0)
|
||||
break;
|
||||
DELAY(100);
|
||||
}
|
||||
@ -457,18 +426,20 @@ a10_mmc_reset(struct a10_mmc_softc *sc)
|
||||
return (ETIMEDOUT);
|
||||
|
||||
/* Set the timeout. */
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_TIMEOUT, 0xffffffff);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_TMOR,
|
||||
A10_MMC_TMOR_DTO_LMT_SHIFT(A10_MMC_TMOR_DTO_LMT_MASK) |
|
||||
A10_MMC_TMOR_RTO_LMT_SHIFT(A10_MMC_TMOR_RTO_LMT_MASK));
|
||||
|
||||
/* Clear pending interrupts. */
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_RINTR, 0xffffffff);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_RISR, 0xffffffff);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_IDST, 0xffffffff);
|
||||
/* Unmask interrupts. */
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_IMASK,
|
||||
A10_MMC_CMD_DONE | A10_MMC_INT_ERR_BIT |
|
||||
A10_MMC_DATA_OVER | A10_MMC_AUTOCMD_DONE);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_IMKR,
|
||||
A10_MMC_INT_CMD_DONE | A10_MMC_INT_ERR_BIT |
|
||||
A10_MMC_INT_DATA_OVER | A10_MMC_INT_AUTO_STOP_DONE);
|
||||
/* Enable interrupts and AHB access. */
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_GCTRL,
|
||||
A10_MMC_READ_4(sc, A10_MMC_GCTRL) | A10_MMC_INT_ENABLE);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_GCTL,
|
||||
A10_MMC_READ_4(sc, A10_MMC_GCTL) | A10_MMC_CTRL_INT_ENB);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -483,12 +454,6 @@ a10_mmc_req_done(struct a10_mmc_softc *sc)
|
||||
if (cmd->error != MMC_ERR_NONE) {
|
||||
/* Reset the controller. */
|
||||
a10_mmc_reset(sc);
|
||||
a10_mmc_update_clock(sc);
|
||||
}
|
||||
if (sc->a10_dma_inuse == 0) {
|
||||
/* Reset the FIFO. */
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_GCTRL,
|
||||
A10_MMC_READ_4(sc, A10_MMC_GCTRL) | A10_MMC_FIFO_RESET);
|
||||
}
|
||||
|
||||
req = sc->a10_req;
|
||||
@ -496,7 +461,6 @@ a10_mmc_req_done(struct a10_mmc_softc *sc)
|
||||
sc->a10_req = NULL;
|
||||
sc->a10_intr = 0;
|
||||
sc->a10_resid = 0;
|
||||
sc->a10_dma_inuse = 0;
|
||||
sc->a10_dma_map_err = 0;
|
||||
sc->a10_intr_wait = 0;
|
||||
req->done(req);
|
||||
@ -511,8 +475,8 @@ a10_mmc_req_ok(struct a10_mmc_softc *sc)
|
||||
|
||||
timeout = 1000;
|
||||
while (--timeout > 0) {
|
||||
status = A10_MMC_READ_4(sc, A10_MMC_STAS);
|
||||
if ((status & A10_MMC_CARD_DATA_BUSY) == 0)
|
||||
status = A10_MMC_READ_4(sc, A10_MMC_STAR);
|
||||
if ((status & A10_MMC_STAR_CARD_BUSY) == 0)
|
||||
break;
|
||||
DELAY(1000);
|
||||
}
|
||||
@ -552,28 +516,6 @@ a10_mmc_timeout(void *arg)
|
||||
"Spurious timeout - no active request\n");
|
||||
}
|
||||
|
||||
static int
|
||||
a10_mmc_pio_transfer(struct a10_mmc_softc *sc, struct mmc_data *data)
|
||||
{
|
||||
int i, write;
|
||||
uint32_t bit, *buf;
|
||||
|
||||
buf = (uint32_t *)data->data;
|
||||
write = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
|
||||
bit = write ? A10_MMC_FIFO_FULL : A10_MMC_FIFO_EMPTY;
|
||||
for (i = sc->a10_resid; i < (data->len >> 2); i++) {
|
||||
if ((A10_MMC_READ_4(sc, A10_MMC_STAS) & bit))
|
||||
return (1);
|
||||
if (write)
|
||||
A10_MMC_WRITE_4(sc, sc->a10_fifo_reg, buf[i]);
|
||||
else
|
||||
buf[i] = A10_MMC_READ_4(sc, sc->a10_fifo_reg);
|
||||
sc->a10_resid = i + 1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
a10_mmc_intr(void *arg)
|
||||
{
|
||||
@ -584,9 +526,9 @@ a10_mmc_intr(void *arg)
|
||||
|
||||
sc = (struct a10_mmc_softc *)arg;
|
||||
A10_MMC_LOCK(sc);
|
||||
rint = A10_MMC_READ_4(sc, A10_MMC_RINTR);
|
||||
rint = A10_MMC_READ_4(sc, A10_MMC_RISR);
|
||||
idst = A10_MMC_READ_4(sc, A10_MMC_IDST);
|
||||
imask = A10_MMC_READ_4(sc, A10_MMC_IMASK);
|
||||
imask = A10_MMC_READ_4(sc, A10_MMC_IMKR);
|
||||
if (idst == 0 && imask == 0 && rint == 0) {
|
||||
A10_MMC_UNLOCK(sc);
|
||||
return;
|
||||
@ -603,14 +545,14 @@ a10_mmc_intr(void *arg)
|
||||
}
|
||||
if (rint & A10_MMC_INT_ERR_BIT) {
|
||||
device_printf(sc->a10_dev, "error rint: 0x%08X\n", rint);
|
||||
if (rint & A10_MMC_RESP_TIMEOUT)
|
||||
if (rint & A10_MMC_INT_RESP_TIMEOUT)
|
||||
sc->a10_req->cmd->error = MMC_ERR_TIMEOUT;
|
||||
else
|
||||
sc->a10_req->cmd->error = MMC_ERR_FAILED;
|
||||
a10_mmc_req_done(sc);
|
||||
goto end;
|
||||
}
|
||||
if (idst & A10_MMC_IDMAC_ERROR) {
|
||||
if (idst & A10_MMC_IDST_ERROR) {
|
||||
device_printf(sc->a10_dev, "error idst: 0x%08x\n", idst);
|
||||
sc->a10_req->cmd->error = MMC_ERR_FAILED;
|
||||
a10_mmc_req_done(sc);
|
||||
@ -619,8 +561,7 @@ a10_mmc_intr(void *arg)
|
||||
|
||||
sc->a10_intr |= rint;
|
||||
data = sc->a10_req->cmd->data;
|
||||
if (data != NULL && sc->a10_dma_inuse == 1 &&
|
||||
(idst & A10_MMC_IDMAC_COMPLETE)) {
|
||||
if (data != NULL && (idst & A10_MMC_IDST_COMPLETE) != 0) {
|
||||
if (data->flags & MMC_DATA_WRITE)
|
||||
sync_op = BUS_DMASYNC_POSTWRITE;
|
||||
else
|
||||
@ -631,16 +572,13 @@ a10_mmc_intr(void *arg)
|
||||
BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(sc->a10_dma_buf_tag, sc->a10_dma_buf_map);
|
||||
sc->a10_resid = data->len >> 2;
|
||||
} else if (data != NULL && sc->a10_dma_inuse == 0 &&
|
||||
(rint & (A10_MMC_DATA_OVER | A10_MMC_RX_DATA_REQ |
|
||||
A10_MMC_TX_DATA_REQ)) != 0)
|
||||
a10_mmc_pio_transfer(sc, data);
|
||||
}
|
||||
if ((sc->a10_intr & sc->a10_intr_wait) == sc->a10_intr_wait)
|
||||
a10_mmc_req_ok(sc);
|
||||
|
||||
end:
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_IDST, idst);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_RINTR, rint);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_RISR, rint);
|
||||
A10_MMC_UNLOCK(sc);
|
||||
}
|
||||
|
||||
@ -650,7 +588,8 @@ a10_mmc_request(device_t bus, device_t child, struct mmc_request *req)
|
||||
int blksz;
|
||||
struct a10_mmc_softc *sc;
|
||||
struct mmc_command *cmd;
|
||||
uint32_t cmdreg, val;
|
||||
uint32_t cmdreg;
|
||||
int err;
|
||||
|
||||
sc = device_get_softc(bus);
|
||||
A10_MMC_LOCK(sc);
|
||||
@ -660,48 +599,39 @@ a10_mmc_request(device_t bus, device_t child, struct mmc_request *req)
|
||||
}
|
||||
sc->a10_req = req;
|
||||
cmd = req->cmd;
|
||||
cmdreg = A10_MMC_START;
|
||||
cmdreg = A10_MMC_CMDR_LOAD;
|
||||
if (cmd->opcode == MMC_GO_IDLE_STATE)
|
||||
cmdreg |= A10_MMC_SEND_INIT_SEQ;
|
||||
cmdreg |= A10_MMC_CMDR_SEND_INIT_SEQ;
|
||||
if (cmd->flags & MMC_RSP_PRESENT)
|
||||
cmdreg |= A10_MMC_RESP_EXP;
|
||||
cmdreg |= A10_MMC_CMDR_RESP_RCV;
|
||||
if (cmd->flags & MMC_RSP_136)
|
||||
cmdreg |= A10_MMC_LONG_RESP;
|
||||
cmdreg |= A10_MMC_CMDR_LONG_RESP;
|
||||
if (cmd->flags & MMC_RSP_CRC)
|
||||
cmdreg |= A10_MMC_CHECK_RESP_CRC;
|
||||
cmdreg |= A10_MMC_CMDR_CHK_RESP_CRC;
|
||||
|
||||
sc->a10_intr = 0;
|
||||
sc->a10_resid = 0;
|
||||
sc->a10_intr_wait = A10_MMC_CMD_DONE;
|
||||
sc->a10_intr_wait = A10_MMC_INT_CMD_DONE;
|
||||
cmd->error = MMC_ERR_NONE;
|
||||
if (cmd->data != NULL) {
|
||||
sc->a10_intr_wait |= A10_MMC_DATA_OVER;
|
||||
cmdreg |= A10_MMC_DATA_EXP | A10_MMC_WAIT_PREOVER;
|
||||
sc->a10_intr_wait |= A10_MMC_INT_DATA_OVER;
|
||||
cmdreg |= A10_MMC_CMDR_DATA_TRANS | A10_MMC_CMDR_WAIT_PRE_OVER;
|
||||
if (cmd->data->flags & MMC_DATA_MULTI) {
|
||||
cmdreg |= A10_MMC_SEND_AUTOSTOP;
|
||||
sc->a10_intr_wait |= A10_MMC_AUTOCMD_DONE;
|
||||
cmdreg |= A10_MMC_CMDR_STOP_CMD_FLAG;
|
||||
sc->a10_intr_wait |= A10_MMC_INT_AUTO_STOP_DONE;
|
||||
}
|
||||
if (cmd->data->flags & MMC_DATA_WRITE)
|
||||
cmdreg |= A10_MMC_WRITE;
|
||||
cmdreg |= A10_MMC_CMDR_DIR_WRITE;
|
||||
blksz = min(cmd->data->len, MMC_SECTOR_SIZE);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_BLKSZ, blksz);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_BCNTR, cmd->data->len);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_BKSR, blksz);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_BYCR, cmd->data->len);
|
||||
|
||||
if (a10_mmc_pio_mode == 0)
|
||||
a10_mmc_prepare_dma(sc);
|
||||
/* Enable PIO access if sc->a10_dma_inuse is not set. */
|
||||
if (sc->a10_dma_inuse == 0) {
|
||||
val = A10_MMC_READ_4(sc, A10_MMC_GCTRL);
|
||||
val &= ~A10_MMC_DMA_ENABLE;
|
||||
val |= A10_MMC_ACCESS_BY_AHB;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_GCTRL, val);
|
||||
val = A10_MMC_READ_4(sc, A10_MMC_IMASK);
|
||||
val |= A10_MMC_RX_DATA_REQ | A10_MMC_TX_DATA_REQ;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_IMASK, val);
|
||||
}
|
||||
err = a10_mmc_prepare_dma(sc);
|
||||
if (err != 0)
|
||||
device_printf(sc->a10_dev, "prepare_dma failed: %d\n", err);
|
||||
}
|
||||
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_CARG, cmd->arg);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_CAGR, cmd->arg);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_CMDR, cmdreg | cmd->opcode);
|
||||
callout_reset(&sc->a10_timeoutc, sc->a10_timeout * hz,
|
||||
a10_mmc_timeout, sc);
|
||||
@ -811,23 +741,32 @@ a10_mmc_write_ivar(device_t bus, device_t child, int which,
|
||||
}
|
||||
|
||||
static int
|
||||
a10_mmc_update_clock(struct a10_mmc_softc *sc)
|
||||
a10_mmc_update_clock(struct a10_mmc_softc *sc, uint32_t clkon)
|
||||
{
|
||||
uint32_t cmdreg;
|
||||
int retry;
|
||||
uint32_t ckcr;
|
||||
|
||||
cmdreg = A10_MMC_START | A10_MMC_UPCLK_ONLY |
|
||||
A10_MMC_WAIT_PREOVER;
|
||||
ckcr = A10_MMC_READ_4(sc, A10_MMC_CKCR);
|
||||
ckcr &= ~(A10_MMC_CKCR_CCLK_ENB | A10_MMC_CKCR_CCLK_CTRL);
|
||||
|
||||
if (clkon)
|
||||
ckcr |= A10_MMC_CKCR_CCLK_ENB;
|
||||
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_CKCR, ckcr);
|
||||
|
||||
cmdreg = A10_MMC_CMDR_LOAD | A10_MMC_CMDR_PRG_CLK |
|
||||
A10_MMC_CMDR_WAIT_PRE_OVER;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_CMDR, cmdreg);
|
||||
retry = 0xfffff;
|
||||
while (--retry > 0) {
|
||||
if ((A10_MMC_READ_4(sc, A10_MMC_CMDR) & A10_MMC_START) == 0) {
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_RINTR, 0xffffffff);
|
||||
if ((A10_MMC_READ_4(sc, A10_MMC_CMDR) & A10_MMC_CMDR_LOAD) == 0) {
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_RISR, 0xffffffff);
|
||||
return (0);
|
||||
}
|
||||
DELAY(10);
|
||||
}
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_RINTR, 0xffffffff);
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_RISR, 0xffffffff);
|
||||
device_printf(sc->a10_dev, "timeout updating clock\n");
|
||||
|
||||
return (ETIMEDOUT);
|
||||
@ -839,28 +778,37 @@ a10_mmc_update_ios(device_t bus, device_t child)
|
||||
int error;
|
||||
struct a10_mmc_softc *sc;
|
||||
struct mmc_ios *ios;
|
||||
uint32_t clkcr;
|
||||
uint32_t ckcr;
|
||||
|
||||
sc = device_get_softc(bus);
|
||||
clkcr = A10_MMC_READ_4(sc, A10_MMC_CLKCR);
|
||||
if (clkcr & A10_MMC_CARD_CLK_ON) {
|
||||
/* Disable clock. */
|
||||
clkcr &= ~A10_MMC_CARD_CLK_ON;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_CLKCR, clkcr);
|
||||
error = a10_mmc_update_clock(sc);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
|
||||
ios = &sc->a10_host.ios;
|
||||
|
||||
/* Set the bus width. */
|
||||
switch (ios->bus_width) {
|
||||
case bus_width_1:
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_BWDR, A10_MMC_BWDR1);
|
||||
break;
|
||||
case bus_width_4:
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_BWDR, A10_MMC_BWDR4);
|
||||
break;
|
||||
case bus_width_8:
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_BWDR, A10_MMC_BWDR8);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ios->clock) {
|
||||
/* Reset the divider. */
|
||||
clkcr &= ~A10_MMC_CLKCR_DIV;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_CLKCR, clkcr);
|
||||
error = a10_mmc_update_clock(sc);
|
||||
|
||||
/* Disable clock */
|
||||
error = a10_mmc_update_clock(sc, 0);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/* Reset the divider. */
|
||||
ckcr = A10_MMC_READ_4(sc, A10_MMC_CKCR);
|
||||
ckcr &= ~A10_MMC_CKCR_CCLK_DIV;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_CKCR, ckcr);
|
||||
|
||||
/* Set the MMC clock. */
|
||||
error = clk_set_freq(sc->a10_clk_mmc, ios->clock,
|
||||
CLK_SET_ROUND_DOWN);
|
||||
@ -872,25 +820,11 @@ a10_mmc_update_ios(device_t bus, device_t child)
|
||||
}
|
||||
|
||||
/* Enable clock. */
|
||||
clkcr |= A10_MMC_CARD_CLK_ON;
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_CLKCR, clkcr);
|
||||
error = a10_mmc_update_clock(sc);
|
||||
error = a10_mmc_update_clock(sc, 1);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Set the bus width. */
|
||||
switch (ios->bus_width) {
|
||||
case bus_width_1:
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_WIDTH, A10_MMC_WIDTH1);
|
||||
break;
|
||||
case bus_width_4:
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_WIDTH, A10_MMC_WIDTH4);
|
||||
break;
|
||||
case bus_width_8:
|
||||
A10_MMC_WRITE_4(sc, A10_MMC_WIDTH, A10_MMC_WIDTH8);
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -29,117 +29,120 @@
|
||||
#ifndef _A10_MMC_H_
|
||||
#define _A10_MMC_H_
|
||||
|
||||
#define A10_MMC_GCTRL 0x00 /* Global Control Register */
|
||||
#define A10_MMC_CLKCR 0x04 /* Clock Control Register */
|
||||
#define A10_MMC_TIMEOUT 0x08 /* Timeout Register */
|
||||
#define A10_MMC_WIDTH 0x0C /* Bus Width Register */
|
||||
#define A10_MMC_BLKSZ 0x10 /* Block Size Register */
|
||||
#define A10_MMC_BCNTR 0x14 /* Byte Count Register */
|
||||
#define A10_MMC_GCTL 0x00 /* Control Register */
|
||||
#define A10_MMC_CKCR 0x04 /* Clock Control Register */
|
||||
#define A10_MMC_TMOR 0x08 /* Timeout Register */
|
||||
#define A10_MMC_BWDR 0x0C /* Bus Width Register */
|
||||
#define A10_MMC_BKSR 0x10 /* Block Size Register */
|
||||
#define A10_MMC_BYCR 0x14 /* Byte Count Register */
|
||||
#define A10_MMC_CMDR 0x18 /* Command Register */
|
||||
#define A10_MMC_CARG 0x1C /* Argument Register */
|
||||
#define A10_MMC_CAGR 0x1C /* Argument Register */
|
||||
#define A10_MMC_RESP0 0x20 /* Response Register 0 */
|
||||
#define A10_MMC_RESP1 0x24 /* Response Register 1 */
|
||||
#define A10_MMC_RESP2 0x28 /* Response Register 2 */
|
||||
#define A10_MMC_RESP3 0x2C /* Response Register 3 */
|
||||
#define A10_MMC_IMASK 0x30 /* Interrupt Mask Register */
|
||||
#define A10_MMC_MISTA 0x34 /* Masked Interrupt Status Register */
|
||||
#define A10_MMC_RINTR 0x38 /* Raw Interrupt Status Register */
|
||||
#define A10_MMC_STAS 0x3C /* Status Register */
|
||||
#define A10_MMC_FTRGL 0x40 /* FIFO Threshold Watermark Register */
|
||||
#define A10_MMC_IMKR 0x30 /* Interrupt Mask Register */
|
||||
#define A10_MMC_MISR 0x34 /* Masked Interrupt Status Register */
|
||||
#define A10_MMC_RISR 0x38 /* Raw Interrupt Status Register */
|
||||
#define A10_MMC_STAR 0x3C /* Status Register */
|
||||
#define A10_MMC_FWLR 0x40 /* FIFO Threshold Watermark Register */
|
||||
#define A10_MMC_FUNS 0x44 /* Function Select Register */
|
||||
#define A10_MMC_CBCR 0x48 /* CIU Byte Count Register */
|
||||
#define A10_MMC_BBCR 0x4C /* BIU Byte Count Register */
|
||||
#define A10_MMC_DBGC 0x50 /* Debug Enable Register */
|
||||
#define A10_MMC_HWRST 0x78 /* Hardware reset (not documented) */
|
||||
#define A10_MMC_DMAC 0x80 /* IDMAC Control Register */
|
||||
#define A10_MMC_DLBA 0x84 /* IDMAC Desc List Base Address Reg */
|
||||
#define A10_MMC_IDST 0x88 /* IDMAC Status Register */
|
||||
#define A10_MMC_IDIE 0x8C /* IDMAC Interrupt Enable Register */
|
||||
#define A10_MMC_CHDA 0x90
|
||||
#define A10_MMC_CBDA 0x94
|
||||
#define A10_MMC_FIFO 0x100 /* FIFO Access Address (A10/A20) */
|
||||
#define A31_MMC_FIFO 0x200 /* FIFO Access Address (A31) */
|
||||
#define A10_MMC_FIFO 0x100 /* FIFO Access Address (A10/A20) */
|
||||
#define A31_MMC_FIFO 0x200 /* FIFO Access Address (A31) */
|
||||
|
||||
/* A10_MMC_GCTRL */
|
||||
#define A10_MMC_SOFT_RESET (1U << 0)
|
||||
#define A10_MMC_FIFO_RESET (1U << 1)
|
||||
#define A10_MMC_DMA_RESET (1U << 2)
|
||||
#define A10_MMC_INT_ENABLE (1U << 4)
|
||||
#define A10_MMC_DMA_ENABLE (1U << 5)
|
||||
#define A10_MMC_DEBOUNCE_ENABLE (1U << 8)
|
||||
#define A10_MMC_DDR_MODE (1U << 10)
|
||||
#define A10_MMC_ACCESS_BY_AHB (1U << 31)
|
||||
/* A10_MMC_GCTL */
|
||||
#define A10_MMC_CTRL_SOFT_RST (1U << 0)
|
||||
#define A10_MMC_CTRL_FIFO_RST (1U << 1)
|
||||
#define A10_MMC_CTRL_DMA_RST (1U << 2)
|
||||
#define A10_MMC_CTRL_INT_ENB (1U << 4)
|
||||
#define A10_MMC_CTRL_DMA_ENB (1U << 5)
|
||||
#define A10_MMC_CTRL_CD_DBC_ENB (1U << 8)
|
||||
#define A10_MMC_CTRL_DDR_MOD_SEL (1U << 10)
|
||||
#define A10_MMC_CTRL_FIFO_AC_MOD (1U << 31)
|
||||
#define A10_MMC_RESET \
|
||||
(A10_MMC_SOFT_RESET | A10_MMC_FIFO_RESET | A10_MMC_DMA_RESET)
|
||||
(A10_MMC_CTRL_SOFT_RST | A10_MMC_CTRL_FIFO_RST | A10_MMC_CTRL_DMA_RST)
|
||||
|
||||
/* A10_MMC_CLKCR */
|
||||
#define A10_MMC_CARD_CLK_ON (1U << 16)
|
||||
#define A10_MMC_LOW_POWER_ON (1U << 17)
|
||||
#define A10_MMC_CLKCR_DIV 0xff
|
||||
/* A10_MMC_CKCR */
|
||||
#define A10_MMC_CKCR_CCLK_ENB (1U << 16)
|
||||
#define A10_MMC_CKCR_CCLK_CTRL (1U << 17)
|
||||
#define A10_MMC_CKCR_CCLK_DIV 0xff
|
||||
|
||||
/* A10_MMC_WIDTH */
|
||||
#define A10_MMC_WIDTH1 0
|
||||
#define A10_MMC_WIDTH4 1
|
||||
#define A10_MMC_WIDTH8 2
|
||||
/* A10_MMC_TMOR */
|
||||
#define A10_MMC_TMOR_RTO_LMT_SHIFT(x) x /* Response timeout limit */
|
||||
#define A10_MMC_TMOR_RTO_LMT_MASK 0xff
|
||||
#define A10_MMC_TMOR_DTO_LMT_SHIFT(x) (x << 8) /* Data timeout limit */
|
||||
#define A10_MMC_TMOR_DTO_LMT_MASK 0xffffff
|
||||
|
||||
/* A10_MMC_BWDR */
|
||||
#define A10_MMC_BWDR1 0
|
||||
#define A10_MMC_BWDR4 1
|
||||
#define A10_MMC_BWDR8 2
|
||||
|
||||
/* A10_MMC_CMDR */
|
||||
#define A10_MMC_RESP_EXP (1U << 6)
|
||||
#define A10_MMC_LONG_RESP (1U << 7)
|
||||
#define A10_MMC_CHECK_RESP_CRC (1U << 8)
|
||||
#define A10_MMC_DATA_EXP (1U << 9)
|
||||
#define A10_MMC_WRITE (1U << 10)
|
||||
#define A10_MMC_SEQ_MODE (1U << 11)
|
||||
#define A10_MMC_SEND_AUTOSTOP (1U << 12)
|
||||
#define A10_MMC_WAIT_PREOVER (1U << 13)
|
||||
#define A10_MMC_STOP_ABORT_CMD (1U << 14)
|
||||
#define A10_MMC_SEND_INIT_SEQ (1U << 15)
|
||||
#define A10_MMC_UPCLK_ONLY (1U << 21)
|
||||
#define A10_MMC_RDCEATADEV (1U << 22)
|
||||
#define A10_MMC_CCS_EXP (1U << 23)
|
||||
#define A10_MMC_ENB_BOOT (1U << 24)
|
||||
#define A10_MMC_ALT_BOOT_OPT (1U << 25)
|
||||
#define A10_MMC_BOOT_ACK_EXP (1U << 26)
|
||||
#define A10_MMC_DISABLE_BOOT (1U << 27)
|
||||
#define A10_MMC_VOL_SWITCH (1U << 28)
|
||||
#define A10_MMC_START (1U << 31)
|
||||
#define A10_MMC_CMDR_RESP_RCV (1U << 6)
|
||||
#define A10_MMC_CMDR_LONG_RESP (1U << 7)
|
||||
#define A10_MMC_CMDR_CHK_RESP_CRC (1U << 8)
|
||||
#define A10_MMC_CMDR_DATA_TRANS (1U << 9)
|
||||
#define A10_MMC_CMDR_DIR_WRITE (1U << 10)
|
||||
#define A10_MMC_CMDR_TRANS_MODE_STREAM (1U << 11)
|
||||
#define A10_MMC_CMDR_STOP_CMD_FLAG (1U << 12)
|
||||
#define A10_MMC_CMDR_WAIT_PRE_OVER (1U << 13)
|
||||
#define A10_MMC_CMDR_STOP_ABT_CMD (1U << 14)
|
||||
#define A10_MMC_CMDR_SEND_INIT_SEQ (1U << 15)
|
||||
#define A10_MMC_CMDR_PRG_CLK (1U << 21)
|
||||
#define A10_MMC_CMDR_RD_CEDATA_DEV (1U << 22)
|
||||
#define A10_MMC_CMDR_CCS_EXP (1U << 23)
|
||||
#define A10_MMC_CMDR_BOOT_MOD_SHIFT 24
|
||||
#define A10_MMC_CMDR_BOOT_MOD_NORMAL 0
|
||||
#define A10_MMC_CMDR_BOOT_MOD_MANDATORY 1
|
||||
#define A10_MMC_CMDR_BOOT_MOD_ALT 2
|
||||
#define A10_MMC_CMDR_EXP_BOOT_ACK (1U << 26)
|
||||
#define A10_MMC_CMDR_BOOT_ABT (1U << 27)
|
||||
#define A10_MMC_CMDR_VOL_SW (1U << 28)
|
||||
#define A10_MMC_CMDR_LOAD (1U << 31)
|
||||
|
||||
/* A10_MMC_IMASK and A10_MMC_RINTR */
|
||||
#define A10_MMC_RESP_ERR (1U << 1)
|
||||
#define A10_MMC_CMD_DONE (1U << 2)
|
||||
#define A10_MMC_DATA_OVER (1U << 3)
|
||||
#define A10_MMC_TX_DATA_REQ (1U << 4)
|
||||
#define A10_MMC_RX_DATA_REQ (1U << 5)
|
||||
#define A10_MMC_RESP_CRC_ERR (1U << 6)
|
||||
#define A10_MMC_DATA_CRC_ERR (1U << 7)
|
||||
#define A10_MMC_RESP_TIMEOUT (1U << 8)
|
||||
#define A10_MMC_ACK_RECV (1U << 8)
|
||||
#define A10_MMC_DATA_TIMEOUT (1U << 9)
|
||||
#define A10_MMC_BOOT_START (1U << 9)
|
||||
#define A10_MMC_DATA_STARVE (1U << 10)
|
||||
#define A10_MMC_VOL_CHG_DONE (1U << 10)
|
||||
#define A10_MMC_FIFO_RUN_ERR (1U << 11)
|
||||
#define A10_MMC_HARDW_LOCKED (1U << 12)
|
||||
#define A10_MMC_START_BIT_ERR (1U << 13)
|
||||
#define A10_MMC_AUTOCMD_DONE (1U << 14)
|
||||
#define A10_MMC_END_BIT_ERR (1U << 15)
|
||||
#define A10_MMC_SDIO_INT (1U << 16)
|
||||
#define A10_MMC_CARD_INSERT (1U << 30)
|
||||
#define A10_MMC_CARD_REMOVE (1U << 31)
|
||||
/* A10_MMC_IMKR and A10_MMC_RISR */
|
||||
#define A10_MMC_INT_RESP_ERR (1U << 1)
|
||||
#define A10_MMC_INT_CMD_DONE (1U << 2)
|
||||
#define A10_MMC_INT_DATA_OVER (1U << 3)
|
||||
#define A10_MMC_INT_TX_DATA_REQ (1U << 4)
|
||||
#define A10_MMC_INT_RX_DATA_REQ (1U << 5)
|
||||
#define A10_MMC_INT_RESP_CRC_ERR (1U << 6)
|
||||
#define A10_MMC_INT_DATA_CRC_ERR (1U << 7)
|
||||
#define A10_MMC_INT_RESP_TIMEOUT (1U << 8)
|
||||
#define A10_MMC_INT_BOOT_ACK_RECV (1U << 8)
|
||||
#define A10_MMC_INT_DATA_TIMEOUT (1U << 9)
|
||||
#define A10_MMC_INT_BOOT_START (1U << 9)
|
||||
#define A10_MMC_INT_DATA_STARVE (1U << 10)
|
||||
#define A10_MMC_INT_VOL_CHG_DONE (1U << 10)
|
||||
#define A10_MMC_INT_FIFO_RUN_ERR (1U << 11)
|
||||
#define A10_MMC_INT_CMD_BUSY (1U << 12)
|
||||
#define A10_MMC_INT_DATA_START_ERR (1U << 13)
|
||||
#define A10_MMC_INT_AUTO_STOP_DONE (1U << 14)
|
||||
#define A10_MMC_INT_DATA_END_BIT_ERR (1U << 15)
|
||||
#define A10_MMC_INT_SDIO (1U << 16)
|
||||
#define A10_MMC_INT_CARD_INSERT (1U << 30)
|
||||
#define A10_MMC_INT_CARD_REMOVE (1U << 31)
|
||||
#define A10_MMC_INT_ERR_BIT \
|
||||
(A10_MMC_RESP_ERR | A10_MMC_RESP_CRC_ERR | \
|
||||
A10_MMC_DATA_CRC_ERR | A10_MMC_RESP_TIMEOUT | \
|
||||
A10_MMC_FIFO_RUN_ERR | A10_MMC_HARDW_LOCKED | \
|
||||
A10_MMC_START_BIT_ERR | A10_MMC_END_BIT_ERR)
|
||||
(A10_MMC_INT_RESP_ERR | A10_MMC_INT_RESP_CRC_ERR | \
|
||||
A10_MMC_INT_DATA_CRC_ERR | A10_MMC_INT_RESP_TIMEOUT | \
|
||||
A10_MMC_INT_FIFO_RUN_ERR | A10_MMC_INT_CMD_BUSY | \
|
||||
A10_MMC_INT_DATA_START_ERR | A10_MMC_INT_DATA_END_BIT_ERR)
|
||||
|
||||
/* A10_MMC_STAS */
|
||||
#define A10_MMC_RX_WLFLAG (1U << 0)
|
||||
#define A10_MMC_TX_WLFLAG (1U << 1)
|
||||
#define A10_MMC_FIFO_EMPTY (1U << 2)
|
||||
#define A10_MMC_FIFO_FULL (1U << 3)
|
||||
#define A10_MMC_CARD_PRESENT (1U << 8)
|
||||
#define A10_MMC_CARD_DATA_BUSY (1U << 9)
|
||||
#define A10_MMC_DATA_FSM_BUSY (1U << 10)
|
||||
#define A10_MMC_DMA_REQ (1U << 31)
|
||||
#define A10_MMC_FIFO_SIZE 16
|
||||
/* A10_MMC_STAR */
|
||||
#define A10_MMC_STAR_FIFO_RX_LEVEL (1U << 0)
|
||||
#define A10_MMC_STAR_FIFO_TX_LEVEL (1U << 1)
|
||||
#define A10_MMC_STAR_FIFO_EMPTY (1U << 2)
|
||||
#define A10_MMC_STAR_FIFO_FULL (1U << 3)
|
||||
#define A10_MMC_STAR_CARD_PRESENT (1U << 8)
|
||||
#define A10_MMC_STAR_CARD_BUSY (1U << 9)
|
||||
#define A10_MMC_STAR_FSM_BUSY (1U << 10)
|
||||
#define A10_MMC_STAR_DMA_REQ (1U << 31)
|
||||
|
||||
/* A10_MMC_FUNS */
|
||||
#define A10_MMC_CE_ATA_ON (0xceaaU << 16)
|
||||
@ -151,52 +154,51 @@
|
||||
#define A10_MMC_CE_ATA_DEV_INT_ENB (1U << 10)
|
||||
|
||||
/* IDMA CONTROLLER BUS MOD BIT FIELD */
|
||||
#define A10_MMC_IDMAC_SOFT_RST (1U << 0)
|
||||
#define A10_MMC_IDMAC_FIX_BURST (1U << 1)
|
||||
#define A10_MMC_IDMAC_IDMA_ON (1U << 7)
|
||||
#define A10_MMC_IDMAC_REFETCH_DES (1U << 31)
|
||||
#define A10_MMC_DMAC_IDMAC_SOFT_RST (1U << 0)
|
||||
#define A10_MMC_DMAC_IDMAC_FIX_BURST (1U << 1)
|
||||
#define A10_MMC_DMAC_IDMAC_IDMA_ON (1U << 7)
|
||||
#define A10_MMC_DMAC_IDMAC_REFETCH_DES (1U << 31)
|
||||
|
||||
/* A10_MMC_IDST */
|
||||
#define A10_MMC_IDMAC_TRANSMIT_INT (1U << 0)
|
||||
#define A10_MMC_IDMAC_RECEIVE_INT (1U << 1)
|
||||
#define A10_MMC_IDMAC_FATAL_BUS_ERR (1U << 2)
|
||||
#define A10_MMC_IDMAC_DES_INVALID (1U << 4)
|
||||
#define A10_MMC_IDMAC_CARD_ERR_SUM (1U << 5)
|
||||
#define A10_MMC_IDMAC_NORMAL_INT_SUM (1U << 8)
|
||||
#define A10_MMC_IDMAC_ABNORMAL_INT_SUM (1U << 9)
|
||||
#define A10_MMC_IDMAC_HOST_ABT_INTX (1U << 10)
|
||||
#define A10_MMC_IDMAC_HOST_ABT_INRX (1U << 10)
|
||||
#define A10_MMC_IDMAC_IDLE (0U << 13)
|
||||
#define A10_MMC_IDMAC_SUSPEND (1U << 13)
|
||||
#define A10_MMC_IDMAC_DESC_RD (2U << 13)
|
||||
#define A10_MMC_IDMAC_DESC_CHECK (3U << 13)
|
||||
#define A10_MMC_IDMAC_RD_REQ_WAIT (4U << 13)
|
||||
#define A10_MMC_IDMAC_WR_REQ_WAIT (5U << 13)
|
||||
#define A10_MMC_IDMAC_RD (6U << 13)
|
||||
#define A10_MMC_IDMAC_WR (7U << 13)
|
||||
#define A10_MMC_IDMAC_DESC_CLOSE (8U << 13)
|
||||
#define A10_MMC_IDMAC_ERROR \
|
||||
(A10_MMC_IDMAC_FATAL_BUS_ERR | A10_MMC_IDMAC_CARD_ERR_SUM | \
|
||||
A10_MMC_IDMAC_DES_INVALID | A10_MMC_IDMAC_ABNORMAL_INT_SUM)
|
||||
#define A10_MMC_IDMAC_COMPLETE \
|
||||
(A10_MMC_IDMAC_TRANSMIT_INT | A10_MMC_IDMAC_RECEIVE_INT)
|
||||
#define A10_MMC_IDST_TX_INT (1U << 0)
|
||||
#define A10_MMC_IDST_RX_INT (1U << 1)
|
||||
#define A10_MMC_IDST_FATAL_BERR_INT (1U << 2)
|
||||
#define A10_MMC_IDST_DES_UNAVL_INT (1U << 4)
|
||||
#define A10_MMC_IDST_ERR_FLAG_SUM (1U << 5)
|
||||
#define A10_MMC_IDST_NOR_INT_SUM (1U << 8)
|
||||
#define A10_MMC_IDST_ABN_INT_SUM (1U << 9)
|
||||
#define A10_MMC_IDST_HOST_ABT_INTX (1U << 10)
|
||||
#define A10_MMC_IDST_HOST_ABT_INRX (1U << 10)
|
||||
#define A10_MMC_IDST_IDLE (0U << 13)
|
||||
#define A10_MMC_IDST_SUSPEND (1U << 13)
|
||||
#define A10_MMC_IDST_DESC_RD (2U << 13)
|
||||
#define A10_MMC_IDST_DESC_CHECK (3U << 13)
|
||||
#define A10_MMC_IDST_RD_REQ_WAIT (4U << 13)
|
||||
#define A10_MMC_IDST_WR_REQ_WAIT (5U << 13)
|
||||
#define A10_MMC_IDST_RD (6U << 13)
|
||||
#define A10_MMC_IDST_WR (7U << 13)
|
||||
#define A10_MMC_IDST_DESC_CLOSE (8U << 13)
|
||||
#define A10_MMC_IDST_ERROR \
|
||||
(A10_MMC_IDST_FATAL_BERR_INT | A10_MMC_IDST_ERR_FLAG_SUM | \
|
||||
A10_MMC_IDST_DES_UNAVL_INT | A10_MMC_IDST_ABN_INT_SUM)
|
||||
#define A10_MMC_IDST_COMPLETE \
|
||||
(A10_MMC_IDST_TX_INT | A10_MMC_IDST_RX_INT)
|
||||
|
||||
/* The DMA descriptor table. */
|
||||
struct a10_mmc_dma_desc {
|
||||
uint32_t config;
|
||||
#define A10_MMC_DMA_CONFIG_DIC (1U << 1)
|
||||
#define A10_MMC_DMA_CONFIG_LD (1U << 2)
|
||||
#define A10_MMC_DMA_CONFIG_FD (1U << 3)
|
||||
#define A10_MMC_DMA_CONFIG_CH (1U << 4)
|
||||
#define A10_MMC_DMA_CONFIG_ER (1U << 5)
|
||||
#define A10_MMC_DMA_CONFIG_CES (1U << 30)
|
||||
#define A10_MMC_DMA_CONFIG_OWN (1U << 31)
|
||||
#define A10_MMC_DMA_CONFIG_DIC (1U << 1) /* Disable Interrupt Completion */
|
||||
#define A10_MMC_DMA_CONFIG_LD (1U << 2) /* Last DES */
|
||||
#define A10_MMC_DMA_CONFIG_FD (1U << 3) /* First DES */
|
||||
#define A10_MMC_DMA_CONFIG_CH (1U << 4) /* CHAIN MOD */
|
||||
#define A10_MMC_DMA_CONFIG_ER (1U << 5) /* End of Ring (undocumented register) */
|
||||
#define A10_MMC_DMA_CONFIG_CES (1U << 30) /* Card Error Summary */
|
||||
#define A10_MMC_DMA_CONFIG_OWN (1U << 31) /* DES Own Flag */
|
||||
uint32_t buf_size;
|
||||
uint32_t buf_addr;
|
||||
uint32_t next;
|
||||
};
|
||||
|
||||
/* DMA descriptors and data buffers must be aligned to 32-bits */
|
||||
#define A10_MMC_DMA_ALIGN 4
|
||||
#define A10_MMC_DMA_ALIGN 4
|
||||
|
||||
#endif /* _A10_MMC_H_ */
|
||||
|
@ -131,3 +131,6 @@ device hdmi
|
||||
device ums
|
||||
device ukbd
|
||||
device kbdmux
|
||||
|
||||
# Uncomment to enable evdev support for ti_adc
|
||||
# options EVDEV
|
||||
|
@ -1,33 +0,0 @@
|
||||
#
|
||||
# CUBIEBOARD -- Custom configuration for the CUBIEBOARD ARM development
|
||||
# platform, check out http://www.cubieboard.org
|
||||
#
|
||||
# For more information on this file, please read the config(5) manual page,
|
||||
# and/or the handbook section on Kernel Configuration Files:
|
||||
#
|
||||
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
|
||||
#
|
||||
# The handbook is also available locally in /usr/share/doc/handbook
|
||||
# if you've installed the doc distribution, otherwise always see the
|
||||
# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
|
||||
# latest information.
|
||||
#
|
||||
# An exhaustive list of options and more detailed explanations of the
|
||||
# device lines is also present in the ../../conf/NOTES and NOTES files.
|
||||
# If you are in doubt as to the purpose or necessity of a line, check first
|
||||
# in NOTES.
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
#NO_UNIVERSE
|
||||
|
||||
include "A10"
|
||||
ident CUBIEBOARD
|
||||
|
||||
# Boot device is 2nd slice on MMC/SD card
|
||||
options ROOTDEVNAME=\"ufs:/dev/da0s2\"
|
||||
|
||||
# Flattened Device Tree
|
||||
options FDT
|
||||
options FDT_DTB_STATIC
|
||||
makeoptions FDT_DTS_FILE=cubieboard.dts
|
@ -27,6 +27,8 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_evdev.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
@ -52,6 +54,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#ifdef EVDEV
|
||||
#include <dev/evdev/input.h>
|
||||
#include <dev/evdev/evdev.h>
|
||||
#endif
|
||||
|
||||
#include <arm/ti/ti_prcm.h>
|
||||
#include <arm/ti/ti_adcreg.h>
|
||||
#include <arm/ti/ti_adcvar.h>
|
||||
@ -80,6 +87,20 @@ static struct ti_adc_input ti_adc_inputs[TI_ADC_NPINS] = {
|
||||
|
||||
static int ti_adc_samples[5] = { 0, 2, 4, 8, 16 };
|
||||
|
||||
static int ti_adc_detach(device_t dev);
|
||||
|
||||
#ifdef EVDEV
|
||||
static void
|
||||
ti_adc_ev_report(struct ti_adc_softc *sc)
|
||||
{
|
||||
|
||||
evdev_push_event(sc->sc_evdev, EV_ABS, ABS_X, sc->sc_x);
|
||||
evdev_push_event(sc->sc_evdev, EV_ABS, ABS_Y, sc->sc_y);
|
||||
evdev_push_event(sc->sc_evdev, EV_KEY, BTN_TOUCH, sc->sc_pen_down);
|
||||
evdev_sync(sc->sc_evdev);
|
||||
}
|
||||
#endif /* EVDEV */
|
||||
|
||||
static void
|
||||
ti_adc_enable(struct ti_adc_softc *sc)
|
||||
{
|
||||
@ -450,7 +471,14 @@ ti_adc_tsc_read_data(struct ti_adc_softc *sc)
|
||||
#ifdef DEBUG_TSC
|
||||
device_printf(sc->sc_dev, "touchscreen x: %d, y: %d\n", x, y);
|
||||
#endif
|
||||
/* TODO: That's where actual event reporting should take place */
|
||||
|
||||
#ifdef EVDEV
|
||||
if ((sc->sc_x != x) || (sc->sc_y != y)) {
|
||||
sc->sc_x = x;
|
||||
sc->sc_y = y;
|
||||
ti_adc_ev_report(sc);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@ -488,11 +516,17 @@ ti_adc_intr(void *arg)
|
||||
status |= ADC_IRQ_HW_PEN_ASYNC;
|
||||
ADC_WRITE4(sc, ADC_IRQENABLE_CLR,
|
||||
ADC_IRQ_HW_PEN_ASYNC);
|
||||
#ifdef EVDEV
|
||||
ti_adc_ev_report(sc);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rawstatus & ADC_IRQ_PEN_UP) {
|
||||
sc->sc_pen_down = 0;
|
||||
status |= ADC_IRQ_PEN_UP;
|
||||
#ifdef EVDEV
|
||||
ti_adc_ev_report(sc);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (status & ADC_IRQ_FIFO0_THRES)
|
||||
@ -840,6 +874,38 @@ ti_adc_attach(device_t dev)
|
||||
ti_adc_setup(sc);
|
||||
TI_ADC_UNLOCK(sc);
|
||||
|
||||
#ifdef EVDEV
|
||||
if (sc->sc_tsc_wires > 0) {
|
||||
sc->sc_evdev = evdev_alloc();
|
||||
evdev_set_name(sc->sc_evdev, device_get_desc(dev));
|
||||
evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev));
|
||||
evdev_set_id(sc->sc_evdev, BUS_VIRTUAL, 0, 0, 0);
|
||||
evdev_support_prop(sc->sc_evdev, INPUT_PROP_DIRECT);
|
||||
evdev_support_event(sc->sc_evdev, EV_SYN);
|
||||
evdev_support_event(sc->sc_evdev, EV_ABS);
|
||||
evdev_support_event(sc->sc_evdev, EV_KEY);
|
||||
|
||||
evdev_support_abs(sc->sc_evdev, ABS_X, 0, 0,
|
||||
ADC_MAX_VALUE, 0, 0, 0);
|
||||
evdev_support_abs(sc->sc_evdev, ABS_Y, 0, 0,
|
||||
ADC_MAX_VALUE, 0, 0, 0);
|
||||
|
||||
evdev_support_key(sc->sc_evdev, BTN_TOUCH);
|
||||
|
||||
err = evdev_register(sc->sc_evdev);
|
||||
if (err) {
|
||||
device_printf(dev,
|
||||
"failed to register evdev: error=%d\n", err);
|
||||
ti_adc_detach(dev);
|
||||
return (err);
|
||||
}
|
||||
|
||||
sc->sc_pen_down = 0;
|
||||
sc->sc_x = -1;
|
||||
sc->sc_y = -1;
|
||||
}
|
||||
#endif /* EVDEV */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -854,6 +920,11 @@ ti_adc_detach(device_t dev)
|
||||
TI_ADC_LOCK(sc);
|
||||
ti_adc_reset(sc);
|
||||
ti_adc_setup(sc);
|
||||
|
||||
#ifdef EVDEV
|
||||
evdev_free(sc->sc_evdev);
|
||||
#endif
|
||||
|
||||
TI_ADC_UNLOCK(sc);
|
||||
|
||||
TI_ADC_LOCK_DESTROY(sc);
|
||||
|
@ -122,5 +122,6 @@
|
||||
#define ADC_FIFO_STEP_ID_MSK 0x000f0000
|
||||
#define ADC_FIFO_STEP_ID_SHIFT 16
|
||||
#define ADC_FIFO_DATA_MSK 0x00000fff
|
||||
#define ADC_MAX_VALUE 0xfff
|
||||
|
||||
#endif /* _TI_ADCREG_H_ */
|
||||
|
@ -55,6 +55,11 @@ struct ti_adc_softc {
|
||||
int sc_yn_bit, sc_yn_inp;
|
||||
uint32_t sc_tsc_enabled;
|
||||
int sc_pen_down;
|
||||
#ifdef EVDEV
|
||||
int sc_x;
|
||||
int sc_y;
|
||||
struct evdev_dev *sc_evdev;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ti_adc_input {
|
||||
|
@ -201,8 +201,10 @@ static void
|
||||
am335x_get_revision(void)
|
||||
{
|
||||
uint32_t dev_feature;
|
||||
uint8_t cpu_last_char;
|
||||
char cpu_last_char;
|
||||
bus_space_handle_t bsh;
|
||||
int major;
|
||||
int minor;
|
||||
|
||||
bus_space_map(fdtbus_bs_tag, AM335X_CONTROL_BASE, AM335X_CONTROL_SIZE, 0, &bsh);
|
||||
chip_revision = bus_space_read_4(fdtbus_bs_tag, bsh, AM335X_CONTROL_DEVICE_ID);
|
||||
@ -232,8 +234,26 @@ am335x_get_revision(void)
|
||||
cpu_last_char='x';
|
||||
}
|
||||
|
||||
printf("Texas Instruments AM335%c Processor, Revision ES1.%u\n",
|
||||
cpu_last_char, AM335X_DEVREV(chip_revision));
|
||||
switch(AM335X_DEVREV(chip_revision)) {
|
||||
case 0:
|
||||
major = 1;
|
||||
minor = 0;
|
||||
break;
|
||||
case 1:
|
||||
major = 2;
|
||||
minor = 0;
|
||||
break;
|
||||
case 2:
|
||||
major = 2;
|
||||
minor = 1;
|
||||
break;
|
||||
default:
|
||||
major = 0;
|
||||
minor = AM335X_DEVREV(chip_revision);
|
||||
break;
|
||||
}
|
||||
printf("Texas Instruments AM335%c Processor, Revision ES%u.%u\n",
|
||||
cpu_last_char, major, minor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,6 +27,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_ddb.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
|
@ -27,6 +27,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_ddb.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
|
@ -179,6 +179,28 @@ print_cpu_features(u_int cpu)
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/*
|
||||
* There is a hardware errata where, if one CPU is performing a TLB
|
||||
* invalidation while another is performing a store-exclusive the
|
||||
* store-exclusive may return the wrong status. A workaround seems
|
||||
* to be to use an IPI to invalidate on each CPU, however given the
|
||||
* limited number of affected units (pass 1.1 is the evaluation
|
||||
* hardware revision), and the lack of information from Cavium
|
||||
* this has not been implemented.
|
||||
*
|
||||
* At the time of writing this the only information is from:
|
||||
* https://lkml.org/lkml/2016/8/4/722
|
||||
*/
|
||||
/*
|
||||
* XXX: CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1 on it's own also
|
||||
* triggers on pass 2.0+.
|
||||
*/
|
||||
if (cpu == 0 && CPU_VAR(PCPU_GET(midr)) == 0 &&
|
||||
CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1)
|
||||
printf("WARNING: ThunderX Pass 1.1 detected.\nThis has known "
|
||||
"hardware bugs that may cause the incorrect operation of "
|
||||
"atomic operations.\n");
|
||||
|
||||
if (cpu != 0 && cpu_print_regs == 0)
|
||||
return;
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
#ifndef _MACHINE_DEBUG_MONITOR_H_
|
||||
#define _MACHINE_DEBUG_MONITOR_H_
|
||||
|
||||
#ifdef KDB
|
||||
#ifdef DDB
|
||||
|
||||
#include <machine/db_machdep.h>
|
||||
|
||||
|
@ -368,7 +368,7 @@ net_print(int verbose)
|
||||
uint32_t
|
||||
net_parse_rootpath()
|
||||
{
|
||||
int i, ipstart;
|
||||
int i;
|
||||
n_long addr = INADDR_NONE;
|
||||
|
||||
netproto = NET_NFS;
|
||||
@ -383,7 +383,7 @@ net_parse_rootpath()
|
||||
break;
|
||||
if (i && i != FNAME_SIZE && rootpath[i] == ':') {
|
||||
rootpath[i++] = '\0';
|
||||
addr = inet_addr(&rootpath[ipstart]);
|
||||
addr = inet_addr(&rootpath[0]);
|
||||
bcopy(&rootpath[i], rootpath, strlen(&rootpath[i])+1);
|
||||
}
|
||||
|
||||
|
@ -97,21 +97,21 @@ static __inline uint8_t
|
||||
fsfind(const char *name, ufs_ino_t * ino)
|
||||
{
|
||||
static char buf[DEV_BSIZE];
|
||||
struct direct *d;
|
||||
static struct direct d;
|
||||
char *s;
|
||||
ssize_t n;
|
||||
|
||||
fs_off = 0;
|
||||
while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0)
|
||||
for (s = buf; s < buf + DEV_BSIZE;) {
|
||||
d = (void *)s;
|
||||
memcpy(&d, s, sizeof(struct direct));
|
||||
if (ls)
|
||||
printf("%s ", d->d_name);
|
||||
else if (!strcmp(name, d->d_name)) {
|
||||
*ino = d->d_ino;
|
||||
return d->d_type;
|
||||
printf("%s ", d.d_name);
|
||||
else if (!strcmp(name, d.d_name)) {
|
||||
*ino = d.d_ino;
|
||||
return d.d_type;
|
||||
}
|
||||
s += d->d_reclen;
|
||||
s += d.d_reclen;
|
||||
}
|
||||
if (n != -1 && ls)
|
||||
printf("\n");
|
||||
|
@ -19,7 +19,7 @@ SECTIONS
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.plt)
|
||||
} =0x00300000010070000002000001000400
|
||||
} =0xCC
|
||||
. = ALIGN(4096);
|
||||
.data : {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
|
@ -15,7 +15,7 @@ SECTIONS
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.plt)
|
||||
} =0x00300000010070000002000001000400
|
||||
} =0xD4200000
|
||||
. = ALIGN(16);
|
||||
.data : {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
|
@ -14,7 +14,7 @@ SECTIONS
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.plt)
|
||||
} =0x00300000010070000002000001000400
|
||||
} =0xCC
|
||||
. = ALIGN(4096);
|
||||
.data : {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
|
@ -432,8 +432,8 @@ callout_callback(struct callout *c)
|
||||
}
|
||||
mtx_unlock(&mtx_callout);
|
||||
|
||||
if (c->func)
|
||||
(c->func) (c->arg);
|
||||
if (c->c_func != NULL)
|
||||
(c->c_func) (c->c_arg);
|
||||
|
||||
if (!(c->flags & CALLOUT_RETURNUNLOCKED))
|
||||
mtx_unlock(c->mtx);
|
||||
@ -487,8 +487,8 @@ callout_reset(struct callout *c, int to_ticks,
|
||||
{
|
||||
callout_stop(c);
|
||||
|
||||
c->func = func;
|
||||
c->arg = arg;
|
||||
c->c_func = func;
|
||||
c->c_arg = arg;
|
||||
c->timeout = ticks + to_ticks;
|
||||
|
||||
mtx_lock(&mtx_callout);
|
||||
@ -507,8 +507,8 @@ callout_stop(struct callout *c)
|
||||
}
|
||||
mtx_unlock(&mtx_callout);
|
||||
|
||||
c->func = NULL;
|
||||
c->arg = NULL;
|
||||
c->c_func = NULL;
|
||||
c->c_arg = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -299,8 +299,8 @@ extern volatile int ticks;
|
||||
|
||||
struct callout {
|
||||
LIST_ENTRY(callout) entry;
|
||||
callout_fn_t *func;
|
||||
void *arg;
|
||||
callout_fn_t *c_func;
|
||||
void *c_arg;
|
||||
struct mtx *mtx;
|
||||
int flags;
|
||||
int timeout;
|
||||
|
@ -187,21 +187,18 @@ lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
|
||||
defined(__amd64) || defined(__ppc64__) || defined(_WIN64) || \
|
||||
defined(__LP64__) || defined(_LP64))
|
||||
#define LZ4_ARCH64 1
|
||||
#else
|
||||
#define LZ4_ARCH64 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Illumos: On amd64 we have 20k of stack and 24k on sun4u and sun4v, so we
|
||||
* can spend 16k on the algorithm
|
||||
* Limits the amount of stack space that the algorithm may consume to hold
|
||||
* the compression lookup table. The value `9' here means we'll never use
|
||||
* more than 2k of stack (see above for a description of COMPRESSIONLEVEL).
|
||||
* If more memory is needed, it is allocated from the heap.
|
||||
*/
|
||||
/* FreeBSD: Use heap for all platforms for now */
|
||||
#define STACKLIMIT 0
|
||||
#else
|
||||
#define LZ4_ARCH64 0
|
||||
/*
|
||||
* Illumos: On i386 we only have 12k of stack, so in order to maintain the
|
||||
* same COMPRESSIONLEVEL we have to use heap allocation. Performance will
|
||||
* suck, but alas, it's ZFS on 32-bit we're talking about, so...
|
||||
*/
|
||||
#define STACKLIMIT 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Little Endian or Big Endian?
|
||||
@ -870,7 +867,7 @@ real_LZ4_compress(const char *source, char *dest, int isize, int osize)
|
||||
/* Decompression functions */
|
||||
|
||||
/*
|
||||
* Note: The decoding functionLZ4_uncompress_unknownOutputSize() is safe
|
||||
* Note: The decoding function LZ4_uncompress_unknownOutputSize() is safe
|
||||
* against "buffer overflow" attack type. They will never write nor
|
||||
* read outside of the provided output buffers.
|
||||
* LZ4_uncompress_unknownOutputSize() also insures that it will never
|
||||
@ -913,6 +910,9 @@ LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize,
|
||||
}
|
||||
/* copy literals */
|
||||
cpy = op + length;
|
||||
/* CORNER-CASE: cpy might overflow. */
|
||||
if (cpy < op)
|
||||
goto _output_error; /* cpy was overflowed, bail! */
|
||||
if ((cpy > oend - COPYLENGTH) ||
|
||||
(ip + length > iend - COPYLENGTH)) {
|
||||
if (cpy > oend)
|
||||
|
@ -144,12 +144,10 @@ linprocfs_domeminfo(PFS_FILL_ARGS)
|
||||
unsigned long memtotal; /* total memory in bytes */
|
||||
unsigned long memused; /* used memory in bytes */
|
||||
unsigned long memfree; /* free memory in bytes */
|
||||
unsigned long memshared; /* shared memory ??? */
|
||||
unsigned long buffers, cached; /* buffer / cache memory ??? */
|
||||
unsigned long long swaptotal; /* total swap space in bytes */
|
||||
unsigned long long swapused; /* used swap space in bytes */
|
||||
unsigned long long swapfree; /* free swap space in bytes */
|
||||
vm_object_t object;
|
||||
int i, j;
|
||||
|
||||
memtotal = physmem * PAGE_SIZE;
|
||||
@ -169,13 +167,6 @@ linprocfs_domeminfo(PFS_FILL_ARGS)
|
||||
swaptotal = (unsigned long long)i * PAGE_SIZE;
|
||||
swapused = (unsigned long long)j * PAGE_SIZE;
|
||||
swapfree = swaptotal - swapused;
|
||||
memshared = 0;
|
||||
mtx_lock(&vm_object_list_mtx);
|
||||
TAILQ_FOREACH(object, &vm_object_list, object_list)
|
||||
if (object->shadow_count > 1)
|
||||
memshared += object->resident_page_count;
|
||||
mtx_unlock(&vm_object_list_mtx);
|
||||
memshared *= PAGE_SIZE;
|
||||
/*
|
||||
* We'd love to be able to write:
|
||||
*
|
||||
@ -188,21 +179,14 @@ linprocfs_domeminfo(PFS_FILL_ARGS)
|
||||
cached = vm_cnt.v_cache_count * PAGE_SIZE;
|
||||
|
||||
sbuf_printf(sb,
|
||||
" total: used: free: shared: buffers: cached:\n"
|
||||
"Mem: %lu %lu %lu %lu %lu %lu\n"
|
||||
"Swap: %llu %llu %llu\n"
|
||||
"MemTotal: %9lu kB\n"
|
||||
"MemFree: %9lu kB\n"
|
||||
"MemShared:%9lu kB\n"
|
||||
"Buffers: %9lu kB\n"
|
||||
"Cached: %9lu kB\n"
|
||||
"SwapTotal:%9llu kB\n"
|
||||
"SwapFree: %9llu kB\n",
|
||||
memtotal, memused, memfree, memshared, buffers, cached,
|
||||
swaptotal, swapused, swapfree,
|
||||
B2K(memtotal), B2K(memfree),
|
||||
B2K(memshared), B2K(buffers), B2K(cached),
|
||||
B2K(swaptotal), B2K(swapfree));
|
||||
B2K(memtotal), B2K(memfree), B2K(buffers),
|
||||
B2K(cached), B2K(swaptotal), B2K(swapfree));
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -218,7 +202,7 @@ linprocfs_docpuinfo(PFS_FILL_ARGS)
|
||||
char model[128];
|
||||
uint64_t freq;
|
||||
size_t size;
|
||||
int class, fqmhz, fqkhz;
|
||||
int fqmhz, fqkhz;
|
||||
int i;
|
||||
|
||||
/*
|
||||
@ -235,33 +219,6 @@ linprocfs_docpuinfo(PFS_FILL_ARGS)
|
||||
"3dnowext", "3dnow"
|
||||
};
|
||||
|
||||
switch (cpu_class) {
|
||||
#ifdef __i386__
|
||||
case CPUCLASS_286:
|
||||
class = 2;
|
||||
break;
|
||||
case CPUCLASS_386:
|
||||
class = 3;
|
||||
break;
|
||||
case CPUCLASS_486:
|
||||
class = 4;
|
||||
break;
|
||||
case CPUCLASS_586:
|
||||
class = 5;
|
||||
break;
|
||||
case CPUCLASS_686:
|
||||
class = 6;
|
||||
break;
|
||||
default:
|
||||
class = 0;
|
||||
break;
|
||||
#else /* __amd64__ */
|
||||
default:
|
||||
class = 15;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
hw_model[0] = CTL_HW;
|
||||
hw_model[1] = HW_MODEL;
|
||||
model[0] = '\0';
|
||||
@ -286,7 +243,7 @@ linprocfs_docpuinfo(PFS_FILL_ARGS)
|
||||
#ifdef __i386__
|
||||
switch (cpu_vendor_id) {
|
||||
case CPU_VENDOR_AMD:
|
||||
if (class < 6)
|
||||
if (cpu_class < CPUCLASS_686)
|
||||
flags[16] = "fcmov";
|
||||
break;
|
||||
case CPU_VENDOR_CYRIX:
|
||||
|
@ -3052,3 +3052,8 @@ options GZIO
|
||||
|
||||
# BHND(4) drivers
|
||||
options BHND_LOGLEVEL # Logging threshold level
|
||||
|
||||
# evdev interface
|
||||
options EVDEV
|
||||
options EVDEV_DEBUG
|
||||
options UINPUT_DEBUG
|
||||
|
@ -1501,6 +1501,11 @@ dev/etherswitch/ip17x/ip17x_vlans.c optional ip17x
|
||||
dev/etherswitch/miiproxy.c optional miiproxy
|
||||
dev/etherswitch/rtl8366/rtl8366rb.c optional rtl8366rb
|
||||
dev/etherswitch/ukswitch/ukswitch.c optional ukswitch
|
||||
dev/evdev/cdev.c optional evdev
|
||||
dev/evdev/evdev.c optional evdev
|
||||
dev/evdev/evdev_mt.c optional evdev
|
||||
dev/evdev/evdev_utils.c optional evdev
|
||||
dev/evdev/uinput.c optional evdev uinput
|
||||
dev/ex/if_ex.c optional ex
|
||||
dev/ex/if_ex_isa.c optional ex isa
|
||||
dev/ex/if_ex_pccard.c optional ex pccard
|
||||
|
@ -62,7 +62,7 @@ arm64/arm64/cpufunc_asm.S standard
|
||||
arm64/arm64/db_disasm.c optional ddb
|
||||
arm64/arm64/db_interface.c optional ddb
|
||||
arm64/arm64/db_trace.c optional ddb
|
||||
arm64/arm64/debug_monitor.c optional kdb
|
||||
arm64/arm64/debug_monitor.c optional ddb
|
||||
arm64/arm64/disassem.c optional ddb
|
||||
arm64/arm64/dump_machdep.c standard
|
||||
arm64/arm64/elf_machdep.c standard
|
||||
|
@ -987,3 +987,8 @@ BHND_LOGLEVEL opt_global.h
|
||||
|
||||
# GPIO and child devices
|
||||
GPIO_SPI_DEBUG opt_gpio.h
|
||||
|
||||
# evdev protocol support
|
||||
EVDEV opt_evdev.h
|
||||
EVDEV_DEBUG opt_evdev.h
|
||||
UINPUT_DEBUG opt_evdev.h
|
||||
|
@ -2339,7 +2339,9 @@ ar9300_attach(u_int16_t devid, HAL_SOFTC sc, HAL_BUS_TAG st,
|
||||
} else {
|
||||
ar9300_disable_pcie_phy(ah);
|
||||
}
|
||||
#if 0
|
||||
ath_hal_printf(ah, "%s: calling ar9300_hw_attach\n", __func__);
|
||||
#endif
|
||||
ecode = ar9300_hw_attach(ah);
|
||||
if (ecode != HAL_OK) {
|
||||
goto bad;
|
||||
@ -3234,7 +3236,9 @@ ar9300_hw_attach(struct ath_hal *ah)
|
||||
return HAL_ESELFTEST;
|
||||
}
|
||||
|
||||
#if 0
|
||||
ath_hal_printf(ah, "%s: calling ar9300_eeprom_attach\n", __func__);
|
||||
#endif
|
||||
ecode = ar9300_eeprom_attach(ah);
|
||||
ath_hal_printf(ah, "%s: ar9300_eeprom_attach returned %d\n", __func__, ecode);
|
||||
if (ecode != HAL_OK) {
|
||||
|
@ -3226,7 +3226,7 @@ ipf_check(ctx, ip, hlen, ifp, out
|
||||
fdp = fin->fin_dif;
|
||||
if ((fdp != NULL) && (fdp->fd_ptr != NULL) &&
|
||||
(fdp->fd_ptr != (void *)-1)) {
|
||||
mc = M_COPY(fin->fin_m);
|
||||
mc = M_COPYM(fin->fin_m);
|
||||
if (mc != NULL)
|
||||
ipf_fastroute(mc, &mc, fin, fdp);
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ struct ether_addr {
|
||||
# define MSGDSIZE(m) mbufchainlen(m)
|
||||
# define M_LEN(m) (m)->m_len
|
||||
# define M_ADJ(m,x) m_adj(m, x)
|
||||
# define M_COPY(x) m_copy((x), 0, M_COPYALL)
|
||||
# define M_COPYM(x) m_copym((x), 0, M_COPYALL, M_NOWAIT)
|
||||
# define M_DUP(m) m_dup(m, M_NOWAIT)
|
||||
# define IPF_PANIC(x,y) if (x) { printf y; panic("ipf_panic"); }
|
||||
typedef struct mbuf mb_t;
|
||||
@ -366,7 +366,7 @@ typedef struct mb_s {
|
||||
# define MSGDSIZE(m) msgdsize(m)
|
||||
# define M_LEN(m) (m)->mb_len
|
||||
# define M_ADJ(m,x) (m)->mb_len += x
|
||||
# define M_COPY(m) dupmbt(m)
|
||||
# define M_COPYM(m) dupmbt(m)
|
||||
# define M_DUP(m) dupmbt(m)
|
||||
# define GETKTIME(x) gettimeofday((struct timeval *)(x), NULL)
|
||||
# define MTOD(m, t) ((t)(m)->mb_data)
|
||||
|
@ -920,7 +920,7 @@ ipf_fastroute(m0, mpp, fin, fdp)
|
||||
mhip->ip_off |= IP_MF;
|
||||
mhip->ip_len = htons((u_short)(len + mhlen));
|
||||
*mnext = m;
|
||||
m->m_next = m_copy(m0, off, len);
|
||||
m->m_next = m_copym(m0, off, len, M_NOWAIT);
|
||||
if (m->m_next == 0) {
|
||||
error = ENOBUFS; /* ??? */
|
||||
goto sendorfree;
|
||||
|
@ -48,15 +48,15 @@ __FBSDID("$FreeBSD$");
|
||||
#include <ddb/db_break.h>
|
||||
#include <ddb/db_access.h>
|
||||
|
||||
static int db_run_mode;
|
||||
#define STEP_NONE 0
|
||||
#define STEP_ONCE 1
|
||||
#define STEP_RETURN 2
|
||||
#define STEP_CALLT 3
|
||||
#define STEP_CONTINUE 4
|
||||
#define STEP_INVISIBLE 5
|
||||
#define STEP_COUNT 6
|
||||
static int db_run_mode = STEP_CONTINUE;
|
||||
|
||||
static bool db_sstep_multiple;
|
||||
static bool db_sstep_print;
|
||||
static int db_loop_count;
|
||||
static int db_call_depth;
|
||||
@ -133,7 +133,24 @@ db_stop_at_pc(int type, int code, bool *is_breakpoint, bool *is_watchpoint)
|
||||
#endif
|
||||
}
|
||||
|
||||
*is_breakpoint = false;
|
||||
*is_breakpoint = false; /* might be a breakpoint, but not ours */
|
||||
|
||||
/*
|
||||
* If stepping, then abort if the trap type is unexpected.
|
||||
* Breakpoints owned by us are expected and were handled above.
|
||||
* Single-steps are expected and are handled below. All others
|
||||
* are unexpected.
|
||||
*
|
||||
* If the MD layer doesn't tell us when it is stepping, use the
|
||||
* bad historical default that all unexepected traps.
|
||||
*/
|
||||
#ifndef IS_SSTEP_TRAP
|
||||
#define IS_SSTEP_TRAP(type, code) true
|
||||
#endif
|
||||
if (db_run_mode != STEP_CONTINUE && !IS_SSTEP_TRAP(type, code)) {
|
||||
printf("Stepping aborted\n");
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (db_run_mode == STEP_INVISIBLE) {
|
||||
db_run_mode = STEP_CONTINUE;
|
||||
@ -184,7 +201,6 @@ db_stop_at_pc(int type, int code, bool *is_breakpoint, bool *is_watchpoint)
|
||||
return (false); /* continue */
|
||||
}
|
||||
}
|
||||
db_run_mode = STEP_NONE;
|
||||
return (true);
|
||||
}
|
||||
|
||||
@ -194,6 +210,7 @@ db_restart_at_pc(bool watchpt)
|
||||
db_addr_t pc = PC_REGS();
|
||||
|
||||
if ((db_run_mode == STEP_COUNT) ||
|
||||
((db_run_mode == STEP_ONCE) && db_sstep_multiple) ||
|
||||
(db_run_mode == STEP_RETURN) ||
|
||||
(db_run_mode == STEP_CALLT)) {
|
||||
/*
|
||||
@ -321,6 +338,7 @@ db_single_step_cmd(db_expr_t addr, bool have_addr, db_expr_t count, char *modif)
|
||||
|
||||
db_run_mode = STEP_ONCE;
|
||||
db_loop_count = count;
|
||||
db_sstep_multiple = (count != 1);
|
||||
db_sstep_print = print;
|
||||
db_inst_count = 0;
|
||||
db_load_count = 0;
|
||||
|
@ -1042,6 +1042,14 @@ ath_tx_calc_protection(struct ath_softc *sc, struct ath_buf *bf)
|
||||
shortPreamble = bf->bf_state.bfs_shpream;
|
||||
wh = mtod(bf->bf_m, struct ieee80211_frame *);
|
||||
|
||||
/* Disable frame protection for TOA probe frames */
|
||||
if (bf->bf_flags & ATH_BUF_TOA_PROBE) {
|
||||
/* XXX count */
|
||||
flags &= ~(HAL_TXDESC_CTSENA | HAL_TXDESC_RTSENA);
|
||||
bf->bf_state.bfs_doprot = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/*
|
||||
* If 802.11g protection is enabled, determine whether
|
||||
* to use RTS/CTS or just CTS. Note that this is only
|
||||
@ -1081,6 +1089,8 @@ ath_tx_calc_protection(struct ath_softc *sc, struct ath_buf *bf)
|
||||
flags |= HAL_TXDESC_RTSENA;
|
||||
sc->sc_stats.ast_tx_htprotect++;
|
||||
}
|
||||
|
||||
finish:
|
||||
bf->bf_state.bfs_txflags = flags;
|
||||
}
|
||||
|
||||
@ -1739,6 +1749,34 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If it's a frame to do location reporting on,
|
||||
* communicate it to the HAL.
|
||||
*/
|
||||
if (ieee80211_get_toa_params(m0, NULL)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: setting TX positioning bit\n", __func__);
|
||||
flags |= HAL_TXDESC_POS;
|
||||
|
||||
/*
|
||||
* Note: The hardware reports timestamps for
|
||||
* each of the RX'ed packets as part of the packet
|
||||
* exchange. So this means things like RTS/CTS
|
||||
* exchanges, as well as the final ACK.
|
||||
*
|
||||
* So, if you send a RTS-protected NULL data frame,
|
||||
* you'll get an RX report for the RTS response, then
|
||||
* an RX report for the NULL frame, and then the TX
|
||||
* completion at the end.
|
||||
*
|
||||
* NOTE: it doesn't work right for CCK frames;
|
||||
* there's no channel info data provided unless
|
||||
* it's OFDM or HT. Will have to dig into it.
|
||||
*/
|
||||
flags &= ~(HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
|
||||
bf->bf_flags |= ATH_BUF_TOA_PROBE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Placeholder: if you want to transmit with the azimuth
|
||||
@ -2175,6 +2213,18 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
try0 = ATH_TXMAXTRY; /* XXX?too many? */
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's a frame to do location reporting on,
|
||||
* communicate it to the HAL.
|
||||
*/
|
||||
if (ieee80211_get_toa_params(m0, NULL)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: setting TX positioning bit\n", __func__);
|
||||
flags |= HAL_TXDESC_POS;
|
||||
flags &= ~(HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
|
||||
bf->bf_flags |= ATH_BUF_TOA_PROBE;
|
||||
}
|
||||
|
||||
txrate = rt->info[rix].rateCode;
|
||||
if (params->ibp_flags & IEEE80211_BPF_SHORTPRE)
|
||||
txrate |= rt->info[rix].shortPreamble;
|
||||
|
@ -268,7 +268,7 @@ ath_tx_edma_push_staging_list(struct ath_softc *sc, struct ath_txq *txq,
|
||||
|
||||
/* Bump FIFO queue */
|
||||
txq->axq_fifo_depth++;
|
||||
DPRINTF(sc, ATH_DEBUG_XMIT,
|
||||
DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_TX_PROC,
|
||||
"%s: queued %d packets; depth=%d, fifo depth=%d\n",
|
||||
__func__, sqdepth, txq->fifo.axq_depth, txq->axq_fifo_depth);
|
||||
|
||||
@ -296,16 +296,21 @@ ath_edma_tx_fifo_fill(struct ath_softc *sc, struct ath_txq *txq)
|
||||
|
||||
ATH_TXQ_LOCK_ASSERT(txq);
|
||||
|
||||
DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s: Q%d: called\n",
|
||||
DPRINTF(sc, ATH_DEBUG_TX_PROC,
|
||||
"%s: Q%d: called; fifo.depth=%d, fifo depth=%d, depth=%d, aggr_depth=%d\n",
|
||||
__func__,
|
||||
txq->axq_qnum);
|
||||
txq->axq_qnum,
|
||||
txq->fifo.axq_depth,
|
||||
txq->axq_fifo_depth,
|
||||
txq->axq_depth,
|
||||
txq->axq_aggr_depth);
|
||||
|
||||
/*
|
||||
* For now, push up to 4 frames per TX FIFO slot.
|
||||
* For now, push up to 32 frames per TX FIFO slot.
|
||||
* If more are in the hardware queue then they'll
|
||||
* get populated when we try to send another frame
|
||||
* or complete a frame - so at most there'll be
|
||||
* 32 non-AMPDU frames per TXQ.
|
||||
* 32 non-AMPDU frames per node/TID anyway.
|
||||
*
|
||||
* Note that the hardware staging queue will limit
|
||||
* how many frames in total we will have pushed into
|
||||
@ -811,10 +816,11 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched)
|
||||
}
|
||||
|
||||
#if defined(ATH_DEBUG_ALQ) && defined(ATH_DEBUG)
|
||||
if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_EDMA_TXSTATUS))
|
||||
if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_EDMA_TXSTATUS)) {
|
||||
if_ath_alq_post(&sc->sc_alq, ATH_ALQ_EDMA_TXSTATUS,
|
||||
sc->sc_tx_statuslen,
|
||||
(char *) txstatus);
|
||||
}
|
||||
#endif /* ATH_DEBUG_ALQ */
|
||||
|
||||
/*
|
||||
|
@ -752,10 +752,20 @@ struct sge {
|
||||
struct hw_buf_info hw_buf_info[SGE_FLBUF_SIZES];
|
||||
};
|
||||
|
||||
struct devnames {
|
||||
const char *nexus_name;
|
||||
const char *ifnet_name;
|
||||
const char *vi_ifnet_name;
|
||||
const char *pf03_drv_name;
|
||||
const char *vf_nexus_name;
|
||||
const char *vf_ifnet_name;
|
||||
};
|
||||
|
||||
struct adapter {
|
||||
SLIST_ENTRY(adapter) link;
|
||||
device_t dev;
|
||||
struct cdev *cdev;
|
||||
const struct devnames *names;
|
||||
|
||||
/* PCIe register resources */
|
||||
int regs_rid;
|
||||
@ -835,7 +845,7 @@ struct adapter {
|
||||
uint16_t niccaps;
|
||||
uint16_t toecaps;
|
||||
uint16_t rdmacaps;
|
||||
uint16_t tlscaps;
|
||||
uint16_t cryptocaps;
|
||||
uint16_t iscsicaps;
|
||||
uint16_t fcoecaps;
|
||||
|
||||
@ -1039,6 +1049,13 @@ is_10G_port(const struct port_info *pi)
|
||||
return ((pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G) != 0);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_25G_port(const struct port_info *pi)
|
||||
{
|
||||
|
||||
return ((pi->link_cfg.supported & FW_PORT_CAP_SPEED_25G) != 0);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_40G_port(const struct port_info *pi)
|
||||
{
|
||||
@ -1046,6 +1063,13 @@ is_40G_port(const struct port_info *pi)
|
||||
return ((pi->link_cfg.supported & FW_PORT_CAP_SPEED_40G) != 0);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_100G_port(const struct port_info *pi)
|
||||
{
|
||||
|
||||
return ((pi->link_cfg.supported & FW_PORT_CAP_SPEED_100G) != 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
port_top_speed(const struct port_info *pi)
|
||||
{
|
||||
@ -1054,6 +1078,8 @@ port_top_speed(const struct port_info *pi)
|
||||
return (100);
|
||||
if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_40G)
|
||||
return (40);
|
||||
if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_25G)
|
||||
return (25);
|
||||
if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G)
|
||||
return (10);
|
||||
if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_1G)
|
||||
@ -1101,6 +1127,7 @@ int t4_os_pci_restore_state(struct adapter *);
|
||||
void t4_os_portmod_changed(const struct adapter *, int);
|
||||
void t4_os_link_changed(struct adapter *, int, int, int);
|
||||
void t4_iterate(void (*)(struct adapter *, void *), void *);
|
||||
void t4_init_devnames(struct adapter *);
|
||||
void t4_add_adapter(struct adapter *);
|
||||
int t4_detach_common(device_t);
|
||||
int t4_filter_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *);
|
||||
|
@ -3669,8 +3669,9 @@ void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf)
|
||||
}
|
||||
|
||||
#define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\
|
||||
FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G | \
|
||||
FW_PORT_CAP_SPEED_100G | FW_PORT_CAP_ANEG)
|
||||
FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_25G | \
|
||||
FW_PORT_CAP_SPEED_40G | FW_PORT_CAP_SPEED_100G | \
|
||||
FW_PORT_CAP_ANEG)
|
||||
|
||||
/**
|
||||
* t4_link_l1cfg - apply link configuration to MAC/PHY
|
||||
@ -5775,6 +5776,11 @@ const char *t4_get_port_type_description(enum fw_port_type port_type)
|
||||
"QSA",
|
||||
"QSFP",
|
||||
"BP40_BA",
|
||||
"KR4_100G",
|
||||
"CR4_QSFP",
|
||||
"CR_QSFP",
|
||||
"CR2_QSFP",
|
||||
"SFP28",
|
||||
};
|
||||
|
||||
if (port_type < ARRAY_SIZE(port_type_description))
|
||||
@ -7462,8 +7468,12 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
|
||||
speed = 1000;
|
||||
else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
|
||||
speed = 10000;
|
||||
else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_25G))
|
||||
speed = 25000;
|
||||
else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G))
|
||||
speed = 40000;
|
||||
else if (stat & V_FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100G))
|
||||
speed = 100000;
|
||||
|
||||
for_each_port(adap, i) {
|
||||
pi = adap2pinfo(adap, i);
|
||||
@ -7866,8 +7876,10 @@ int t4_init_sge_params(struct adapter *adapter)
|
||||
sp->fl_starve_threshold = G_EGRTHRESHOLD(r) * 2 + 1;
|
||||
if (is_t4(adapter))
|
||||
sp->fl_starve_threshold2 = sp->fl_starve_threshold;
|
||||
else
|
||||
else if (is_t5(adapter))
|
||||
sp->fl_starve_threshold2 = G_EGRTHRESHOLDPACKING(r) * 2 + 1;
|
||||
else
|
||||
sp->fl_starve_threshold2 = G_T6_EGRTHRESHOLDPACKING(r) * 2 + 1;
|
||||
|
||||
/* egress queues: log2 of # of doorbells per BAR2 page */
|
||||
r = t4_read_reg(adapter, A_SGE_EGRESS_QUEUES_PER_PAGE_PF);
|
||||
@ -7890,7 +7902,13 @@ int t4_init_sge_params(struct adapter *adapter)
|
||||
sp->sge_control = r;
|
||||
sp->spg_len = r & F_EGRSTATUSPAGESIZE ? 128 : 64;
|
||||
sp->fl_pktshift = G_PKTSHIFT(r);
|
||||
sp->pad_boundary = 1 << (G_INGPADBOUNDARY(r) + 5);
|
||||
if (chip_id(adapter) <= CHELSIO_T5) {
|
||||
sp->pad_boundary = 1 << (G_INGPADBOUNDARY(r) +
|
||||
X_INGPADBOUNDARY_SHIFT);
|
||||
} else {
|
||||
sp->pad_boundary = 1 << (G_INGPADBOUNDARY(r) +
|
||||
X_T6_INGPADBOUNDARY_SHIFT);
|
||||
}
|
||||
if (is_t4(adapter))
|
||||
sp->pack_boundary = sp->pad_boundary;
|
||||
else {
|
||||
|
@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "common.h"
|
||||
#include "t4_regs.h"
|
||||
#include "t4_regs_values.h"
|
||||
|
||||
#undef msleep
|
||||
#define msleep(x) do { \
|
||||
@ -130,9 +131,10 @@ int t4vf_get_sge_params(struct adapter *adapter)
|
||||
sp->fl_starve_threshold = G_EGRTHRESHOLD(vals[5]) * 2 + 1;
|
||||
if (is_t4(adapter))
|
||||
sp->fl_starve_threshold2 = sp->fl_starve_threshold;
|
||||
else if (is_t5(adapter))
|
||||
sp->fl_starve_threshold2 = G_EGRTHRESHOLDPACKING(vals[5]) * 2 + 1;
|
||||
else
|
||||
sp->fl_starve_threshold2 = G_EGRTHRESHOLDPACKING(vals[5]) * 2 +
|
||||
1;
|
||||
sp->fl_starve_threshold2 = G_T6_EGRTHRESHOLDPACKING(vals[5]) * 2 + 1;
|
||||
|
||||
/*
|
||||
* We need the Queues/Page and Host Page Size for our VF.
|
||||
@ -168,7 +170,13 @@ int t4vf_get_sge_params(struct adapter *adapter)
|
||||
*/
|
||||
sp->spg_len = sp->sge_control & F_EGRSTATUSPAGESIZE ? 128 : 64;
|
||||
sp->fl_pktshift = G_PKTSHIFT(sp->sge_control);
|
||||
sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) + 5);
|
||||
if (chip_id(adapter) <= CHELSIO_T5) {
|
||||
sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) +
|
||||
X_INGPADBOUNDARY_SHIFT);
|
||||
} else {
|
||||
sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) +
|
||||
X_T6_INGPADBOUNDARY_SHIFT);
|
||||
}
|
||||
if (is_t4(adapter))
|
||||
sp->pack_boundary = sp->pad_boundary;
|
||||
else {
|
||||
|
@ -135,7 +135,9 @@ enum fw_wr_opcodes {
|
||||
FW_POFCOE_ULPTX_WR = 0x43,
|
||||
FW_ISCSI_TX_DATA_WR = 0x45,
|
||||
FW_PTP_TX_PKT_WR = 0x46,
|
||||
FW_SEC_LOOKASIDE_LPBK_WR= 0x6d,
|
||||
FW_TLSTX_DATA_WR = 0x68,
|
||||
FW_TLS_KEYCTX_TX_WR = 0x69,
|
||||
FW_CRYPTO_LOOKASIDE_WR = 0x6d,
|
||||
FW_COiSCSI_TGT_WR = 0x70,
|
||||
FW_COiSCSI_TGT_CONN_WR = 0x71,
|
||||
FW_COiSCSI_TGT_XMIT_WR = 0x72,
|
||||
@ -3384,8 +3386,429 @@ struct fw_pi_error {
|
||||
#define G_FW_PI_ERROR_ERR_TYPE(x) \
|
||||
(((x) >> S_FW_PI_ERROR_ERR_TYPE) & M_FW_PI_ERROR_ERR_TYPE)
|
||||
|
||||
struct fw_tlstx_data_wr {
|
||||
__be32 op_to_immdlen;
|
||||
__be32 flowid_len16;
|
||||
__be32 plen;
|
||||
__be32 lsodisable_to_flags;
|
||||
__be32 ddraddr;
|
||||
__be32 ctxloc_to_exp;
|
||||
__be16 mfs;
|
||||
__u8 r6[6];
|
||||
};
|
||||
|
||||
struct fw_sec_lookaside_lpbk_wr {
|
||||
#define S_FW_TLSTX_DATA_WR_COMPL 21
|
||||
#define M_FW_TLSTX_DATA_WR_COMPL 0x1
|
||||
#define V_FW_TLSTX_DATA_WR_COMPL(x) ((x) << S_FW_TLSTX_DATA_WR_COMPL)
|
||||
#define G_FW_TLSTX_DATA_WR_COMPL(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_COMPL) & M_FW_TLSTX_DATA_WR_COMPL)
|
||||
#define F_FW_TLSTX_DATA_WR_COMPL V_FW_TLSTX_DATA_WR_COMPL(1U)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_IMMDLEN 0
|
||||
#define M_FW_TLSTX_DATA_WR_IMMDLEN 0xff
|
||||
#define V_FW_TLSTX_DATA_WR_IMMDLEN(x) ((x) << S_FW_TLSTX_DATA_WR_IMMDLEN)
|
||||
#define G_FW_TLSTX_DATA_WR_IMMDLEN(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_IMMDLEN) & M_FW_TLSTX_DATA_WR_IMMDLEN)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_FLOWID 8
|
||||
#define M_FW_TLSTX_DATA_WR_FLOWID 0xfffff
|
||||
#define V_FW_TLSTX_DATA_WR_FLOWID(x) ((x) << S_FW_TLSTX_DATA_WR_FLOWID)
|
||||
#define G_FW_TLSTX_DATA_WR_FLOWID(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_FLOWID) & M_FW_TLSTX_DATA_WR_FLOWID)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_LEN16 0
|
||||
#define M_FW_TLSTX_DATA_WR_LEN16 0xff
|
||||
#define V_FW_TLSTX_DATA_WR_LEN16(x) ((x) << S_FW_TLSTX_DATA_WR_LEN16)
|
||||
#define G_FW_TLSTX_DATA_WR_LEN16(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_LEN16) & M_FW_TLSTX_DATA_WR_LEN16)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_LSODISABLE 31
|
||||
#define M_FW_TLSTX_DATA_WR_LSODISABLE 0x1
|
||||
#define V_FW_TLSTX_DATA_WR_LSODISABLE(x) \
|
||||
((x) << S_FW_TLSTX_DATA_WR_LSODISABLE)
|
||||
#define G_FW_TLSTX_DATA_WR_LSODISABLE(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_LSODISABLE) & M_FW_TLSTX_DATA_WR_LSODISABLE)
|
||||
#define F_FW_TLSTX_DATA_WR_LSODISABLE V_FW_TLSTX_DATA_WR_LSODISABLE(1U)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_ALIGNPLD 30
|
||||
#define M_FW_TLSTX_DATA_WR_ALIGNPLD 0x1
|
||||
#define V_FW_TLSTX_DATA_WR_ALIGNPLD(x) ((x) << S_FW_TLSTX_DATA_WR_ALIGNPLD)
|
||||
#define G_FW_TLSTX_DATA_WR_ALIGNPLD(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_ALIGNPLD) & M_FW_TLSTX_DATA_WR_ALIGNPLD)
|
||||
#define F_FW_TLSTX_DATA_WR_ALIGNPLD V_FW_TLSTX_DATA_WR_ALIGNPLD(1U)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_ALIGNPLDSHOVE 29
|
||||
#define M_FW_TLSTX_DATA_WR_ALIGNPLDSHOVE 0x1
|
||||
#define V_FW_TLSTX_DATA_WR_ALIGNPLDSHOVE(x) \
|
||||
((x) << S_FW_TLSTX_DATA_WR_ALIGNPLDSHOVE)
|
||||
#define G_FW_TLSTX_DATA_WR_ALIGNPLDSHOVE(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_ALIGNPLDSHOVE) & \
|
||||
M_FW_TLSTX_DATA_WR_ALIGNPLDSHOVE)
|
||||
#define F_FW_TLSTX_DATA_WR_ALIGNPLDSHOVE V_FW_TLSTX_DATA_WR_ALIGNPLDSHOVE(1U)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_FLAGS 0
|
||||
#define M_FW_TLSTX_DATA_WR_FLAGS 0xfffffff
|
||||
#define V_FW_TLSTX_DATA_WR_FLAGS(x) ((x) << S_FW_TLSTX_DATA_WR_FLAGS)
|
||||
#define G_FW_TLSTX_DATA_WR_FLAGS(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_FLAGS) & M_FW_TLSTX_DATA_WR_FLAGS)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_CTXLOC 30
|
||||
#define M_FW_TLSTX_DATA_WR_CTXLOC 0x3
|
||||
#define V_FW_TLSTX_DATA_WR_CTXLOC(x) ((x) << S_FW_TLSTX_DATA_WR_CTXLOC)
|
||||
#define G_FW_TLSTX_DATA_WR_CTXLOC(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_CTXLOC) & M_FW_TLSTX_DATA_WR_CTXLOC)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_IVDSGL 29
|
||||
#define M_FW_TLSTX_DATA_WR_IVDSGL 0x1
|
||||
#define V_FW_TLSTX_DATA_WR_IVDSGL(x) ((x) << S_FW_TLSTX_DATA_WR_IVDSGL)
|
||||
#define G_FW_TLSTX_DATA_WR_IVDSGL(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_IVDSGL) & M_FW_TLSTX_DATA_WR_IVDSGL)
|
||||
#define F_FW_TLSTX_DATA_WR_IVDSGL V_FW_TLSTX_DATA_WR_IVDSGL(1U)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_KEYSIZE 24
|
||||
#define M_FW_TLSTX_DATA_WR_KEYSIZE 0x1f
|
||||
#define V_FW_TLSTX_DATA_WR_KEYSIZE(x) ((x) << S_FW_TLSTX_DATA_WR_KEYSIZE)
|
||||
#define G_FW_TLSTX_DATA_WR_KEYSIZE(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_KEYSIZE) & M_FW_TLSTX_DATA_WR_KEYSIZE)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_NUMIVS 14
|
||||
#define M_FW_TLSTX_DATA_WR_NUMIVS 0xff
|
||||
#define V_FW_TLSTX_DATA_WR_NUMIVS(x) ((x) << S_FW_TLSTX_DATA_WR_NUMIVS)
|
||||
#define G_FW_TLSTX_DATA_WR_NUMIVS(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_NUMIVS) & M_FW_TLSTX_DATA_WR_NUMIVS)
|
||||
|
||||
#define S_FW_TLSTX_DATA_WR_EXP 0
|
||||
#define M_FW_TLSTX_DATA_WR_EXP 0x3fff
|
||||
#define V_FW_TLSTX_DATA_WR_EXP(x) ((x) << S_FW_TLSTX_DATA_WR_EXP)
|
||||
#define G_FW_TLSTX_DATA_WR_EXP(x) \
|
||||
(((x) >> S_FW_TLSTX_DATA_WR_EXP) & M_FW_TLSTX_DATA_WR_EXP)
|
||||
|
||||
struct fw_tls_keyctx_tx_wr {
|
||||
__be32 op_to_compl;
|
||||
__be32 flowid_len16;
|
||||
union fw_key_ctx {
|
||||
struct fw_tx_keyctx_hdr {
|
||||
__u8 ctxlen;
|
||||
__u8 r2;
|
||||
__be16 dualck_to_txvalid;
|
||||
__u8 txsalt[4];
|
||||
__be64 r5;
|
||||
} txhdr;
|
||||
struct fw_rx_keyctx_hdr {
|
||||
__u8 flitcnt_hmacctrl;
|
||||
__u8 protover_ciphmode;
|
||||
__u8 authmode_to_rxvalid;
|
||||
__u8 ivpresent_to_rxmk_size;
|
||||
__u8 rxsalt[4];
|
||||
__be64 ivinsert_to_authinsrt;
|
||||
} rxhdr;
|
||||
struct fw_keyctx_clear {
|
||||
__be32 tx_key;
|
||||
__be32 rx_key;
|
||||
} kctx_clr;
|
||||
} u;
|
||||
struct keys {
|
||||
__u8 edkey[32];
|
||||
__u8 ipad[64];
|
||||
__u8 opad[64];
|
||||
} keys;
|
||||
__u8 reneg_to_write_rx;
|
||||
__u8 protocol;
|
||||
__u8 r7[2];
|
||||
__be32 ftid;
|
||||
};
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_OPCODE 24
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_OPCODE 0xff
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_OPCODE(x) ((x) << S_FW_TLS_KEYCTX_TX_WR_OPCODE)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_OPCODE(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_OPCODE) & M_FW_TLS_KEYCTX_TX_WR_OPCODE)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_ATOMIC 23
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_ATOMIC 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_ATOMIC(x) ((x) << S_FW_TLS_KEYCTX_TX_WR_ATOMIC)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_ATOMIC(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_ATOMIC) & M_FW_TLS_KEYCTX_TX_WR_ATOMIC)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_ATOMIC V_FW_TLS_KEYCTX_TX_WR_ATOMIC(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_FLUSH 22
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_FLUSH 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_FLUSH(x) ((x) << S_FW_TLS_KEYCTX_TX_WR_FLUSH)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_FLUSH(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_FLUSH) & M_FW_TLS_KEYCTX_TX_WR_FLUSH)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_FLUSH V_FW_TLS_KEYCTX_TX_WR_FLUSH(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_COMPL 21
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_COMPL 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_COMPL(x) ((x) << S_FW_TLS_KEYCTX_TX_WR_COMPL)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_COMPL(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_COMPL) & M_FW_TLS_KEYCTX_TX_WR_COMPL)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_COMPL V_FW_TLS_KEYCTX_TX_WR_COMPL(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_FLOWID 8
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_FLOWID 0xfffff
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_FLOWID(x) ((x) << S_FW_TLS_KEYCTX_TX_WR_FLOWID)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_FLOWID(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_FLOWID) & M_FW_TLS_KEYCTX_TX_WR_FLOWID)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_LEN16 0
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_LEN16 0xff
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_LEN16(x) ((x) << S_FW_TLS_KEYCTX_TX_WR_LEN16)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_LEN16(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_LEN16) & M_FW_TLS_KEYCTX_TX_WR_LEN16)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_DUALCK 12
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_DUALCK 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_DUALCK(x) ((x) << S_FW_TLS_KEYCTX_TX_WR_DUALCK)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_DUALCK(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_DUALCK) & M_FW_TLS_KEYCTX_TX_WR_DUALCK)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_DUALCK V_FW_TLS_KEYCTX_TX_WR_DUALCK(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_TXOPAD_PRESENT 11
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_TXOPAD_PRESENT 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_TXOPAD_PRESENT(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_TXOPAD_PRESENT)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_TXOPAD_PRESENT(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_TXOPAD_PRESENT) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_TXOPAD_PRESENT)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_TXOPAD_PRESENT \
|
||||
V_FW_TLS_KEYCTX_TX_WR_TXOPAD_PRESENT(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_SALT_PRESENT 10
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_SALT_PRESENT 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_SALT_PRESENT(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_SALT_PRESENT)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_SALT_PRESENT(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_SALT_PRESENT) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_SALT_PRESENT)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_SALT_PRESENT \
|
||||
V_FW_TLS_KEYCTX_TX_WR_SALT_PRESENT(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_TXCK_SIZE 6
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_TXCK_SIZE 0xf
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_TXCK_SIZE(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_TXCK_SIZE)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_TXCK_SIZE(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_TXCK_SIZE) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_TXCK_SIZE)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_TXMK_SIZE 2
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_TXMK_SIZE 0xf
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_TXMK_SIZE(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_TXMK_SIZE)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_TXMK_SIZE(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_TXMK_SIZE) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_TXMK_SIZE)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_TXVALID 0
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_TXVALID 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_TXVALID(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_TXVALID)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_TXVALID(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_TXVALID) & M_FW_TLS_KEYCTX_TX_WR_TXVALID)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_TXVALID V_FW_TLS_KEYCTX_TX_WR_TXVALID(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_FLITCNT 3
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_FLITCNT 0x1f
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_FLITCNT(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_FLITCNT)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_FLITCNT(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_FLITCNT) & M_FW_TLS_KEYCTX_TX_WR_FLITCNT)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_HMACCTRL 0
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_HMACCTRL 0x7
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_HMACCTRL(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_HMACCTRL)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_HMACCTRL(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_HMACCTRL) & M_FW_TLS_KEYCTX_TX_WR_HMACCTRL)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_PROTOVER 4
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_PROTOVER 0xf
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_PROTOVER(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_PROTOVER)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_PROTOVER(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_PROTOVER) & M_FW_TLS_KEYCTX_TX_WR_PROTOVER)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_CIPHMODE 0
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_CIPHMODE 0xf
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_CIPHMODE(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_CIPHMODE)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_CIPHMODE(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_CIPHMODE) & M_FW_TLS_KEYCTX_TX_WR_CIPHMODE)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_AUTHMODE 4
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_AUTHMODE 0xf
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_AUTHMODE(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_AUTHMODE)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_AUTHMODE(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_AUTHMODE) & M_FW_TLS_KEYCTX_TX_WR_AUTHMODE)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_CIPHAUTHSEQCTRL 3
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_CIPHAUTHSEQCTRL 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_CIPHAUTHSEQCTRL(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_CIPHAUTHSEQCTRL)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_CIPHAUTHSEQCTRL(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_CIPHAUTHSEQCTRL) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_CIPHAUTHSEQCTRL)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_CIPHAUTHSEQCTRL \
|
||||
V_FW_TLS_KEYCTX_TX_WR_CIPHAUTHSEQCTRL(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_SEQNUMCTRL 1
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_SEQNUMCTRL 0x3
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_SEQNUMCTRL(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_SEQNUMCTRL)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_SEQNUMCTRL(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_SEQNUMCTRL) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_SEQNUMCTRL)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_RXVALID 0
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_RXVALID 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_RXVALID(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_RXVALID)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_RXVALID(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_RXVALID) & M_FW_TLS_KEYCTX_TX_WR_RXVALID)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_RXVALID V_FW_TLS_KEYCTX_TX_WR_RXVALID(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_IVPRESENT 7
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_IVPRESENT 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_IVPRESENT(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_IVPRESENT)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_IVPRESENT(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_IVPRESENT) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_IVPRESENT)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_IVPRESENT V_FW_TLS_KEYCTX_TX_WR_IVPRESENT(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_RXOPAD_PRESENT 6
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_RXOPAD_PRESENT 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_RXOPAD_PRESENT(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_RXOPAD_PRESENT)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_RXOPAD_PRESENT(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_RXOPAD_PRESENT) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_RXOPAD_PRESENT)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_RXOPAD_PRESENT \
|
||||
V_FW_TLS_KEYCTX_TX_WR_RXOPAD_PRESENT(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_RXCK_SIZE 3
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_RXCK_SIZE 0x7
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_RXCK_SIZE(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_RXCK_SIZE)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_RXCK_SIZE(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_RXCK_SIZE) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_RXCK_SIZE)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_RXMK_SIZE 0
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_RXMK_SIZE 0x7
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_RXMK_SIZE(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_RXMK_SIZE)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_RXMK_SIZE(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_RXMK_SIZE) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_RXMK_SIZE)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_IVINSERT 55
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_IVINSERT 0x1ffULL
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_IVINSERT(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_IVINSERT)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_IVINSERT(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_IVINSERT) & M_FW_TLS_KEYCTX_TX_WR_IVINSERT)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_AADSTRTOFST 47
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_AADSTRTOFST 0xffULL
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_AADSTRTOFST(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_AADSTRTOFST)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_AADSTRTOFST(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_AADSTRTOFST) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_AADSTRTOFST)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_AADSTOPOFST 39
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_AADSTOPOFST 0xffULL
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_AADSTOPOFST(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_AADSTOPOFST)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_AADSTOPOFST(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_AADSTOPOFST) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_AADSTOPOFST)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_CIPHERSRTOFST 30
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_CIPHERSRTOFST 0x1ffULL
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_CIPHERSRTOFST(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_CIPHERSRTOFST)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_CIPHERSRTOFST(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_CIPHERSRTOFST) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_CIPHERSRTOFST)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_CIPHERSTOPOFST 23
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_CIPHERSTOPOFST 0x7f
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_CIPHERSTOPOFST(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_CIPHERSTOPOFST)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_CIPHERSTOPOFST(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_CIPHERSTOPOFST) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_CIPHERSTOPOFST)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_AUTHSRTOFST 14
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_AUTHSRTOFST 0x1ff
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_AUTHSRTOFST(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_AUTHSRTOFST)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_AUTHSRTOFST(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_AUTHSRTOFST) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_AUTHSRTOFST)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_AUTHSTOPOFST 7
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_AUTHSTOPOFST 0x7f
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_AUTHSTOPOFST(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_AUTHSTOPOFST)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_AUTHSTOPOFST(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_AUTHSTOPOFST) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_AUTHSTOPOFST)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_AUTHINSRT 0
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_AUTHINSRT 0x7f
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_AUTHINSRT(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_AUTHINSRT)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_AUTHINSRT(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_AUTHINSRT) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_AUTHINSRT)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_RENEG 4
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_RENEG 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_RENEG(x) ((x) << S_FW_TLS_KEYCTX_TX_WR_RENEG)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_RENEG(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_RENEG) & M_FW_TLS_KEYCTX_TX_WR_RENEG)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_RENEG V_FW_TLS_KEYCTX_TX_WR_RENEG(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_DELETE_TX 3
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_DELETE_TX 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_DELETE_TX(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_DELETE_TX)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_DELETE_TX(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_DELETE_TX) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_DELETE_TX)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_DELETE_TX V_FW_TLS_KEYCTX_TX_WR_DELETE_TX(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_DELETE_RX 2
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_DELETE_RX 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_DELETE_RX(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_DELETE_RX)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_DELETE_RX(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_DELETE_RX) & \
|
||||
M_FW_TLS_KEYCTX_TX_WR_DELETE_RX)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_DELETE_RX V_FW_TLS_KEYCTX_TX_WR_DELETE_RX(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_WRITE_TX 1
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_WRITE_TX 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_WRITE_TX(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_WRITE_TX)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_WRITE_TX(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_WRITE_TX) & M_FW_TLS_KEYCTX_TX_WR_WRITE_TX)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_WRITE_TX V_FW_TLS_KEYCTX_TX_WR_WRITE_TX(1U)
|
||||
|
||||
#define S_FW_TLS_KEYCTX_TX_WR_WRITE_RX 0
|
||||
#define M_FW_TLS_KEYCTX_TX_WR_WRITE_RX 0x1
|
||||
#define V_FW_TLS_KEYCTX_TX_WR_WRITE_RX(x) \
|
||||
((x) << S_FW_TLS_KEYCTX_TX_WR_WRITE_RX)
|
||||
#define G_FW_TLS_KEYCTX_TX_WR_WRITE_RX(x) \
|
||||
(((x) >> S_FW_TLS_KEYCTX_TX_WR_WRITE_RX) & M_FW_TLS_KEYCTX_TX_WR_WRITE_RX)
|
||||
#define F_FW_TLS_KEYCTX_TX_WR_WRITE_RX V_FW_TLS_KEYCTX_TX_WR_WRITE_RX(1U)
|
||||
|
||||
struct fw_crypto_lookaside_wr {
|
||||
__be32 op_to_cctx_size;
|
||||
__be32 len16_pkd;
|
||||
__be32 session_id;
|
||||
@ -3395,116 +3818,116 @@ struct fw_sec_lookaside_lpbk_wr {
|
||||
__be64 cookie;
|
||||
};
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_OPCODE 24
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_OPCODE 0xff
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_OPCODE(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_OPCODE)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_OPCODE(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_OPCODE) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_OPCODE)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_OPCODE 24
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_OPCODE 0xff
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_OPCODE(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_OPCODE)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_OPCODE(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_OPCODE) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_OPCODE)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_COMPL 23
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_COMPL 0x1
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_COMPL(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_COMPL)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_COMPL(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_COMPL) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_COMPL)
|
||||
#define F_FW_SEC_LOOKASIDE_LPBK_WR_COMPL V_FW_SEC_LOOKASIDE_LPBK_WR_COMPL(1U)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_COMPL 23
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_COMPL 0x1
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_COMPL(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_COMPL)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_COMPL(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_COMPL) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_COMPL)
|
||||
#define F_FW_CRYPTO_LOOKASIDE_WR_COMPL V_FW_CRYPTO_LOOKASIDE_WR_COMPL(1U)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_IMM_LEN 15
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_IMM_LEN 0xff
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_IMM_LEN(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_IMM_LEN)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_IMM_LEN(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_IMM_LEN) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_IMM_LEN)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_IMM_LEN 15
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_IMM_LEN 0xff
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_IMM_LEN(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_IMM_LEN)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_IMM_LEN(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_IMM_LEN) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_IMM_LEN)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_LOC 5
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_LOC 0x3
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_LOC(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_LOC)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_LOC(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_LOC) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_LOC)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC 5
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC 0x3
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_CCTX_LOC)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_SIZE 0
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_SIZE 0x1f
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_SIZE(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_SIZE)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_SIZE(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_SIZE) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_CCTX_SIZE)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE 0
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE 0x1f
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_CCTX_SIZE)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_LEN16 0
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_LEN16 0xff
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_LEN16(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_LEN16)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_LEN16(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_LEN16) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_LEN16)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_LEN16 0
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_LEN16 0xff
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_LEN16(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_LEN16)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_LEN16(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_LEN16) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_LEN16)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_RX_CHID 29
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_RX_CHID 0x3
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_RX_CHID(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_RX_CHID)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_RX_CHID(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_RX_CHID) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_RX_CHID)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_RX_CHID 29
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_RX_CHID 0x3
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_RX_CHID(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_RX_CHID)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_RX_CHID(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_RX_CHID) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_RX_CHID)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_LCB 27
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_LCB 0x3
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_LCB(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_LCB)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_LCB(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_LCB) & M_FW_SEC_LOOKASIDE_LPBK_WR_LCB)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_LCB 27
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_LCB 0x3
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_LCB(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_LCB)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_LCB(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_LCB) & M_FW_CRYPTO_LOOKASIDE_WR_LCB)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_PHASH 25
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_PHASH 0x3
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_PHASH(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_PHASH)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_PHASH(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_PHASH) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_PHASH)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_PHASH 25
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_PHASH 0x3
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_PHASH(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_PHASH)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_PHASH(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_PHASH) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_PHASH)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_IV 23
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_IV 0x3
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_IV(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_IV)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_IV(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_IV) & M_FW_SEC_LOOKASIDE_LPBK_WR_IV)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_IV 23
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_IV 0x3
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_IV(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_IV)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_IV(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_IV) & M_FW_CRYPTO_LOOKASIDE_WR_IV)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_TX_CH 10
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_TX_CH 0x3
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_TX_CH(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_TX_CH)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_TX_CH(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_TX_CH) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_TX_CH)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_TX_CH 10
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_TX_CH 0x3
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_TX_CH(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_TX_CH)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_TX_CH(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_TX_CH) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_TX_CH)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_RX_Q_ID 0
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_RX_Q_ID 0x3ff
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_RX_Q_ID(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_RX_Q_ID)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_RX_Q_ID(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_RX_Q_ID) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_RX_Q_ID)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID 0
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID 0x3ff
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_RX_Q_ID)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_PLD_SIZE 24
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_PLD_SIZE 0xff
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_PLD_SIZE(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_PLD_SIZE)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_PLD_SIZE(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_PLD_SIZE) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_PLD_SIZE)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE 24
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE 0xff
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE)
|
||||
|
||||
#define S_FW_SEC_LOOKASIDE_LPBK_WR_HASH_SIZE 17
|
||||
#define M_FW_SEC_LOOKASIDE_LPBK_WR_HASH_SIZE 0x7f
|
||||
#define V_FW_SEC_LOOKASIDE_LPBK_WR_HASH_SIZE(x) \
|
||||
((x) << S_FW_SEC_LOOKASIDE_LPBK_WR_HASH_SIZE)
|
||||
#define G_FW_SEC_LOOKASIDE_LPBK_WR_HASH_SIZE(x) \
|
||||
(((x) >> S_FW_SEC_LOOKASIDE_LPBK_WR_HASH_SIZE) & \
|
||||
M_FW_SEC_LOOKASIDE_LPBK_WR_HASH_SIZE)
|
||||
#define S_FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE 17
|
||||
#define M_FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE 0x7f
|
||||
#define V_FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE(x) \
|
||||
((x) << S_FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE)
|
||||
#define G_FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE(x) \
|
||||
(((x) >> S_FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE) & \
|
||||
M_FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE)
|
||||
|
||||
/******************************************************************************
|
||||
* C O M M A N D s
|
||||
@ -4095,8 +4518,9 @@ enum fw_caps_config_iscsi {
|
||||
FW_CAPS_CONFIG_ISCSI_TARGET_CMDOFLD = 0x00000100,
|
||||
};
|
||||
|
||||
enum fw_caps_config_tls {
|
||||
FW_CAPS_CONFIG_TLSKEYS = 0x00000001,
|
||||
enum fw_caps_config_crypto {
|
||||
FW_CAPS_CONFIG_CRYPTO_LOOKASIDE = 0x00000001,
|
||||
FW_CAPS_CONFIG_TLSKEYS = 0x00000002,
|
||||
};
|
||||
|
||||
enum fw_caps_config_fcoe {
|
||||
@ -4128,7 +4552,7 @@ struct fw_caps_config_cmd {
|
||||
__be16 niccaps;
|
||||
__be16 toecaps;
|
||||
__be16 rdmacaps;
|
||||
__be16 tlscaps;
|
||||
__be16 cryptocaps;
|
||||
__be16 iscsicaps;
|
||||
__be16 fcoecaps;
|
||||
__be32 cfcsum;
|
||||
@ -6305,7 +6729,7 @@ struct fw_acl_vlan_cmd {
|
||||
enum fw_port_cap {
|
||||
FW_PORT_CAP_SPEED_100M = 0x0001,
|
||||
FW_PORT_CAP_SPEED_1G = 0x0002,
|
||||
FW_PORT_CAP_SPEED_2_5G = 0x0004,
|
||||
FW_PORT_CAP_SPEED_25G = 0x0004,
|
||||
FW_PORT_CAP_SPEED_10G = 0x0008,
|
||||
FW_PORT_CAP_SPEED_40G = 0x0010,
|
||||
FW_PORT_CAP_SPEED_100G = 0x0020,
|
||||
@ -6776,6 +7200,11 @@ enum fw_port_type {
|
||||
FW_PORT_TYPE_QSA = 13, /* No, 1, Yes, No, No, No, 10G */
|
||||
FW_PORT_TYPE_QSFP = 14, /* No, 4, Yes, No, No, No, 40G */
|
||||
FW_PORT_TYPE_BP40_BA = 15, /* No, 4, No, No, Yes, Yes, 40G/10G/1G, BP ANGE */
|
||||
FW_PORT_TYPE_KR4_100G = 16, /* No, 4, 100G */
|
||||
FW_PORT_TYPE_CR4_QSFP = 17, /* No, 4, 100G */
|
||||
FW_PORT_TYPE_CR_QSFP = 18, /* No, 1, 25G */
|
||||
FW_PORT_TYPE_CR2_QSFP = 19, /* No, 2, 50G */
|
||||
FW_PORT_TYPE_SFP28 = 20, /* No, 1, 25G */
|
||||
|
||||
FW_PORT_TYPE_NONE = M_FW_PORT_CMD_PTYPE
|
||||
};
|
||||
@ -8786,6 +9215,11 @@ enum {
|
||||
T5FW_VERSION_MINOR = 0x05,
|
||||
T5FW_VERSION_MICRO = 0x25,
|
||||
T5FW_VERSION_BUILD = 0x00,
|
||||
|
||||
T6FW_VERSION_MAJOR = 0x00,
|
||||
T6FW_VERSION_MINOR = 0x00,
|
||||
T6FW_VERSION_MICRO = 0x00,
|
||||
T6FW_VERSION_BUILD = 0x00,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
44
sys/dev/cxgbe/if_cc.c
Normal file
44
sys/dev/cxgbe/if_cc.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Chelsio Communications, Inc.
|
||||
* All rights reserved.
|
||||
* Written by: Navdeep Parhar <np@FreeBSD.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
static int
|
||||
mod_event(module_t mod, int cmd, void *arg)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
static moduledata_t if_cc_mod = {"if_cc", mod_event};
|
||||
DECLARE_MODULE(if_cc, if_cc_mod, SI_SUB_EXEC, SI_ORDER_ANY);
|
||||
MODULE_VERSION(if_cc, 1);
|
||||
MODULE_DEPEND(if_cc, cc, 1, 1, 1);
|
44
sys/dev/cxgbe/if_ccv.c
Normal file
44
sys/dev/cxgbe/if_ccv.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Chelsio Communications, Inc.
|
||||
* All rights reserved.
|
||||
* Written by: Navdeep Parhar <np@FreeBSD.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
static int
|
||||
mod_event(module_t mod, int cmd, void *arg)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
static moduledata_t if_ccv_mod = {"if_ccv", mod_event};
|
||||
DECLARE_MODULE(if_ccv, if_ccv_mod, SI_SUB_EXEC, SI_ORDER_ANY);
|
||||
MODULE_VERSION(if_ccv, 1);
|
||||
MODULE_DEPEND(if_ccv, ccv, 1, 1, 1);
|
@ -90,6 +90,12 @@ struct {
|
||||
{0x500f, "Chelsio Amsterdam"},
|
||||
{0x5013, "Chelsio T580-CHR"},
|
||||
#endif
|
||||
}, t6iov_pciids[] = {
|
||||
{0x6001, "Chelsio T6225-CR"}, /* 2 x 10/25G */
|
||||
{0x6002, "Chelsio T6225-SO-CR"}, /* 2 x 10/25G, nomem */
|
||||
{0x6007, "Chelsio T62100-LP-CR"}, /* 2 x 40/50/100G */
|
||||
{0x6008, "Chelsio T62100-SO-CR"}, /* 2 x 40/50/100G, nomem */
|
||||
{0x600d, "Chelsio T62100-CR"}, /* 2 x 40/50/100G */
|
||||
};
|
||||
|
||||
static int t4iov_attach_child(device_t dev);
|
||||
@ -97,7 +103,7 @@ static int t4iov_attach_child(device_t dev);
|
||||
static int
|
||||
t4iov_probe(device_t dev)
|
||||
{
|
||||
uint16_t d;
|
||||
uint16_t d;
|
||||
size_t i;
|
||||
|
||||
d = pci_get_device(dev);
|
||||
@ -114,7 +120,7 @@ t4iov_probe(device_t dev)
|
||||
static int
|
||||
t5iov_probe(device_t dev)
|
||||
{
|
||||
uint16_t d;
|
||||
uint16_t d;
|
||||
size_t i;
|
||||
|
||||
d = pci_get_device(dev);
|
||||
@ -128,6 +134,23 @@ t5iov_probe(device_t dev)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
t6iov_probe(device_t dev)
|
||||
{
|
||||
uint16_t d;
|
||||
size_t i;
|
||||
|
||||
d = pci_get_device(dev);
|
||||
for (i = 0; i < nitems(t6iov_pciids); i++) {
|
||||
if (d == t6iov_pciids[i].device) {
|
||||
device_set_desc(dev, t6iov_pciids[i].desc);
|
||||
device_quiet(dev);
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
}
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
t4iov_attach(device_t dev)
|
||||
{
|
||||
@ -217,7 +240,6 @@ t4iov_detach(device_t dev)
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
device_verbose(dev);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -289,10 +311,36 @@ static driver_t t5iov_driver = {
|
||||
sizeof(struct t4iov_softc)
|
||||
};
|
||||
|
||||
static devclass_t t4iov_devclass, t5iov_devclass;
|
||||
static device_method_t t6iov_methods[] = {
|
||||
DEVMETHOD(device_probe, t6iov_probe),
|
||||
DEVMETHOD(device_attach, t4iov_attach),
|
||||
DEVMETHOD(device_detach, t4iov_detach),
|
||||
|
||||
#ifdef PCI_IOV
|
||||
DEVMETHOD(pci_iov_init, t4iov_iov_init),
|
||||
DEVMETHOD(pci_iov_uninit, t4iov_iov_uninit),
|
||||
DEVMETHOD(pci_iov_add_vf, t4iov_add_vf),
|
||||
#endif
|
||||
|
||||
DEVMETHOD(t4_attach_child, t4iov_attach_child),
|
||||
DEVMETHOD(t4_detach_child, t4iov_detach_child),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t t6iov_driver = {
|
||||
"t6iov",
|
||||
t6iov_methods,
|
||||
sizeof(struct t4iov_softc)
|
||||
};
|
||||
|
||||
static devclass_t t4iov_devclass, t5iov_devclass, t6iov_devclass;
|
||||
|
||||
DRIVER_MODULE(t4iov, pci, t4iov_driver, t4iov_devclass, 0, 0);
|
||||
MODULE_VERSION(t4iov, 1);
|
||||
|
||||
DRIVER_MODULE(t5iov, pci, t5iov_driver, t5iov_devclass, 0, 0);
|
||||
MODULE_VERSION(t5iov, 1);
|
||||
|
||||
DRIVER_MODULE(t6iov, pci, t6iov_driver, t6iov_devclass, 0, 0);
|
||||
MODULE_VERSION(t6iov, 1);
|
||||
|
@ -174,6 +174,39 @@ static driver_t vcxl_driver = {
|
||||
sizeof(struct vi_info)
|
||||
};
|
||||
|
||||
/* T6 bus driver interface */
|
||||
static int t6_probe(device_t);
|
||||
static device_method_t t6_methods[] = {
|
||||
DEVMETHOD(device_probe, t6_probe),
|
||||
DEVMETHOD(device_attach, t4_attach),
|
||||
DEVMETHOD(device_detach, t4_detach),
|
||||
|
||||
DEVMETHOD(t4_is_main_ready, t4_ready),
|
||||
DEVMETHOD(t4_read_port_device, t4_read_port_device),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
static driver_t t6_driver = {
|
||||
"t6nex",
|
||||
t6_methods,
|
||||
sizeof(struct adapter)
|
||||
};
|
||||
|
||||
|
||||
/* T6 port (cc) interface */
|
||||
static driver_t cc_driver = {
|
||||
"cc",
|
||||
cxgbe_methods,
|
||||
sizeof(struct port_info)
|
||||
};
|
||||
|
||||
/* T6 VI (vcc) interface */
|
||||
static driver_t vcc_driver = {
|
||||
"vcc",
|
||||
vcxgbe_methods,
|
||||
sizeof(struct vi_info)
|
||||
};
|
||||
|
||||
/* ifnet + media interface */
|
||||
static void cxgbe_init(void *);
|
||||
static int cxgbe_ioctl(struct ifnet *, unsigned long, caddr_t);
|
||||
@ -355,8 +388,8 @@ TUNABLE_INT("hw.cxgbe.toecaps_allowed", &t4_toecaps_allowed);
|
||||
static int t4_rdmacaps_allowed = -1;
|
||||
TUNABLE_INT("hw.cxgbe.rdmacaps_allowed", &t4_rdmacaps_allowed);
|
||||
|
||||
static int t4_tlscaps_allowed = 0;
|
||||
TUNABLE_INT("hw.cxgbe.tlscaps_allowed", &t4_tlscaps_allowed);
|
||||
static int t4_cryptocaps_allowed = 0;
|
||||
TUNABLE_INT("hw.cxgbe.cryptocaps_allowed", &t4_cryptocaps_allowed);
|
||||
|
||||
static int t4_iscsicaps_allowed = -1;
|
||||
TUNABLE_INT("hw.cxgbe.iscsicaps_allowed", &t4_iscsicaps_allowed);
|
||||
@ -567,6 +600,13 @@ struct {
|
||||
{0x540f, "Chelsio Amsterdam"},
|
||||
{0x5413, "Chelsio T580-CHR"},
|
||||
#endif
|
||||
}, t6_pciids[] = {
|
||||
{0xc006, "Chelsio Terminator 6 FPGA"}, /* T6 PE10K6 FPGA (PF0) */
|
||||
{0x6401, "Chelsio T6225-CR"}, /* 2 x 10/25G */
|
||||
{0x6402, "Chelsio T6225-SO-CR"}, /* 2 x 10/25G, nomem */
|
||||
{0x6407, "Chelsio T62100-LP-CR"}, /* 2 x 40/50/100G */
|
||||
{0x6408, "Chelsio T62100-SO-CR"}, /* 2 x 40/50/100G, nomem */
|
||||
{0x640d, "Chelsio T62100-CR"}, /* 2 x 40/50/100G */
|
||||
};
|
||||
|
||||
#ifdef TCP_OFFLOAD
|
||||
@ -629,6 +669,26 @@ t5_probe(device_t dev)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
t6_probe(device_t dev)
|
||||
{
|
||||
int i;
|
||||
uint16_t v = pci_get_vendor(dev);
|
||||
uint16_t d = pci_get_device(dev);
|
||||
|
||||
if (v != PCI_VENDOR_ID_CHELSIO)
|
||||
return (ENXIO);
|
||||
|
||||
for (i = 0; i < nitems(t6_pciids); i++) {
|
||||
if (d == t6_pciids[i].device) {
|
||||
device_set_desc(dev, t6_pciids[i].desc);
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static void
|
||||
t5_attribute_workaround(device_t dev)
|
||||
{
|
||||
@ -656,6 +716,45 @@ t5_attribute_workaround(device_t dev)
|
||||
device_get_nameunit(root_port));
|
||||
}
|
||||
|
||||
static const struct devnames devnames[] = {
|
||||
{
|
||||
.nexus_name = "t4nex",
|
||||
.ifnet_name = "cxgbe",
|
||||
.vi_ifnet_name = "vcxgbe",
|
||||
.pf03_drv_name = "t4iov",
|
||||
.vf_nexus_name = "t4vf",
|
||||
.vf_ifnet_name = "cxgbev"
|
||||
}, {
|
||||
.nexus_name = "t5nex",
|
||||
.ifnet_name = "cxl",
|
||||
.vi_ifnet_name = "vcxl",
|
||||
.pf03_drv_name = "t5iov",
|
||||
.vf_nexus_name = "t5vf",
|
||||
.vf_ifnet_name = "cxlv"
|
||||
}, {
|
||||
.nexus_name = "t6nex",
|
||||
.ifnet_name = "cc",
|
||||
.vi_ifnet_name = "vcc",
|
||||
.pf03_drv_name = "t6iov",
|
||||
.vf_nexus_name = "t6vf",
|
||||
.vf_ifnet_name = "ccv"
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
t4_init_devnames(struct adapter *sc)
|
||||
{
|
||||
int id;
|
||||
|
||||
id = chip_id(sc);
|
||||
if (id >= CHELSIO_T4 && id - CHELSIO_T4 < nitems(devnames))
|
||||
sc->names = &devnames[id - CHELSIO_T4];
|
||||
else {
|
||||
device_printf(sc->dev, "chip id %d is not supported.\n", id);
|
||||
sc->names = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
t4_attach(device_t dev)
|
||||
{
|
||||
@ -675,7 +774,7 @@ t4_attach(device_t dev)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
TUNABLE_INT_FETCH("hw.cxgbe.debug_flags", &sc->debug_flags);
|
||||
TUNABLE_INT_FETCH("hw.cxgbe.dflags", &sc->debug_flags);
|
||||
|
||||
if ((pci_get_device(dev) & 0xff00) == 0x5400)
|
||||
t5_attribute_workaround(dev);
|
||||
@ -733,6 +832,12 @@ t4_attach(device_t dev)
|
||||
goto done;
|
||||
}
|
||||
|
||||
t4_init_devnames(sc);
|
||||
if (sc->names == NULL) {
|
||||
rc = ENOTSUP;
|
||||
goto done; /* error message displayed already */
|
||||
}
|
||||
|
||||
/*
|
||||
* Do this really early, with the memory windows set up even before the
|
||||
* character device. The userland tool's register i/o and mem read
|
||||
@ -872,7 +977,7 @@ t4_attach(device_t dev)
|
||||
|
||||
pi->linkdnrc = -1;
|
||||
|
||||
pi->dev = device_add_child(dev, is_t4(sc) ? "cxgbe" : "cxl", -1);
|
||||
pi->dev = device_add_child(dev, sc->names->ifnet_name, -1);
|
||||
if (pi->dev == NULL) {
|
||||
device_printf(dev,
|
||||
"failed to add device for port %d.\n", i);
|
||||
@ -1355,6 +1460,7 @@ static int
|
||||
cxgbe_attach(device_t dev)
|
||||
{
|
||||
struct port_info *pi = device_get_softc(dev);
|
||||
struct adapter *sc = pi->adapter;
|
||||
struct vi_info *vi;
|
||||
int i, rc;
|
||||
|
||||
@ -1367,8 +1473,7 @@ cxgbe_attach(device_t dev)
|
||||
for_each_vi(pi, i, vi) {
|
||||
if (i == 0)
|
||||
continue;
|
||||
vi->dev = device_add_child(dev, is_t4(pi->adapter) ?
|
||||
"vcxgbe" : "vcxl", -1);
|
||||
vi->dev = device_add_child(dev, sc->names->vi_ifnet_name, -1);
|
||||
if (vi->dev == NULL) {
|
||||
device_printf(dev, "failed to add VI %d\n", i);
|
||||
continue;
|
||||
@ -2027,11 +2132,11 @@ t4_map_bar_2(struct adapter *sc)
|
||||
}
|
||||
sc->udbs_base = rman_get_virtual(sc->udbs_res);
|
||||
|
||||
if (is_t5(sc)) {
|
||||
if (chip_id(sc) >= CHELSIO_T5) {
|
||||
setbit(&sc->doorbells, DOORBELL_UDB);
|
||||
#if defined(__i386__) || defined(__amd64__)
|
||||
if (t5_write_combine) {
|
||||
int rc;
|
||||
int rc, mode;
|
||||
|
||||
/*
|
||||
* Enable write combining on BAR2. This is the
|
||||
@ -2054,8 +2159,9 @@ t4_map_bar_2(struct adapter *sc)
|
||||
rc);
|
||||
}
|
||||
|
||||
mode = is_t5(sc) ? V_STATMODE(0) : V_T6_STATMODE(0);
|
||||
t4_write_reg(sc, A_SGE_STAT_CFG,
|
||||
V_STATSOURCE_T5(7) | V_STATMODE(0));
|
||||
V_STATSOURCE_T5(7) | mode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -2685,6 +2791,22 @@ struct fw_info {
|
||||
.intfver_fcoepdu = FW_INTFVER(T5, FCOEPDU),
|
||||
.intfver_fcoe = FW_INTFVER(T5, FCOE),
|
||||
},
|
||||
}, {
|
||||
.chip = CHELSIO_T6,
|
||||
.kld_name = "t6fw_cfg",
|
||||
.fw_mod_name = "t6fw",
|
||||
.fw_hdr = {
|
||||
.chip = FW_HDR_CHIP_T6,
|
||||
.fw_ver = htobe32_const(FW_VERSION(T6)),
|
||||
.intfver_nic = FW_INTFVER(T6, NIC),
|
||||
.intfver_vnic = FW_INTFVER(T6, VNIC),
|
||||
.intfver_ofld = FW_INTFVER(T6, OFLD),
|
||||
.intfver_ri = FW_INTFVER(T6, RI),
|
||||
.intfver_iscsipdu = FW_INTFVER(T6, ISCSIPDU),
|
||||
.intfver_iscsi = FW_INTFVER(T6, ISCSI),
|
||||
.intfver_fcoepdu = FW_INTFVER(T6, FCOEPDU),
|
||||
.intfver_fcoe = FW_INTFVER(T6, FCOE),
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@ -3113,7 +3235,7 @@ partition_resources(struct adapter *sc, const struct firmware *default_cfg,
|
||||
LIMIT_CAPS(niccaps);
|
||||
LIMIT_CAPS(toecaps);
|
||||
LIMIT_CAPS(rdmacaps);
|
||||
LIMIT_CAPS(tlscaps);
|
||||
LIMIT_CAPS(cryptocaps);
|
||||
LIMIT_CAPS(iscsicaps);
|
||||
LIMIT_CAPS(fcoecaps);
|
||||
#undef LIMIT_CAPS
|
||||
@ -3250,7 +3372,7 @@ get_params__post_init(struct adapter *sc)
|
||||
READ_CAPS(niccaps);
|
||||
READ_CAPS(toecaps);
|
||||
READ_CAPS(rdmacaps);
|
||||
READ_CAPS(tlscaps);
|
||||
READ_CAPS(cryptocaps);
|
||||
READ_CAPS(iscsicaps);
|
||||
READ_CAPS(fcoecaps);
|
||||
|
||||
@ -3459,6 +3581,38 @@ build_medialist(struct port_info *pi, struct ifmedia *media)
|
||||
}
|
||||
break;
|
||||
|
||||
case FW_PORT_TYPE_CR_QSFP:
|
||||
case FW_PORT_TYPE_SFP28:
|
||||
switch (pi->mod_type) {
|
||||
|
||||
case FW_PORT_MOD_TYPE_SR:
|
||||
MPASS(pi->port_type == FW_PORT_TYPE_SFP28);
|
||||
ifmedia_add(media, m | IFM_25G_SR, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_25G_SR);
|
||||
break;
|
||||
|
||||
case FW_PORT_MOD_TYPE_TWINAX_PASSIVE:
|
||||
case FW_PORT_MOD_TYPE_TWINAX_ACTIVE:
|
||||
ifmedia_add(media, m | IFM_25G_CR, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_25G_CR);
|
||||
break;
|
||||
|
||||
case FW_PORT_MOD_TYPE_NONE:
|
||||
m &= ~IFM_FDX;
|
||||
ifmedia_add(media, m | IFM_NONE, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_NONE);
|
||||
break;
|
||||
|
||||
default:
|
||||
device_printf(pi->dev,
|
||||
"unknown port_type (%d), mod_type (%d)\n",
|
||||
pi->port_type, pi->mod_type);
|
||||
ifmedia_add(media, m | IFM_UNKNOWN, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_UNKNOWN);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FW_PORT_TYPE_QSFP:
|
||||
switch (pi->mod_type) {
|
||||
|
||||
@ -3494,6 +3648,67 @@ build_medialist(struct port_info *pi, struct ifmedia *media)
|
||||
}
|
||||
break;
|
||||
|
||||
case FW_PORT_TYPE_CR2_QSFP:
|
||||
switch (pi->mod_type) {
|
||||
|
||||
case FW_PORT_MOD_TYPE_TWINAX_PASSIVE:
|
||||
case FW_PORT_MOD_TYPE_TWINAX_ACTIVE:
|
||||
ifmedia_add(media, m | IFM_50G_CR2, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_50G_CR2);
|
||||
break;
|
||||
|
||||
case FW_PORT_MOD_TYPE_NONE:
|
||||
m &= ~IFM_FDX;
|
||||
ifmedia_add(media, m | IFM_NONE, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_NONE);
|
||||
break;
|
||||
|
||||
default:
|
||||
device_printf(pi->dev,
|
||||
"unknown port_type (%d), mod_type (%d)\n",
|
||||
pi->port_type, pi->mod_type);
|
||||
ifmedia_add(media, m | IFM_UNKNOWN, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_UNKNOWN);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FW_PORT_TYPE_KR4_100G:
|
||||
case FW_PORT_TYPE_CR4_QSFP:
|
||||
switch (pi->mod_type) {
|
||||
|
||||
case FW_PORT_MOD_TYPE_LR:
|
||||
ifmedia_add(media, m | IFM_100G_LR4, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_100G_LR4);
|
||||
break;
|
||||
|
||||
case FW_PORT_MOD_TYPE_SR:
|
||||
ifmedia_add(media, m | IFM_100G_SR4, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_100G_SR4);
|
||||
break;
|
||||
|
||||
case FW_PORT_MOD_TYPE_TWINAX_PASSIVE:
|
||||
case FW_PORT_MOD_TYPE_TWINAX_ACTIVE:
|
||||
ifmedia_add(media, m | IFM_100G_CR4, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_100G_CR4);
|
||||
break;
|
||||
|
||||
case FW_PORT_MOD_TYPE_NONE:
|
||||
m &= ~IFM_FDX;
|
||||
ifmedia_add(media, m | IFM_NONE, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_NONE);
|
||||
break;
|
||||
|
||||
default:
|
||||
device_printf(pi->dev,
|
||||
"unknown port_type (%d), mod_type (%d)\n",
|
||||
pi->port_type, pi->mod_type);
|
||||
ifmedia_add(media, m | IFM_UNKNOWN, 0, NULL);
|
||||
ifmedia_set(media, m | IFM_UNKNOWN);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
device_printf(pi->dev,
|
||||
"unknown port_type (%d), mod_type (%d)\n", pi->port_type,
|
||||
@ -4590,7 +4805,7 @@ static char *caps_decoder[] = {
|
||||
"\005INITIATOR_SSNOFLD\006TARGET_SSNOFLD"
|
||||
"\007T10DIF"
|
||||
"\010INITIATOR_CMDOFLD\011TARGET_CMDOFLD",
|
||||
"\20\00KEYS", /* 7: TLS */
|
||||
"\20\001LOOKASIDE\002TLSKEYS", /* 7: Crypto */
|
||||
"\20\001INITIATOR\002TARGET\003CTRL_OFLD" /* 8: FCoE */
|
||||
"\004PO_INITIATOR\005PO_TARGET",
|
||||
};
|
||||
@ -4641,7 +4856,7 @@ t4_sysctls(struct adapter *sc)
|
||||
SYSCTL_ADD_INT(ctx, children, OID_AUTO, "lro_timeout", CTLFLAG_RW,
|
||||
&sc->lro_timeout, 0, "lro inactive-flush timeout (in us)");
|
||||
|
||||
SYSCTL_ADD_INT(ctx, children, OID_AUTO, "debug_flags", CTLFLAG_RW,
|
||||
SYSCTL_ADD_INT(ctx, children, OID_AUTO, "dflags", CTLFLAG_RW,
|
||||
&sc->debug_flags, 0, "flags to enable runtime debugging");
|
||||
|
||||
SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "tp_version",
|
||||
@ -4698,7 +4913,7 @@ t4_sysctls(struct adapter *sc)
|
||||
SYSCTL_CAP(toecaps, 4, "TCP offload");
|
||||
SYSCTL_CAP(rdmacaps, 5, "RDMA");
|
||||
SYSCTL_CAP(iscsicaps, 6, "iSCSI");
|
||||
SYSCTL_CAP(tlscaps, 7, "TLS");
|
||||
SYSCTL_CAP(cryptocaps, 7, "crypto");
|
||||
SYSCTL_CAP(fcoecaps, 8, "FCoE");
|
||||
#undef SYSCTL_CAP
|
||||
|
||||
@ -7472,6 +7687,8 @@ sysctl_wcwr_stats(SYSCTL_HANDLER_ARGS)
|
||||
struct sbuf *sb;
|
||||
int rc, v;
|
||||
|
||||
MPASS(chip_id(sc) >= CHELSIO_T5);
|
||||
|
||||
rc = sysctl_wire_old_buffer(req, 0);
|
||||
if (rc != 0)
|
||||
return (rc);
|
||||
@ -7482,14 +7699,19 @@ sysctl_wcwr_stats(SYSCTL_HANDLER_ARGS)
|
||||
|
||||
v = t4_read_reg(sc, A_SGE_STAT_CFG);
|
||||
if (G_STATSOURCE_T5(v) == 7) {
|
||||
if (G_STATMODE(v) == 0) {
|
||||
int mode;
|
||||
|
||||
mode = is_t5(sc) ? G_STATMODE(v) : G_T6_STATMODE(v);
|
||||
if (mode == 0) {
|
||||
sbuf_printf(sb, "total %d, incomplete %d",
|
||||
t4_read_reg(sc, A_SGE_STAT_TOTAL),
|
||||
t4_read_reg(sc, A_SGE_STAT_MATCH));
|
||||
} else if (G_STATMODE(v) == 1) {
|
||||
} else if (mode == 1) {
|
||||
sbuf_printf(sb, "total %d, data overflow %d",
|
||||
t4_read_reg(sc, A_SGE_STAT_TOTAL),
|
||||
t4_read_reg(sc, A_SGE_STAT_MATCH));
|
||||
} else {
|
||||
sbuf_printf(sb, "unknown mode %d", mode);
|
||||
}
|
||||
}
|
||||
rc = sbuf_finish(sb);
|
||||
@ -9545,9 +9767,9 @@ mod_event(module_t mod, int cmd, void *arg)
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static devclass_t t4_devclass, t5_devclass;
|
||||
static devclass_t cxgbe_devclass, cxl_devclass;
|
||||
static devclass_t vcxgbe_devclass, vcxl_devclass;
|
||||
static devclass_t t4_devclass, t5_devclass, t6_devclass;
|
||||
static devclass_t cxgbe_devclass, cxl_devclass, cc_devclass;
|
||||
static devclass_t vcxgbe_devclass, vcxl_devclass, vcc_devclass;
|
||||
|
||||
DRIVER_MODULE(t4nex, pci, t4_driver, t4_devclass, mod_event, 0);
|
||||
MODULE_VERSION(t4nex, 1);
|
||||
@ -9556,7 +9778,6 @@ MODULE_DEPEND(t4nex, firmware, 1, 1, 1);
|
||||
MODULE_DEPEND(t4nex, netmap, 1, 1, 1);
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
|
||||
DRIVER_MODULE(t5nex, pci, t5_driver, t5_devclass, mod_event, 0);
|
||||
MODULE_VERSION(t5nex, 1);
|
||||
MODULE_DEPEND(t5nex, firmware, 1, 1, 1);
|
||||
@ -9564,14 +9785,27 @@ MODULE_DEPEND(t5nex, firmware, 1, 1, 1);
|
||||
MODULE_DEPEND(t5nex, netmap, 1, 1, 1);
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
DRIVER_MODULE(t6nex, pci, t6_driver, t6_devclass, mod_event, 0);
|
||||
MODULE_VERSION(t6nex, 1);
|
||||
MODULE_DEPEND(t6nex, firmware, 1, 1, 1);
|
||||
#ifdef DEV_NETMAP
|
||||
MODULE_DEPEND(t6nex, netmap, 1, 1, 1);
|
||||
#endif /* DEV_NETMAP */
|
||||
|
||||
DRIVER_MODULE(cxgbe, t4nex, cxgbe_driver, cxgbe_devclass, 0, 0);
|
||||
MODULE_VERSION(cxgbe, 1);
|
||||
|
||||
DRIVER_MODULE(cxl, t5nex, cxl_driver, cxl_devclass, 0, 0);
|
||||
MODULE_VERSION(cxl, 1);
|
||||
|
||||
DRIVER_MODULE(cc, t6nex, cc_driver, cc_devclass, 0, 0);
|
||||
MODULE_VERSION(cc, 1);
|
||||
|
||||
DRIVER_MODULE(vcxgbe, cxgbe, vcxgbe_driver, vcxgbe_devclass, 0, 0);
|
||||
MODULE_VERSION(vcxgbe, 1);
|
||||
|
||||
DRIVER_MODULE(vcxl, cxl, vcxl_driver, vcxl_devclass, 0, 0);
|
||||
MODULE_VERSION(vcxl, 1);
|
||||
|
||||
DRIVER_MODULE(vcc, cc, vcc_driver, vcc_devclass, 0, 0);
|
||||
MODULE_VERSION(vcc, 1);
|
||||
|
@ -139,8 +139,10 @@ alloc_nm_rxq_hwq(struct vi_info *vi, struct sge_nm_rxq *nm_rxq, int cong)
|
||||
(fl_pad ? F_FW_IQ_CMD_FL0PADEN : 0) |
|
||||
(black_hole == 2 ? F_FW_IQ_CMD_FL0PACKEN : 0));
|
||||
c.fl0dcaen_to_fl0cidxfthresh =
|
||||
htobe16(V_FW_IQ_CMD_FL0FBMIN(X_FETCHBURSTMIN_128B) |
|
||||
V_FW_IQ_CMD_FL0FBMAX(X_FETCHBURSTMAX_512B));
|
||||
htobe16(V_FW_IQ_CMD_FL0FBMIN(chip_id(sc) <= CHELSIO_T5 ?
|
||||
X_FETCHBURSTMIN_128B : X_FETCHBURSTMIN_64B) |
|
||||
V_FW_IQ_CMD_FL0FBMAX(chip_id(sc) <= CHELSIO_T5 ?
|
||||
X_FETCHBURSTMAX_512B : X_FETCHBURSTMAX_256B));
|
||||
c.fl0size = htobe16(na->num_rx_desc / 8 + sp->spg_len / EQ_ESIZE);
|
||||
c.fl0addr = htobe64(nm_rxq->fl_ba);
|
||||
|
||||
|
@ -229,8 +229,8 @@ static inline u_int txpkts0_len16(u_int);
|
||||
static inline u_int txpkts1_len16(void);
|
||||
static u_int write_txpkt_wr(struct sge_txq *, struct fw_eth_tx_pkt_wr *,
|
||||
struct mbuf *, u_int);
|
||||
static u_int write_txpkt_vm_wr(struct sge_txq *, struct fw_eth_tx_pkt_vm_wr *,
|
||||
struct mbuf *, u_int);
|
||||
static u_int write_txpkt_vm_wr(struct adapter *, struct sge_txq *,
|
||||
struct fw_eth_tx_pkt_vm_wr *, struct mbuf *, u_int);
|
||||
static int try_txpkts(struct mbuf *, struct mbuf *, struct txpkts *, u_int);
|
||||
static int add_to_txpkts(struct mbuf *, struct txpkts *, u_int);
|
||||
static u_int write_txpkts_wr(struct sge_txq *, struct fw_eth_tx_pkts_wr *,
|
||||
@ -433,16 +433,20 @@ static inline void
|
||||
setup_pad_and_pack_boundaries(struct adapter *sc)
|
||||
{
|
||||
uint32_t v, m;
|
||||
int pad, pack;
|
||||
int pad, pack, pad_shift;
|
||||
|
||||
pad_shift = chip_id(sc) > CHELSIO_T5 ? X_T6_INGPADBOUNDARY_SHIFT :
|
||||
X_INGPADBOUNDARY_SHIFT;
|
||||
pad = fl_pad;
|
||||
if (fl_pad < 32 || fl_pad > 4096 || !powerof2(fl_pad)) {
|
||||
if (fl_pad < (1 << pad_shift) ||
|
||||
fl_pad > (1 << (pad_shift + M_INGPADBOUNDARY)) ||
|
||||
!powerof2(fl_pad)) {
|
||||
/*
|
||||
* If there is any chance that we might use buffer packing and
|
||||
* the chip is a T4, then pick 64 as the pad/pack boundary. Set
|
||||
* it to 32 in all other cases.
|
||||
* it to the minimum allowed in all other cases.
|
||||
*/
|
||||
pad = is_t4(sc) && buffer_packing ? 64 : 32;
|
||||
pad = is_t4(sc) && buffer_packing ? 64 : 1 << pad_shift;
|
||||
|
||||
/*
|
||||
* For fl_pad = 0 we'll still write a reasonable value to the
|
||||
@ -456,7 +460,7 @@ setup_pad_and_pack_boundaries(struct adapter *sc)
|
||||
}
|
||||
}
|
||||
m = V_INGPADBOUNDARY(M_INGPADBOUNDARY);
|
||||
v = V_INGPADBOUNDARY(ilog2(pad) - 5);
|
||||
v = V_INGPADBOUNDARY(ilog2(pad) - pad_shift);
|
||||
t4_set_reg_field(sc, A_SGE_CONTROL, m, v);
|
||||
|
||||
if (is_t4(sc)) {
|
||||
@ -2460,7 +2464,8 @@ eth_tx(struct mp_ring *r, u_int cidx, u_int pidx)
|
||||
total++;
|
||||
remaining--;
|
||||
ETHER_BPF_MTAP(ifp, m0);
|
||||
n = write_txpkt_vm_wr(txq, (void *)wr, m0, available);
|
||||
n = write_txpkt_vm_wr(sc, txq, (void *)wr, m0,
|
||||
available);
|
||||
} else if (remaining > 1 &&
|
||||
try_txpkts(m0, r->items[next_cidx], &txp, available) == 0) {
|
||||
|
||||
@ -2728,8 +2733,10 @@ alloc_iq_fl(struct vi_info *vi, struct sge_iq *iq, struct sge_fl *fl,
|
||||
F_FW_IQ_CMD_FL0CONGEN);
|
||||
}
|
||||
c.fl0dcaen_to_fl0cidxfthresh =
|
||||
htobe16(V_FW_IQ_CMD_FL0FBMIN(X_FETCHBURSTMIN_128B) |
|
||||
V_FW_IQ_CMD_FL0FBMAX(X_FETCHBURSTMAX_512B));
|
||||
htobe16(V_FW_IQ_CMD_FL0FBMIN(chip_id(sc) <= CHELSIO_T5 ?
|
||||
X_FETCHBURSTMIN_128B : X_FETCHBURSTMIN_64B) |
|
||||
V_FW_IQ_CMD_FL0FBMAX(chip_id(sc) <= CHELSIO_T5 ?
|
||||
X_FETCHBURSTMAX_512B : X_FETCHBURSTMAX_256B));
|
||||
c.fl0size = htobe16(fl->qsize);
|
||||
c.fl0addr = htobe64(fl->ba);
|
||||
}
|
||||
@ -3246,8 +3253,9 @@ alloc_nm_txq(struct vi_info *vi, struct sge_nm_txq *nm_txq, int iqidx, int idx,
|
||||
nm_txq->nid = idx;
|
||||
nm_txq->iqidx = iqidx;
|
||||
nm_txq->cpl_ctrl0 = htobe32(V_TXPKT_OPCODE(CPL_TX_PKT) |
|
||||
V_TXPKT_INTF(pi->tx_chan) | V_TXPKT_VF_VLD(1) |
|
||||
V_TXPKT_VF(vi->viid));
|
||||
V_TXPKT_INTF(pi->tx_chan) | V_TXPKT_PF(G_FW_VIID_PFN(vi->viid)) |
|
||||
V_TXPKT_VF(G_FW_VIID_VIN(vi->viid)) |
|
||||
V_TXPKT_VF_VLD(G_FW_VIID_VIVLD(vi->viid)));
|
||||
|
||||
snprintf(name, sizeof(name), "%d", idx);
|
||||
oid = SYSCTL_ADD_NODE(&vi->ctx, children, OID_AUTO, name, CTLFLAG_RD,
|
||||
@ -3613,8 +3621,10 @@ alloc_txq(struct vi_info *vi, struct sge_txq *txq, int idx,
|
||||
V_TXPKT_INTF(pi->tx_chan));
|
||||
else
|
||||
txq->cpl_ctrl0 = htobe32(V_TXPKT_OPCODE(CPL_TX_PKT) |
|
||||
V_TXPKT_INTF(pi->tx_chan) | V_TXPKT_VF_VLD(1) |
|
||||
V_TXPKT_VF(vi->viid));
|
||||
V_TXPKT_INTF(pi->tx_chan) |
|
||||
V_TXPKT_PF(G_FW_VIID_PFN(vi->viid)) |
|
||||
V_TXPKT_VF(G_FW_VIID_VIN(vi->viid)) |
|
||||
V_TXPKT_VF_VLD(G_FW_VIID_VIVLD(vi->viid)));
|
||||
txq->tc_idx = -1;
|
||||
txq->sdesc = malloc(eq->sidx * sizeof(struct tx_sdesc), M_CXGBE,
|
||||
M_ZERO | M_WAITOK);
|
||||
@ -4039,8 +4049,8 @@ imm_payload(u_int ndesc)
|
||||
* The return value is the # of hardware descriptors used.
|
||||
*/
|
||||
static u_int
|
||||
write_txpkt_vm_wr(struct sge_txq *txq, struct fw_eth_tx_pkt_vm_wr *wr,
|
||||
struct mbuf *m0, u_int available)
|
||||
write_txpkt_vm_wr(struct adapter *sc, struct sge_txq *txq,
|
||||
struct fw_eth_tx_pkt_vm_wr *wr, struct mbuf *m0, u_int available)
|
||||
{
|
||||
struct sge_eq *eq = &txq->eq;
|
||||
struct tx_sdesc *txsd;
|
||||
@ -4156,9 +4166,13 @@ write_txpkt_vm_wr(struct sge_txq *txq, struct fw_eth_tx_pkt_vm_wr *wr,
|
||||
("%s: mbuf %p needs checksum offload but missing header lengths",
|
||||
__func__, m0));
|
||||
|
||||
/* XXX: T6 */
|
||||
ctrl1 |= V_TXPKT_ETHHDR_LEN(m0->m_pkthdr.l2hlen -
|
||||
ETHER_HDR_LEN);
|
||||
if (chip_id(sc) <= CHELSIO_T5) {
|
||||
ctrl1 |= V_TXPKT_ETHHDR_LEN(m0->m_pkthdr.l2hlen -
|
||||
ETHER_HDR_LEN);
|
||||
} else {
|
||||
ctrl1 |= V_T6_TXPKT_ETHHDR_LEN(m0->m_pkthdr.l2hlen -
|
||||
ETHER_HDR_LEN);
|
||||
}
|
||||
ctrl1 |= V_TXPKT_IPHDR_LEN(m0->m_pkthdr.l3hlen);
|
||||
ctrl1 |= V_TXPKT_CSUM_TYPE(csum_type);
|
||||
} else
|
||||
|
@ -124,7 +124,8 @@ t4_cloner_match(struct if_clone *ifc, const char *name)
|
||||
{
|
||||
|
||||
if (strncmp(name, "t4nex", 5) != 0 &&
|
||||
strncmp(name, "t5nex", 5) != 0)
|
||||
strncmp(name, "t5nex", 5) != 0 &&
|
||||
strncmp(name, "t6nex", 5) != 0)
|
||||
return (0);
|
||||
if (name[5] < '0' || name[5] > '9')
|
||||
return (0);
|
||||
|
@ -111,6 +111,12 @@ struct {
|
||||
{0x580f, "Chelsio Amsterdam VF"},
|
||||
{0x5813, "Chelsio T580-CHR VF"},
|
||||
#endif
|
||||
}, t6vf_pciids[] = {
|
||||
{0x6801, "Chelsio T6225-CR VF"}, /* 2 x 10/25G */
|
||||
{0x6802, "Chelsio T6225-SO-CR VF"}, /* 2 x 10/25G, nomem */
|
||||
{0x6807, "Chelsio T62100-LP-CR VF"}, /* 2 x 40/50/100G */
|
||||
{0x6808, "Chelsio T62100-SO-CR VF"}, /* 2 x 40/50/100G, nomem */
|
||||
{0x680d, "Chelsio T62100-CR VF"}, /* 2 x 40/50/100G */
|
||||
};
|
||||
|
||||
static d_ioctl_t t4vf_ioctl;
|
||||
@ -124,7 +130,7 @@ static struct cdevsw t4vf_cdevsw = {
|
||||
static int
|
||||
t4vf_probe(device_t dev)
|
||||
{
|
||||
uint16_t d;
|
||||
uint16_t d;
|
||||
size_t i;
|
||||
|
||||
d = pci_get_device(dev);
|
||||
@ -140,7 +146,7 @@ t4vf_probe(device_t dev)
|
||||
static int
|
||||
t5vf_probe(device_t dev)
|
||||
{
|
||||
uint16_t d;
|
||||
uint16_t d;
|
||||
size_t i;
|
||||
|
||||
d = pci_get_device(dev);
|
||||
@ -153,6 +159,22 @@ t5vf_probe(device_t dev)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
t6vf_probe(device_t dev)
|
||||
{
|
||||
uint16_t d;
|
||||
size_t i;
|
||||
|
||||
d = pci_get_device(dev);
|
||||
for (i = 0; i < nitems(t6vf_pciids); i++) {
|
||||
if (d == t6vf_pciids[i].device) {
|
||||
device_set_desc(dev, t6vf_pciids[i].desc);
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
}
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
#define FW_PARAM_DEV(param) \
|
||||
(V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
|
||||
V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))
|
||||
@ -498,6 +520,12 @@ t4vf_attach(device_t dev)
|
||||
if (rc != 0)
|
||||
goto done;
|
||||
|
||||
t4_init_devnames(sc);
|
||||
if (sc->names == NULL) {
|
||||
rc = ENOTSUP;
|
||||
goto done; /* error message displayed already */
|
||||
}
|
||||
|
||||
/*
|
||||
* Leave the 'pf' and 'mbox' values as zero. This ensures
|
||||
* that various firmware messages do not set the fields which
|
||||
@ -642,8 +670,7 @@ t4vf_attach(device_t dev)
|
||||
|
||||
pi->linkdnrc = -1;
|
||||
|
||||
pi->dev = device_add_child(dev, is_t4(sc) ? "cxgbev" : "cxlv",
|
||||
-1);
|
||||
pi->dev = device_add_child(dev, sc->names->vf_ifnet_name, -1);
|
||||
if (pi->dev == NULL) {
|
||||
device_printf(dev,
|
||||
"failed to add device for port %d.\n", i);
|
||||
@ -653,7 +680,7 @@ t4vf_attach(device_t dev)
|
||||
pi->vi[0].dev = pi->dev;
|
||||
device_set_softc(pi->dev, pi);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Interrupt type, # of interrupts, # of rx/tx queues, etc.
|
||||
*/
|
||||
@ -920,6 +947,20 @@ static driver_t t5vf_driver = {
|
||||
sizeof(struct adapter)
|
||||
};
|
||||
|
||||
static device_method_t t6vf_methods[] = {
|
||||
DEVMETHOD(device_probe, t6vf_probe),
|
||||
DEVMETHOD(device_attach, t4vf_attach),
|
||||
DEVMETHOD(device_detach, t4_detach_common),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t t6vf_driver = {
|
||||
"t6vf",
|
||||
t6vf_methods,
|
||||
sizeof(struct adapter)
|
||||
};
|
||||
|
||||
static driver_t cxgbev_driver = {
|
||||
"cxgbev",
|
||||
cxgbe_methods,
|
||||
@ -932,8 +973,14 @@ static driver_t cxlv_driver = {
|
||||
sizeof(struct port_info)
|
||||
};
|
||||
|
||||
static devclass_t t4vf_devclass, t5vf_devclass;
|
||||
static devclass_t cxgbev_devclass, cxlv_devclass;
|
||||
static driver_t ccv_driver = {
|
||||
"ccv",
|
||||
cxgbe_methods,
|
||||
sizeof(struct port_info)
|
||||
};
|
||||
|
||||
static devclass_t t4vf_devclass, t5vf_devclass, t6vf_devclass;
|
||||
static devclass_t cxgbev_devclass, cxlv_devclass, ccv_devclass;
|
||||
|
||||
DRIVER_MODULE(t4vf, pci, t4vf_driver, t4vf_devclass, 0, 0);
|
||||
MODULE_VERSION(t4vf, 1);
|
||||
@ -943,8 +990,15 @@ DRIVER_MODULE(t5vf, pci, t5vf_driver, t5vf_devclass, 0, 0);
|
||||
MODULE_VERSION(t5vf, 1);
|
||||
MODULE_DEPEND(t5vf, t5nex, 1, 1, 1);
|
||||
|
||||
DRIVER_MODULE(t6vf, pci, t6vf_driver, t6vf_devclass, 0, 0);
|
||||
MODULE_VERSION(t6vf, 1);
|
||||
MODULE_DEPEND(t6vf, t6nex, 1, 1, 1);
|
||||
|
||||
DRIVER_MODULE(cxgbev, t4vf, cxgbev_driver, cxgbev_devclass, 0, 0);
|
||||
MODULE_VERSION(cxgbev, 1);
|
||||
|
||||
DRIVER_MODULE(cxlv, t5vf, cxlv_driver, cxlv_devclass, 0, 0);
|
||||
MODULE_VERSION(cxlv, 1);
|
||||
|
||||
DRIVER_MODULE(ccv, t6vf, ccv_driver, ccv_devclass, 0, 0);
|
||||
MODULE_VERSION(ccv, 1);
|
||||
|
860
sys/dev/evdev/cdev.c
Normal file
860
sys/dev/evdev/cdev.c
Normal file
@ -0,0 +1,860 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
|
||||
* Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_evdev.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/bitstring.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/filio.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <dev/evdev/input.h>
|
||||
#include <dev/evdev/evdev.h>
|
||||
#include <dev/evdev/evdev_private.h>
|
||||
|
||||
#ifdef EVDEV_DEBUG
|
||||
#define debugf(client, fmt, args...) printf("evdev cdev: "fmt"\n", ##args)
|
||||
#else
|
||||
#define debugf(client, fmt, args...)
|
||||
#endif
|
||||
|
||||
#define DEF_RING_REPORTS 8
|
||||
|
||||
static d_open_t evdev_open;
|
||||
static d_read_t evdev_read;
|
||||
static d_write_t evdev_write;
|
||||
static d_ioctl_t evdev_ioctl;
|
||||
static d_poll_t evdev_poll;
|
||||
static d_kqfilter_t evdev_kqfilter;
|
||||
|
||||
static int evdev_kqread(struct knote *kn, long hint);
|
||||
static void evdev_kqdetach(struct knote *kn);
|
||||
static void evdev_dtor(void *);
|
||||
static int evdev_ioctl_eviocgbit(struct evdev_dev *, int, int, caddr_t);
|
||||
static void evdev_client_filter_queue(struct evdev_client *, uint16_t);
|
||||
|
||||
static struct cdevsw evdev_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_open = evdev_open,
|
||||
.d_read = evdev_read,
|
||||
.d_write = evdev_write,
|
||||
.d_ioctl = evdev_ioctl,
|
||||
.d_poll = evdev_poll,
|
||||
.d_kqfilter = evdev_kqfilter,
|
||||
.d_name = "evdev",
|
||||
};
|
||||
|
||||
static struct filterops evdev_cdev_filterops = {
|
||||
.f_isfd = 1,
|
||||
.f_attach = NULL,
|
||||
.f_detach = evdev_kqdetach,
|
||||
.f_event = evdev_kqread,
|
||||
};
|
||||
|
||||
static int
|
||||
evdev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
||||
{
|
||||
struct evdev_dev *evdev = dev->si_drv1;
|
||||
struct evdev_client *client;
|
||||
size_t buffer_size;
|
||||
int ret;
|
||||
|
||||
if (evdev == NULL)
|
||||
return (ENODEV);
|
||||
|
||||
/* Initialize client structure */
|
||||
buffer_size = evdev->ev_report_size * DEF_RING_REPORTS;
|
||||
client = malloc(offsetof(struct evdev_client, ec_buffer) +
|
||||
sizeof(struct input_event) * buffer_size,
|
||||
M_EVDEV, M_WAITOK | M_ZERO);
|
||||
|
||||
/* Initialize ring buffer */
|
||||
client->ec_buffer_size = buffer_size;
|
||||
client->ec_buffer_head = 0;
|
||||
client->ec_buffer_tail = 0;
|
||||
client->ec_buffer_ready = 0;
|
||||
|
||||
client->ec_evdev = evdev;
|
||||
mtx_init(&client->ec_buffer_mtx, "evclient", "evdev", MTX_DEF);
|
||||
knlist_init_mtx(&client->ec_selp.si_note, &client->ec_buffer_mtx);
|
||||
|
||||
/* Avoid race with evdev_unregister */
|
||||
EVDEV_LOCK(evdev);
|
||||
if (dev->si_drv1 == NULL)
|
||||
ret = ENODEV;
|
||||
else
|
||||
ret = evdev_register_client(evdev, client);
|
||||
|
||||
if (ret != 0)
|
||||
evdev_revoke_client(client);
|
||||
/*
|
||||
* Unlock evdev here because non-sleepable lock held
|
||||
* while calling devfs_set_cdevpriv upsets WITNESS
|
||||
*/
|
||||
EVDEV_UNLOCK(evdev);
|
||||
|
||||
if (!ret)
|
||||
ret = devfs_set_cdevpriv(client, evdev_dtor);
|
||||
|
||||
if (ret != 0) {
|
||||
debugf(client, "cannot register evdev client");
|
||||
evdev_dtor(client);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_dtor(void *data)
|
||||
{
|
||||
struct evdev_client *client = (struct evdev_client *)data;
|
||||
|
||||
EVDEV_LOCK(client->ec_evdev);
|
||||
if (!client->ec_revoked)
|
||||
evdev_dispose_client(client->ec_evdev, client);
|
||||
EVDEV_UNLOCK(client->ec_evdev);
|
||||
|
||||
knlist_clear(&client->ec_selp.si_note, 0);
|
||||
seldrain(&client->ec_selp);
|
||||
knlist_destroy(&client->ec_selp.si_note);
|
||||
funsetown(&client->ec_sigio);
|
||||
mtx_destroy(&client->ec_buffer_mtx);
|
||||
free(client, M_EVDEV);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_read(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct evdev_client *client;
|
||||
struct input_event *event;
|
||||
int ret = 0;
|
||||
int remaining;
|
||||
|
||||
ret = devfs_get_cdevpriv((void **)&client);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
debugf(client, "read %zd bytes by thread %d", uio->uio_resid,
|
||||
uio->uio_td->td_tid);
|
||||
|
||||
if (client->ec_revoked)
|
||||
return (ENODEV);
|
||||
|
||||
/* Zero-sized reads are allowed for error checking */
|
||||
if (uio->uio_resid != 0 && uio->uio_resid < sizeof(struct input_event))
|
||||
return (EINVAL);
|
||||
|
||||
remaining = uio->uio_resid / sizeof(struct input_event);
|
||||
|
||||
EVDEV_CLIENT_LOCKQ(client);
|
||||
|
||||
if (EVDEV_CLIENT_EMPTYQ(client)) {
|
||||
if (ioflag & O_NONBLOCK)
|
||||
ret = EWOULDBLOCK;
|
||||
else {
|
||||
if (remaining != 0) {
|
||||
client->ec_blocked = true;
|
||||
ret = mtx_sleep(client, &client->ec_buffer_mtx,
|
||||
PCATCH, "evread", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (ret == 0 && !EVDEV_CLIENT_EMPTYQ(client) && remaining > 0) {
|
||||
event = &client->ec_buffer[client->ec_buffer_head];
|
||||
client->ec_buffer_head =
|
||||
(client->ec_buffer_head + 1) % client->ec_buffer_size;
|
||||
remaining--;
|
||||
|
||||
EVDEV_CLIENT_UNLOCKQ(client);
|
||||
ret = uiomove(event, sizeof(struct input_event), uio);
|
||||
EVDEV_CLIENT_LOCKQ(client);
|
||||
}
|
||||
|
||||
EVDEV_CLIENT_UNLOCKQ(client);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct evdev_dev *evdev = dev->si_drv1;
|
||||
struct evdev_client *client;
|
||||
struct input_event event;
|
||||
int ret = 0;
|
||||
|
||||
ret = devfs_get_cdevpriv((void **)&client);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
debugf(client, "write %zd bytes by thread %d", uio->uio_resid,
|
||||
uio->uio_td->td_tid);
|
||||
|
||||
if (client->ec_revoked || evdev == NULL)
|
||||
return (ENODEV);
|
||||
|
||||
if (uio->uio_resid % sizeof(struct input_event) != 0) {
|
||||
debugf(client, "write size not multiple of input_event size");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
while (uio->uio_resid > 0 && ret == 0) {
|
||||
ret = uiomove(&event, sizeof(struct input_event), uio);
|
||||
if (ret == 0)
|
||||
ret = evdev_inject_event(evdev, event.type, event.code,
|
||||
event.value);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_poll(struct cdev *dev, int events, struct thread *td)
|
||||
{
|
||||
struct evdev_client *client;
|
||||
int ret;
|
||||
int revents = 0;
|
||||
|
||||
ret = devfs_get_cdevpriv((void **)&client);
|
||||
if (ret != 0)
|
||||
return (POLLNVAL);
|
||||
|
||||
debugf(client, "poll by thread %d", td->td_tid);
|
||||
|
||||
if (client->ec_revoked)
|
||||
return (POLLHUP);
|
||||
|
||||
if (events & (POLLIN | POLLRDNORM)) {
|
||||
EVDEV_CLIENT_LOCKQ(client);
|
||||
if (!EVDEV_CLIENT_EMPTYQ(client))
|
||||
revents = events & (POLLIN | POLLRDNORM);
|
||||
else {
|
||||
client->ec_selected = true;
|
||||
selrecord(td, &client->ec_selp);
|
||||
}
|
||||
EVDEV_CLIENT_UNLOCKQ(client);
|
||||
}
|
||||
|
||||
return (revents);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_kqfilter(struct cdev *dev, struct knote *kn)
|
||||
{
|
||||
struct evdev_client *client;
|
||||
int ret;
|
||||
|
||||
ret = devfs_get_cdevpriv((void **)&client);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
if (client->ec_revoked)
|
||||
return (ENODEV);
|
||||
|
||||
switch(kn->kn_filter) {
|
||||
case EVFILT_READ:
|
||||
kn->kn_fop = &evdev_cdev_filterops;
|
||||
break;
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
kn->kn_hook = (caddr_t)client;
|
||||
|
||||
knlist_add(&client->ec_selp.si_note, kn, 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_kqread(struct knote *kn, long hint)
|
||||
{
|
||||
struct evdev_client *client;
|
||||
int ret;
|
||||
|
||||
client = (struct evdev_client *)kn->kn_hook;
|
||||
|
||||
EVDEV_CLIENT_LOCKQ_ASSERT(client);
|
||||
|
||||
if (client->ec_revoked) {
|
||||
kn->kn_flags |= EV_EOF;
|
||||
ret = 1;
|
||||
} else {
|
||||
kn->kn_data = EVDEV_CLIENT_SIZEQ(client) *
|
||||
sizeof(struct input_event);
|
||||
ret = !EVDEV_CLIENT_EMPTYQ(client);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_kqdetach(struct knote *kn)
|
||||
{
|
||||
struct evdev_client *client;
|
||||
|
||||
client = (struct evdev_client *)kn->kn_hook;
|
||||
knlist_remove(&client->ec_selp.si_note, kn, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
||||
struct thread *td)
|
||||
{
|
||||
struct evdev_dev *evdev = dev->si_drv1;
|
||||
struct evdev_client *client;
|
||||
struct input_keymap_entry *ke;
|
||||
int ret, len, limit, type_num;
|
||||
uint32_t code;
|
||||
size_t nvalues;
|
||||
|
||||
ret = devfs_get_cdevpriv((void **)&client);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
if (client->ec_revoked || evdev == NULL)
|
||||
return (ENODEV);
|
||||
|
||||
/* file I/O ioctl handling */
|
||||
switch (cmd) {
|
||||
case FIOSETOWN:
|
||||
return (fsetown(*(int *)data, &client->ec_sigio));
|
||||
|
||||
case FIOGETOWN:
|
||||
*(int *)data = fgetown(&client->ec_sigio);
|
||||
return (0);
|
||||
|
||||
case FIONBIO:
|
||||
return (0);
|
||||
|
||||
case FIOASYNC:
|
||||
if (*(int *)data)
|
||||
client->ec_async = true;
|
||||
else
|
||||
client->ec_async = false;
|
||||
|
||||
return (0);
|
||||
|
||||
case FIONREAD:
|
||||
EVDEV_CLIENT_LOCKQ(client);
|
||||
*(int *)data =
|
||||
EVDEV_CLIENT_SIZEQ(client) * sizeof(struct input_event);
|
||||
EVDEV_CLIENT_UNLOCKQ(client);
|
||||
return (0);
|
||||
}
|
||||
|
||||
len = IOCPARM_LEN(cmd);
|
||||
debugf(client, "ioctl called: cmd=0x%08lx, data=%p", cmd, data);
|
||||
|
||||
/* evdev fixed-length ioctls handling */
|
||||
switch (cmd) {
|
||||
case EVIOCGVERSION:
|
||||
*(int *)data = EV_VERSION;
|
||||
return (0);
|
||||
|
||||
case EVIOCGID:
|
||||
debugf(client, "EVIOCGID: bus=%d vendor=0x%04x product=0x%04x",
|
||||
evdev->ev_id.bustype, evdev->ev_id.vendor,
|
||||
evdev->ev_id.product);
|
||||
memcpy(data, &evdev->ev_id, sizeof(struct input_id));
|
||||
return (0);
|
||||
|
||||
case EVIOCGREP:
|
||||
if (!evdev_event_supported(evdev, EV_REP))
|
||||
return (ENOTSUP);
|
||||
|
||||
memcpy(data, evdev->ev_rep, sizeof(evdev->ev_rep));
|
||||
return (0);
|
||||
|
||||
case EVIOCSREP:
|
||||
if (!evdev_event_supported(evdev, EV_REP))
|
||||
return (ENOTSUP);
|
||||
|
||||
evdev_inject_event(evdev, EV_REP, REP_DELAY, ((int *)data)[0]);
|
||||
evdev_inject_event(evdev, EV_REP, REP_PERIOD,
|
||||
((int *)data)[1]);
|
||||
return (0);
|
||||
|
||||
case EVIOCGKEYCODE:
|
||||
/* Fake unsupported ioctl */
|
||||
return (0);
|
||||
|
||||
case EVIOCGKEYCODE_V2:
|
||||
if (evdev->ev_methods == NULL ||
|
||||
evdev->ev_methods->ev_get_keycode == NULL)
|
||||
return (ENOTSUP);
|
||||
|
||||
ke = (struct input_keymap_entry *)data;
|
||||
evdev->ev_methods->ev_get_keycode(evdev, evdev->ev_softc, ke);
|
||||
return (0);
|
||||
|
||||
case EVIOCSKEYCODE:
|
||||
/* Fake unsupported ioctl */
|
||||
return (0);
|
||||
|
||||
case EVIOCSKEYCODE_V2:
|
||||
if (evdev->ev_methods == NULL ||
|
||||
evdev->ev_methods->ev_set_keycode == NULL)
|
||||
return (ENOTSUP);
|
||||
|
||||
ke = (struct input_keymap_entry *)data;
|
||||
evdev->ev_methods->ev_set_keycode(evdev, evdev->ev_softc, ke);
|
||||
return (0);
|
||||
|
||||
case EVIOCGABS(0) ... EVIOCGABS(ABS_MAX):
|
||||
if (evdev->ev_absinfo == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
memcpy(data, &evdev->ev_absinfo[cmd - EVIOCGABS(0)],
|
||||
sizeof(struct input_absinfo));
|
||||
return (0);
|
||||
|
||||
case EVIOCSABS(0) ... EVIOCSABS(ABS_MAX):
|
||||
if (evdev->ev_absinfo == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
code = cmd - EVIOCSABS(0);
|
||||
/* mt-slot number can not be changed */
|
||||
if (code == ABS_MT_SLOT)
|
||||
return (EINVAL);
|
||||
|
||||
EVDEV_LOCK(evdev);
|
||||
evdev_set_absinfo(evdev, code, (struct input_absinfo *)data);
|
||||
EVDEV_UNLOCK(evdev);
|
||||
return (0);
|
||||
|
||||
case EVIOCSFF:
|
||||
case EVIOCRMFF:
|
||||
case EVIOCGEFFECTS:
|
||||
/* Fake unsupported ioctls */
|
||||
return (0);
|
||||
|
||||
case EVIOCGRAB:
|
||||
EVDEV_LOCK(evdev);
|
||||
if (*(int *)data)
|
||||
ret = evdev_grab_client(evdev, client);
|
||||
else
|
||||
ret = evdev_release_client(evdev, client);
|
||||
EVDEV_UNLOCK(evdev);
|
||||
return (ret);
|
||||
|
||||
case EVIOCREVOKE:
|
||||
if (*(int *)data != 0)
|
||||
return (EINVAL);
|
||||
|
||||
EVDEV_LOCK(evdev);
|
||||
if (dev->si_drv1 != NULL && !client->ec_revoked) {
|
||||
evdev_dispose_client(evdev, client);
|
||||
evdev_revoke_client(client);
|
||||
}
|
||||
EVDEV_UNLOCK(evdev);
|
||||
return (0);
|
||||
|
||||
case EVIOCSCLOCKID:
|
||||
switch (*(int *)data) {
|
||||
case CLOCK_REALTIME:
|
||||
client->ec_clock_id = EV_CLOCK_REALTIME;
|
||||
return (0);
|
||||
case CLOCK_MONOTONIC:
|
||||
client->ec_clock_id = EV_CLOCK_MONOTONIC;
|
||||
return (0);
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* evdev variable-length ioctls handling */
|
||||
switch (IOCBASECMD(cmd)) {
|
||||
case EVIOCGNAME(0):
|
||||
strlcpy(data, evdev->ev_name, len);
|
||||
return (0);
|
||||
|
||||
case EVIOCGPHYS(0):
|
||||
if (evdev->ev_shortname[0] == 0)
|
||||
return (ENOENT);
|
||||
|
||||
strlcpy(data, evdev->ev_shortname, len);
|
||||
return (0);
|
||||
|
||||
case EVIOCGUNIQ(0):
|
||||
if (evdev->ev_serial[0] == 0)
|
||||
return (ENOENT);
|
||||
|
||||
strlcpy(data, evdev->ev_serial, len);
|
||||
return (0);
|
||||
|
||||
case EVIOCGPROP(0):
|
||||
limit = MIN(len, bitstr_size(INPUT_PROP_CNT));
|
||||
memcpy(data, evdev->ev_prop_flags, limit);
|
||||
return (0);
|
||||
|
||||
case EVIOCGMTSLOTS(0):
|
||||
if (evdev->ev_mt == NULL)
|
||||
return (EINVAL);
|
||||
if (len < sizeof(uint32_t))
|
||||
return (EINVAL);
|
||||
code = *(uint32_t *)data;
|
||||
if (!ABS_IS_MT(code))
|
||||
return (EINVAL);
|
||||
|
||||
nvalues =
|
||||
MIN(len / sizeof(int32_t) - 1, MAXIMAL_MT_SLOT(evdev) + 1);
|
||||
for (int i = 0; i < nvalues; i++)
|
||||
((int32_t *)data)[i + 1] =
|
||||
evdev_get_mt_value(evdev, i, code);
|
||||
return (0);
|
||||
|
||||
case EVIOCGKEY(0):
|
||||
limit = MIN(len, bitstr_size(KEY_CNT));
|
||||
EVDEV_LOCK(evdev);
|
||||
evdev_client_filter_queue(client, EV_KEY);
|
||||
memcpy(data, evdev->ev_key_states, limit);
|
||||
EVDEV_UNLOCK(evdev);
|
||||
return (0);
|
||||
|
||||
case EVIOCGLED(0):
|
||||
limit = MIN(len, bitstr_size(LED_CNT));
|
||||
EVDEV_LOCK(evdev);
|
||||
evdev_client_filter_queue(client, EV_LED);
|
||||
memcpy(data, evdev->ev_led_states, limit);
|
||||
EVDEV_UNLOCK(evdev);
|
||||
return (0);
|
||||
|
||||
case EVIOCGSND(0):
|
||||
limit = MIN(len, bitstr_size(SND_CNT));
|
||||
EVDEV_LOCK(evdev);
|
||||
evdev_client_filter_queue(client, EV_SND);
|
||||
memcpy(data, evdev->ev_snd_states, limit);
|
||||
EVDEV_UNLOCK(evdev);
|
||||
return (0);
|
||||
|
||||
case EVIOCGSW(0):
|
||||
limit = MIN(len, bitstr_size(SW_CNT));
|
||||
EVDEV_LOCK(evdev);
|
||||
evdev_client_filter_queue(client, EV_SW);
|
||||
memcpy(data, evdev->ev_sw_states, limit);
|
||||
EVDEV_UNLOCK(evdev);
|
||||
return (0);
|
||||
|
||||
case EVIOCGBIT(0, 0) ... EVIOCGBIT(EV_MAX, 0):
|
||||
type_num = IOCBASECMD(cmd) - EVIOCGBIT(0, 0);
|
||||
debugf(client, "EVIOCGBIT(%d): data=%p, len=%d", type_num,
|
||||
data, len);
|
||||
return (evdev_ioctl_eviocgbit(evdev, type_num, len, data));
|
||||
}
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_ioctl_eviocgbit(struct evdev_dev *evdev, int type, int len, caddr_t data)
|
||||
{
|
||||
unsigned long *bitmap;
|
||||
int limit;
|
||||
|
||||
switch (type) {
|
||||
case 0:
|
||||
bitmap = evdev->ev_type_flags;
|
||||
limit = EV_CNT;
|
||||
break;
|
||||
case EV_KEY:
|
||||
bitmap = evdev->ev_key_flags;
|
||||
limit = KEY_CNT;
|
||||
break;
|
||||
case EV_REL:
|
||||
bitmap = evdev->ev_rel_flags;
|
||||
limit = REL_CNT;
|
||||
break;
|
||||
case EV_ABS:
|
||||
bitmap = evdev->ev_abs_flags;
|
||||
limit = ABS_CNT;
|
||||
break;
|
||||
case EV_MSC:
|
||||
bitmap = evdev->ev_msc_flags;
|
||||
limit = MSC_CNT;
|
||||
break;
|
||||
case EV_LED:
|
||||
bitmap = evdev->ev_led_flags;
|
||||
limit = LED_CNT;
|
||||
break;
|
||||
case EV_SND:
|
||||
bitmap = evdev->ev_snd_flags;
|
||||
limit = SND_CNT;
|
||||
break;
|
||||
case EV_SW:
|
||||
bitmap = evdev->ev_sw_flags;
|
||||
limit = SW_CNT;
|
||||
break;
|
||||
case EV_FF:
|
||||
/*
|
||||
* We don't support EV_FF now, so let's
|
||||
* just fake it returning only zeros.
|
||||
*/
|
||||
bzero(data, len);
|
||||
return (0);
|
||||
default:
|
||||
return (ENOTTY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear ioctl data buffer in case it's bigger than
|
||||
* bitmap size
|
||||
*/
|
||||
bzero(data, len);
|
||||
|
||||
limit = bitstr_size(limit);
|
||||
len = MIN(limit, len);
|
||||
memcpy(data, bitmap, len);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_revoke_client(struct evdev_client *client)
|
||||
{
|
||||
|
||||
EVDEV_LOCK_ASSERT(client->ec_evdev);
|
||||
|
||||
client->ec_revoked = true;
|
||||
}
|
||||
|
||||
void
|
||||
evdev_notify_event(struct evdev_client *client)
|
||||
{
|
||||
|
||||
EVDEV_CLIENT_LOCKQ_ASSERT(client);
|
||||
|
||||
if (client->ec_blocked) {
|
||||
client->ec_blocked = false;
|
||||
wakeup(client);
|
||||
}
|
||||
if (client->ec_selected) {
|
||||
client->ec_selected = false;
|
||||
selwakeup(&client->ec_selp);
|
||||
}
|
||||
KNOTE_LOCKED(&client->ec_selp.si_note, 0);
|
||||
|
||||
if (client->ec_async && client->ec_sigio != NULL)
|
||||
pgsigio(&client->ec_sigio, SIGIO, 0);
|
||||
}
|
||||
|
||||
int
|
||||
evdev_cdev_create(struct evdev_dev *evdev)
|
||||
{
|
||||
struct make_dev_args mda;
|
||||
int ret, unit = 0;
|
||||
|
||||
make_dev_args_init(&mda);
|
||||
mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME;
|
||||
mda.mda_devsw = &evdev_cdevsw;
|
||||
mda.mda_uid = UID_ROOT;
|
||||
mda.mda_gid = GID_WHEEL;
|
||||
mda.mda_mode = 0600;
|
||||
mda.mda_si_drv1 = evdev;
|
||||
|
||||
/* Try to coexist with cuse-backed input/event devices */
|
||||
while ((ret = make_dev_s(&mda, &evdev->ev_cdev, "input/event%d", unit))
|
||||
== EEXIST)
|
||||
unit++;
|
||||
|
||||
if (ret == 0)
|
||||
evdev->ev_unit = unit;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
evdev_cdev_destroy(struct evdev_dev *evdev)
|
||||
{
|
||||
|
||||
destroy_dev(evdev->ev_cdev);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_client_gettime(struct evdev_client *client, struct timeval *tv)
|
||||
{
|
||||
|
||||
switch (client->ec_clock_id) {
|
||||
case EV_CLOCK_BOOTTIME:
|
||||
/*
|
||||
* XXX: FreeBSD does not support true POSIX monotonic clock.
|
||||
* So aliase EV_CLOCK_BOOTTIME to EV_CLOCK_MONOTONIC.
|
||||
*/
|
||||
case EV_CLOCK_MONOTONIC:
|
||||
microuptime(tv);
|
||||
break;
|
||||
|
||||
case EV_CLOCK_REALTIME:
|
||||
default:
|
||||
microtime(tv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evdev_client_push(struct evdev_client *client, uint16_t type, uint16_t code,
|
||||
int32_t value)
|
||||
{
|
||||
struct timeval time;
|
||||
size_t count, head, tail, ready;
|
||||
|
||||
EVDEV_CLIENT_LOCKQ_ASSERT(client);
|
||||
head = client->ec_buffer_head;
|
||||
tail = client->ec_buffer_tail;
|
||||
ready = client->ec_buffer_ready;
|
||||
count = client->ec_buffer_size;
|
||||
|
||||
/* If queue is full drop its content and place SYN_DROPPED event */
|
||||
if ((tail + 1) % count == head) {
|
||||
debugf(client, "client %p: buffer overflow", client);
|
||||
|
||||
head = (tail + count - 1) % count;
|
||||
client->ec_buffer[head] = (struct input_event) {
|
||||
.type = EV_SYN,
|
||||
.code = SYN_DROPPED,
|
||||
.value = 0
|
||||
};
|
||||
/*
|
||||
* XXX: Here is a small race window from now till the end of
|
||||
* report. The queue is empty but client has been already
|
||||
* notified of data readyness. Can be fixed in two ways:
|
||||
* 1. Implement bulk insert so queue lock would not be dropped
|
||||
* till the SYN_REPORT event.
|
||||
* 2. Insert SYN_REPORT just now and skip remaining events
|
||||
*/
|
||||
client->ec_buffer_head = head;
|
||||
client->ec_buffer_ready = head;
|
||||
}
|
||||
|
||||
client->ec_buffer[tail].type = type;
|
||||
client->ec_buffer[tail].code = code;
|
||||
client->ec_buffer[tail].value = value;
|
||||
client->ec_buffer_tail = (tail + 1) % count;
|
||||
|
||||
/* Allow users to read events only after report has been completed */
|
||||
if (type == EV_SYN && code == SYN_REPORT) {
|
||||
evdev_client_gettime(client, &time);
|
||||
for (; ready != client->ec_buffer_tail;
|
||||
ready = (ready + 1) % count)
|
||||
client->ec_buffer[ready].time = time;
|
||||
client->ec_buffer_ready = client->ec_buffer_tail;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
evdev_client_dumpqueue(struct evdev_client *client)
|
||||
{
|
||||
struct input_event *event;
|
||||
size_t i, head, tail, ready, size;
|
||||
|
||||
head = client->ec_buffer_head;
|
||||
tail = client->ec_buffer_tail;
|
||||
ready = client->ec_buffer_ready;
|
||||
size = client->ec_buffer_size;
|
||||
|
||||
printf("evdev client: %p\n", client);
|
||||
printf("event queue: head=%zu ready=%zu tail=%zu size=%zu\n",
|
||||
head, ready, tail, size);
|
||||
|
||||
printf("queue contents:\n");
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
event = &client->ec_buffer[i];
|
||||
printf("%zu: ", i);
|
||||
|
||||
if (i < head || i > tail)
|
||||
printf("unused\n");
|
||||
else
|
||||
printf("type=%d code=%d value=%d ", event->type,
|
||||
event->code, event->value);
|
||||
|
||||
if (i == head)
|
||||
printf("<- head\n");
|
||||
else if (i == tail)
|
||||
printf("<- tail\n");
|
||||
else if (i == ready)
|
||||
printf("<- ready\n");
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_client_filter_queue(struct evdev_client *client, uint16_t type)
|
||||
{
|
||||
struct input_event *event;
|
||||
size_t head, tail, count, i;
|
||||
bool last_was_syn = false;
|
||||
|
||||
EVDEV_CLIENT_LOCKQ(client);
|
||||
|
||||
i = head = client->ec_buffer_head;
|
||||
tail = client->ec_buffer_tail;
|
||||
count = client->ec_buffer_size;
|
||||
client->ec_buffer_ready = client->ec_buffer_tail;
|
||||
|
||||
while (i != client->ec_buffer_tail) {
|
||||
event = &client->ec_buffer[i];
|
||||
i = (i + 1) % count;
|
||||
|
||||
/* Skip event of given type */
|
||||
if (event->type == type)
|
||||
continue;
|
||||
|
||||
/* Remove empty SYN_REPORT events */
|
||||
if (event->type == EV_SYN && event->code == SYN_REPORT) {
|
||||
if (last_was_syn)
|
||||
continue;
|
||||
else
|
||||
client->ec_buffer_ready = (tail + 1) % count;
|
||||
}
|
||||
|
||||
/* Rewrite entry */
|
||||
memcpy(&client->ec_buffer[tail], event,
|
||||
sizeof(struct input_event));
|
||||
|
||||
last_was_syn = (event->type == EV_SYN &&
|
||||
event->code == SYN_REPORT);
|
||||
|
||||
tail = (tail + 1) % count;
|
||||
}
|
||||
|
||||
client->ec_buffer_head = i;
|
||||
client->ec_buffer_tail = tail;
|
||||
|
||||
EVDEV_CLIENT_UNLOCKQ(client);
|
||||
}
|
917
sys/dev/evdev/evdev.c
Normal file
917
sys/dev/evdev/evdev.c
Normal file
@ -0,0 +1,917 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
|
||||
* Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_evdev.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/bitstring.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <dev/evdev/input.h>
|
||||
#include <dev/evdev/evdev.h>
|
||||
#include <dev/evdev/evdev_private.h>
|
||||
|
||||
#ifdef EVDEV_DEBUG
|
||||
#define debugf(evdev, fmt, args...) printf("evdev: " fmt "\n", ##args)
|
||||
#else
|
||||
#define debugf(evdev, fmt, args...)
|
||||
#endif
|
||||
|
||||
#ifdef FEATURE
|
||||
FEATURE(evdev, "Input event devices support");
|
||||
#endif
|
||||
|
||||
enum evdev_sparse_result
|
||||
{
|
||||
EV_SKIP_EVENT, /* Event value not changed */
|
||||
EV_REPORT_EVENT, /* Event value changed */
|
||||
EV_REPORT_MT_SLOT, /* Event value and MT slot number changed */
|
||||
};
|
||||
|
||||
MALLOC_DEFINE(M_EVDEV, "evdev", "evdev memory");
|
||||
|
||||
int evdev_rcpt_mask = EVDEV_RCPT_SYSMOUSE | EVDEV_RCPT_KBDMUX;
|
||||
|
||||
SYSCTL_NODE(_kern, OID_AUTO, evdev, CTLFLAG_RW, 0, "Evdev args");
|
||||
SYSCTL_INT(_kern_evdev, OID_AUTO, rcpt_mask, CTLFLAG_RW, &evdev_rcpt_mask, 0,
|
||||
"Who is receiving events: bit0 - sysmouse, bit1 - kbdmux, "
|
||||
"bit2 - mouse hardware, bit3 - keyboard hardware");
|
||||
|
||||
static void evdev_start_repeat(struct evdev_dev *, uint16_t);
|
||||
static void evdev_stop_repeat(struct evdev_dev *);
|
||||
static int evdev_check_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
|
||||
|
||||
static inline void
|
||||
bit_change(bitstr_t *bitstr, int bit, int value)
|
||||
{
|
||||
if (value)
|
||||
bit_set(bitstr, bit);
|
||||
else
|
||||
bit_clear(bitstr, bit);
|
||||
}
|
||||
|
||||
struct evdev_dev *
|
||||
evdev_alloc(void)
|
||||
{
|
||||
|
||||
return malloc(sizeof(struct evdev_dev), M_EVDEV, M_WAITOK | M_ZERO);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_free(struct evdev_dev *evdev)
|
||||
{
|
||||
|
||||
if (evdev->ev_cdev != NULL && evdev->ev_cdev->si_drv1 != NULL)
|
||||
evdev_unregister(evdev);
|
||||
|
||||
free(evdev, M_EVDEV);
|
||||
}
|
||||
|
||||
static struct input_absinfo *
|
||||
evdev_alloc_absinfo(void)
|
||||
{
|
||||
|
||||
return (malloc(sizeof(struct input_absinfo) * ABS_CNT, M_EVDEV,
|
||||
M_WAITOK | M_ZERO));
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_free_absinfo(struct input_absinfo *absinfo)
|
||||
{
|
||||
|
||||
free(absinfo, M_EVDEV);
|
||||
}
|
||||
|
||||
int
|
||||
evdev_set_report_size(struct evdev_dev *evdev, size_t report_size)
|
||||
{
|
||||
if (report_size > KEY_CNT + REL_CNT + ABS_CNT + MAX_MT_SLOTS * MT_CNT +
|
||||
MSC_CNT + LED_CNT + SND_CNT + SW_CNT + FF_CNT)
|
||||
return (EINVAL);
|
||||
|
||||
evdev->ev_report_size = report_size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static size_t
|
||||
evdev_estimate_report_size(struct evdev_dev *evdev)
|
||||
{
|
||||
size_t size = 0;
|
||||
int res;
|
||||
|
||||
/*
|
||||
* Keyboards generate one event per report but other devices with
|
||||
* buttons like mouses can report events simultaneously
|
||||
*/
|
||||
bit_ffs_at(evdev->ev_key_flags, KEY_OK, KEY_CNT - KEY_OK, &res);
|
||||
if (res == -1)
|
||||
bit_ffs(evdev->ev_key_flags, BTN_MISC, &res);
|
||||
size += (res != -1);
|
||||
bit_count(evdev->ev_key_flags, BTN_MISC, KEY_OK - BTN_MISC, &res);
|
||||
size += res;
|
||||
|
||||
/* All relative axes can be reported simultaneously */
|
||||
bit_count(evdev->ev_rel_flags, 0, REL_CNT, &res);
|
||||
size += res;
|
||||
|
||||
/*
|
||||
* All absolute axes can be reported simultaneously.
|
||||
* Multitouch axes can be reported ABS_MT_SLOT times
|
||||
*/
|
||||
if (evdev->ev_absinfo != NULL) {
|
||||
bit_count(evdev->ev_abs_flags, 0, ABS_CNT, &res);
|
||||
size += res;
|
||||
bit_count(evdev->ev_abs_flags, ABS_MT_FIRST, MT_CNT, &res);
|
||||
if (res > 0) {
|
||||
res++; /* ABS_MT_SLOT or SYN_MT_REPORT */
|
||||
if (bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
|
||||
/* MT type B */
|
||||
size += res * MAXIMAL_MT_SLOT(evdev);
|
||||
else
|
||||
/* MT type A */
|
||||
size += res * (MAX_MT_REPORTS - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* All misc events can be reported simultaneously */
|
||||
bit_count(evdev->ev_msc_flags, 0, MSC_CNT, &res);
|
||||
size += res;
|
||||
|
||||
/* All leds can be reported simultaneously */
|
||||
bit_count(evdev->ev_led_flags, 0, LED_CNT, &res);
|
||||
size += res;
|
||||
|
||||
/* Assume other events are generated once per report */
|
||||
bit_ffs(evdev->ev_snd_flags, SND_CNT, &res);
|
||||
size += (res != -1);
|
||||
|
||||
bit_ffs(evdev->ev_sw_flags, SW_CNT, &res);
|
||||
size += (res != -1);
|
||||
|
||||
/* XXX: FF part is not implemented yet */
|
||||
|
||||
size++; /* SYN_REPORT */
|
||||
return (size);
|
||||
}
|
||||
|
||||
int
|
||||
evdev_register(struct evdev_dev *evdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
debugf(evdev, "%s: registered evdev provider: %s <%s>\n",
|
||||
evdev->ev_shortname, evdev->ev_name, evdev->ev_serial);
|
||||
|
||||
/* Initialize internal structures */
|
||||
mtx_init(&evdev->ev_mtx, "evmtx", NULL, MTX_DEF);
|
||||
LIST_INIT(&evdev->ev_clients);
|
||||
|
||||
if (evdev_event_supported(evdev, EV_REP) &&
|
||||
bit_test(evdev->ev_flags, EVDEV_FLAG_SOFTREPEAT)) {
|
||||
/* Initialize callout */
|
||||
callout_init_mtx(&evdev->ev_rep_callout, &evdev->ev_mtx, 0);
|
||||
|
||||
if (evdev->ev_rep[REP_DELAY] == 0 &&
|
||||
evdev->ev_rep[REP_PERIOD] == 0) {
|
||||
/* Supply default values */
|
||||
evdev->ev_rep[REP_DELAY] = 250;
|
||||
evdev->ev_rep[REP_PERIOD] = 33;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize multitouch protocol type B states */
|
||||
if (bit_test(evdev->ev_abs_flags, ABS_MT_SLOT) &&
|
||||
evdev->ev_absinfo != NULL && MAXIMAL_MT_SLOT(evdev) > 0)
|
||||
evdev_mt_init(evdev);
|
||||
|
||||
/* Estimate maximum report size */
|
||||
if (evdev->ev_report_size == 0) {
|
||||
ret = evdev_set_report_size(evdev,
|
||||
evdev_estimate_report_size(evdev));
|
||||
if (ret != 0)
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
/* Create char device node */
|
||||
ret = evdev_cdev_create(evdev);
|
||||
bail_out:
|
||||
if (ret != 0)
|
||||
mtx_destroy(&evdev->ev_mtx);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
evdev_unregister(struct evdev_dev *evdev)
|
||||
{
|
||||
struct evdev_client *client;
|
||||
int ret;
|
||||
debugf(evdev, "%s: unregistered evdev provider: %s\n",
|
||||
evdev->ev_shortname, evdev->ev_name);
|
||||
|
||||
EVDEV_LOCK(evdev);
|
||||
evdev->ev_cdev->si_drv1 = NULL;
|
||||
/* Wake up sleepers */
|
||||
LIST_FOREACH(client, &evdev->ev_clients, ec_link) {
|
||||
evdev_revoke_client(client);
|
||||
evdev_dispose_client(evdev, client);
|
||||
EVDEV_CLIENT_LOCKQ(client);
|
||||
evdev_notify_event(client);
|
||||
EVDEV_CLIENT_UNLOCKQ(client);
|
||||
}
|
||||
EVDEV_UNLOCK(evdev);
|
||||
|
||||
/* destroy_dev can sleep so release lock */
|
||||
ret = evdev_cdev_destroy(evdev);
|
||||
evdev->ev_cdev = NULL;
|
||||
if (ret == 0)
|
||||
mtx_destroy(&evdev->ev_mtx);
|
||||
|
||||
evdev_free_absinfo(evdev->ev_absinfo);
|
||||
evdev_mt_free(evdev);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_set_name(struct evdev_dev *evdev, const char *name)
|
||||
{
|
||||
|
||||
snprintf(evdev->ev_name, NAMELEN, "%s", name);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_set_id(struct evdev_dev *evdev, uint16_t bustype, uint16_t vendor,
|
||||
uint16_t product, uint16_t version)
|
||||
{
|
||||
|
||||
evdev->ev_id = (struct input_id) {
|
||||
.bustype = bustype,
|
||||
.vendor = vendor,
|
||||
.product = product,
|
||||
.version = version
|
||||
};
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_set_phys(struct evdev_dev *evdev, const char *name)
|
||||
{
|
||||
|
||||
snprintf(evdev->ev_shortname, NAMELEN, "%s", name);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_set_serial(struct evdev_dev *evdev, const char *serial)
|
||||
{
|
||||
|
||||
snprintf(evdev->ev_serial, NAMELEN, "%s", serial);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_set_methods(struct evdev_dev *evdev, void *softc,
|
||||
struct evdev_methods *methods)
|
||||
{
|
||||
|
||||
evdev->ev_methods = methods;
|
||||
evdev->ev_softc = softc;
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_support_prop(struct evdev_dev *evdev, uint16_t prop)
|
||||
{
|
||||
|
||||
KASSERT(prop < INPUT_PROP_CNT, ("invalid evdev input property"));
|
||||
bit_set(evdev->ev_prop_flags, prop);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_support_event(struct evdev_dev *evdev, uint16_t type)
|
||||
{
|
||||
|
||||
KASSERT(type < EV_CNT, ("invalid evdev event property"));
|
||||
bit_set(evdev->ev_type_flags, type);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_support_key(struct evdev_dev *evdev, uint16_t code)
|
||||
{
|
||||
|
||||
KASSERT(code < KEY_CNT, ("invalid evdev key property"));
|
||||
bit_set(evdev->ev_key_flags, code);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_support_rel(struct evdev_dev *evdev, uint16_t code)
|
||||
{
|
||||
|
||||
KASSERT(code < REL_CNT, ("invalid evdev rel property"));
|
||||
bit_set(evdev->ev_rel_flags, code);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_support_abs(struct evdev_dev *evdev, uint16_t code, int32_t value,
|
||||
int32_t minimum, int32_t maximum, int32_t fuzz, int32_t flat,
|
||||
int32_t resolution)
|
||||
{
|
||||
struct input_absinfo absinfo;
|
||||
|
||||
KASSERT(code < ABS_CNT, ("invalid evdev abs property"));
|
||||
|
||||
absinfo = (struct input_absinfo) {
|
||||
.value = value,
|
||||
.minimum = minimum,
|
||||
.maximum = maximum,
|
||||
.fuzz = fuzz,
|
||||
.flat = flat,
|
||||
.resolution = resolution,
|
||||
};
|
||||
evdev_set_abs_bit(evdev, code);
|
||||
evdev_set_absinfo(evdev, code, &absinfo);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_set_abs_bit(struct evdev_dev *evdev, uint16_t code)
|
||||
{
|
||||
|
||||
KASSERT(code < ABS_CNT, ("invalid evdev abs property"));
|
||||
if (evdev->ev_absinfo == NULL)
|
||||
evdev->ev_absinfo = evdev_alloc_absinfo();
|
||||
bit_set(evdev->ev_abs_flags, code);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_support_msc(struct evdev_dev *evdev, uint16_t code)
|
||||
{
|
||||
|
||||
KASSERT(code < MSC_CNT, ("invalid evdev msc property"));
|
||||
bit_set(evdev->ev_msc_flags, code);
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
evdev_support_led(struct evdev_dev *evdev, uint16_t code)
|
||||
{
|
||||
|
||||
KASSERT(code < LED_CNT, ("invalid evdev led property"));
|
||||
bit_set(evdev->ev_led_flags, code);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_support_snd(struct evdev_dev *evdev, uint16_t code)
|
||||
{
|
||||
|
||||
KASSERT(code < SND_CNT, ("invalid evdev snd property"));
|
||||
bit_set(evdev->ev_snd_flags, code);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_support_sw(struct evdev_dev *evdev, uint16_t code)
|
||||
{
|
||||
|
||||
KASSERT(code < SW_CNT, ("invalid evdev sw property"));
|
||||
bit_set(evdev->ev_sw_flags, code);
|
||||
}
|
||||
|
||||
bool
|
||||
evdev_event_supported(struct evdev_dev *evdev, uint16_t type)
|
||||
{
|
||||
|
||||
KASSERT(type < EV_CNT, ("invalid evdev event property"));
|
||||
return (bit_test(evdev->ev_type_flags, type));
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_set_absinfo(struct evdev_dev *evdev, uint16_t axis,
|
||||
struct input_absinfo *absinfo)
|
||||
{
|
||||
|
||||
KASSERT(axis < ABS_CNT, ("invalid evdev abs property"));
|
||||
|
||||
if (axis == ABS_MT_SLOT &&
|
||||
(absinfo->maximum < 1 || absinfo->maximum >= MAX_MT_SLOTS))
|
||||
return;
|
||||
|
||||
if (evdev->ev_absinfo == NULL)
|
||||
evdev->ev_absinfo = evdev_alloc_absinfo();
|
||||
|
||||
if (axis == ABS_MT_SLOT)
|
||||
evdev->ev_absinfo[ABS_MT_SLOT].maximum = absinfo->maximum;
|
||||
else
|
||||
memcpy(&evdev->ev_absinfo[axis], absinfo,
|
||||
sizeof(struct input_absinfo));
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_set_repeat_params(struct evdev_dev *evdev, uint16_t property, int value)
|
||||
{
|
||||
|
||||
KASSERT(property < REP_CNT, ("invalid evdev repeat property"));
|
||||
evdev->ev_rep[property] = value;
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_set_flag(struct evdev_dev *evdev, uint16_t flag)
|
||||
{
|
||||
|
||||
KASSERT(flag < EVDEV_FLAG_CNT, ("invalid evdev flag property"));
|
||||
bit_set(evdev->ev_flags, flag);
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_check_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
|
||||
int32_t value)
|
||||
{
|
||||
|
||||
if (type >= EV_CNT)
|
||||
return (EINVAL);
|
||||
|
||||
/* Allow SYN events implicitly */
|
||||
if (type != EV_SYN && !evdev_event_supported(evdev, type))
|
||||
return (EINVAL);
|
||||
|
||||
switch (type) {
|
||||
case EV_SYN:
|
||||
if (code >= SYN_CNT)
|
||||
return (EINVAL);
|
||||
break;
|
||||
|
||||
case EV_KEY:
|
||||
if (code >= KEY_CNT)
|
||||
return (EINVAL);
|
||||
if (!bit_test(evdev->ev_key_flags, code))
|
||||
return (EINVAL);
|
||||
break;
|
||||
|
||||
case EV_REL:
|
||||
if (code >= REL_CNT)
|
||||
return (EINVAL);
|
||||
if (!bit_test(evdev->ev_rel_flags, code))
|
||||
return (EINVAL);
|
||||
break;
|
||||
|
||||
case EV_ABS:
|
||||
if (code >= ABS_CNT)
|
||||
return (EINVAL);
|
||||
if (!bit_test(evdev->ev_abs_flags, code))
|
||||
return (EINVAL);
|
||||
if (code == ABS_MT_SLOT &&
|
||||
(value < 0 || value > MAXIMAL_MT_SLOT(evdev)))
|
||||
return (EINVAL);
|
||||
if (ABS_IS_MT(code) && evdev->ev_mt == NULL &&
|
||||
bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
|
||||
return (EINVAL);
|
||||
break;
|
||||
|
||||
case EV_MSC:
|
||||
if (code >= MSC_CNT)
|
||||
return (EINVAL);
|
||||
if (!bit_test(evdev->ev_msc_flags, code))
|
||||
return (EINVAL);
|
||||
break;
|
||||
|
||||
case EV_LED:
|
||||
if (code >= LED_CNT)
|
||||
return (EINVAL);
|
||||
if (!bit_test(evdev->ev_led_flags, code))
|
||||
return (EINVAL);
|
||||
break;
|
||||
|
||||
case EV_SND:
|
||||
if (code >= SND_CNT)
|
||||
return (EINVAL);
|
||||
if (!bit_test(evdev->ev_snd_flags, code))
|
||||
return (EINVAL);
|
||||
break;
|
||||
|
||||
case EV_SW:
|
||||
if (code >= SW_CNT)
|
||||
return (EINVAL);
|
||||
if (!bit_test(evdev->ev_sw_flags, code))
|
||||
return (EINVAL);
|
||||
break;
|
||||
|
||||
case EV_REP:
|
||||
if (code >= REP_CNT)
|
||||
return (EINVAL);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_modify_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
|
||||
int32_t *value)
|
||||
{
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
switch (type) {
|
||||
case EV_KEY:
|
||||
if (!evdev_event_supported(evdev, EV_REP))
|
||||
break;
|
||||
|
||||
if (!bit_test(evdev->ev_flags, EVDEV_FLAG_SOFTREPEAT)) {
|
||||
/* Detect driver key repeats. */
|
||||
if (bit_test(evdev->ev_key_states, code) &&
|
||||
*value == KEY_EVENT_DOWN)
|
||||
*value = KEY_EVENT_REPEAT;
|
||||
} else {
|
||||
/* Start/stop callout for evdev repeats */
|
||||
if (bit_test(evdev->ev_key_states, code) == !*value) {
|
||||
if (*value == KEY_EVENT_DOWN)
|
||||
evdev_start_repeat(evdev, code);
|
||||
else
|
||||
evdev_stop_repeat(evdev);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EV_ABS:
|
||||
/* TBD: implement fuzz */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static enum evdev_sparse_result
|
||||
evdev_sparse_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
|
||||
int32_t value)
|
||||
{
|
||||
int32_t last_mt_slot;
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
/*
|
||||
* For certain event types, update device state bits
|
||||
* and convert level reporting to edge reporting
|
||||
*/
|
||||
switch (type) {
|
||||
case EV_KEY:
|
||||
switch (value) {
|
||||
case KEY_EVENT_UP:
|
||||
case KEY_EVENT_DOWN:
|
||||
if (bit_test(evdev->ev_key_states, code) == value)
|
||||
return (EV_SKIP_EVENT);
|
||||
bit_change(evdev->ev_key_states, code, value);
|
||||
break;
|
||||
|
||||
case KEY_EVENT_REPEAT:
|
||||
if (bit_test(evdev->ev_key_states, code) == 0 ||
|
||||
!evdev_event_supported(evdev, EV_REP))
|
||||
return (EV_SKIP_EVENT);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (EV_SKIP_EVENT);
|
||||
}
|
||||
break;
|
||||
|
||||
case EV_LED:
|
||||
if (bit_test(evdev->ev_led_states, code) == value)
|
||||
return (EV_SKIP_EVENT);
|
||||
bit_change(evdev->ev_led_states, code, value);
|
||||
break;
|
||||
|
||||
case EV_SND:
|
||||
if (bit_test(evdev->ev_snd_states, code) == value)
|
||||
return (EV_SKIP_EVENT);
|
||||
bit_change(evdev->ev_snd_states, code, value);
|
||||
break;
|
||||
|
||||
case EV_SW:
|
||||
if (bit_test(evdev->ev_sw_states, code) == value)
|
||||
return (EV_SKIP_EVENT);
|
||||
bit_change(evdev->ev_sw_states, code, value);
|
||||
break;
|
||||
|
||||
case EV_REP:
|
||||
if (evdev->ev_rep[code] == value)
|
||||
return (EV_SKIP_EVENT);
|
||||
evdev_set_repeat_params(evdev, code, value);
|
||||
break;
|
||||
|
||||
case EV_REL:
|
||||
if (value == 0)
|
||||
return (EV_SKIP_EVENT);
|
||||
break;
|
||||
|
||||
/* For EV_ABS, save last value in absinfo and ev_mt_states */
|
||||
case EV_ABS:
|
||||
switch (code) {
|
||||
case ABS_MT_SLOT:
|
||||
/* Postpone ABS_MT_SLOT till next event */
|
||||
evdev_set_last_mt_slot(evdev, value);
|
||||
return (EV_SKIP_EVENT);
|
||||
|
||||
case ABS_MT_FIRST ... ABS_MT_LAST:
|
||||
/* Pass MT protocol type A events as is */
|
||||
if (!bit_test(evdev->ev_abs_flags, ABS_MT_SLOT))
|
||||
break;
|
||||
/* Don`t repeat MT protocol type B events */
|
||||
last_mt_slot = evdev_get_last_mt_slot(evdev);
|
||||
if (evdev_get_mt_value(evdev, last_mt_slot, code)
|
||||
== value)
|
||||
return (EV_SKIP_EVENT);
|
||||
evdev_set_mt_value(evdev, last_mt_slot, code, value);
|
||||
if (last_mt_slot != CURRENT_MT_SLOT(evdev)) {
|
||||
CURRENT_MT_SLOT(evdev) = last_mt_slot;
|
||||
evdev->ev_report_opened = true;
|
||||
return (EV_REPORT_MT_SLOT);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (evdev->ev_absinfo[code].value == value)
|
||||
return (EV_SKIP_EVENT);
|
||||
evdev->ev_absinfo[code].value = value;
|
||||
}
|
||||
break;
|
||||
|
||||
case EV_SYN:
|
||||
if (code == SYN_REPORT) {
|
||||
/* Skip empty reports */
|
||||
if (!evdev->ev_report_opened)
|
||||
return (EV_SKIP_EVENT);
|
||||
evdev->ev_report_opened = false;
|
||||
return (EV_REPORT_EVENT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
evdev->ev_report_opened = true;
|
||||
return (EV_REPORT_EVENT);
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_propagate_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
|
||||
int32_t value)
|
||||
{
|
||||
struct evdev_client *client;
|
||||
|
||||
debugf(evdev, "%s pushed event %d/%d/%d",
|
||||
evdev->ev_shortname, type, code, value);
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
/* Propagate event through all clients */
|
||||
LIST_FOREACH(client, &evdev->ev_clients, ec_link) {
|
||||
if (evdev->ev_grabber != NULL && evdev->ev_grabber != client)
|
||||
continue;
|
||||
|
||||
EVDEV_CLIENT_LOCKQ(client);
|
||||
evdev_client_push(client, type, code, value);
|
||||
if (type == EV_SYN && code == SYN_REPORT)
|
||||
evdev_notify_event(client);
|
||||
EVDEV_CLIENT_UNLOCKQ(client);
|
||||
}
|
||||
|
||||
/* Update counters */
|
||||
evdev->ev_event_count++;
|
||||
if (type == EV_SYN && code == SYN_REPORT)
|
||||
evdev->ev_report_count++;
|
||||
}
|
||||
|
||||
void
|
||||
evdev_send_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
|
||||
int32_t value)
|
||||
{
|
||||
enum evdev_sparse_result sparse;
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
sparse = evdev_sparse_event(evdev, type, code, value);
|
||||
switch (sparse) {
|
||||
case EV_REPORT_MT_SLOT:
|
||||
/* report postponed ABS_MT_SLOT */
|
||||
evdev_propagate_event(evdev, EV_ABS, ABS_MT_SLOT,
|
||||
CURRENT_MT_SLOT(evdev));
|
||||
/* FALLTHROUGH */
|
||||
case EV_REPORT_EVENT:
|
||||
evdev_propagate_event(evdev, type, code, value);
|
||||
/* FALLTHROUGH */
|
||||
case EV_SKIP_EVENT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
evdev_push_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
|
||||
int32_t value)
|
||||
{
|
||||
|
||||
if (evdev_check_event(evdev, type, code, value) != 0)
|
||||
return (EINVAL);
|
||||
|
||||
EVDEV_LOCK(evdev);
|
||||
evdev_modify_event(evdev, type, code, &value);
|
||||
if (type == EV_SYN && code == SYN_REPORT && evdev->ev_report_opened &&
|
||||
bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
|
||||
evdev_send_mt_compat(evdev);
|
||||
evdev_send_event(evdev, type, code, value);
|
||||
EVDEV_UNLOCK(evdev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evdev_inject_event(struct evdev_dev *evdev, uint16_t type, uint16_t code,
|
||||
int32_t value)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (type) {
|
||||
case EV_REP:
|
||||
/* evdev repeats should not be processed by hardware driver */
|
||||
if (bit_test(evdev->ev_flags, EVDEV_FLAG_SOFTREPEAT))
|
||||
goto push;
|
||||
/* FALLTHROUGH */
|
||||
case EV_LED:
|
||||
case EV_MSC:
|
||||
case EV_SND:
|
||||
case EV_FF:
|
||||
if (evdev->ev_methods != NULL &&
|
||||
evdev->ev_methods->ev_event != NULL)
|
||||
evdev->ev_methods->ev_event(evdev, evdev->ev_softc,
|
||||
type, code, value);
|
||||
/*
|
||||
* Leds and driver repeats should be reported in ev_event
|
||||
* method body to interoperate with kbdmux states and rates
|
||||
* propagation so both ways (ioctl and evdev) of changing it
|
||||
* will produce only one evdev event report to client.
|
||||
*/
|
||||
if (type == EV_LED || type == EV_REP)
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
case EV_SYN:
|
||||
case EV_KEY:
|
||||
case EV_REL:
|
||||
case EV_ABS:
|
||||
case EV_SW:
|
||||
push:
|
||||
ret = evdev_push_event(evdev, type, code, value);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = EINVAL;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
inline int
|
||||
evdev_sync(struct evdev_dev *evdev)
|
||||
{
|
||||
|
||||
return (evdev_push_event(evdev, EV_SYN, SYN_REPORT, 1));
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
evdev_mt_sync(struct evdev_dev *evdev)
|
||||
{
|
||||
|
||||
return (evdev_push_event(evdev, EV_SYN, SYN_MT_REPORT, 1));
|
||||
}
|
||||
|
||||
int
|
||||
evdev_register_client(struct evdev_dev *evdev, struct evdev_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
debugf(evdev, "adding new client for device %s", evdev->ev_shortname);
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
if (LIST_EMPTY(&evdev->ev_clients) && evdev->ev_methods != NULL &&
|
||||
evdev->ev_methods->ev_open != NULL) {
|
||||
debugf(evdev, "calling ev_open() on device %s",
|
||||
evdev->ev_shortname);
|
||||
ret = evdev->ev_methods->ev_open(evdev, evdev->ev_softc);
|
||||
}
|
||||
if (ret == 0)
|
||||
LIST_INSERT_HEAD(&evdev->ev_clients, client, ec_link);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_dispose_client(struct evdev_dev *evdev, struct evdev_client *client)
|
||||
{
|
||||
debugf(evdev, "removing client for device %s", evdev->ev_shortname);
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
LIST_REMOVE(client, ec_link);
|
||||
if (LIST_EMPTY(&evdev->ev_clients)) {
|
||||
if (evdev->ev_methods != NULL &&
|
||||
evdev->ev_methods->ev_close != NULL)
|
||||
evdev->ev_methods->ev_close(evdev, evdev->ev_softc);
|
||||
if (evdev_event_supported(evdev, EV_REP) &&
|
||||
bit_test(evdev->ev_flags, EVDEV_FLAG_SOFTREPEAT))
|
||||
evdev_stop_repeat(evdev);
|
||||
}
|
||||
evdev_release_client(evdev, client);
|
||||
}
|
||||
|
||||
int
|
||||
evdev_grab_client(struct evdev_dev *evdev, struct evdev_client *client)
|
||||
{
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
if (evdev->ev_grabber != NULL)
|
||||
return (EBUSY);
|
||||
|
||||
evdev->ev_grabber = client;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
evdev_release_client(struct evdev_dev *evdev, struct evdev_client *client)
|
||||
{
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
if (evdev->ev_grabber != client)
|
||||
return (EINVAL);
|
||||
|
||||
evdev->ev_grabber = NULL;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_repeat_callout(void *arg)
|
||||
{
|
||||
struct evdev_dev *evdev = (struct evdev_dev *)arg;
|
||||
|
||||
evdev_send_event(evdev, EV_KEY, evdev->ev_rep_key, KEY_EVENT_REPEAT);
|
||||
evdev_send_event(evdev, EV_SYN, SYN_REPORT, 1);
|
||||
|
||||
if (evdev->ev_rep[REP_PERIOD])
|
||||
callout_reset(&evdev->ev_rep_callout,
|
||||
evdev->ev_rep[REP_PERIOD] * hz / 1000,
|
||||
evdev_repeat_callout, evdev);
|
||||
else
|
||||
evdev->ev_rep_key = KEY_RESERVED;
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_start_repeat(struct evdev_dev *evdev, uint16_t key)
|
||||
{
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
if (evdev->ev_rep[REP_DELAY]) {
|
||||
evdev->ev_rep_key = key;
|
||||
callout_reset(&evdev->ev_rep_callout,
|
||||
evdev->ev_rep[REP_DELAY] * hz / 1000,
|
||||
evdev_repeat_callout, evdev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_stop_repeat(struct evdev_dev *evdev)
|
||||
{
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
if (evdev->ev_rep_key != KEY_RESERVED) {
|
||||
callout_stop(&evdev->ev_rep_callout);
|
||||
evdev->ev_rep_key = KEY_RESERVED;
|
||||
}
|
||||
}
|
128
sys/dev/evdev/evdev.h
Normal file
128
sys/dev/evdev/evdev.h
Normal file
@ -0,0 +1,128 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Jakub Wojciech Klama <jceel@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$
|
||||
*/
|
||||
|
||||
#ifndef _DEV_EVDEV_EVDEV_H
|
||||
#define _DEV_EVDEV_EVDEV_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/kbio.h>
|
||||
#include <dev/evdev/input.h>
|
||||
#include <dev/kbd/kbdreg.h>
|
||||
|
||||
#define NAMELEN 80
|
||||
|
||||
struct evdev_dev;
|
||||
|
||||
typedef int (evdev_open_t)(struct evdev_dev *, void *);
|
||||
typedef void (evdev_close_t)(struct evdev_dev *, void *);
|
||||
typedef void (evdev_event_t)(struct evdev_dev *, void *, uint16_t,
|
||||
uint16_t, int32_t);
|
||||
typedef void (evdev_keycode_t)(struct evdev_dev *, void *,
|
||||
struct input_keymap_entry *);
|
||||
|
||||
/*
|
||||
* Keyboard and mouse events recipient mask.
|
||||
* evdev_rcpt_mask variable should be respected by keyboard and mouse drivers
|
||||
* that are able to send events through both evdev and sysmouse/kbdmux
|
||||
* interfaces so user can choose prefered one to not receive one event twice.
|
||||
*/
|
||||
#define EVDEV_RCPT_SYSMOUSE (1<<0)
|
||||
#define EVDEV_RCPT_KBDMUX (1<<1)
|
||||
#define EVDEV_RCPT_HW_MOUSE (1<<2)
|
||||
#define EVDEV_RCPT_HW_KBD (1<<3)
|
||||
extern int evdev_rcpt_mask;
|
||||
|
||||
#define ABS_MT_FIRST ABS_MT_TOUCH_MAJOR
|
||||
#define ABS_MT_LAST ABS_MT_TOOL_Y
|
||||
#define ABS_IS_MT(x) ((x) >= ABS_MT_FIRST && (x) <= ABS_MT_LAST)
|
||||
#define ABS_MT_INDEX(x) ((x) - ABS_MT_FIRST)
|
||||
#define MT_CNT (ABS_MT_INDEX(ABS_MT_LAST) + 1)
|
||||
/* Multitouch protocol type A */
|
||||
#define MAX_MT_REPORTS 5
|
||||
/* Multitouch protocol type B interface */
|
||||
#define MAX_MT_SLOTS 16
|
||||
|
||||
#define EVDEV_FLAG_SOFTREPEAT 0x00 /* use evdev to repeat keys */
|
||||
#define EVDEV_FLAG_MT_STCOMPAT 0x01 /* autogenerate ST-compatible events
|
||||
* for MT protocol type B reports */
|
||||
#define EVDEV_FLAG_MAX 0x1F
|
||||
#define EVDEV_FLAG_CNT (EVDEV_FLAG_MAX + 1)
|
||||
|
||||
struct evdev_methods
|
||||
{
|
||||
evdev_open_t *ev_open;
|
||||
evdev_close_t *ev_close;
|
||||
evdev_event_t *ev_event;
|
||||
evdev_keycode_t *ev_get_keycode;
|
||||
evdev_keycode_t *ev_set_keycode;
|
||||
};
|
||||
|
||||
/* Input device interface: */
|
||||
struct evdev_dev *evdev_alloc(void);
|
||||
void evdev_free(struct evdev_dev *);
|
||||
void evdev_set_name(struct evdev_dev *, const char *);
|
||||
void evdev_set_id(struct evdev_dev *, uint16_t, uint16_t, uint16_t, uint16_t);
|
||||
void evdev_set_phys(struct evdev_dev *, const char *);
|
||||
void evdev_set_serial(struct evdev_dev *, const char *);
|
||||
void evdev_set_methods(struct evdev_dev *, void *, struct evdev_methods *);
|
||||
int evdev_register(struct evdev_dev *);
|
||||
int evdev_unregister(struct evdev_dev *);
|
||||
int evdev_push_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
|
||||
int evdev_sync(struct evdev_dev *);
|
||||
int evdev_mt_sync(struct evdev_dev *);
|
||||
void evdev_support_prop(struct evdev_dev *, uint16_t);
|
||||
void evdev_support_event(struct evdev_dev *, uint16_t);
|
||||
void evdev_support_key(struct evdev_dev *, uint16_t);
|
||||
void evdev_support_rel(struct evdev_dev *, uint16_t);
|
||||
void evdev_support_abs(struct evdev_dev *, uint16_t, int32_t, int32_t, int32_t,
|
||||
int32_t, int32_t, int32_t);
|
||||
void evdev_support_msc(struct evdev_dev *, uint16_t);
|
||||
void evdev_support_led(struct evdev_dev *, uint16_t);
|
||||
void evdev_support_snd(struct evdev_dev *, uint16_t);
|
||||
void evdev_support_sw(struct evdev_dev *, uint16_t);
|
||||
void evdev_set_repeat_params(struct evdev_dev *, uint16_t, int);
|
||||
int evdev_set_report_size(struct evdev_dev *, size_t);
|
||||
void evdev_set_flag(struct evdev_dev *, uint16_t);
|
||||
|
||||
/* Multitouch related functions: */
|
||||
int32_t evdev_get_mt_slot_by_tracking_id(struct evdev_dev *, int32_t);
|
||||
void evdev_support_nfingers(struct evdev_dev *, int32_t);
|
||||
void evdev_support_mt_compat(struct evdev_dev *);
|
||||
void evdev_push_nfingers(struct evdev_dev *, int32_t);
|
||||
void evdev_push_mt_compat(struct evdev_dev *);
|
||||
|
||||
/* Utility functions: */
|
||||
uint16_t evdev_hid2key(int);
|
||||
void evdev_support_all_known_keys(struct evdev_dev *);
|
||||
uint16_t evdev_scancode2key(int *, int);
|
||||
void evdev_push_mouse_btn(struct evdev_dev *, int);
|
||||
void evdev_push_leds(struct evdev_dev *, int);
|
||||
void evdev_push_repeats(struct evdev_dev *, keyboard_t *);
|
||||
evdev_event_t evdev_ev_kbd_event;
|
||||
|
||||
#endif /* _DEV_EVDEV_EVDEV_H */
|
269
sys/dev/evdev/evdev_mt.c
Normal file
269
sys/dev/evdev/evdev_mt.c
Normal file
@ -0,0 +1,269 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Vladimir Kondratyev <wulf@cicgroup.ru>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/evdev/input.h>
|
||||
#include <dev/evdev/evdev.h>
|
||||
#include <dev/evdev/evdev_private.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define debugf(fmt, args...) printf("evdev: " fmt "\n", ##args)
|
||||
#else
|
||||
#define debugf(fmt, args...)
|
||||
#endif
|
||||
|
||||
static uint16_t evdev_fngmap[] = {
|
||||
BTN_TOOL_FINGER,
|
||||
BTN_TOOL_DOUBLETAP,
|
||||
BTN_TOOL_TRIPLETAP,
|
||||
BTN_TOOL_QUADTAP,
|
||||
BTN_TOOL_QUINTTAP,
|
||||
};
|
||||
|
||||
static uint16_t evdev_mtstmap[][2] = {
|
||||
{ ABS_MT_POSITION_X, ABS_X },
|
||||
{ ABS_MT_POSITION_Y, ABS_Y },
|
||||
{ ABS_MT_PRESSURE, ABS_PRESSURE },
|
||||
{ ABS_MT_TOUCH_MAJOR, ABS_TOOL_WIDTH },
|
||||
};
|
||||
|
||||
struct evdev_mt_slot {
|
||||
uint64_t ev_report;
|
||||
int32_t ev_mt_states[MT_CNT];
|
||||
};
|
||||
|
||||
struct evdev_mt {
|
||||
int32_t ev_mt_last_reported_slot;
|
||||
struct evdev_mt_slot ev_mt_slots[];
|
||||
};
|
||||
|
||||
void
|
||||
evdev_mt_init(struct evdev_dev *evdev)
|
||||
{
|
||||
int32_t slot, slots;
|
||||
|
||||
slots = MAXIMAL_MT_SLOT(evdev) + 1;
|
||||
|
||||
evdev->ev_mt = malloc(offsetof(struct evdev_mt, ev_mt_slots) +
|
||||
sizeof(struct evdev_mt_slot) * slots, M_EVDEV, M_WAITOK | M_ZERO);
|
||||
|
||||
/* Initialize multitouch protocol type B states */
|
||||
for (slot = 0; slot < slots; slot++) {
|
||||
/*
|
||||
* .ev_report should not be initialized to initial value of
|
||||
* report counter (0) as it brokes free slot detection in
|
||||
* evdev_get_mt_slot_by_tracking_id. So initialize it to -1
|
||||
*/
|
||||
evdev->ev_mt->ev_mt_slots[slot] = (struct evdev_mt_slot) {
|
||||
.ev_report = 0xFFFFFFFFFFFFFFFFULL,
|
||||
.ev_mt_states[ABS_MT_INDEX(ABS_MT_TRACKING_ID)] = -1,
|
||||
};
|
||||
}
|
||||
|
||||
if (bit_test(evdev->ev_flags, EVDEV_FLAG_MT_STCOMPAT))
|
||||
evdev_support_mt_compat(evdev);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_mt_free(struct evdev_dev *evdev)
|
||||
{
|
||||
|
||||
free(evdev->ev_mt, M_EVDEV);
|
||||
}
|
||||
|
||||
int32_t
|
||||
evdev_get_last_mt_slot(struct evdev_dev *evdev)
|
||||
{
|
||||
|
||||
return (evdev->ev_mt->ev_mt_last_reported_slot);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_set_last_mt_slot(struct evdev_dev *evdev, int32_t slot)
|
||||
{
|
||||
|
||||
evdev->ev_mt->ev_mt_last_reported_slot = slot;
|
||||
}
|
||||
|
||||
inline int32_t
|
||||
evdev_get_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code)
|
||||
{
|
||||
|
||||
return (evdev->ev_mt->
|
||||
ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)]);
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_set_mt_value(struct evdev_dev *evdev, int32_t slot, int16_t code,
|
||||
int32_t value)
|
||||
{
|
||||
|
||||
if (code == ABS_MT_TRACKING_ID && value == -1)
|
||||
evdev->ev_mt->ev_mt_slots[slot].ev_report =
|
||||
evdev->ev_report_count;
|
||||
|
||||
evdev->ev_mt->ev_mt_slots[slot].ev_mt_states[ABS_MT_INDEX(code)] =
|
||||
value;
|
||||
}
|
||||
|
||||
int32_t
|
||||
evdev_get_mt_slot_by_tracking_id(struct evdev_dev *evdev, int32_t tracking_id)
|
||||
{
|
||||
int32_t tr_id, slot, free_slot = -1;
|
||||
|
||||
for (slot = 0; slot <= MAXIMAL_MT_SLOT(evdev); slot++) {
|
||||
tr_id = evdev_get_mt_value(evdev, slot, ABS_MT_TRACKING_ID);
|
||||
if (tr_id == tracking_id)
|
||||
return (slot);
|
||||
/*
|
||||
* Its possible that slot will be reassigned in a place of just
|
||||
* released one within the same report. To avoid this compare
|
||||
* report counter with slot`s report number updated with each
|
||||
* ABS_MT_TRACKING_ID change.
|
||||
*/
|
||||
if (free_slot == -1 && tr_id == -1 &&
|
||||
evdev->ev_mt->ev_mt_slots[slot].ev_report !=
|
||||
evdev->ev_report_count)
|
||||
free_slot = slot;
|
||||
}
|
||||
|
||||
return (free_slot);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_support_nfingers(struct evdev_dev *evdev, int32_t nfingers)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
for (i = 0; i < MIN(nitems(evdev_fngmap), nfingers); i++)
|
||||
evdev_support_key(evdev, evdev_fngmap[i]);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_support_mt_compat(struct evdev_dev *evdev)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
if (evdev->ev_absinfo == NULL)
|
||||
return;
|
||||
|
||||
evdev_support_event(evdev, EV_KEY);
|
||||
evdev_support_key(evdev, BTN_TOUCH);
|
||||
|
||||
/* Touchscreens should not advertise tap tool capabilities */
|
||||
if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
|
||||
evdev_support_nfingers(evdev, MAXIMAL_MT_SLOT(evdev) + 1);
|
||||
|
||||
/* Echo 0-th MT-slot as ST-slot */
|
||||
for (i = 0; i < nitems(evdev_mtstmap); i++)
|
||||
if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][0]))
|
||||
evdev_support_abs(evdev, evdev_mtstmap[i][1],
|
||||
evdev->ev_absinfo[evdev_mtstmap[i][0]].value,
|
||||
evdev->ev_absinfo[evdev_mtstmap[i][0]].minimum,
|
||||
evdev->ev_absinfo[evdev_mtstmap[i][0]].maximum,
|
||||
evdev->ev_absinfo[evdev_mtstmap[i][0]].fuzz,
|
||||
evdev->ev_absinfo[evdev_mtstmap[i][0]].flat,
|
||||
evdev->ev_absinfo[evdev_mtstmap[i][0]].resolution);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
evdev_count_fingers(struct evdev_dev *evdev)
|
||||
{
|
||||
int32_t nfingers = 0, i;
|
||||
|
||||
for (i = 0; i <= MAXIMAL_MT_SLOT(evdev); i++)
|
||||
if (evdev_get_mt_value(evdev, i, ABS_MT_TRACKING_ID) != -1)
|
||||
nfingers++;
|
||||
|
||||
return (nfingers);
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_send_nfingers(struct evdev_dev *evdev, int32_t nfingers)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
if (nfingers > nitems(evdev_fngmap))
|
||||
nfingers = nitems(evdev_fngmap);
|
||||
|
||||
for (i = 0; i < nitems(evdev_fngmap); i++)
|
||||
evdev_send_event(evdev, EV_KEY, evdev_fngmap[i],
|
||||
nfingers == i + 1);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_push_nfingers(struct evdev_dev *evdev, int32_t nfingers)
|
||||
{
|
||||
|
||||
EVDEV_LOCK(evdev);
|
||||
evdev_send_nfingers(evdev, nfingers);
|
||||
EVDEV_UNLOCK(evdev);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_send_mt_compat(struct evdev_dev *evdev)
|
||||
{
|
||||
int32_t nfingers, i;
|
||||
|
||||
EVDEV_LOCK_ASSERT(evdev);
|
||||
|
||||
nfingers = evdev_count_fingers(evdev);
|
||||
evdev_send_event(evdev, EV_KEY, BTN_TOUCH, nfingers > 0);
|
||||
|
||||
if (evdev_get_mt_value(evdev, 0, ABS_MT_TRACKING_ID) != -1)
|
||||
/* Echo 0-th MT-slot as ST-slot */
|
||||
for (i = 0; i < nitems(evdev_mtstmap); i++)
|
||||
if (bit_test(evdev->ev_abs_flags, evdev_mtstmap[i][1]))
|
||||
evdev_send_event(evdev, EV_ABS,
|
||||
evdev_mtstmap[i][1],
|
||||
evdev_get_mt_value(evdev, 0,
|
||||
evdev_mtstmap[i][0]));
|
||||
|
||||
/* Touchscreens should not report tool taps */
|
||||
if (!bit_test(evdev->ev_prop_flags, INPUT_PROP_DIRECT))
|
||||
evdev_send_nfingers(evdev, nfingers);
|
||||
|
||||
if (nfingers == 0)
|
||||
evdev_send_event(evdev, EV_ABS, ABS_PRESSURE, 0);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_push_mt_compat(struct evdev_dev *evdev)
|
||||
{
|
||||
|
||||
EVDEV_LOCK(evdev);
|
||||
evdev_send_mt_compat(evdev);
|
||||
EVDEV_UNLOCK(evdev);
|
||||
}
|
191
sys/dev/evdev/evdev_private.h
Normal file
191
sys/dev/evdev/evdev_private.h
Normal file
@ -0,0 +1,191 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
|
||||
* Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#ifndef _DEV_EVDEV_EVDEV_PRIVATE_H
|
||||
#define _DEV_EVDEV_EVDEV_PRIVATE_H
|
||||
|
||||
#include <sys/bitstring.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kbio.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <dev/evdev/evdev.h>
|
||||
#include <dev/evdev/input.h>
|
||||
#include <dev/kbd/kbdreg.h>
|
||||
|
||||
#define NAMELEN 80
|
||||
|
||||
/*
|
||||
* bitstr_t implementation must be identical to one found in EVIOCG*
|
||||
* libevdev ioctls. Our bitstring(3) API is compatible since r299090.
|
||||
*/
|
||||
_Static_assert(sizeof(bitstr_t) == sizeof(unsigned long),
|
||||
"bitstr_t size mismatch");
|
||||
|
||||
MALLOC_DECLARE(M_EVDEV);
|
||||
|
||||
struct evdev_client;
|
||||
struct evdev_mt;
|
||||
|
||||
#define CURRENT_MT_SLOT(evdev) ((evdev)->ev_absinfo[ABS_MT_SLOT].value)
|
||||
#define MAXIMAL_MT_SLOT(evdev) ((evdev)->ev_absinfo[ABS_MT_SLOT].maximum)
|
||||
|
||||
enum evdev_key_events
|
||||
{
|
||||
KEY_EVENT_UP,
|
||||
KEY_EVENT_DOWN,
|
||||
KEY_EVENT_REPEAT
|
||||
};
|
||||
|
||||
/* evdev clock IDs in Linux semantic */
|
||||
enum evdev_clock_id
|
||||
{
|
||||
EV_CLOCK_REALTIME = 0, /* UTC clock */
|
||||
EV_CLOCK_MONOTONIC, /* monotonic, stops on suspend */
|
||||
EV_CLOCK_BOOTTIME /* monotonic, suspend-awared */
|
||||
};
|
||||
|
||||
struct evdev_dev
|
||||
{
|
||||
char ev_name[NAMELEN];
|
||||
char ev_shortname[NAMELEN];
|
||||
char ev_serial[NAMELEN];
|
||||
struct cdev * ev_cdev;
|
||||
int ev_unit;
|
||||
struct mtx ev_mtx;
|
||||
struct input_id ev_id;
|
||||
struct evdev_client * ev_grabber;
|
||||
size_t ev_report_size;
|
||||
|
||||
/* Supported features: */
|
||||
bitstr_t bit_decl(ev_prop_flags, INPUT_PROP_CNT);
|
||||
bitstr_t bit_decl(ev_type_flags, EV_CNT);
|
||||
bitstr_t bit_decl(ev_key_flags, KEY_CNT);
|
||||
bitstr_t bit_decl(ev_rel_flags, REL_CNT);
|
||||
bitstr_t bit_decl(ev_abs_flags, ABS_CNT);
|
||||
bitstr_t bit_decl(ev_msc_flags, MSC_CNT);
|
||||
bitstr_t bit_decl(ev_led_flags, LED_CNT);
|
||||
bitstr_t bit_decl(ev_snd_flags, SND_CNT);
|
||||
bitstr_t bit_decl(ev_sw_flags, SW_CNT);
|
||||
struct input_absinfo * ev_absinfo;
|
||||
bitstr_t bit_decl(ev_flags, EVDEV_FLAG_CNT);
|
||||
|
||||
/* Repeat parameters & callout: */
|
||||
int ev_rep[REP_CNT];
|
||||
struct callout ev_rep_callout;
|
||||
uint16_t ev_rep_key;
|
||||
|
||||
/* State: */
|
||||
bitstr_t bit_decl(ev_key_states, KEY_CNT);
|
||||
bitstr_t bit_decl(ev_led_states, LED_CNT);
|
||||
bitstr_t bit_decl(ev_snd_states, SND_CNT);
|
||||
bitstr_t bit_decl(ev_sw_states, SW_CNT);
|
||||
bool ev_report_opened;
|
||||
|
||||
/* Multitouch protocol type B state: */
|
||||
struct evdev_mt * ev_mt;
|
||||
|
||||
/* Counters: */
|
||||
uint64_t ev_event_count;
|
||||
uint64_t ev_report_count;
|
||||
|
||||
/* Parent driver callbacks: */
|
||||
struct evdev_methods * ev_methods;
|
||||
void * ev_softc;
|
||||
|
||||
LIST_ENTRY(evdev_dev) ev_link;
|
||||
LIST_HEAD(, evdev_client) ev_clients;
|
||||
};
|
||||
|
||||
#define EVDEV_LOCK(evdev) mtx_lock(&(evdev)->ev_mtx)
|
||||
#define EVDEV_UNLOCK(evdev) mtx_unlock(&(evdev)->ev_mtx)
|
||||
#define EVDEV_LOCK_ASSERT(evdev) mtx_assert(&(evdev)->ev_mtx, MA_OWNED)
|
||||
|
||||
struct evdev_client
|
||||
{
|
||||
struct evdev_dev * ec_evdev;
|
||||
struct mtx ec_buffer_mtx;
|
||||
size_t ec_buffer_size;
|
||||
size_t ec_buffer_head;
|
||||
size_t ec_buffer_tail;
|
||||
size_t ec_buffer_ready;
|
||||
enum evdev_clock_id ec_clock_id;
|
||||
struct selinfo ec_selp;
|
||||
struct sigio * ec_sigio;
|
||||
bool ec_async;
|
||||
bool ec_revoked;
|
||||
bool ec_blocked;
|
||||
bool ec_selected;
|
||||
|
||||
LIST_ENTRY(evdev_client) ec_link;
|
||||
|
||||
struct input_event ec_buffer[];
|
||||
};
|
||||
|
||||
#define EVDEV_CLIENT_LOCKQ(client) mtx_lock(&(client)->ec_buffer_mtx)
|
||||
#define EVDEV_CLIENT_UNLOCKQ(client) mtx_unlock(&(client)->ec_buffer_mtx)
|
||||
#define EVDEV_CLIENT_LOCKQ_ASSERT(client) \
|
||||
mtx_assert(&(client)->ec_buffer_mtx, MA_OWNED)
|
||||
#define EVDEV_CLIENT_EMPTYQ(client) \
|
||||
((client)->ec_buffer_head == (client)->ec_buffer_ready)
|
||||
#define EVDEV_CLIENT_SIZEQ(client) \
|
||||
(((client)->ec_buffer_ready + (client)->ec_buffer_size - \
|
||||
(client)->ec_buffer_head) % (client)->ec_buffer_size)
|
||||
|
||||
/* Input device interface: */
|
||||
void evdev_send_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
|
||||
int evdev_inject_event(struct evdev_dev *, uint16_t, uint16_t, int32_t);
|
||||
int evdev_cdev_create(struct evdev_dev *);
|
||||
int evdev_cdev_destroy(struct evdev_dev *);
|
||||
bool evdev_event_supported(struct evdev_dev *, uint16_t);
|
||||
void evdev_set_abs_bit(struct evdev_dev *, uint16_t);
|
||||
void evdev_set_absinfo(struct evdev_dev *, uint16_t, struct input_absinfo *);
|
||||
|
||||
/* Client interface: */
|
||||
int evdev_register_client(struct evdev_dev *, struct evdev_client *);
|
||||
void evdev_dispose_client(struct evdev_dev *, struct evdev_client *);
|
||||
int evdev_grab_client(struct evdev_dev *, struct evdev_client *);
|
||||
int evdev_release_client(struct evdev_dev *, struct evdev_client *);
|
||||
void evdev_client_push(struct evdev_client *, uint16_t, uint16_t, int32_t);
|
||||
void evdev_notify_event(struct evdev_client *);
|
||||
void evdev_revoke_client(struct evdev_client *);
|
||||
|
||||
/* Multitouch related functions: */
|
||||
void evdev_mt_init(struct evdev_dev *);
|
||||
void evdev_mt_free(struct evdev_dev *);
|
||||
int32_t evdev_get_last_mt_slot(struct evdev_dev *);
|
||||
void evdev_set_last_mt_slot(struct evdev_dev *, int32_t);
|
||||
int32_t evdev_get_mt_value(struct evdev_dev *, int32_t, int16_t);
|
||||
void evdev_set_mt_value(struct evdev_dev *, int32_t, int16_t, int32_t);
|
||||
void evdev_send_mt_compat(struct evdev_dev *);
|
||||
|
||||
/* Utility functions: */
|
||||
void evdev_client_dumpqueue(struct evdev_client *);
|
||||
|
||||
#endif /* _DEV_EVDEV_EVDEV_PRIVATE_H */
|
334
sys/dev/evdev/evdev_utils.c
Normal file
334
sys/dev/evdev/evdev_utils.c
Normal file
@ -0,0 +1,334 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
|
||||
* Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kbio.h>
|
||||
|
||||
#include <dev/evdev/input.h>
|
||||
#include <dev/evdev/evdev.h>
|
||||
|
||||
#include <dev/kbd/kbdreg.h>
|
||||
|
||||
#define NONE KEY_RESERVED
|
||||
|
||||
static uint16_t evdev_usb_scancodes[256] = {
|
||||
/* 0x00 - 0x27 */
|
||||
NONE, NONE, NONE, NONE, KEY_A, KEY_B, KEY_C, KEY_D,
|
||||
KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L,
|
||||
KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
|
||||
KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2,
|
||||
KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0,
|
||||
/* 0x28 - 0x3f */
|
||||
KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB,
|
||||
KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE,
|
||||
KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON,
|
||||
KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_DOT,
|
||||
KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2,
|
||||
KEY_F3, KEY_F4, KEY_F5, KEY_F6,
|
||||
/* 0x40 - 0x5f */
|
||||
KEY_F7, KEY_F8, KEY_F9, KEY_F10,
|
||||
KEY_F11, KEY_F12, KEY_SYSRQ, KEY_SCROLLLOCK,
|
||||
KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP,
|
||||
KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT,
|
||||
KEY_LEFT, KEY_DOWN, KEY_UP, KEY_NUMLOCK,
|
||||
KEY_SLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS,
|
||||
KEY_KPENTER, KEY_KP1, KEY_KP2, KEY_KP3,
|
||||
KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7,
|
||||
/* 0x60 - 0x7f */
|
||||
KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT,
|
||||
KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL,
|
||||
KEY_F13, KEY_F14, KEY_F15, KEY_F16,
|
||||
KEY_F17, KEY_F18, KEY_F19, KEY_F20,
|
||||
KEY_F21, KEY_F22, KEY_F23, KEY_F24,
|
||||
KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT,
|
||||
KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT,
|
||||
KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE,
|
||||
/* 0x80 - 0x9f */
|
||||
KEY_VOLUMEUP, KEY_VOLUMEDOWN, NONE, NONE,
|
||||
NONE, KEY_KPCOMMA, NONE, KEY_RO,
|
||||
KEY_KATAKANAHIRAGANA, KEY_YEN,KEY_HENKAN, KEY_MUHENKAN,
|
||||
KEY_KPJPCOMMA, NONE, NONE, NONE,
|
||||
KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA,
|
||||
KEY_ZENKAKUHANKAKU, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
/* 0xa0 - 0xbf */
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
/* 0xc0 - 0xdf */
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
/* 0xe0 - 0xff */
|
||||
KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA,
|
||||
KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA,
|
||||
KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG,KEY_NEXTSONG,
|
||||
KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE,
|
||||
KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP,
|
||||
KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT,
|
||||
KEY_SLEEP, KEY_COFFEE, KEY_REFRESH, KEY_CALC,
|
||||
NONE, NONE, NONE, NONE,
|
||||
|
||||
};
|
||||
|
||||
static uint16_t evdev_at_set1_scancodes[] = {
|
||||
/* 0x00 - 0x1f */
|
||||
NONE, KEY_ESC, KEY_1, KEY_2,
|
||||
KEY_3, KEY_4, KEY_5, KEY_6,
|
||||
KEY_7, KEY_8, KEY_9, KEY_0,
|
||||
KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_TAB,
|
||||
KEY_Q, KEY_W, KEY_E, KEY_R,
|
||||
KEY_T, KEY_Y, KEY_U, KEY_I,
|
||||
KEY_O, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE,
|
||||
KEY_ENTER, KEY_LEFTCTRL, KEY_A, KEY_S,
|
||||
/* 0x20 - 0x3f */
|
||||
KEY_D, KEY_F, KEY_G, KEY_H,
|
||||
KEY_J, KEY_K, KEY_L, KEY_SEMICOLON,
|
||||
KEY_APOSTROPHE, KEY_GRAVE, KEY_LEFTSHIFT, KEY_BACKSLASH,
|
||||
KEY_Z, KEY_X, KEY_C, KEY_V,
|
||||
KEY_B, KEY_N, KEY_M, KEY_COMMA,
|
||||
KEY_DOT, KEY_SLASH, KEY_RIGHTSHIFT, NONE,
|
||||
KEY_LEFTALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
|
||||
KEY_F2, KEY_F3, KEY_F4, KEY_F5,
|
||||
/* 0x40 - 0x5f */
|
||||
KEY_F6, KEY_F7, KEY_F8, KEY_F9,
|
||||
KEY_F10, KEY_NUMLOCK, KEY_SCROLLLOCK, KEY_KP7,
|
||||
KEY_KP8, KEY_KP9, KEY_KPMINUS, KEY_KP4,
|
||||
KEY_KP5, KEY_KP6, KEY_KPPLUS, KEY_KP1,
|
||||
KEY_KP2, KEY_KP3, KEY_KP0, KEY_KPDOT,
|
||||
NONE, NONE, NONE, KEY_F11,
|
||||
KEY_F12, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
/* 0x60 - 0x7f */
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
KEY_KATAKANAHIRAGANA, NONE, NONE, KEY_RO,
|
||||
NONE, NONE, KEY_ZENKAKUHANKAKU, KEY_HIRAGANA,
|
||||
KEY_KATAKANA, KEY_HENKAN, NONE, KEY_MUHENKAN,
|
||||
NONE, KEY_YEN, KEY_KPCOMMA, NONE,
|
||||
/* 0x00 - 0x1f. 0xE0 prefixed */
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
KEY_PREVIOUSSONG, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, KEY_NEXTSONG, NONE, NONE,
|
||||
NONE, KEY_KPENTER, KEY_RIGHTCTRL, NONE,
|
||||
/* 0x20 - 0x3f. 0xE0 prefixed */
|
||||
KEY_MUTE, KEY_CALC, KEY_PLAYPAUSE, NONE,
|
||||
KEY_STOPCD, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, KEY_VOLUMEDOWN, NONE,
|
||||
KEY_VOLUMEUP, NONE, KEY_HOMEPAGE, NONE,
|
||||
NONE, KEY_KPASTERISK, NONE, KEY_SYSRQ,
|
||||
KEY_RIGHTALT, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
/* 0x40 - 0x5f. 0xE0 prefixed */
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, KEY_PAUSE, KEY_HOME,
|
||||
KEY_UP, KEY_PAGEUP, NONE, KEY_LEFT,
|
||||
NONE, KEY_RIGHT, NONE, KEY_END,
|
||||
KEY_DOWN, KEY_PAGEDOWN, KEY_INSERT, KEY_DELETE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, KEY_LEFTMETA,
|
||||
KEY_RIGHTMETA, KEY_MENU, KEY_POWER, KEY_SLEEP,
|
||||
/* 0x60 - 0x7f. 0xE0 prefixed */
|
||||
NONE, NONE, NONE, KEY_WAKEUP,
|
||||
NONE, KEY_SEARCH, KEY_BOOKMARKS, KEY_REFRESH,
|
||||
KEY_STOP, KEY_FORWARD, KEY_BACK, KEY_COMPUTER,
|
||||
KEY_MAIL, KEY_MEDIA, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
NONE, NONE, NONE, NONE,
|
||||
};
|
||||
|
||||
static uint16_t evdev_mouse_button_codes[] = {
|
||||
BTN_LEFT,
|
||||
BTN_MIDDLE,
|
||||
BTN_RIGHT,
|
||||
BTN_SIDE,
|
||||
BTN_EXTRA,
|
||||
BTN_FORWARD,
|
||||
BTN_BACK,
|
||||
BTN_TASK,
|
||||
};
|
||||
|
||||
static uint16_t evdev_led_codes[] = {
|
||||
LED_CAPSL, /* CLKED */
|
||||
LED_NUML, /* NLKED */
|
||||
LED_SCROLLL, /* SLKED */
|
||||
};
|
||||
|
||||
inline uint16_t
|
||||
evdev_hid2key(int scancode)
|
||||
{
|
||||
return evdev_usb_scancodes[scancode];
|
||||
}
|
||||
|
||||
inline void
|
||||
evdev_support_all_known_keys(struct evdev_dev *evdev)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = KEY_RESERVED; i < nitems(evdev_at_set1_scancodes); i++)
|
||||
if (evdev_at_set1_scancodes[i] != NONE)
|
||||
evdev_support_key(evdev, evdev_at_set1_scancodes[i]);
|
||||
}
|
||||
|
||||
inline uint16_t
|
||||
evdev_scancode2key(int *state, int scancode)
|
||||
{
|
||||
uint16_t keycode;
|
||||
|
||||
/* translate the scan code into a keycode */
|
||||
keycode = evdev_at_set1_scancodes[scancode & 0x7f];
|
||||
switch (*state) {
|
||||
case 0x00: /* normal scancode */
|
||||
switch(scancode) {
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
*state = scancode;
|
||||
return (NONE);
|
||||
}
|
||||
break;
|
||||
case 0xE0: /* 0xE0 prefix */
|
||||
*state = 0;
|
||||
keycode = evdev_at_set1_scancodes[0x80 + (scancode & 0x7f)];
|
||||
break;
|
||||
case 0xE1: /* 0xE1 prefix */
|
||||
/*
|
||||
* The pause/break key on the 101 keyboard produces:
|
||||
* E1-1D-45 E1-9D-C5
|
||||
* Ctrl-pause/break produces:
|
||||
* E0-46 E0-C6 (See above.)
|
||||
*/
|
||||
*state = 0;
|
||||
if ((scancode & 0x7f) == 0x1D)
|
||||
*state = 0x1D;
|
||||
return (NONE);
|
||||
/* NOT REACHED */
|
||||
case 0x1D: /* pause / break */
|
||||
*state = 0;
|
||||
if (scancode != 0x45)
|
||||
return (NONE);
|
||||
keycode = KEY_PAUSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return (keycode);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_push_mouse_btn(struct evdev_dev *evdev, int buttons)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < nitems(evdev_mouse_button_codes); i++)
|
||||
evdev_push_event(evdev, EV_KEY, evdev_mouse_button_codes[i],
|
||||
(buttons & (1 << i)) != 0);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_push_leds(struct evdev_dev *evdev, int leds)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* Some drivers initialize leds before evdev */
|
||||
if (evdev == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < nitems(evdev_led_codes); i++)
|
||||
evdev_push_event(evdev, EV_LED, evdev_led_codes[i],
|
||||
(leds & (1 << i)) != 0);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_push_repeats(struct evdev_dev *evdev, keyboard_t *kbd)
|
||||
{
|
||||
/* Some drivers initialize typematics before evdev */
|
||||
if (evdev == NULL)
|
||||
return;
|
||||
|
||||
evdev_push_event(evdev, EV_REP, REP_DELAY, kbd->kb_delay1);
|
||||
evdev_push_event(evdev, EV_REP, REP_PERIOD, kbd->kb_delay2);
|
||||
}
|
||||
|
||||
void
|
||||
evdev_ev_kbd_event(struct evdev_dev *evdev, void *softc, uint16_t type,
|
||||
uint16_t code, int32_t value)
|
||||
{
|
||||
keyboard_t *kbd = (keyboard_t *)softc;
|
||||
int delay[2], leds, oleds;
|
||||
size_t i;
|
||||
|
||||
if (type == EV_LED) {
|
||||
leds = oleds = KBD_LED_VAL(kbd);
|
||||
for (i = 0; i < nitems(evdev_led_codes); i++) {
|
||||
if (evdev_led_codes[i] == code) {
|
||||
if (value)
|
||||
leds |= 1 << i;
|
||||
else
|
||||
leds &= ~(1 << i);
|
||||
if (leds != oleds)
|
||||
kbdd_ioctl(kbd, KDSETLED,
|
||||
(caddr_t)&leds);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (type == EV_REP && code == REP_DELAY) {
|
||||
delay[0] = value;
|
||||
delay[1] = kbd->kb_delay2;
|
||||
kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
|
||||
} else if (type == EV_REP && code == REP_PERIOD) {
|
||||
delay[0] = kbd->kb_delay1;
|
||||
delay[1] = value;
|
||||
kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
|
||||
}
|
||||
}
|
819
sys/dev/evdev/input-event-codes.h
Normal file
819
sys/dev/evdev/input-event-codes.h
Normal file
@ -0,0 +1,819 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
|
||||
* Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#ifndef _EVDEV_INPUT_EVENT_CODES_H
|
||||
#define _EVDEV_INPUT_EVENT_CODES_H
|
||||
|
||||
/*
|
||||
* Device properties and quirks
|
||||
*/
|
||||
|
||||
#define INPUT_PROP_POINTER 0x00 /* needs a pointer */
|
||||
#define INPUT_PROP_DIRECT 0x01 /* direct input devices */
|
||||
#define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */
|
||||
#define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */
|
||||
#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
|
||||
#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */
|
||||
#define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */
|
||||
|
||||
#define INPUT_PROP_MAX 0x1f
|
||||
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
|
||||
|
||||
/*
|
||||
* Event types
|
||||
*/
|
||||
|
||||
#define EV_SYN 0x00
|
||||
#define EV_KEY 0x01
|
||||
#define EV_REL 0x02
|
||||
#define EV_ABS 0x03
|
||||
#define EV_MSC 0x04
|
||||
#define EV_SW 0x05
|
||||
#define EV_LED 0x11
|
||||
#define EV_SND 0x12
|
||||
#define EV_REP 0x14
|
||||
#define EV_FF 0x15
|
||||
#define EV_PWR 0x16
|
||||
#define EV_FF_STATUS 0x17
|
||||
#define EV_MAX 0x1f
|
||||
#define EV_CNT (EV_MAX+1)
|
||||
|
||||
/*
|
||||
* Synchronization events.
|
||||
*/
|
||||
|
||||
#define SYN_REPORT 0
|
||||
#define SYN_CONFIG 1
|
||||
#define SYN_MT_REPORT 2
|
||||
#define SYN_DROPPED 3
|
||||
#define SYN_MAX 0xf
|
||||
#define SYN_CNT (SYN_MAX+1)
|
||||
|
||||
/*
|
||||
* Keys and buttons
|
||||
*/
|
||||
|
||||
/*
|
||||
* Abbreviations in the comments:
|
||||
* AC - Application Control
|
||||
* AL - Application Launch Button
|
||||
* SC - System Control
|
||||
*/
|
||||
|
||||
#define KEY_RESERVED 0
|
||||
#define KEY_ESC 1
|
||||
#define KEY_1 2
|
||||
#define KEY_2 3
|
||||
#define KEY_3 4
|
||||
#define KEY_4 5
|
||||
#define KEY_5 6
|
||||
#define KEY_6 7
|
||||
#define KEY_7 8
|
||||
#define KEY_8 9
|
||||
#define KEY_9 10
|
||||
#define KEY_0 11
|
||||
#define KEY_MINUS 12
|
||||
#define KEY_EQUAL 13
|
||||
#define KEY_BACKSPACE 14
|
||||
#define KEY_TAB 15
|
||||
#define KEY_Q 16
|
||||
#define KEY_W 17
|
||||
#define KEY_E 18
|
||||
#define KEY_R 19
|
||||
#define KEY_T 20
|
||||
#define KEY_Y 21
|
||||
#define KEY_U 22
|
||||
#define KEY_I 23
|
||||
#define KEY_O 24
|
||||
#define KEY_P 25
|
||||
#define KEY_LEFTBRACE 26
|
||||
#define KEY_RIGHTBRACE 27
|
||||
#define KEY_ENTER 28
|
||||
#define KEY_LEFTCTRL 29
|
||||
#define KEY_A 30
|
||||
#define KEY_S 31
|
||||
#define KEY_D 32
|
||||
#define KEY_F 33
|
||||
#define KEY_G 34
|
||||
#define KEY_H 35
|
||||
#define KEY_J 36
|
||||
#define KEY_K 37
|
||||
#define KEY_L 38
|
||||
#define KEY_SEMICOLON 39
|
||||
#define KEY_APOSTROPHE 40
|
||||
#define KEY_GRAVE 41
|
||||
#define KEY_LEFTSHIFT 42
|
||||
#define KEY_BACKSLASH 43
|
||||
#define KEY_Z 44
|
||||
#define KEY_X 45
|
||||
#define KEY_C 46
|
||||
#define KEY_V 47
|
||||
#define KEY_B 48
|
||||
#define KEY_N 49
|
||||
#define KEY_M 50
|
||||
#define KEY_COMMA 51
|
||||
#define KEY_DOT 52
|
||||
#define KEY_SLASH 53
|
||||
#define KEY_RIGHTSHIFT 54
|
||||
#define KEY_KPASTERISK 55
|
||||
#define KEY_LEFTALT 56
|
||||
#define KEY_SPACE 57
|
||||
#define KEY_CAPSLOCK 58
|
||||
#define KEY_F1 59
|
||||
#define KEY_F2 60
|
||||
#define KEY_F3 61
|
||||
#define KEY_F4 62
|
||||
#define KEY_F5 63
|
||||
#define KEY_F6 64
|
||||
#define KEY_F7 65
|
||||
#define KEY_F8 66
|
||||
#define KEY_F9 67
|
||||
#define KEY_F10 68
|
||||
#define KEY_NUMLOCK 69
|
||||
#define KEY_SCROLLLOCK 70
|
||||
#define KEY_KP7 71
|
||||
#define KEY_KP8 72
|
||||
#define KEY_KP9 73
|
||||
#define KEY_KPMINUS 74
|
||||
#define KEY_KP4 75
|
||||
#define KEY_KP5 76
|
||||
#define KEY_KP6 77
|
||||
#define KEY_KPPLUS 78
|
||||
#define KEY_KP1 79
|
||||
#define KEY_KP2 80
|
||||
#define KEY_KP3 81
|
||||
#define KEY_KP0 82
|
||||
#define KEY_KPDOT 83
|
||||
|
||||
#define KEY_ZENKAKUHANKAKU 85
|
||||
#define KEY_102ND 86
|
||||
#define KEY_F11 87
|
||||
#define KEY_F12 88
|
||||
#define KEY_RO 89
|
||||
#define KEY_KATAKANA 90
|
||||
#define KEY_HIRAGANA 91
|
||||
#define KEY_HENKAN 92
|
||||
#define KEY_KATAKANAHIRAGANA 93
|
||||
#define KEY_MUHENKAN 94
|
||||
#define KEY_KPJPCOMMA 95
|
||||
#define KEY_KPENTER 96
|
||||
#define KEY_RIGHTCTRL 97
|
||||
#define KEY_KPSLASH 98
|
||||
#define KEY_SYSRQ 99
|
||||
#define KEY_RIGHTALT 100
|
||||
#define KEY_LINEFEED 101
|
||||
#define KEY_HOME 102
|
||||
#define KEY_UP 103
|
||||
#define KEY_PAGEUP 104
|
||||
#define KEY_LEFT 105
|
||||
#define KEY_RIGHT 106
|
||||
#define KEY_END 107
|
||||
#define KEY_DOWN 108
|
||||
#define KEY_PAGEDOWN 109
|
||||
#define KEY_INSERT 110
|
||||
#define KEY_DELETE 111
|
||||
#define KEY_MACRO 112
|
||||
#define KEY_MUTE 113
|
||||
#define KEY_VOLUMEDOWN 114
|
||||
#define KEY_VOLUMEUP 115
|
||||
#define KEY_POWER 116 /* SC System Power Down */
|
||||
#define KEY_KPEQUAL 117
|
||||
#define KEY_KPPLUSMINUS 118
|
||||
#define KEY_PAUSE 119
|
||||
#define KEY_SCALE 120 /* AL Compiz Scale (Expose) */
|
||||
|
||||
#define KEY_KPCOMMA 121
|
||||
#define KEY_HANGEUL 122
|
||||
#define KEY_HANGUEL KEY_HANGEUL
|
||||
#define KEY_HANJA 123
|
||||
#define KEY_YEN 124
|
||||
#define KEY_LEFTMETA 125
|
||||
#define KEY_RIGHTMETA 126
|
||||
#define KEY_COMPOSE 127
|
||||
|
||||
#define KEY_STOP 128 /* AC Stop */
|
||||
#define KEY_AGAIN 129
|
||||
#define KEY_PROPS 130 /* AC Properties */
|
||||
#define KEY_UNDO 131 /* AC Undo */
|
||||
#define KEY_FRONT 132
|
||||
#define KEY_COPY 133 /* AC Copy */
|
||||
#define KEY_OPEN 134 /* AC Open */
|
||||
#define KEY_PASTE 135 /* AC Paste */
|
||||
#define KEY_FIND 136 /* AC Search */
|
||||
#define KEY_CUT 137 /* AC Cut */
|
||||
#define KEY_HELP 138 /* AL Integrated Help Center */
|
||||
#define KEY_MENU 139 /* Menu (show menu) */
|
||||
#define KEY_CALC 140 /* AL Calculator */
|
||||
#define KEY_SETUP 141
|
||||
#define KEY_SLEEP 142 /* SC System Sleep */
|
||||
#define KEY_WAKEUP 143 /* System Wake Up */
|
||||
#define KEY_FILE 144 /* AL Local Machine Browser */
|
||||
#define KEY_SENDFILE 145
|
||||
#define KEY_DELETEFILE 146
|
||||
#define KEY_XFER 147
|
||||
#define KEY_PROG1 148
|
||||
#define KEY_PROG2 149
|
||||
#define KEY_WWW 150 /* AL Internet Browser */
|
||||
#define KEY_MSDOS 151
|
||||
#define KEY_COFFEE 152 /* AL Terminal Lock/Screensaver */
|
||||
#define KEY_SCREENLOCK KEY_COFFEE
|
||||
#define KEY_ROTATE_DISPLAY 153 /* Display orientation for e.g. tablets */
|
||||
#define KEY_DIRECTION KEY_ROTATE_DISPLAY
|
||||
#define KEY_CYCLEWINDOWS 154
|
||||
#define KEY_MAIL 155
|
||||
#define KEY_BOOKMARKS 156 /* AC Bookmarks */
|
||||
#define KEY_COMPUTER 157
|
||||
#define KEY_BACK 158 /* AC Back */
|
||||
#define KEY_FORWARD 159 /* AC Forward */
|
||||
#define KEY_CLOSECD 160
|
||||
#define KEY_EJECTCD 161
|
||||
#define KEY_EJECTCLOSECD 162
|
||||
#define KEY_NEXTSONG 163
|
||||
#define KEY_PLAYPAUSE 164
|
||||
#define KEY_PREVIOUSSONG 165
|
||||
#define KEY_STOPCD 166
|
||||
#define KEY_RECORD 167
|
||||
#define KEY_REWIND 168
|
||||
#define KEY_PHONE 169 /* Media Select Telephone */
|
||||
#define KEY_ISO 170
|
||||
#define KEY_CONFIG 171 /* AL Consumer Control Configuration */
|
||||
#define KEY_HOMEPAGE 172 /* AC Home */
|
||||
#define KEY_REFRESH 173 /* AC Refresh */
|
||||
#define KEY_EXIT 174 /* AC Exit */
|
||||
#define KEY_MOVE 175
|
||||
#define KEY_EDIT 176
|
||||
#define KEY_SCROLLUP 177
|
||||
#define KEY_SCROLLDOWN 178
|
||||
#define KEY_KPLEFTPAREN 179
|
||||
#define KEY_KPRIGHTPAREN 180
|
||||
#define KEY_NEW 181 /* AC New */
|
||||
#define KEY_REDO 182 /* AC Redo/Repeat */
|
||||
|
||||
#define KEY_F13 183
|
||||
#define KEY_F14 184
|
||||
#define KEY_F15 185
|
||||
#define KEY_F16 186
|
||||
#define KEY_F17 187
|
||||
#define KEY_F18 188
|
||||
#define KEY_F19 189
|
||||
#define KEY_F20 190
|
||||
#define KEY_F21 191
|
||||
#define KEY_F22 192
|
||||
#define KEY_F23 193
|
||||
#define KEY_F24 194
|
||||
|
||||
#define KEY_PLAYCD 200
|
||||
#define KEY_PAUSECD 201
|
||||
#define KEY_PROG3 202
|
||||
#define KEY_PROG4 203
|
||||
#define KEY_DASHBOARD 204 /* AL Dashboard */
|
||||
#define KEY_SUSPEND 205
|
||||
#define KEY_CLOSE 206 /* AC Close */
|
||||
#define KEY_PLAY 207
|
||||
#define KEY_FASTFORWARD 208
|
||||
#define KEY_BASSBOOST 209
|
||||
#define KEY_PRINT 210 /* AC Print */
|
||||
#define KEY_HP 211
|
||||
#define KEY_CAMERA 212
|
||||
#define KEY_SOUND 213
|
||||
#define KEY_QUESTION 214
|
||||
#define KEY_EMAIL 215
|
||||
#define KEY_CHAT 216
|
||||
#define KEY_SEARCH 217
|
||||
#define KEY_CONNECT 218
|
||||
#define KEY_FINANCE 219 /* AL Checkbook/Finance */
|
||||
#define KEY_SPORT 220
|
||||
#define KEY_SHOP 221
|
||||
#define KEY_ALTERASE 222
|
||||
#define KEY_CANCEL 223 /* AC Cancel */
|
||||
#define KEY_BRIGHTNESSDOWN 224
|
||||
#define KEY_BRIGHTNESSUP 225
|
||||
#define KEY_MEDIA 226
|
||||
|
||||
#define KEY_SWITCHVIDEOMODE 227 /* Cycle between available video
|
||||
outputs (Monitor/LCD/TV-out/etc) */
|
||||
#define KEY_KBDILLUMTOGGLE 228
|
||||
#define KEY_KBDILLUMDOWN 229
|
||||
#define KEY_KBDILLUMUP 230
|
||||
|
||||
#define KEY_SEND 231 /* AC Send */
|
||||
#define KEY_REPLY 232 /* AC Reply */
|
||||
#define KEY_FORWARDMAIL 233 /* AC Forward Msg */
|
||||
#define KEY_SAVE 234 /* AC Save */
|
||||
#define KEY_DOCUMENTS 235
|
||||
|
||||
#define KEY_BATTERY 236
|
||||
|
||||
#define KEY_BLUETOOTH 237
|
||||
#define KEY_WLAN 238
|
||||
#define KEY_UWB 239
|
||||
|
||||
#define KEY_UNKNOWN 240
|
||||
|
||||
#define KEY_VIDEO_NEXT 241 /* drive next video source */
|
||||
#define KEY_VIDEO_PREV 242 /* drive previous video source */
|
||||
#define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */
|
||||
#define KEY_BRIGHTNESS_AUTO 244 /* Set Auto Brightness: manual
|
||||
brightness control is off,
|
||||
rely on ambient */
|
||||
#define KEY_BRIGHTNESS_ZERO KEY_BRIGHTNESS_AUTO
|
||||
#define KEY_DISPLAY_OFF 245 /* display device to off state */
|
||||
|
||||
#define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */
|
||||
#define KEY_WIMAX KEY_WWAN
|
||||
#define KEY_RFKILL 247 /* Key that controls all radios */
|
||||
|
||||
#define KEY_MICMUTE 248 /* Mute / unmute the microphone */
|
||||
|
||||
/* Code 255 is reserved for special needs of AT keyboard driver */
|
||||
|
||||
#define BTN_MISC 0x100
|
||||
#define BTN_0 0x100
|
||||
#define BTN_1 0x101
|
||||
#define BTN_2 0x102
|
||||
#define BTN_3 0x103
|
||||
#define BTN_4 0x104
|
||||
#define BTN_5 0x105
|
||||
#define BTN_6 0x106
|
||||
#define BTN_7 0x107
|
||||
#define BTN_8 0x108
|
||||
#define BTN_9 0x109
|
||||
|
||||
#define BTN_MOUSE 0x110
|
||||
#define BTN_LEFT 0x110
|
||||
#define BTN_RIGHT 0x111
|
||||
#define BTN_MIDDLE 0x112
|
||||
#define BTN_SIDE 0x113
|
||||
#define BTN_EXTRA 0x114
|
||||
#define BTN_FORWARD 0x115
|
||||
#define BTN_BACK 0x116
|
||||
#define BTN_TASK 0x117
|
||||
|
||||
#define BTN_JOYSTICK 0x120
|
||||
#define BTN_TRIGGER 0x120
|
||||
#define BTN_THUMB 0x121
|
||||
#define BTN_THUMB2 0x122
|
||||
#define BTN_TOP 0x123
|
||||
#define BTN_TOP2 0x124
|
||||
#define BTN_PINKIE 0x125
|
||||
#define BTN_BASE 0x126
|
||||
#define BTN_BASE2 0x127
|
||||
#define BTN_BASE3 0x128
|
||||
#define BTN_BASE4 0x129
|
||||
#define BTN_BASE5 0x12a
|
||||
#define BTN_BASE6 0x12b
|
||||
#define BTN_DEAD 0x12f
|
||||
|
||||
#define BTN_GAMEPAD 0x130
|
||||
#define BTN_SOUTH 0x130
|
||||
#define BTN_A BTN_SOUTH
|
||||
#define BTN_EAST 0x131
|
||||
#define BTN_B BTN_EAST
|
||||
#define BTN_C 0x132
|
||||
#define BTN_NORTH 0x133
|
||||
#define BTN_X BTN_NORTH
|
||||
#define BTN_WEST 0x134
|
||||
#define BTN_Y BTN_WEST
|
||||
#define BTN_Z 0x135
|
||||
#define BTN_TL 0x136
|
||||
#define BTN_TR 0x137
|
||||
#define BTN_TL2 0x138
|
||||
#define BTN_TR2 0x139
|
||||
#define BTN_SELECT 0x13a
|
||||
#define BTN_START 0x13b
|
||||
#define BTN_MODE 0x13c
|
||||
#define BTN_THUMBL 0x13d
|
||||
#define BTN_THUMBR 0x13e
|
||||
|
||||
#define BTN_DIGI 0x140
|
||||
#define BTN_TOOL_PEN 0x140
|
||||
#define BTN_TOOL_RUBBER 0x141
|
||||
#define BTN_TOOL_BRUSH 0x142
|
||||
#define BTN_TOOL_PENCIL 0x143
|
||||
#define BTN_TOOL_AIRBRUSH 0x144
|
||||
#define BTN_TOOL_FINGER 0x145
|
||||
#define BTN_TOOL_MOUSE 0x146
|
||||
#define BTN_TOOL_LENS 0x147
|
||||
#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */
|
||||
#define BTN_TOUCH 0x14a
|
||||
#define BTN_STYLUS 0x14b
|
||||
#define BTN_STYLUS2 0x14c
|
||||
#define BTN_TOOL_DOUBLETAP 0x14d
|
||||
#define BTN_TOOL_TRIPLETAP 0x14e
|
||||
#define BTN_TOOL_QUADTAP 0x14f /* Four fingers on trackpad */
|
||||
|
||||
#define BTN_WHEEL 0x150
|
||||
#define BTN_GEAR_DOWN 0x150
|
||||
#define BTN_GEAR_UP 0x151
|
||||
|
||||
#define KEY_OK 0x160
|
||||
#define KEY_SELECT 0x161
|
||||
#define KEY_GOTO 0x162
|
||||
#define KEY_CLEAR 0x163
|
||||
#define KEY_POWER2 0x164
|
||||
#define KEY_OPTION 0x165
|
||||
#define KEY_INFO 0x166 /* AL OEM Features/Tips/Tutorial */
|
||||
#define KEY_TIME 0x167
|
||||
#define KEY_VENDOR 0x168
|
||||
#define KEY_ARCHIVE 0x169
|
||||
#define KEY_PROGRAM 0x16a /* Media Select Program Guide */
|
||||
#define KEY_CHANNEL 0x16b
|
||||
#define KEY_FAVORITES 0x16c
|
||||
#define KEY_EPG 0x16d
|
||||
#define KEY_PVR 0x16e /* Media Select Home */
|
||||
#define KEY_MHP 0x16f
|
||||
#define KEY_LANGUAGE 0x170
|
||||
#define KEY_TITLE 0x171
|
||||
#define KEY_SUBTITLE 0x172
|
||||
#define KEY_ANGLE 0x173
|
||||
#define KEY_ZOOM 0x174
|
||||
#define KEY_MODE 0x175
|
||||
#define KEY_KEYBOARD 0x176
|
||||
#define KEY_SCREEN 0x177
|
||||
#define KEY_PC 0x178 /* Media Select Computer */
|
||||
#define KEY_TV 0x179 /* Media Select TV */
|
||||
#define KEY_TV2 0x17a /* Media Select Cable */
|
||||
#define KEY_VCR 0x17b /* Media Select VCR */
|
||||
#define KEY_VCR2 0x17c /* VCR Plus */
|
||||
#define KEY_SAT 0x17d /* Media Select Satellite */
|
||||
#define KEY_SAT2 0x17e
|
||||
#define KEY_CD 0x17f /* Media Select CD */
|
||||
#define KEY_TAPE 0x180 /* Media Select Tape */
|
||||
#define KEY_RADIO 0x181
|
||||
#define KEY_TUNER 0x182 /* Media Select Tuner */
|
||||
#define KEY_PLAYER 0x183
|
||||
#define KEY_TEXT 0x184
|
||||
#define KEY_DVD 0x185 /* Media Select DVD */
|
||||
#define KEY_AUX 0x186
|
||||
#define KEY_MP3 0x187
|
||||
#define KEY_AUDIO 0x188 /* AL Audio Browser */
|
||||
#define KEY_VIDEO 0x189 /* AL Movie Browser */
|
||||
#define KEY_DIRECTORY 0x18a
|
||||
#define KEY_LIST 0x18b
|
||||
#define KEY_MEMO 0x18c /* Media Select Messages */
|
||||
#define KEY_CALENDAR 0x18d
|
||||
#define KEY_RED 0x18e
|
||||
#define KEY_GREEN 0x18f
|
||||
#define KEY_YELLOW 0x190
|
||||
#define KEY_BLUE 0x191
|
||||
#define KEY_CHANNELUP 0x192 /* Channel Increment */
|
||||
#define KEY_CHANNELDOWN 0x193 /* Channel Decrement */
|
||||
#define KEY_FIRST 0x194
|
||||
#define KEY_LAST 0x195 /* Recall Last */
|
||||
#define KEY_AB 0x196
|
||||
#define KEY_NEXT 0x197
|
||||
#define KEY_RESTART 0x198
|
||||
#define KEY_SLOW 0x199
|
||||
#define KEY_SHUFFLE 0x19a
|
||||
#define KEY_BREAK 0x19b
|
||||
#define KEY_PREVIOUS 0x19c
|
||||
#define KEY_DIGITS 0x19d
|
||||
#define KEY_TEEN 0x19e
|
||||
#define KEY_TWEN 0x19f
|
||||
#define KEY_VIDEOPHONE 0x1a0 /* Media Select Video Phone */
|
||||
#define KEY_GAMES 0x1a1 /* Media Select Games */
|
||||
#define KEY_ZOOMIN 0x1a2 /* AC Zoom In */
|
||||
#define KEY_ZOOMOUT 0x1a3 /* AC Zoom Out */
|
||||
#define KEY_ZOOMRESET 0x1a4 /* AC Zoom */
|
||||
#define KEY_WORDPROCESSOR 0x1a5 /* AL Word Processor */
|
||||
#define KEY_EDITOR 0x1a6 /* AL Text Editor */
|
||||
#define KEY_SPREADSHEET 0x1a7 /* AL Spreadsheet */
|
||||
#define KEY_GRAPHICSEDITOR 0x1a8 /* AL Graphics Editor */
|
||||
#define KEY_PRESENTATION 0x1a9 /* AL Presentation App */
|
||||
#define KEY_DATABASE 0x1aa /* AL Database App */
|
||||
#define KEY_NEWS 0x1ab /* AL Newsreader */
|
||||
#define KEY_VOICEMAIL 0x1ac /* AL Voicemail */
|
||||
#define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */
|
||||
#define KEY_MESSENGER 0x1ae /* AL Instant Messaging */
|
||||
#define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */
|
||||
#define KEY_BRIGHTNESS_TOGGLE KEY_DISPLAYTOGGLE
|
||||
#define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */
|
||||
#define KEY_LOGOFF 0x1b1 /* AL Logoff */
|
||||
|
||||
#define KEY_DOLLAR 0x1b2
|
||||
#define KEY_EURO 0x1b3
|
||||
|
||||
#define KEY_FRAMEBACK 0x1b4 /* Consumer - transport controls */
|
||||
#define KEY_FRAMEFORWARD 0x1b5
|
||||
#define KEY_CONTEXT_MENU 0x1b6 /* GenDesc - system context menu */
|
||||
#define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */
|
||||
#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */
|
||||
#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */
|
||||
#define KEY_IMAGES 0x1ba /* AL Image Browser */
|
||||
|
||||
#define KEY_DEL_EOL 0x1c0
|
||||
#define KEY_DEL_EOS 0x1c1
|
||||
#define KEY_INS_LINE 0x1c2
|
||||
#define KEY_DEL_LINE 0x1c3
|
||||
|
||||
#define KEY_FN 0x1d0
|
||||
#define KEY_FN_ESC 0x1d1
|
||||
#define KEY_FN_F1 0x1d2
|
||||
#define KEY_FN_F2 0x1d3
|
||||
#define KEY_FN_F3 0x1d4
|
||||
#define KEY_FN_F4 0x1d5
|
||||
#define KEY_FN_F5 0x1d6
|
||||
#define KEY_FN_F6 0x1d7
|
||||
#define KEY_FN_F7 0x1d8
|
||||
#define KEY_FN_F8 0x1d9
|
||||
#define KEY_FN_F9 0x1da
|
||||
#define KEY_FN_F10 0x1db
|
||||
#define KEY_FN_F11 0x1dc
|
||||
#define KEY_FN_F12 0x1dd
|
||||
#define KEY_FN_1 0x1de
|
||||
#define KEY_FN_2 0x1df
|
||||
#define KEY_FN_D 0x1e0
|
||||
#define KEY_FN_E 0x1e1
|
||||
#define KEY_FN_F 0x1e2
|
||||
#define KEY_FN_S 0x1e3
|
||||
#define KEY_FN_B 0x1e4
|
||||
|
||||
#define KEY_BRL_DOT1 0x1f1
|
||||
#define KEY_BRL_DOT2 0x1f2
|
||||
#define KEY_BRL_DOT3 0x1f3
|
||||
#define KEY_BRL_DOT4 0x1f4
|
||||
#define KEY_BRL_DOT5 0x1f5
|
||||
#define KEY_BRL_DOT6 0x1f6
|
||||
#define KEY_BRL_DOT7 0x1f7
|
||||
#define KEY_BRL_DOT8 0x1f8
|
||||
#define KEY_BRL_DOT9 0x1f9
|
||||
#define KEY_BRL_DOT10 0x1fa
|
||||
|
||||
#define KEY_NUMERIC_0 0x200 /* used by phones, remote controls, */
|
||||
#define KEY_NUMERIC_1 0x201 /* and other keypads */
|
||||
#define KEY_NUMERIC_2 0x202
|
||||
#define KEY_NUMERIC_3 0x203
|
||||
#define KEY_NUMERIC_4 0x204
|
||||
#define KEY_NUMERIC_5 0x205
|
||||
#define KEY_NUMERIC_6 0x206
|
||||
#define KEY_NUMERIC_7 0x207
|
||||
#define KEY_NUMERIC_8 0x208
|
||||
#define KEY_NUMERIC_9 0x209
|
||||
#define KEY_NUMERIC_STAR 0x20a
|
||||
#define KEY_NUMERIC_POUND 0x20b
|
||||
#define KEY_NUMERIC_A 0x20c /* Phone key A - HUT Telephony 0xb9 */
|
||||
#define KEY_NUMERIC_B 0x20d
|
||||
#define KEY_NUMERIC_C 0x20e
|
||||
#define KEY_NUMERIC_D 0x20f
|
||||
|
||||
#define KEY_CAMERA_FOCUS 0x210
|
||||
#define KEY_WPS_BUTTON 0x211 /* WiFi Protected Setup key */
|
||||
|
||||
#define KEY_TOUCHPAD_TOGGLE 0x212 /* Request switch touchpad on or off */
|
||||
#define KEY_TOUCHPAD_ON 0x213
|
||||
#define KEY_TOUCHPAD_OFF 0x214
|
||||
|
||||
#define KEY_CAMERA_ZOOMIN 0x215
|
||||
#define KEY_CAMERA_ZOOMOUT 0x216
|
||||
#define KEY_CAMERA_UP 0x217
|
||||
#define KEY_CAMERA_DOWN 0x218
|
||||
#define KEY_CAMERA_LEFT 0x219
|
||||
#define KEY_CAMERA_RIGHT 0x21a
|
||||
|
||||
#define KEY_ATTENDANT_ON 0x21b
|
||||
#define KEY_ATTENDANT_OFF 0x21c
|
||||
#define KEY_ATTENDANT_TOGGLE 0x21d /* Attendant call on or off */
|
||||
#define KEY_LIGHTS_TOGGLE 0x21e /* Reading light on or off */
|
||||
|
||||
#define BTN_DPAD_UP 0x220
|
||||
#define BTN_DPAD_DOWN 0x221
|
||||
#define BTN_DPAD_LEFT 0x222
|
||||
#define BTN_DPAD_RIGHT 0x223
|
||||
|
||||
#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
|
||||
|
||||
#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */
|
||||
#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */
|
||||
#define KEY_JOURNAL 0x242 /* AL Log/Journal/Timecard */
|
||||
#define KEY_CONTROLPANEL 0x243 /* AL Control Panel */
|
||||
#define KEY_APPSELECT 0x244 /* AL Select Task/Application */
|
||||
#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
|
||||
#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
|
||||
|
||||
#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
|
||||
#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
|
||||
|
||||
#define KEY_KBDINPUTASSIST_PREV 0x260
|
||||
#define KEY_KBDINPUTASSIST_NEXT 0x261
|
||||
#define KEY_KBDINPUTASSIST_PREVGROUP 0x262
|
||||
#define KEY_KBDINPUTASSIST_NEXTGROUP 0x263
|
||||
#define KEY_KBDINPUTASSIST_ACCEPT 0x264
|
||||
#define KEY_KBDINPUTASSIST_CANCEL 0x265
|
||||
|
||||
#define BTN_TRIGGER_HAPPY 0x2c0
|
||||
#define BTN_TRIGGER_HAPPY1 0x2c0
|
||||
#define BTN_TRIGGER_HAPPY2 0x2c1
|
||||
#define BTN_TRIGGER_HAPPY3 0x2c2
|
||||
#define BTN_TRIGGER_HAPPY4 0x2c3
|
||||
#define BTN_TRIGGER_HAPPY5 0x2c4
|
||||
#define BTN_TRIGGER_HAPPY6 0x2c5
|
||||
#define BTN_TRIGGER_HAPPY7 0x2c6
|
||||
#define BTN_TRIGGER_HAPPY8 0x2c7
|
||||
#define BTN_TRIGGER_HAPPY9 0x2c8
|
||||
#define BTN_TRIGGER_HAPPY10 0x2c9
|
||||
#define BTN_TRIGGER_HAPPY11 0x2ca
|
||||
#define BTN_TRIGGER_HAPPY12 0x2cb
|
||||
#define BTN_TRIGGER_HAPPY13 0x2cc
|
||||
#define BTN_TRIGGER_HAPPY14 0x2cd
|
||||
#define BTN_TRIGGER_HAPPY15 0x2ce
|
||||
#define BTN_TRIGGER_HAPPY16 0x2cf
|
||||
#define BTN_TRIGGER_HAPPY17 0x2d0
|
||||
#define BTN_TRIGGER_HAPPY18 0x2d1
|
||||
#define BTN_TRIGGER_HAPPY19 0x2d2
|
||||
#define BTN_TRIGGER_HAPPY20 0x2d3
|
||||
#define BTN_TRIGGER_HAPPY21 0x2d4
|
||||
#define BTN_TRIGGER_HAPPY22 0x2d5
|
||||
#define BTN_TRIGGER_HAPPY23 0x2d6
|
||||
#define BTN_TRIGGER_HAPPY24 0x2d7
|
||||
#define BTN_TRIGGER_HAPPY25 0x2d8
|
||||
#define BTN_TRIGGER_HAPPY26 0x2d9
|
||||
#define BTN_TRIGGER_HAPPY27 0x2da
|
||||
#define BTN_TRIGGER_HAPPY28 0x2db
|
||||
#define BTN_TRIGGER_HAPPY29 0x2dc
|
||||
#define BTN_TRIGGER_HAPPY30 0x2dd
|
||||
#define BTN_TRIGGER_HAPPY31 0x2de
|
||||
#define BTN_TRIGGER_HAPPY32 0x2df
|
||||
#define BTN_TRIGGER_HAPPY33 0x2e0
|
||||
#define BTN_TRIGGER_HAPPY34 0x2e1
|
||||
#define BTN_TRIGGER_HAPPY35 0x2e2
|
||||
#define BTN_TRIGGER_HAPPY36 0x2e3
|
||||
#define BTN_TRIGGER_HAPPY37 0x2e4
|
||||
#define BTN_TRIGGER_HAPPY38 0x2e5
|
||||
#define BTN_TRIGGER_HAPPY39 0x2e6
|
||||
#define BTN_TRIGGER_HAPPY40 0x2e7
|
||||
|
||||
/* We avoid low common keys in module aliases so they don't get huge. */
|
||||
#define KEY_MIN_INTERESTING KEY_MUTE
|
||||
#define KEY_MAX 0x2ff
|
||||
#define KEY_CNT (KEY_MAX+1)
|
||||
|
||||
/*
|
||||
* Relative axes
|
||||
*/
|
||||
|
||||
#define REL_X 0x00
|
||||
#define REL_Y 0x01
|
||||
#define REL_Z 0x02
|
||||
#define REL_RX 0x03
|
||||
#define REL_RY 0x04
|
||||
#define REL_RZ 0x05
|
||||
#define REL_HWHEEL 0x06
|
||||
#define REL_DIAL 0x07
|
||||
#define REL_WHEEL 0x08
|
||||
#define REL_MISC 0x09
|
||||
#define REL_MAX 0x0f
|
||||
#define REL_CNT (REL_MAX+1)
|
||||
|
||||
/*
|
||||
* Absolute axes
|
||||
*/
|
||||
|
||||
#define ABS_X 0x00
|
||||
#define ABS_Y 0x01
|
||||
#define ABS_Z 0x02
|
||||
#define ABS_RX 0x03
|
||||
#define ABS_RY 0x04
|
||||
#define ABS_RZ 0x05
|
||||
#define ABS_THROTTLE 0x06
|
||||
#define ABS_RUDDER 0x07
|
||||
#define ABS_WHEEL 0x08
|
||||
#define ABS_GAS 0x09
|
||||
#define ABS_BRAKE 0x0a
|
||||
#define ABS_HAT0X 0x10
|
||||
#define ABS_HAT0Y 0x11
|
||||
#define ABS_HAT1X 0x12
|
||||
#define ABS_HAT1Y 0x13
|
||||
#define ABS_HAT2X 0x14
|
||||
#define ABS_HAT2Y 0x15
|
||||
#define ABS_HAT3X 0x16
|
||||
#define ABS_HAT3Y 0x17
|
||||
#define ABS_PRESSURE 0x18
|
||||
#define ABS_DISTANCE 0x19
|
||||
#define ABS_TILT_X 0x1a
|
||||
#define ABS_TILT_Y 0x1b
|
||||
#define ABS_TOOL_WIDTH 0x1c
|
||||
|
||||
#define ABS_VOLUME 0x20
|
||||
|
||||
#define ABS_MISC 0x28
|
||||
|
||||
#define ABS_MT_SLOT 0x2f /* MT slot being modified */
|
||||
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
|
||||
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
|
||||
#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
|
||||
#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
|
||||
#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
|
||||
#define ABS_MT_POSITION_X 0x35 /* Center X touch position */
|
||||
#define ABS_MT_POSITION_Y 0x36 /* Center Y touch position */
|
||||
#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
|
||||
#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
|
||||
#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
|
||||
#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */
|
||||
#define ABS_MT_DISTANCE 0x3b /* Contact hover distance */
|
||||
#define ABS_MT_TOOL_X 0x3c /* Center X tool position */
|
||||
#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */
|
||||
|
||||
#define ABS_MAX 0x3f
|
||||
#define ABS_CNT (ABS_MAX+1)
|
||||
|
||||
/*
|
||||
* Switch events
|
||||
*/
|
||||
|
||||
#define SW_LID 0x00 /* set = lid shut */
|
||||
#define SW_TABLET_MODE 0x01 /* set = tablet mode */
|
||||
#define SW_HEADPHONE_INSERT 0x02 /* set = inserted */
|
||||
#define SW_RFKILL_ALL 0x03 /* rfkill master switch, type "any"
|
||||
set = radio enabled */
|
||||
#define SW_RADIO SW_RFKILL_ALL /* deprecated */
|
||||
#define SW_MICROPHONE_INSERT 0x04 /* set = inserted */
|
||||
#define SW_DOCK 0x05 /* set = plugged into dock */
|
||||
#define SW_LINEOUT_INSERT 0x06 /* set = inserted */
|
||||
#define SW_JACK_PHYSICAL_INSERT 0x07 /* set = mechanical switch set */
|
||||
#define SW_VIDEOOUT_INSERT 0x08 /* set = inserted */
|
||||
#define SW_CAMERA_LENS_COVER 0x09 /* set = lens covered */
|
||||
#define SW_KEYPAD_SLIDE 0x0a /* set = keypad slide out */
|
||||
#define SW_FRONT_PROXIMITY 0x0b /* set = front proximity sensor active */
|
||||
#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */
|
||||
#define SW_LINEIN_INSERT 0x0d /* set = inserted */
|
||||
#define SW_MUTE_DEVICE 0x0e /* set = device disabled */
|
||||
#define SW_MAX 0x0f
|
||||
#define SW_CNT (SW_MAX+1)
|
||||
|
||||
/*
|
||||
* Misc events
|
||||
*/
|
||||
|
||||
#define MSC_SERIAL 0x00
|
||||
#define MSC_PULSELED 0x01
|
||||
#define MSC_GESTURE 0x02
|
||||
#define MSC_RAW 0x03
|
||||
#define MSC_SCAN 0x04
|
||||
#define MSC_TIMESTAMP 0x05
|
||||
#define MSC_MAX 0x07
|
||||
#define MSC_CNT (MSC_MAX+1)
|
||||
|
||||
/*
|
||||
* LEDs
|
||||
*/
|
||||
|
||||
#define LED_NUML 0x00
|
||||
#define LED_CAPSL 0x01
|
||||
#define LED_SCROLLL 0x02
|
||||
#define LED_COMPOSE 0x03
|
||||
#define LED_KANA 0x04
|
||||
#define LED_SLEEP 0x05
|
||||
#define LED_SUSPEND 0x06
|
||||
#define LED_MUTE 0x07
|
||||
#define LED_MISC 0x08
|
||||
#define LED_MAIL 0x09
|
||||
#define LED_CHARGING 0x0a
|
||||
#define LED_MAX 0x0f
|
||||
#define LED_CNT (LED_MAX+1)
|
||||
|
||||
/*
|
||||
* Autorepeat values
|
||||
*/
|
||||
|
||||
#define REP_DELAY 0x00
|
||||
#define REP_PERIOD 0x01
|
||||
#define REP_MAX 0x01
|
||||
#define REP_CNT (REP_MAX+1)
|
||||
|
||||
/*
|
||||
* Sounds
|
||||
*/
|
||||
|
||||
#define SND_CLICK 0x00
|
||||
#define SND_BELL 0x01
|
||||
#define SND_TONE 0x02
|
||||
#define SND_MAX 0x07
|
||||
#define SND_CNT (SND_MAX+1)
|
||||
|
||||
#endif /* _EVDEV_INPUT_EVENT_CODES_H */
|
273
sys/dev/evdev/input.h
Normal file
273
sys/dev/evdev/input.h
Normal file
@ -0,0 +1,273 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
|
||||
* Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#ifndef _EVDEV_INPUT_H
|
||||
#define _EVDEV_INPUT_H
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioccom.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "input-event-codes.h"
|
||||
|
||||
struct input_event {
|
||||
struct timeval time;
|
||||
uint16_t type;
|
||||
uint16_t code;
|
||||
int32_t value;
|
||||
};
|
||||
|
||||
#define EV_VERSION 0x010001
|
||||
|
||||
struct input_id {
|
||||
uint16_t bustype;
|
||||
uint16_t vendor;
|
||||
uint16_t product;
|
||||
uint16_t version;
|
||||
};
|
||||
|
||||
struct input_absinfo {
|
||||
int32_t value;
|
||||
int32_t minimum;
|
||||
int32_t maximum;
|
||||
int32_t fuzz;
|
||||
int32_t flat;
|
||||
int32_t resolution;
|
||||
};
|
||||
|
||||
#define INPUT_KEYMAP_BY_INDEX (1 << 0)
|
||||
|
||||
struct input_keymap_entry {
|
||||
uint8_t flags;
|
||||
uint8_t len;
|
||||
uint16_t index;
|
||||
uint32_t keycode;
|
||||
uint8_t scancode[32];
|
||||
};
|
||||
|
||||
#define EVDEV_IOC_MAGIC 'E'
|
||||
#define EVIOCGVERSION _IOR(EVDEV_IOC_MAGIC, 0x01, int) /* get driver version */
|
||||
#define EVIOCGID _IOR(EVDEV_IOC_MAGIC, 0x02, struct input_id) /* get device ID */
|
||||
#define EVIOCGREP _IOR(EVDEV_IOC_MAGIC, 0x03, unsigned int[2]) /* get repeat settings */
|
||||
#define EVIOCSREP _IOW(EVDEV_IOC_MAGIC, 0x03, unsigned int[2]) /* set repeat settings */
|
||||
|
||||
#define EVIOCGKEYCODE _IOWR(EVDEV_IOC_MAGIC, 0x04, unsigned int[2]) /* get keycode */
|
||||
#define EVIOCGKEYCODE_V2 _IOWR(EVDEV_IOC_MAGIC, 0x04, struct input_keymap_entry)
|
||||
#define EVIOCSKEYCODE _IOW(EVDEV_IOC_MAGIC, 0x04, unsigned int[2]) /* set keycode */
|
||||
#define EVIOCSKEYCODE_V2 _IOW(EVDEV_IOC_MAGIC, 0x04, struct input_keymap_entry)
|
||||
|
||||
#define EVIOCGNAME(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x06, len) /* get device name */
|
||||
#define EVIOCGPHYS(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x07, len) /* get physical location */
|
||||
#define EVIOCGUNIQ(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x08, len) /* get unique identifier */
|
||||
#define EVIOCGPROP(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x09, len) /* get device properties */
|
||||
|
||||
#define EVIOCGMTSLOTS(len) _IOC(IOC_INOUT, EVDEV_IOC_MAGIC, 0x0a, len) /* get MT slots values */
|
||||
|
||||
#define EVIOCGKEY(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x18, len) /* get global key state */
|
||||
#define EVIOCGLED(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x19, len) /* get all LEDs */
|
||||
#define EVIOCGSND(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x1a, len) /* get all sounds status */
|
||||
#define EVIOCGSW(len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x1b, len) /* get all switch states */
|
||||
|
||||
#define EVIOCGBIT(ev,len) _IOC(IOC_OUT, EVDEV_IOC_MAGIC, 0x20 + (ev), len) /* get event bits */
|
||||
#define EVIOCGABS(abs) _IOR(EVDEV_IOC_MAGIC, 0x40 + (abs), struct input_absinfo) /* get abs value/limits */
|
||||
#define EVIOCSABS(abs) _IOW(EVDEV_IOC_MAGIC, 0xc0 + (abs), struct input_absinfo) /* set abs value/limits */
|
||||
|
||||
#define EVIOCSFF _IOW(EVDEV_IOC_MAGIC, 0x80, struct ff_effect) /* send a force effect to a force feedback device */
|
||||
#define EVIOCRMFF _IOWINT(EVDEV_IOC_MAGIC, 0x81) /* Erase a force effect */
|
||||
#define EVIOCGEFFECTS _IOR(EVDEV_IOC_MAGIC, 0x84, int) /* Report number of effects playable at the same time */
|
||||
|
||||
#define EVIOCGRAB _IOWINT(EVDEV_IOC_MAGIC, 0x90) /* Grab/Release device */
|
||||
#define EVIOCREVOKE _IOWINT(EVDEV_IOC_MAGIC, 0x91) /* Revoke device access */
|
||||
|
||||
#define EVIOCSCLOCKID _IOW(EVDEV_IOC_MAGIC, 0xa0, int) /* Set clockid to be used for timestamps */
|
||||
|
||||
/*
|
||||
* IDs.
|
||||
*/
|
||||
|
||||
#define ID_BUS 0
|
||||
#define ID_VENDOR 1
|
||||
#define ID_PRODUCT 2
|
||||
#define ID_VERSION 3
|
||||
|
||||
#define BUS_PCI 0x01
|
||||
#define BUS_ISAPNP 0x02
|
||||
#define BUS_USB 0x03
|
||||
#define BUS_HIL 0x04
|
||||
#define BUS_BLUETOOTH 0x05
|
||||
#define BUS_VIRTUAL 0x06
|
||||
|
||||
#define BUS_ISA 0x10
|
||||
#define BUS_I8042 0x11
|
||||
#define BUS_XTKBD 0x12
|
||||
#define BUS_RS232 0x13
|
||||
#define BUS_GAMEPORT 0x14
|
||||
#define BUS_PARPORT 0x15
|
||||
#define BUS_AMIGA 0x16
|
||||
#define BUS_ADB 0x17
|
||||
#define BUS_I2C 0x18
|
||||
#define BUS_HOST 0x19
|
||||
#define BUS_GSC 0x1A
|
||||
#define BUS_ATARI 0x1B
|
||||
#define BUS_SPI 0x1C
|
||||
|
||||
/*
|
||||
* MT_TOOL types
|
||||
*/
|
||||
#define MT_TOOL_FINGER 0
|
||||
#define MT_TOOL_PEN 1
|
||||
#define MT_TOOL_PALM 2
|
||||
#define MT_TOOL_MAX 2
|
||||
|
||||
/*
|
||||
* Values describing the status of a force-feedback effect
|
||||
*/
|
||||
#define FF_STATUS_STOPPED 0x00
|
||||
#define FF_STATUS_PLAYING 0x01
|
||||
#define FF_STATUS_MAX 0x01
|
||||
|
||||
/* scheduling info for force feedback effect */
|
||||
struct ff_replay {
|
||||
uint16_t length; /* length of the effect (ms) */
|
||||
uint16_t delay; /* delay before effect starts (ms) */
|
||||
};
|
||||
|
||||
/* trigger for force feedback effect */
|
||||
struct ff_trigger {
|
||||
uint16_t button; /* trigger button number */
|
||||
uint16_t interval; /* delay between re-triggers */
|
||||
};
|
||||
|
||||
/* force feedback effect envelop */
|
||||
struct ff_envelope {
|
||||
uint16_t attack_length; /* duration of the attach (ms) */
|
||||
uint16_t attack_level; /* level at the beginning (0x0000 - 0x7fff) */
|
||||
uint16_t fade_length; /* duratin of fade (ms) */
|
||||
uint16_t fade_level; /* level at the end of fade */
|
||||
};
|
||||
|
||||
struct ff_constant_effect {
|
||||
int16_t level;
|
||||
struct ff_envelope envelope;
|
||||
};
|
||||
|
||||
struct ff_ramp_effect {
|
||||
int16_t start_level;
|
||||
int16_t end_level;
|
||||
struct ff_envelope envelope;
|
||||
};
|
||||
|
||||
struct ff_condition_effect {
|
||||
/* maximum level when joystick moved to respective side */
|
||||
uint16_t right_saturation;
|
||||
|
||||
uint16_t left_saturation;
|
||||
/* how fast force grows when joystick move to the respective side */
|
||||
int16_t right_coeff;
|
||||
int16_t left_coeff;
|
||||
|
||||
uint16_t deadband; /* size of dead zone when no force is produced */
|
||||
int16_t center; /* center of dead zone */
|
||||
};
|
||||
|
||||
/*
|
||||
* Force feedback periodic effect types
|
||||
*/
|
||||
|
||||
#define FF_SQUARE 0x58
|
||||
#define FF_TRIANGLE 0x59
|
||||
#define FF_SINE 0x5a
|
||||
#define FF_SAW_UP 0x5b
|
||||
#define FF_SAW_DOWN 0x5c
|
||||
#define FF_CUSTOM 0x5d
|
||||
|
||||
#define FF_WAVEFORM_MIN FF_SQUARE
|
||||
#define FF_WAVEFORM_MAX FF_CUSTOM
|
||||
|
||||
struct ff_periodic_effect {
|
||||
uint16_t waveform;
|
||||
uint16_t period; /* ms */
|
||||
int16_t magnitude; /* peak */
|
||||
int16_t offset; /* mean, roughly */
|
||||
uint16_t phase; /* horizontal shift */
|
||||
struct ff_envelope envelope;
|
||||
uint32_t custom_len; /* FF_CUSTOM waveform only */
|
||||
int16_t *custom_data; /* FF_CUSTOM waveform only */
|
||||
};
|
||||
|
||||
struct ff_rumble_effect {
|
||||
uint16_t strong_magnitude; /* magnitude of the heavy motor */
|
||||
uint16_t weak_magnitude; /* magnitude of the light motor */
|
||||
};
|
||||
|
||||
/*
|
||||
* Force feedback effect types
|
||||
*/
|
||||
|
||||
#define FF_RUMBLE 0x50
|
||||
#define FF_PERIODIC 0x51
|
||||
#define FF_CONSTANT 0x52
|
||||
#define FF_SPRING 0x53
|
||||
#define FF_FRICTION 0x54
|
||||
#define FF_DAMPER 0x55
|
||||
#define FF_INERTIA 0x56
|
||||
#define FF_RAMP 0x57
|
||||
|
||||
#define FF_EFFECT_MIN FF_RUMBLE
|
||||
#define FF_EFFECT_MAX FF_RAMP
|
||||
|
||||
struct ff_effect {
|
||||
uint16_t type;
|
||||
int16_t id;
|
||||
uint16_t direction; /* [0 .. 360) degrees -> [0 .. 0x10000) */
|
||||
struct ff_trigger trigger;
|
||||
struct ff_replay replay;
|
||||
|
||||
union {
|
||||
struct ff_constant_effect constant;
|
||||
struct ff_ramp_effect ramp;
|
||||
struct ff_periodic_effect periodic;
|
||||
struct ff_condition_effect condition[2]; /* One for each axis */
|
||||
struct ff_rumble_effect rumble;
|
||||
} u;
|
||||
};
|
||||
|
||||
/*
|
||||
* force feedback device properties
|
||||
*/
|
||||
|
||||
#define FF_GAIN 0x60
|
||||
#define FF_AUTOCENTER 0x61
|
||||
|
||||
#define FF_MAX 0x7f
|
||||
#define FF_CNT (FF_MAX+1)
|
||||
|
||||
#endif /* _EVDEV_INPUT_H */
|
710
sys/dev/evdev/uinput.c
Normal file
710
sys/dev/evdev/uinput.c
Normal file
@ -0,0 +1,710 @@
|
||||
/*-
|
||||
* Copyright (c) 2014 Jakub Wojciech Klama <jceel@FreeBSD.org>
|
||||
* Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_evdev.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/sx.h>
|
||||
|
||||
#include <dev/evdev/input.h>
|
||||
#include <dev/evdev/uinput.h>
|
||||
#include <dev/evdev/evdev.h>
|
||||
#include <dev/evdev/evdev_private.h>
|
||||
|
||||
#ifdef UINPUT_DEBUG
|
||||
#define debugf(state, fmt, args...) printf("uinput: " fmt "\n", ##args)
|
||||
#else
|
||||
#define debugf(state, fmt, args...)
|
||||
#endif
|
||||
|
||||
#define UINPUT_BUFFER_SIZE 16
|
||||
|
||||
#define UINPUT_LOCK(state) sx_xlock(&(state)->ucs_lock)
|
||||
#define UINPUT_UNLOCK(state) sx_unlock(&(state)->ucs_lock)
|
||||
#define UINPUT_LOCK_ASSERT(state) sx_assert(&(state)->ucs_lock, SA_LOCKED)
|
||||
#define UINPUT_EMPTYQ(state) \
|
||||
((state)->ucs_buffer_head == (state)->ucs_buffer_tail)
|
||||
|
||||
enum uinput_state
|
||||
{
|
||||
UINPUT_NEW = 0,
|
||||
UINPUT_CONFIGURED,
|
||||
UINPUT_RUNNING
|
||||
};
|
||||
|
||||
static evdev_event_t uinput_ev_event;
|
||||
|
||||
static d_open_t uinput_open;
|
||||
static d_read_t uinput_read;
|
||||
static d_write_t uinput_write;
|
||||
static d_ioctl_t uinput_ioctl;
|
||||
static d_poll_t uinput_poll;
|
||||
static d_kqfilter_t uinput_kqfilter;
|
||||
static void uinput_dtor(void *);
|
||||
|
||||
static int uinput_kqread(struct knote *kn, long hint);
|
||||
static void uinput_kqdetach(struct knote *kn);
|
||||
|
||||
static struct cdevsw uinput_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_open = uinput_open,
|
||||
.d_read = uinput_read,
|
||||
.d_write = uinput_write,
|
||||
.d_ioctl = uinput_ioctl,
|
||||
.d_poll = uinput_poll,
|
||||
.d_kqfilter = uinput_kqfilter,
|
||||
.d_name = "uinput",
|
||||
};
|
||||
|
||||
static struct cdev *uinput_cdev;
|
||||
|
||||
static struct evdev_methods uinput_ev_methods = {
|
||||
.ev_open = NULL,
|
||||
.ev_close = NULL,
|
||||
.ev_event = uinput_ev_event,
|
||||
};
|
||||
|
||||
static struct filterops uinput_filterops = {
|
||||
.f_isfd = 1,
|
||||
.f_attach = NULL,
|
||||
.f_detach = uinput_kqdetach,
|
||||
.f_event = uinput_kqread,
|
||||
};
|
||||
|
||||
struct uinput_cdev_state
|
||||
{
|
||||
enum uinput_state ucs_state;
|
||||
struct evdev_dev * ucs_evdev;
|
||||
struct sx ucs_lock;
|
||||
size_t ucs_buffer_head;
|
||||
size_t ucs_buffer_tail;
|
||||
struct selinfo ucs_selp;
|
||||
bool ucs_blocked;
|
||||
bool ucs_selected;
|
||||
struct input_event ucs_buffer[UINPUT_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
static void uinput_enqueue_event(struct uinput_cdev_state *, uint16_t,
|
||||
uint16_t, int32_t);
|
||||
static int uinput_setup_provider(struct uinput_cdev_state *,
|
||||
struct uinput_user_dev *);
|
||||
static int uinput_cdev_create(void);
|
||||
static void uinput_notify(struct uinput_cdev_state *);
|
||||
|
||||
static void
|
||||
uinput_knllock(void *arg)
|
||||
{
|
||||
struct sx *sx = arg;
|
||||
|
||||
sx_xlock(sx);
|
||||
}
|
||||
|
||||
static void
|
||||
uinput_knlunlock(void *arg)
|
||||
{
|
||||
struct sx *sx = arg;
|
||||
|
||||
sx_unlock(sx);
|
||||
}
|
||||
|
||||
static void
|
||||
uinput_knl_assert_locked(void *arg)
|
||||
{
|
||||
|
||||
sx_assert((struct sx*)arg, SA_XLOCKED);
|
||||
}
|
||||
|
||||
static void
|
||||
uinput_knl_assert_unlocked(void *arg)
|
||||
{
|
||||
|
||||
sx_assert((struct sx*)arg, SA_UNLOCKED);
|
||||
}
|
||||
|
||||
static void
|
||||
uinput_ev_event(struct evdev_dev *evdev, void *softc, uint16_t type,
|
||||
uint16_t code, int32_t value)
|
||||
{
|
||||
struct uinput_cdev_state *state = softc;
|
||||
|
||||
if (type == EV_LED)
|
||||
evdev_push_event(evdev, type, code, value);
|
||||
|
||||
UINPUT_LOCK(state);
|
||||
if (state->ucs_state == UINPUT_RUNNING) {
|
||||
uinput_enqueue_event(state, type, code, value);
|
||||
uinput_notify(state);
|
||||
}
|
||||
UINPUT_UNLOCK(state);
|
||||
}
|
||||
|
||||
static void
|
||||
uinput_enqueue_event(struct uinput_cdev_state *state, uint16_t type,
|
||||
uint16_t code, int32_t value)
|
||||
{
|
||||
size_t head, tail;
|
||||
|
||||
UINPUT_LOCK_ASSERT(state);
|
||||
|
||||
head = state->ucs_buffer_head;
|
||||
tail = (state->ucs_buffer_tail + 1) % UINPUT_BUFFER_SIZE;
|
||||
|
||||
microtime(&state->ucs_buffer[tail].time);
|
||||
state->ucs_buffer[tail].type = type;
|
||||
state->ucs_buffer[tail].code = code;
|
||||
state->ucs_buffer[tail].value = value;
|
||||
state->ucs_buffer_tail = tail;
|
||||
|
||||
/* If queue is full remove oldest event */
|
||||
if (tail == head) {
|
||||
debugf(state, "state %p: buffer overflow", state);
|
||||
|
||||
head = (head + 1) % UINPUT_BUFFER_SIZE;
|
||||
state->ucs_buffer_head = head;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
||||
{
|
||||
struct uinput_cdev_state *state;
|
||||
|
||||
state = malloc(sizeof(struct uinput_cdev_state), M_EVDEV,
|
||||
M_WAITOK | M_ZERO);
|
||||
state->ucs_evdev = evdev_alloc();
|
||||
|
||||
sx_init(&state->ucs_lock, "uinput");
|
||||
knlist_init(&state->ucs_selp.si_note, &state->ucs_lock, uinput_knllock,
|
||||
uinput_knlunlock, uinput_knl_assert_locked,
|
||||
uinput_knl_assert_unlocked);
|
||||
|
||||
devfs_set_cdevpriv(state, uinput_dtor);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
uinput_dtor(void *data)
|
||||
{
|
||||
struct uinput_cdev_state *state = (struct uinput_cdev_state *)data;
|
||||
|
||||
evdev_free(state->ucs_evdev);
|
||||
|
||||
knlist_clear(&state->ucs_selp.si_note, 0);
|
||||
seldrain(&state->ucs_selp);
|
||||
knlist_destroy(&state->ucs_selp.si_note);
|
||||
sx_destroy(&state->ucs_lock);
|
||||
free(data, M_EVDEV);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_read(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct uinput_cdev_state *state;
|
||||
struct input_event *event;
|
||||
int remaining, ret;
|
||||
|
||||
ret = devfs_get_cdevpriv((void **)&state);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
debugf(state, "read %zd bytes by thread %d", uio->uio_resid,
|
||||
uio->uio_td->td_tid);
|
||||
|
||||
/* Zero-sized reads are allowed for error checking */
|
||||
if (uio->uio_resid != 0 && uio->uio_resid < sizeof(struct input_event))
|
||||
return (EINVAL);
|
||||
|
||||
remaining = uio->uio_resid / sizeof(struct input_event);
|
||||
|
||||
UINPUT_LOCK(state);
|
||||
|
||||
if (state->ucs_state != UINPUT_RUNNING)
|
||||
ret = EINVAL;
|
||||
|
||||
if (ret == 0 && UINPUT_EMPTYQ(state)) {
|
||||
if (ioflag & O_NONBLOCK)
|
||||
ret = EWOULDBLOCK;
|
||||
else {
|
||||
if (remaining != 0) {
|
||||
state->ucs_blocked = true;
|
||||
ret = sx_sleep(state, &state->ucs_lock,
|
||||
PCATCH, "uiread", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (ret == 0 && !UINPUT_EMPTYQ(state) && remaining > 0) {
|
||||
event = &state->ucs_buffer[state->ucs_buffer_head];
|
||||
state->ucs_buffer_head = (state->ucs_buffer_head + 1) %
|
||||
UINPUT_BUFFER_SIZE;
|
||||
remaining--;
|
||||
ret = uiomove(event, sizeof(struct input_event), uio);
|
||||
}
|
||||
|
||||
UINPUT_UNLOCK(state);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct uinput_cdev_state *state;
|
||||
struct uinput_user_dev userdev;
|
||||
struct input_event event;
|
||||
int ret = 0;
|
||||
|
||||
ret = devfs_get_cdevpriv((void **)&state);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
debugf(state, "write %zd bytes by thread %d", uio->uio_resid,
|
||||
uio->uio_td->td_tid);
|
||||
|
||||
UINPUT_LOCK(state);
|
||||
|
||||
if (state->ucs_state != UINPUT_RUNNING) {
|
||||
/* Process written struct uinput_user_dev */
|
||||
if (uio->uio_resid != sizeof(struct uinput_user_dev)) {
|
||||
debugf(state, "write size not multiple of "
|
||||
"struct uinput_user_dev size");
|
||||
ret = EINVAL;
|
||||
} else {
|
||||
ret = uiomove(&userdev, sizeof(struct uinput_user_dev),
|
||||
uio);
|
||||
if (ret == 0)
|
||||
uinput_setup_provider(state, &userdev);
|
||||
}
|
||||
} else {
|
||||
/* Process written event */
|
||||
if (uio->uio_resid % sizeof(struct input_event) != 0) {
|
||||
debugf(state, "write size not multiple of "
|
||||
"struct input_event size");
|
||||
ret = EINVAL;
|
||||
}
|
||||
|
||||
while (ret == 0 && uio->uio_resid > 0) {
|
||||
uiomove(&event, sizeof(struct input_event), uio);
|
||||
ret = evdev_push_event(state->ucs_evdev, event.type,
|
||||
event.code, event.value);
|
||||
}
|
||||
}
|
||||
|
||||
UINPUT_UNLOCK(state);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_setup_dev(struct uinput_cdev_state *state, struct input_id *id,
|
||||
char *name, uint32_t ff_effects_max)
|
||||
{
|
||||
|
||||
if (name[0] == 0)
|
||||
return (EINVAL);
|
||||
|
||||
evdev_set_name(state->ucs_evdev, name);
|
||||
evdev_set_id(state->ucs_evdev, id->bustype, id->vendor, id->product,
|
||||
id->version);
|
||||
state->ucs_state = UINPUT_CONFIGURED;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_setup_provider(struct uinput_cdev_state *state,
|
||||
struct uinput_user_dev *udev)
|
||||
{
|
||||
struct input_absinfo absinfo;
|
||||
int i, ret;
|
||||
|
||||
debugf(state, "setup_provider called, udev=%p", udev);
|
||||
|
||||
ret = uinput_setup_dev(state, &udev->id, udev->name,
|
||||
udev->ff_effects_max);
|
||||
if (ret)
|
||||
return (ret);
|
||||
|
||||
bzero(&absinfo, sizeof(struct input_absinfo));
|
||||
for (i = 0; i < ABS_CNT; i++) {
|
||||
if (!bit_test(state->ucs_evdev->ev_abs_flags, i))
|
||||
continue;
|
||||
|
||||
absinfo.minimum = udev->absmin[i];
|
||||
absinfo.maximum = udev->absmax[i];
|
||||
absinfo.fuzz = udev->absfuzz[i];
|
||||
absinfo.flat = udev->absflat[i];
|
||||
evdev_set_absinfo(state->ucs_evdev, i, &absinfo);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_poll(struct cdev *dev, int events, struct thread *td)
|
||||
{
|
||||
struct uinput_cdev_state *state;
|
||||
int revents = 0;
|
||||
|
||||
if (devfs_get_cdevpriv((void **)&state) != 0)
|
||||
return (POLLNVAL);
|
||||
|
||||
debugf(state, "poll by thread %d", td->td_tid);
|
||||
|
||||
/* Always allow write */
|
||||
if (events & (POLLOUT | POLLWRNORM))
|
||||
revents |= (events & (POLLOUT | POLLWRNORM));
|
||||
|
||||
if (events & (POLLIN | POLLRDNORM)) {
|
||||
UINPUT_LOCK(state);
|
||||
if (!UINPUT_EMPTYQ(state))
|
||||
revents = events & (POLLIN | POLLRDNORM);
|
||||
else {
|
||||
state->ucs_selected = true;
|
||||
selrecord(td, &state->ucs_selp);
|
||||
}
|
||||
UINPUT_UNLOCK(state);
|
||||
}
|
||||
|
||||
return (revents);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_kqfilter(struct cdev *dev, struct knote *kn)
|
||||
{
|
||||
struct uinput_cdev_state *state;
|
||||
int ret;
|
||||
|
||||
ret = devfs_get_cdevpriv((void **)&state);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
switch(kn->kn_filter) {
|
||||
case EVFILT_READ:
|
||||
kn->kn_fop = &uinput_filterops;
|
||||
break;
|
||||
default:
|
||||
return(EINVAL);
|
||||
}
|
||||
kn->kn_hook = (caddr_t)state;
|
||||
|
||||
knlist_add(&state->ucs_selp.si_note, kn, 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_kqread(struct knote *kn, long hint)
|
||||
{
|
||||
struct uinput_cdev_state *state;
|
||||
int ret;
|
||||
|
||||
state = (struct uinput_cdev_state *)kn->kn_hook;
|
||||
|
||||
UINPUT_LOCK_ASSERT(state);
|
||||
|
||||
ret = !UINPUT_EMPTYQ(state);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
uinput_kqdetach(struct knote *kn)
|
||||
{
|
||||
struct uinput_cdev_state *state;
|
||||
|
||||
state = (struct uinput_cdev_state *)kn->kn_hook;
|
||||
knlist_remove(&state->ucs_selp.si_note, kn, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
uinput_notify(struct uinput_cdev_state *state)
|
||||
{
|
||||
|
||||
UINPUT_LOCK_ASSERT(state);
|
||||
|
||||
if (state->ucs_blocked) {
|
||||
state->ucs_blocked = false;
|
||||
wakeup(state);
|
||||
}
|
||||
if (state->ucs_selected) {
|
||||
state->ucs_selected = false;
|
||||
selwakeup(&state->ucs_selp);
|
||||
}
|
||||
KNOTE_LOCKED(&state->ucs_selp.si_note, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_ioctl_sub(struct uinput_cdev_state *state, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct uinput_setup *us;
|
||||
struct uinput_abs_setup *uabs;
|
||||
int ret, len, intdata;
|
||||
char buf[NAMELEN];
|
||||
|
||||
UINPUT_LOCK_ASSERT(state);
|
||||
|
||||
len = IOCPARM_LEN(cmd);
|
||||
if ((cmd & IOC_DIRMASK) == IOC_VOID && len == sizeof(int))
|
||||
intdata = *(int *)data;
|
||||
|
||||
switch (IOCBASECMD(cmd)) {
|
||||
case UI_GET_SYSNAME(0):
|
||||
if (state->ucs_state != UINPUT_RUNNING)
|
||||
return (ENOENT);
|
||||
if (len == 0)
|
||||
return (EINVAL);
|
||||
snprintf(data, len, "event%d", state->ucs_evdev->ev_unit);
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case UI_DEV_CREATE:
|
||||
if (state->ucs_state != UINPUT_CONFIGURED)
|
||||
return (EINVAL);
|
||||
|
||||
evdev_set_methods(state->ucs_evdev, state, &uinput_ev_methods);
|
||||
evdev_set_flag(state->ucs_evdev, EVDEV_FLAG_SOFTREPEAT);
|
||||
evdev_register(state->ucs_evdev);
|
||||
state->ucs_state = UINPUT_RUNNING;
|
||||
return (0);
|
||||
|
||||
case UI_DEV_DESTROY:
|
||||
if (state->ucs_state != UINPUT_RUNNING)
|
||||
return (0);
|
||||
|
||||
evdev_unregister(state->ucs_evdev);
|
||||
bzero(state->ucs_evdev, sizeof(struct evdev_dev));
|
||||
state->ucs_state = UINPUT_NEW;
|
||||
return (0);
|
||||
|
||||
case UI_DEV_SETUP:
|
||||
if (state->ucs_state == UINPUT_RUNNING)
|
||||
return (EINVAL);
|
||||
|
||||
us = (struct uinput_setup *)data;
|
||||
return (uinput_setup_dev(state, &us->id, us->name,
|
||||
us->ff_effects_max));
|
||||
|
||||
case UI_ABS_SETUP:
|
||||
if (state->ucs_state == UINPUT_RUNNING)
|
||||
return (EINVAL);
|
||||
|
||||
uabs = (struct uinput_abs_setup *)data;
|
||||
if (uabs->code > ABS_MAX || uabs->code < 0)
|
||||
return (EINVAL);
|
||||
|
||||
evdev_support_abs(state->ucs_evdev, uabs->code,
|
||||
uabs->absinfo.value, uabs->absinfo.minimum,
|
||||
uabs->absinfo.maximum, uabs->absinfo.fuzz,
|
||||
uabs->absinfo.flat, uabs->absinfo.resolution);
|
||||
return (0);
|
||||
|
||||
case UI_SET_EVBIT:
|
||||
if (state->ucs_state == UINPUT_RUNNING ||
|
||||
intdata > EV_MAX || intdata < 0)
|
||||
return (EINVAL);
|
||||
evdev_support_event(state->ucs_evdev, intdata);
|
||||
return (0);
|
||||
|
||||
case UI_SET_KEYBIT:
|
||||
if (state->ucs_state == UINPUT_RUNNING ||
|
||||
intdata > KEY_MAX || intdata < 0)
|
||||
return (EINVAL);
|
||||
evdev_support_key(state->ucs_evdev, intdata);
|
||||
return (0);
|
||||
|
||||
case UI_SET_RELBIT:
|
||||
if (state->ucs_state == UINPUT_RUNNING ||
|
||||
intdata > REL_MAX || intdata < 0)
|
||||
return (EINVAL);
|
||||
evdev_support_rel(state->ucs_evdev, intdata);
|
||||
return (0);
|
||||
|
||||
case UI_SET_ABSBIT:
|
||||
if (state->ucs_state == UINPUT_RUNNING ||
|
||||
intdata > ABS_MAX || intdata < 0)
|
||||
return (EINVAL);
|
||||
evdev_set_abs_bit(state->ucs_evdev, intdata);
|
||||
return (0);
|
||||
|
||||
case UI_SET_MSCBIT:
|
||||
if (state->ucs_state == UINPUT_RUNNING ||
|
||||
intdata > MSC_MAX || intdata < 0)
|
||||
return (EINVAL);
|
||||
evdev_support_msc(state->ucs_evdev, intdata);
|
||||
return (0);
|
||||
|
||||
case UI_SET_LEDBIT:
|
||||
if (state->ucs_state == UINPUT_RUNNING ||
|
||||
intdata > LED_MAX || intdata < 0)
|
||||
return (EINVAL);
|
||||
evdev_support_led(state->ucs_evdev, intdata);
|
||||
return (0);
|
||||
|
||||
case UI_SET_SNDBIT:
|
||||
if (state->ucs_state == UINPUT_RUNNING ||
|
||||
intdata > SND_MAX || intdata < 0)
|
||||
return (EINVAL);
|
||||
evdev_support_snd(state->ucs_evdev, intdata);
|
||||
return (0);
|
||||
|
||||
case UI_SET_FFBIT:
|
||||
if (state->ucs_state == UINPUT_RUNNING ||
|
||||
intdata > FF_MAX || intdata < 0)
|
||||
return (EINVAL);
|
||||
/* Fake unsupported ioctl */
|
||||
return (0);
|
||||
|
||||
case UI_SET_PHYS:
|
||||
if (state->ucs_state == UINPUT_RUNNING)
|
||||
return (EINVAL);
|
||||
ret = copyinstr(*(void **)data, buf, sizeof(buf), NULL);
|
||||
/* Linux returns EINVAL when string does not fit the buffer */
|
||||
if (ret == ENAMETOOLONG)
|
||||
ret = EINVAL;
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
evdev_set_phys(state->ucs_evdev, buf);
|
||||
return (0);
|
||||
|
||||
case UI_SET_SWBIT:
|
||||
if (state->ucs_state == UINPUT_RUNNING ||
|
||||
intdata > SW_MAX || intdata < 0)
|
||||
return (EINVAL);
|
||||
evdev_support_sw(state->ucs_evdev, intdata);
|
||||
return (0);
|
||||
|
||||
case UI_SET_PROPBIT:
|
||||
if (state->ucs_state == UINPUT_RUNNING ||
|
||||
intdata > INPUT_PROP_MAX || intdata < 0)
|
||||
return (EINVAL);
|
||||
evdev_support_prop(state->ucs_evdev, intdata);
|
||||
return (0);
|
||||
|
||||
case UI_BEGIN_FF_UPLOAD:
|
||||
case UI_END_FF_UPLOAD:
|
||||
case UI_BEGIN_FF_ERASE:
|
||||
case UI_END_FF_ERASE:
|
||||
if (state->ucs_state == UINPUT_RUNNING)
|
||||
return (EINVAL);
|
||||
/* Fake unsupported ioctl */
|
||||
return (0);
|
||||
|
||||
case UI_GET_VERSION:
|
||||
*(unsigned int *)data = UINPUT_VERSION;
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
||||
struct thread *td)
|
||||
{
|
||||
struct uinput_cdev_state *state;
|
||||
int ret;
|
||||
|
||||
ret = devfs_get_cdevpriv((void **)&state);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
debugf(state, "ioctl called: cmd=0x%08lx, data=%p", cmd, data);
|
||||
|
||||
UINPUT_LOCK(state);
|
||||
ret = uinput_ioctl_sub(state, cmd, data);
|
||||
UINPUT_UNLOCK(state);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_cdev_create(void)
|
||||
{
|
||||
struct make_dev_args mda;
|
||||
int ret;
|
||||
|
||||
make_dev_args_init(&mda);
|
||||
mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME;
|
||||
mda.mda_devsw = &uinput_cdevsw;
|
||||
mda.mda_uid = UID_ROOT;
|
||||
mda.mda_gid = GID_WHEEL;
|
||||
mda.mda_mode = 0600;
|
||||
|
||||
ret = make_dev_s(&mda, &uinput_cdev, "uinput");
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_cdev_destroy(void)
|
||||
{
|
||||
|
||||
destroy_dev(uinput_cdev);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
uinput_modevent(module_t mod __unused, int cmd, void *data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case MOD_LOAD:
|
||||
ret = uinput_cdev_create();
|
||||
break;
|
||||
|
||||
case MOD_UNLOAD:
|
||||
ret = uinput_cdev_destroy();
|
||||
break;
|
||||
|
||||
case MOD_SHUTDOWN:
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
DEV_MODULE(uinput, uinput_modevent, NULL);
|
107
sys/dev/evdev/uinput.h
Normal file
107
sys/dev/evdev/uinput.h
Normal file
@ -0,0 +1,107 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
|
||||
* Copyright (c) 2015-2016 Vladimir Kondratyev <wulf@cicgroup.ru>
|
||||
* 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$
|
||||
*/
|
||||
|
||||
#ifndef _EVDEV_UINPUT_H_
|
||||
#define _EVDEV_UINPUT_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dev/evdev/input.h>
|
||||
|
||||
#define UINPUT_VERSION 5
|
||||
#define UINPUT_MAX_NAME_SIZE 80
|
||||
|
||||
struct uinput_ff_upload {
|
||||
uint32_t request_id;
|
||||
int32_t retval;
|
||||
struct ff_effect effect;
|
||||
struct ff_effect old;
|
||||
};
|
||||
|
||||
struct uinput_ff_erase {
|
||||
uint32_t request_id;
|
||||
int32_t retval;
|
||||
uint32_t effect_id;
|
||||
};
|
||||
|
||||
/* ioctl */
|
||||
#define UINPUT_IOCTL_BASE 'U'
|
||||
|
||||
#define UI_DEV_CREATE _IO(UINPUT_IOCTL_BASE, 1)
|
||||
#define UI_DEV_DESTROY _IO(UINPUT_IOCTL_BASE, 2)
|
||||
|
||||
struct uinput_setup {
|
||||
struct input_id id;
|
||||
char name[UINPUT_MAX_NAME_SIZE];
|
||||
uint32_t ff_effects_max;
|
||||
};
|
||||
|
||||
#define UI_DEV_SETUP _IOW(UINPUT_IOCTL_BASE, 3, struct uinput_setup)
|
||||
|
||||
struct uinput_abs_setup {
|
||||
uint16_t code; /* axis code */
|
||||
struct input_absinfo absinfo;
|
||||
};
|
||||
|
||||
#define UI_ABS_SETUP _IOW(UINPUT_IOCTL_BASE, 4, struct uinput_abs_setup)
|
||||
|
||||
#define UI_GET_SYSNAME(len) _IOC(IOC_OUT, UINPUT_IOCTL_BASE, 44, len)
|
||||
#define UI_GET_VERSION _IOR(UINPUT_IOCTL_BASE, 45, unsigned int)
|
||||
|
||||
#define UI_SET_EVBIT _IOWINT(UINPUT_IOCTL_BASE, 100)
|
||||
#define UI_SET_KEYBIT _IOWINT(UINPUT_IOCTL_BASE, 101)
|
||||
#define UI_SET_RELBIT _IOWINT(UINPUT_IOCTL_BASE, 102)
|
||||
#define UI_SET_ABSBIT _IOWINT(UINPUT_IOCTL_BASE, 103)
|
||||
#define UI_SET_MSCBIT _IOWINT(UINPUT_IOCTL_BASE, 104)
|
||||
#define UI_SET_LEDBIT _IOWINT(UINPUT_IOCTL_BASE, 105)
|
||||
#define UI_SET_SNDBIT _IOWINT(UINPUT_IOCTL_BASE, 106)
|
||||
#define UI_SET_FFBIT _IOWINT(UINPUT_IOCTL_BASE, 107)
|
||||
#define UI_SET_PHYS _IO(UINPUT_IOCTL_BASE, 108)
|
||||
#define UI_SET_SWBIT _IOWINT(UINPUT_IOCTL_BASE, 109)
|
||||
#define UI_SET_PROPBIT _IOWINT(UINPUT_IOCTL_BASE, 110)
|
||||
|
||||
#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
|
||||
#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
|
||||
#define UI_BEGIN_FF_ERASE _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
|
||||
#define UI_END_FF_ERASE _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
|
||||
|
||||
#define EV_UINPUT 0x0101
|
||||
#define UI_FF_UPLOAD 1
|
||||
#define UI_FF_ERASE 2
|
||||
|
||||
struct uinput_user_dev {
|
||||
char name[UINPUT_MAX_NAME_SIZE];
|
||||
struct input_id id;
|
||||
uint32_t ff_effects_max;
|
||||
int32_t absmax[ABS_CNT];
|
||||
int32_t absmin[ABS_CNT];
|
||||
int32_t absfuzz[ABS_CNT];
|
||||
int32_t absflat[ABS_CNT];
|
||||
};
|
||||
|
||||
#endif /* _EVDEV_UINPUT_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user