Merge ^/head r305397 through r305430.

This commit is contained in:
Dimitry Andric 2016-09-05 18:05:45 +00:00
commit 1839de1a4b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang390-import/; revision=305431
45 changed files with 2283 additions and 309 deletions

View File

@ -347,9 +347,12 @@ extern void abort (void);
??? C99 designated initializers are not supported by most C++
compilers, including G++. -- gdr, 2005-05-18 */
#if !defined(HAVE_DESIGNATED_INITIALIZERS)
#define HAVE_DESIGNATED_INITIALIZERS \
((!defined(__cplusplus) && (GCC_VERSION >= 2007)) \
|| (__STDC_VERSION__ >= 199901L))
# if (!defined(__cplusplus) && (GCC_VERSION >= 2007)) \
||(__STDC_VERSION__ >= 199901L)
# define HAVE_DESIGNATED_INITIALIZERS 1
# else
# define HAVE_DESIGNATED_INITIALIZERS 0
# endif
#endif
/* Be conservative and only use enum bitfields with GCC.

View File

@ -1,163 +0,0 @@
README for libarchive bundle.
Questions? Issues?
* http://www.libarchive.org is the home for ongoing
libarchive development, including documentation, and
links to the libarchive mailing lists.
* To report an issue, use the issue tracker at
https://github.com/libarchive/libarchive/issues
* To submit an enhancement to libarchive, please submit
a pull request via GitHub.
https://github.com/libarchive/libarchive/pulls
This distribution bundle includes the following components:
* libarchive: a library for reading and writing streaming archives
* tar: the 'bsdtar' program is a full-featured 'tar'
implementation built on libarchive
* cpio: the 'bsdcpio' program is a different interface to
essentially the same functionality
* cat: the 'bsdcat' program is a simple replacement tool for
zcat, bzcat, xzcat, and such
* examples: Some small example programs that you may find useful.
* examples/minitar: a compact sample demonstrating use of libarchive.
* contrib: Various items sent to me by third parties;
please contact the authors with any questions.
The top-level directory contains the following information files:
* NEWS - highlights of recent changes
* COPYING - what you can do with this
* INSTALL - installation instructions
* README - this file
* configure - configuration script, see INSTALL for details.
* CMakeLists.txt - input for "cmake" build tool, see INSTALL
The following files in the top-level directory are used by the
'configure' script:
* Makefile.am, aclocal.m4, configure.ac
- used to build this distribution, only needed by maintainers
* Makefile.in, config.h.in
- templates used by configure script
Guide to Documentation installed by this system:
* bsdtar.1 explains the use of the bsdtar program
* bsdcpio.1 explains the use of the bsdcpio program
* bsdcat.1 explains the use of the bsdcat program
* libarchive.3 gives an overview of the library as a whole
* archive_read.3, archive_write.3, archive_write_disk.3, and
archive_read_disk.3 provide detailed calling sequences for the read
and write APIs
* archive_entry.3 details the "struct archive_entry" utility class
* archive_internals.3 provides some insight into libarchive's
internal structure and operation.
* libarchive-formats.5 documents the file formats supported by the library
* cpio.5, mtree.5, and tar.5 provide detailed information about these
popular archive formats, including hard-to-find details about
modern cpio and tar variants.
The manual pages above are provided in the 'doc' directory in
a number of different formats.
You should also read the copious comments in "archive.h" and the
source code for the sample programs for more details. Please let us
know about any errors or omissions you find.
Currently, the library automatically detects and reads the following fomats:
* GNU tar format (including GNU long filenames, long link names, and sparse files)
* Solaris 9 extended tar format (including ACLs)
* Old V7 tar archives
* POSIX ustar
* POSIX pax interchange format
* POSIX octet-oriented cpio
* SVR4 ASCII cpio
* POSIX octet-oriented cpio
* Binary cpio (big-endian or little-endian)
* ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
* ZIP archives (with uncompressed or "deflate" compressed entries)
* GNU and BSD 'ar' archives
* 'mtree' format
* 7-Zip archives
* Microsoft CAB format
* LHA and LZH archives
* RAR archives
* XAR archives
The library also detects and handles any of the following before evaluating the archive:
* uuencoded files
* files with RPM wrapper
* gzip compression
* bzip2 compression
* compress/LZW compression
* lzma, lzip, and xz compression
* lz4 compression
* lzop compression
The library can create archives in any of the following formats:
* POSIX ustar
* POSIX pax interchange format
* "restricted" pax format, which will create ustar archives except for
entries that require pax extensions (for long filenames, ACLs, etc).
* Old GNU tar format
* Old V7 tar format
* POSIX octet-oriented cpio
* SVR4 "newc" cpio
* shar archives
* ZIP archives (with uncompressed or "deflate" compressed entries)
* GNU and BSD 'ar' archives
* 'mtree' format
* ISO9660 format
* 7-Zip archives
* XAR archives
When creating archives, the result can be filtered with any of the following:
* uuencode
* gzip compression
* bzip2 compression
* compress/LZW compression
* lzma, lzip, and xz compression
* lz4 compression
* lzop compression
Notes about the library architecture:
* This is a heavily stream-oriented system. There is no direct
support for in-place modification or random access.
* The library is designed to be extended with new compression and
archive formats. The only requirement is that the format be
readable or writable as a stream and that each archive entry be
independent. There are articles on the libarchive Wiki explaining
how to extend libarchive.
* On read, compression and format are always detected automatically.
* I've attempted to minimize static link pollution. If you don't
explicitly invoke a particular feature (such as support for a
particular compression or format), it won't get pulled in to
statically-linked programs. In particular, if you don't explicitly
enable a particular compression or decompression support, you won't
need to link against the corresponding compression or decompression
libraries. This also reduces the size of statically-linked
binaries in environments where that matters.
* On read, the library accepts whatever blocks you hand it.
Your read callback is free to pass the library a byte at a time
or mmap the entire archive and give it to the library at once.
On write, the library always produces correctly-blocked output.
* The object-style approach allows you to have multiple archive streams
open at once. bsdtar uses this in its "@archive" extension.
* The archive itself is read/written using callback functions.
You can read an archive directly from an in-memory buffer or
write it to a socket, if you wish. There are some utility
functions to provide easy-to-use "open file," etc, capabilities.
* The read/write APIs are designed to allow individual entries
to be read or written to any data source: You can create
a block of data in memory and add it to a tar archive without
first writing a temporary file. You can also read an entry from
an archive and write the data directly to a socket. If you want
to read/write entries to disk, there are convenience functions to
make this especially easy.
* Note: "pax interchange format" is really an extended tar format,
despite what the name says.

View File

@ -0,0 +1,222 @@
# Welcome to libarchive!
The libarchive project develops a portable, efficient C library that
can read and write streaming archives in a variety of formats. It
also includes implementations of the common `tar`, `cpio`, and `zcat`
command-line tools that use the libarchive library.
## Questions? Issues?
* http://www.libarchive.org is the home for ongoing
libarchive development, including documentation,
and links to the libarchive mailing lists.
* To report an issue, use the issue tracker at
https://github.com/libarchive/libarchive/issues
* To submit an enhancement to libarchive, please
submit a pull request via GitHub: https://github.com/libarchive/libarchive/pulls
## Contents of the Distribution
This distribution bundle includes the following major components:
* **libarchive**: a library for reading and writing streaming archives
* **tar**: the 'bsdtar' program is a full-featured 'tar' implementation built on libarchive
* **cpio**: the 'bsdcpio' program is a different interface to essentially the same functionality
* **cat**: the 'bsdcat' program is a simple replacement tool for zcat, bzcat, xzcat, and such
* **examples**: Some small example programs that you may find useful.
* **examples/minitar**: a compact sample demonstrating use of libarchive.
* **contrib**: Various items sent to me by third parties; please contact the authors with any questions.
The top-level directory contains the following information files:
* **NEWS** - highlights of recent changes
* **COPYING** - what you can do with this
* **INSTALL** - installation instructions
* **README** - this file
* **CMakeLists.txt** - input for "cmake" build tool, see INSTALL
* **configure** - configuration script, see INSTALL for details. If your copy of the source lacks a `configure` script, you can try to construct it by running the script in `build/autogen.sh` (or use `cmake`).
The following files in the top-level directory are used by the 'configure' script:
* `Makefile.am`, `aclocal.m4`, `configure.ac` - used to build this distribution, only needed by maintainers
* `Makefile.in`, `config.h.in` - templates used by configure script
## Documentation
In addition to the informational articles and documentation
in the online [libarchive Wiki](https://github.com/libarchive/libarchive/wiki),
the distribution also includes a number of manual pages:
* bsdtar.1 explains the use of the bsdtar program
* bsdcpio.1 explains the use of the bsdcpio program
* bsdcat.1 explains the use of the bsdcat program
* libarchive.3 gives an overview of the library as a whole
* archive_read.3, archive_write.3, archive_write_disk.3, and
archive_read_disk.3 provide detailed calling sequences for the read
and write APIs
* archive_entry.3 details the "struct archive_entry" utility class
* archive_internals.3 provides some insight into libarchive's
internal structure and operation.
* libarchive-formats.5 documents the file formats supported by the library
* cpio.5, mtree.5, and tar.5 provide detailed information about these
popular archive formats, including hard-to-find details about
modern cpio and tar variants.
The manual pages above are provided in the 'doc' directory in
a number of different formats.
You should also read the copious comments in `archive.h` and the
source code for the sample programs for more details. Please let us
know about any errors or omissions you find.
## Supported Formats
Currently, the library automatically detects and reads the following fomats:
* Old V7 tar archives
* POSIX ustar
* GNU tar format (including GNU long filenames, long link names, and sparse files)
* Solaris 9 extended tar format (including ACLs)
* POSIX pax interchange format
* POSIX octet-oriented cpio
* SVR4 ASCII cpio
* POSIX octet-oriented cpio
* Binary cpio (big-endian or little-endian)
* ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
* ZIP archives (with uncompressed or "deflate" compressed entries, including support for encrypted Zip archives)
* GNU and BSD 'ar' archives
* 'mtree' format
* 7-Zip archives
* Microsoft CAB format
* LHA and LZH archives
* RAR archives (with some limitations due to RAR's proprietary status)
* XAR archives
The library also detects and handles any of the following before evaluating the archive:
* uuencoded files
* files with RPM wrapper
* gzip compression
* bzip2 compression
* compress/LZW compression
* lzma, lzip, and xz compression
* lz4 compression
* lzop compression
The library can create archives in any of the following formats:
* POSIX ustar
* POSIX pax interchange format
* "restricted" pax format, which will create ustar archives except for
entries that require pax extensions (for long filenames, ACLs, etc).
* Old GNU tar format
* Old V7 tar format
* POSIX octet-oriented cpio
* SVR4 "newc" cpio
* shar archives
* ZIP archives (with uncompressed or "deflate" compressed entries)
* GNU and BSD 'ar' archives
* 'mtree' format
* ISO9660 format
* 7-Zip archives
* XAR archives
When creating archives, the result can be filtered with any of the following:
* uuencode
* gzip compression
* bzip2 compression
* compress/LZW compression
* lzma, lzip, and xz compression
* lz4 compression
* lzop compression
## Notes about the Library Design
The following notes address many of the most common
questions we are asked about libarchive:
* This is a heavily stream-oriented system. That means that
it is optimized to read or write the archive in a single
pass from beginning to end. For example, this allows
libarchive to process archives too large to store on disk
by processing them on-the-fly as they are read from or
written to a network or tape drive. This also makes
libarchive useful for tools that need to produce
archives on-the-fly (such as webservers that provide
archived contents of a users account).
* In-place modification and random access to the contents
of an archive are not directly supported. For some formats,
this is not an issue: For example, tar.gz archives are not
designed for random access. In some other cases, libarchive
can re-open an archive and scan it from the beginning quickly
enough to provide the needed abilities even without true
random access. Of course, some applications do require true
random access; those applications should consider alternatives
to libarchive.
* The library is designed to be extended with new compression and
archive formats. The only requirement is that the format be
readable or writable as a stream and that each archive entry be
independent. There are articles on the libarchive Wiki explaining
how to extend libarchive.
* On read, compression and format are always detected automatically.
* The same API is used for all formats; in particular, it's very
easy for software using libarchive to transparently handle
any of libarchive's archiving formats.
* Libarchive's automatic support for decompression can be used
without archiving by explicitly selecting the "raw" and "empty"
formats.
* I've attempted to minimize static link pollution. If you don't
explicitly invoke a particular feature (such as support for a
particular compression or format), it won't get pulled in to
statically-linked programs. In particular, if you don't explicitly
enable a particular compression or decompression support, you won't
need to link against the corresponding compression or decompression
libraries. This also reduces the size of statically-linked
binaries in environments where that matters.
* The library is generally _thread safe_ depending on the platform:
it does not define any global variables of its own. However, some
platforms do not provide fully thread-safe versions of key C library
functions. On those platforms, libarchive will use the non-thread-safe
functions. Patches to improve this are of great interest to us.
* In particular, libarchive's modules to read or write a directory
tree do use `chdir()` to optimize the directory traversals. This
can cause problems for programs that expect to do disk access from
multiple threads. Of course, those modules are completely
optional and you can use the rest of libarchive without them.
* The library is _not_ thread aware, however. It does no locking
or thread management of any kind. If you create a libarchive
object and need to access it from multiple threads, you will
need to provide your own locking.
* On read, the library accepts whatever blocks you hand it.
Your read callback is free to pass the library a byte at a time
or mmap the entire archive and give it to the library at once.
On write, the library always produces correctly-blocked output.
* The object-style approach allows you to have multiple archive streams
open at once. bsdtar uses this in its "@archive" extension.
* The archive itself is read/written using callback functions.
You can read an archive directly from an in-memory buffer or
write it to a socket, if you wish. There are some utility
functions to provide easy-to-use "open file," etc, capabilities.
* The read/write APIs are designed to allow individual entries
to be read or written to any data source: You can create
a block of data in memory and add it to a tar archive without
first writing a temporary file. You can also read an entry from
an archive and write the data directly to a socket. If you want
to read/write entries to disk, there are convenience functions to
make this especially easy.
* Note: The "pax interchange format" is a POSIX standard extended tar
format that should be used when the older _ustar_ format is not
appropriate. It has many advantages over other tar formats
(including the legacy GNU tar format) and is widely supported by
current tar implementations.

View File

@ -707,10 +707,11 @@ archive_acl_text_l(struct archive_acl *acl, int flags,
if (r != 0)
return (-1);
*p++ = separator;
if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)
if (name == NULL || (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) {
id = ap->id;
else
} else {
id = -1;
}
append_entry(&p, NULL, ap->tag, name,
ap->permset, id);
count++;

View File

@ -419,12 +419,32 @@ setup_acls(struct archive_read_disk *a,
if (accpath == NULL)
accpath = archive_entry_pathname(entry);
if (*fd < 0 && a->tree != NULL) {
if (a->follow_symlinks ||
archive_entry_filetype(entry) != AE_IFLNK)
*fd = a->open_on_current_dir(a->tree,
accpath, O_RDONLY | O_NONBLOCK);
if (*fd < 0) {
if (a->tree_enter_working_dir(a->tree) != 0) {
archive_set_error(&a->archive, errno,
"Couldn't access %s", accpath);
return (ARCHIVE_FAILED);
}
}
}
archive_entry_acl_clear(entry);
acl = NULL;
#ifdef ACL_TYPE_NFS4
/* Try NFS4 ACL first. */
if (*fd >= 0)
#if HAVE_ACL_GET_FD_NP
acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
#else
acl = acl_get_fd(*fd);
#endif
#if HAVE_ACL_GET_LINK_NP
else if (!a->follow_symlinks)
acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
@ -437,12 +457,19 @@ setup_acls(struct archive_read_disk *a,
#endif
else
acl = acl_get_file(accpath, ACL_TYPE_NFS4);
#if HAVE_ACL_IS_TRIVIAL_NP
/* Ignore "trivial" ACLs that just mirror the file mode. */
acl_is_trivial_np(acl, &r);
if (r) {
acl_free(acl);
acl = NULL;
if (acl != NULL && acl_is_trivial_np(acl, &r) == 0) {
/* Ignore "trivial" ACLs that just mirror the file mode. */
if (r) {
acl_free(acl);
acl = NULL;
/*
* Simultaneous NFSv4 and POSIX.1e ACLs for the same
* entry are not allowed, so we should return here
*/
return (ARCHIVE_OK);
}
}
#endif
if (acl != NULL) {
@ -450,7 +477,7 @@ setup_acls(struct archive_read_disk *a,
acl_free(acl);
return (ARCHIVE_OK);
}
#endif
#endif /* ACL_TYPE_NFS4 */
/* Retrieve access ACL from file. */
if (*fd >= 0)
@ -467,10 +494,22 @@ setup_acls(struct archive_read_disk *a,
#endif
else
acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
#if HAVE_ACL_IS_TRIVIAL_NP
/* Ignore "trivial" ACLs that just mirror the file mode. */
if (acl != NULL && acl_is_trivial_np(acl, &r) == 0) {
if (r) {
acl_free(acl);
acl = NULL;
}
}
#endif
if (acl != NULL) {
translate_acl(a, entry, acl,
ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
acl_free(acl);
acl = NULL;
}
/* Only directories can have default ACLs. */

View File

@ -1504,10 +1504,19 @@ setup_current_filesystem(struct archive_read_disk *a)
struct tree *t = a->tree;
struct statfs sfs;
#if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC)
# if defined(HAVE_STRUCT_VFSCONF)
struct vfsconf vfc;
# else
/* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make
* this accurate; some platforms have both and we need the one that's
* used by getvfsbyname()
*
* Then the following would become:
* #if defined(GETVFSBYNAME_ARG_TYPE)
* GETVFSBYNAME_ARG_TYPE vfc;
* #endif
*/
# if defined(HAVE_STRUCT_XVFSCONF)
struct xvfsconf vfc;
# else
struct vfsconf vfc;
# endif
#endif
int r, xr = 0;

View File

@ -70,15 +70,9 @@ set_acls(struct archive_entry *ae, struct myacl_t *acls)
}
static int
acl_match(acl_entry_t aclent, struct myacl_t *myacl)
{
gid_t g, *gp;
uid_t u, *up;
acl_tag_t tag_type;
acl_permset_t opaque_ps;
acl_entry_get_perm(acl_entry_t aclent) {
int permset = 0;
acl_get_tag_type(aclent, &tag_type);
acl_permset_t opaque_ps;
/* translate the silly opaque permset to a bitmap */
acl_get_permset(aclent, &opaque_ps);
@ -88,10 +82,61 @@ acl_match(acl_entry_t aclent, struct myacl_t *myacl)
permset |= ARCHIVE_ENTRY_ACL_WRITE;
if (acl_get_perm_np(opaque_ps, ACL_READ))
permset |= ARCHIVE_ENTRY_ACL_READ;
return permset;
}
if (permset != myacl->permset)
#if 0
static int
acl_get_specific_entry(acl_t acl, acl_tag_t requested_tag_type, int requested_tag) {
int entry_id = ACL_FIRST_ENTRY;
acl_entry_t acl_entry;
acl_tag_t acl_tag_type;
while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
/* After the first time... */
entry_id = ACL_NEXT_ENTRY;
/* If this matches, return perm mask */
acl_get_tag_type(acl_entry, &acl_tag_type);
if (acl_tag_type == requested_tag_type) {
switch (acl_tag_type) {
case ACL_USER_OBJ:
if ((uid_t)requested_tag == *(uid_t *)(acl_get_qualifier(acl_entry))) {
return acl_entry_get_perm(acl_entry);
}
break;
case ACL_GROUP_OBJ:
if ((gid_t)requested_tag == *(gid_t *)(acl_get_qualifier(acl_entry))) {
return acl_entry_get_perm(acl_entry);
}
break;
case ACL_USER:
case ACL_GROUP:
case ACL_OTHER:
return acl_entry_get_perm(acl_entry);
default:
failure("Unexpected ACL tag type");
assert(0);
}
}
}
return -1;
}
#endif
static int
acl_match(acl_entry_t aclent, struct myacl_t *myacl)
{
gid_t g, *gp;
uid_t u, *up;
acl_tag_t tag_type;
if (myacl->permset != acl_entry_get_perm(aclent))
return (0);
acl_get_tag_type(aclent, &tag_type);
switch (tag_type) {
case ACL_USER_OBJ:
if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
@ -190,7 +235,7 @@ compare_acls(acl_t acl, struct myacl_t *myacls)
* Verify ACL restore-to-disk. This test is FreeBSD-specific.
*/
DEFINE_TEST(test_acl_freebsd_posix1e)
DEFINE_TEST(test_acl_freebsd_posix1e_restore)
{
#if !defined(__FreeBSD__)
skipping("FreeBSD-specific ACL restore test");
@ -263,3 +308,111 @@ DEFINE_TEST(test_acl_freebsd_posix1e)
acl_free(acl);
#endif
}
/*
* Verify ACL reaed-from-disk. This test is FreeBSD-specific.
*/
DEFINE_TEST(test_acl_freebsd_posix1e_read)
{
#if !defined(__FreeBSD__)
skipping("FreeBSD-specific ACL read test");
#elif __FreeBSD__ < 5
skipping("ACL read supported only on FreeBSD 5.0 and later");
#else
struct archive *a;
struct archive_entry *ae;
int n, fd;
const char *acl1_text, *acl2_text;
acl_t acl1, acl2;
/*
* Manually construct a directory and two files with
* different ACLs. This also serves to verify that ACLs
* are supported on the local filesystem.
*/
/* Create a test file f1 with acl1 */
acl1_text = "user::rwx,group::rwx,other::rwx,user:1:rw-,group:15:r-x,mask::rwx";
acl1 = acl_from_text(acl1_text);
assert((void *)acl1 != NULL);
fd = open("f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
failure("Could not create test file?!");
if (!assert(fd >= 0)) {
acl_free(acl1);
return;
}
n = acl_set_fd(fd, acl1);
acl_free(acl1);
if (n != 0 && errno == EOPNOTSUPP) {
close(fd);
skipping("ACL tests require that ACL support be enabled on the filesystem");
return;
}
if (n != 0 && errno == EINVAL) {
close(fd);
skipping("This filesystem does not support POSIX.1e ACLs");
return;
}
failure("acl_set_fd(): errno = %d (%s)",
errno, strerror(errno));
assertEqualInt(0, n);
close(fd);
assertMakeDir("d", 0700);
/*
* Create file d/f1 with acl2
*
* This differs from acl1 in the u:1: and g:15: permissions.
*
* This file deliberately has the same name but a different ACL.
* Github Issue #777 explains how libarchive's directory traversal
* did not always correctly enter directories before attempting
* to read ACLs, resulting in reading the ACL from a like-named
* file in the wrong directory.
*/
acl2_text = "user::rwx,group::rwx,other::---,user:1:r--,group:15:r--,mask::rwx";
acl2 = acl_from_text(acl2_text);
assert((void *)acl2 != NULL);
fd = open("d/f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
failure("Could not create test file?!");
if (!assert(fd >= 0)) {
acl_free(acl2);
return;
}
n = acl_set_fd(fd, acl2);
acl_free(acl2);
if (n != 0 && errno == EOPNOTSUPP) {
close(fd);
skipping("ACL tests require that ACL support be enabled on the filesystem");
return;
}
if (n != 0 && errno == EINVAL) {
close(fd);
skipping("This filesystem does not support POSIX.1e ACLs");
return;
}
failure("acl_set_fd(): errno = %d (%s)",
errno, strerror(errno));
assertEqualInt(0, n);
close(fd);
/* Create a read-from-disk object. */
assert(NULL != (a = archive_read_disk_new()));
assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
assert(NULL != (ae = archive_entry_new()));
/* Walk the dir until we see both of the files */
while (ARCHIVE_OK == archive_read_next_header2(a, ae)) {
archive_read_disk_descend(a);
if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
assertEqualString(archive_entry_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), acl1_text);
} else if (strcmp(archive_entry_pathname(ae), "./d/f1") == 0) {
assertEqualString(archive_entry_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS), acl2_text);
}
}
archive_free(a);
#endif
}

View File

@ -104,6 +104,7 @@ S - toggle the displaying of system processes\n\
a - toggle the displaying of process titles\n\
t - toggle the display of this process\n\
u - display processes for only one user (+ selects all users)\n\
w - toggle the display of swap use for each process\n\
z - toggle the displaying of the system idle process\n\
\n\
\n", stdout);

View File

@ -72,6 +72,7 @@ struct process_select
int wcpu; /* show weighted cpu */
int jid; /* only this jid (unless jid == -1) */
int jail; /* show jail ID */
int swap; /* show swap usage */
int kidle; /* show per-CPU idle threads */
char *command; /* only this command (unless == NULL) */
};
@ -82,8 +83,8 @@ char *format_header();
char *format_next_process();
void toggle_pcpustats(void);
void get_system_info(struct system_info *si);
int machine_init(struct statics *statics, char do_unames);
int proc_owner(int pid);
int machine_init(struct statics *statics, char do_unames);
int proc_owner(int pid);
/* non-int routines typically used by the machine dependent module */
char *printable();

View File

@ -188,9 +188,9 @@ char *argv[];
fd_set readfds;
#ifdef ORDER
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJo";
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJwo";
#else
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJ";
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJw";
#endif
/* these defines enumerate the "strchr"s of the commands in command_chars */
#define CMD_redraw 0
@ -219,8 +219,9 @@ char *argv[];
#define CMD_kidletog 22
#define CMD_pcputog 23
#define CMD_jail 24
#define CMD_swaptog 25
#ifdef ORDER
#define CMD_order 25
#define CMD_order 26
#endif
/* set the buffer for stdout */
@ -254,6 +255,7 @@ char *argv[];
ps.wcpu = 1;
ps.jid = -1;
ps.jail = No;
ps.swap = No;
ps.kidle = Yes;
ps.command = NULL;
@ -280,7 +282,7 @@ char *argv[];
optind = 1;
}
while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:t")) != EOF)
while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:tw")) != EOF)
{
switch(i)
{
@ -418,6 +420,10 @@ char *argv[];
pcpu_stats = !pcpu_stats;
break;
case 'w':
ps.swap = 1;
break;
case 'z':
ps.kidle = !ps.kidle;
break;
@ -1141,6 +1147,15 @@ char *argv[];
reset_display();
putchar('\r');
break;
case CMD_swaptog:
ps.swap = !ps.swap;
new_message(MT_standout | MT_delayed,
" %sisplaying per-process swap usage.",
ps.swap ? "D" : "Not d");
header_text = format_header(uname_field);
reset_display();
putchar('\r');
break;
default:
new_message(MT_standout, " BAD CASE IN SWITCH!");
putchar('\r');

View File

@ -10,7 +10,7 @@ top \- display and update information about the top cpu processes
.SH SYNOPSIS
.B top
[
.B \-abCHIijnPqStuvz
.B \-abCHIijnPqStuvwz
] [
.BI \-d count
] [
@ -148,6 +148,9 @@ Write version number information to stderr then exit immediately.
No other processing takes place when this option is used. To see current
revision information while top is running, use the help command \*(lq?\*(rq.
.TP
.B \-w
Display approximate swap usage for each process.
.TP
.B \-z
Do not display the system idle process.
.TP
@ -167,11 +170,12 @@ Set the delay between screen updates to
seconds. The default delay between updates is \nD seconds.
.TP
.BI \-o field
Sort the process display area on the specified field. The field name is
the name of the column as seen in the output, but in lower case. Likely
values are \*(lqcpu\*(rq, \*(lqsize\*(rq, \*(lqres\*(rq, and \*(lqtime\*(rq,
but may vary on different operating systems. Note that
not all operating systems support this option.
Sort the process display area on the specified field. The field name
is the name of the column as seen in the output, but in lower case:
\*(lqcpu\*(lq, \*(rqsize\*(lq, \*(rqres\*(lq, \*(rqtime\*(lq,
\*(rqpri\*(lq, \*(rqthreads\*(lq, \*(lqtotal\*(lq, \*(rqread\*(lq,
\*(rqwrite\*(lq, \*(rqfault\*(lq, \*(rqvcsw\*(lq, \*(rqivcsw\*(lq,
\*(lqjid\*(lq, \*(rqswap\*(lq or \*(rqpid\*(lq.
.TP
.BI \-J jail
Show only those processes owned by
@ -226,6 +230,7 @@ The options
.BR \-S ,
.BR \-t ,
.BR \-u ,
.BR \-w ,
and
.B \-z
are actually toggles. A second specification of any of these options
@ -346,6 +351,9 @@ Toggle the display of the
.I top
process.
.TP
.B w
Toggle the display of swap usage.
.TP
.B z
Toggle the display of the system idle process.
.SH "THE DISPLAY"
@ -379,8 +387,9 @@ is specified, a UID column will be substituted for USERNAME),
PRI is the current priority of the process,
NICE is the nice amount (in the range \-20 to 20),
SIZE is the total size of the process (text, data, and stack),
RES is the current amount of resident memory (both SIZE and RES are
given in kilobytes),
RES is the current amount of resident memory,
SWAP is the approximate amount of swap, if enabled
(SIZE, RES and SWAP are given in kilobytes),
STATE is the current state (one of \*(lqSTART\*(rq, \*(lqRUN\*(rq
(shown as \*(lqCPUn\*(rq on SMP systems), \*(lqSLEEP\*(rq, \*(lqSTOP\*(rq,
\*(lqZOMB\*(rq, \*(lqWAIT\*(rq, \*(lqLOCK\*(rq or the event on which the

View File

@ -30,6 +30,7 @@
/* FreeBSD 5.0 and later have ACL and extattr support. */
#if __FreeBSD__ > 4
#define HAVE_ACL_CREATE_ENTRY 1
#define HAVE_ACL_GET_FD_NP 1
#define HAVE_ACL_GET_LINK_NP 1
#define HAVE_ACL_GET_PERM_NP 1
#define HAVE_ACL_INIT 1
@ -45,6 +46,7 @@
#define HAVE_EXTATTR_LIST_FILE 1
#define HAVE_EXTATTR_SET_FD 1
#define HAVE_EXTATTR_SET_FILE 1
#define HAVE_STRUCT_XVFSCONF 1
#define HAVE_SYS_ACL_H 1
#define HAVE_SYS_EXTATTR_H 1
#endif

View File

@ -37,6 +37,7 @@ static char sccsid[] = "@(#)fgets.c 8.2 (Berkeley) 12/22/93";
__FBSDID("$FreeBSD$");
#include "namespace.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "un-namespace.h"
@ -55,11 +56,16 @@ fgets(char * __restrict buf, int n, FILE * __restrict fp)
char *s;
unsigned char *p, *t;
if (n <= 0) /* sanity check */
return (NULL);
FLOCKFILE(fp);
ORIENT(fp, -1);
if (n <= 0) { /* sanity check */
fp->_flags |= __SERR;
errno = EINVAL;
FUNLOCKFILE(fp);
return (NULL);
}
s = buf;
n--; /* leave space for NUL */
while (n != 0) {
@ -69,7 +75,7 @@ fgets(char * __restrict buf, int n, FILE * __restrict fp)
if ((len = fp->_r) <= 0) {
if (__srefill(fp)) {
/* EOF/error: stop with partial or no line */
if (s == buf) {
if (!__sfeof(fp) || s == buf) {
FUNLOCKFILE(fp);
return (NULL);
}

View File

@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
wchar_t *
fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale)
{
int sret;
wchar_t *wsp;
size_t nconv;
const char *src;
@ -56,23 +57,31 @@ fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale)
ORIENT(fp, 1);
if (n <= 0) {
fp->_flags |= __SERR;
errno = EINVAL;
goto error;
}
if (fp->_r <= 0 && __srefill(fp))
/* EOF */
goto error;
wsp = ws;
if (n == 1)
goto ok;
if (fp->_r <= 0 && __srefill(fp))
/* EOF or ferror */
goto error;
sret = 0;
do {
src = fp->_p;
nl = memchr(fp->_p, '\n', fp->_r);
nconv = l->__mbsnrtowcs(wsp, &src,
nl != NULL ? (nl - fp->_p + 1) : fp->_r,
n - 1, &fp->_mbstate);
if (nconv == (size_t)-1)
if (nconv == (size_t)-1) {
/* Conversion error */
fp->_flags |= __SERR;
goto error;
}
if (src == NULL) {
/*
* We hit a null byte. Increment the character count,
@ -88,23 +97,30 @@ fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale)
fp->_p = (unsigned char *)src;
n -= nconv;
wsp += nconv;
} while (wsp[-1] != L'\n' && n > 1 && (fp->_r > 0 ||
__srefill(fp) == 0));
} while ((wsp == ws || wsp[-1] != L'\n') && n > 1 && (fp->_r > 0 ||
(sret = __srefill(fp)) == 0));
if (sret && !__sfeof(fp))
/* ferror */
goto error;
if (!l->__mbsinit(&fp->_mbstate)) {
/* Incomplete character */
fp->_flags |= __SERR;
errno = EILSEQ;
goto error;
}
if (wsp == ws)
/* EOF */
goto error;
if (!l->__mbsinit(&fp->_mbstate))
/* Incomplete character */
goto error;
ok:
*wsp = L'\0';
FUNLOCKFILE(fp);
return (ws);
error:
FUNLOCKFILE(fp);
return (NULL);
}
wchar_t *
fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp)
{

View File

@ -82,16 +82,26 @@ __FBSDID("$FreeBSD$");
#define A83T_FILTER 0x4
#define A83T_INTC 0x1000
#define A83T_TEMP_BASE 2719000
#define A83T_TEMP_MUL 1000
#define A83T_TEMP_DIV 14186
#define A83T_CLK_RATE 24000000
#define A64_ADC_ACQUIRE_TIME 0x190
#define A64_FILTER 0x6
#define A64_INTC 0x18000
#define A64_INTC 0x18000
#define A64_TEMP_BASE 2170000
#define A64_TEMP_MUL 1000
#define A64_TEMP_DIV 8560
#define A64_CLK_RATE 4000000
#define H3_ADC_ACQUIRE_TIME 0x3f
#define H3_FILTER 0x6
#define H3_INTC 0x191000
#define H3_TEMP_BASE 217000000
#define H3_TEMP_MUL 121168
#define H3_TEMP_DIV 1000000
#define H3_CLK_RATE 4000000
#define TEMP_C_TO_K 273
#define SENSOR_ENABLE_ALL (SENSOR0_EN|SENSOR1_EN|SENSOR2_EN)
#define SHUT_INT_ALL (SHUT_INT0_STS|SHUT_INT1_STS|SHUT_INT2_STS)
@ -110,8 +120,10 @@ struct aw_thermal_config {
uint32_t adc_acquire_time;
uint32_t filter;
uint32_t intc;
uint32_t temp_base;
uint32_t temp_div;
int temp_base;
int temp_mul;
int temp_div;
int calib;
};
static const struct aw_thermal_config a83t_config = {
@ -135,7 +147,9 @@ static const struct aw_thermal_config a83t_config = {
.filter = A83T_FILTER,
.intc = A83T_INTC,
.temp_base = A83T_TEMP_BASE,
.temp_mul = A83T_TEMP_MUL,
.temp_div = A83T_TEMP_DIV,
.calib = 1,
};
static const struct aw_thermal_config a64_config = {
@ -159,11 +173,30 @@ static const struct aw_thermal_config a64_config = {
.filter = A64_FILTER,
.intc = A64_INTC,
.temp_base = A64_TEMP_BASE,
.temp_mul = A64_TEMP_MUL,
.temp_div = A64_TEMP_DIV,
};
static const struct aw_thermal_config h3_config = {
.nsensors = 1,
.sensors = {
[0] = {
.name = "cpu",
.desc = "CPU temperature",
},
},
.clk_rate = H3_CLK_RATE,
.adc_acquire_time = H3_ADC_ACQUIRE_TIME,
.filter = H3_FILTER,
.intc = H3_INTC,
.temp_base = H3_TEMP_BASE,
.temp_mul = H3_TEMP_MUL,
.temp_div = H3_TEMP_DIV,
};
static struct ofw_compat_data compat_data[] = {
{ "allwinner,sun8i-a83t-ts", (uintptr_t)&a83t_config },
{ "allwinner,sun8i-h3-ts", (uintptr_t)&h3_config },
{ "allwinner,sun50i-a64-ts", (uintptr_t)&a64_config },
{ NULL, (uintptr_t)NULL }
};
@ -191,14 +224,16 @@ aw_thermal_init(struct aw_thermal_softc *sc)
uint32_t calib0, calib1;
int error;
/* Read calibration settings from SRAM */
error = aw_sid_read_tscalib(&calib0, &calib1);
if (error != 0)
return (error);
if (sc->conf->calib) {
/* Read calibration settings from SRAM */
error = aw_sid_read_tscalib(&calib0, &calib1);
if (error != 0)
return (error);
/* Write calibration settings to thermal controller */
WR4(sc, THS_CALIB0, calib0);
WR4(sc, THS_CALIB1, calib1);
/* Write calibration settings to thermal controller */
WR4(sc, THS_CALIB0, calib0);
WR4(sc, THS_CALIB1, calib1);
}
/* Configure ADC acquire time (CLK_IN/(N+1)) and enable sensors */
WR4(sc, THS_CTRL1, ADC_CALI_EN);
@ -221,7 +256,8 @@ aw_thermal_init(struct aw_thermal_softc *sc)
static int
aw_thermal_reg_to_temp(struct aw_thermal_softc *sc, uint32_t val)
{
return ((sc->conf->temp_base - val * 1000) / sc->conf->temp_div);
return ((sc->conf->temp_base - (val * sc->conf->temp_mul)) /
sc->conf->temp_div);
}
static int

View File

@ -187,6 +187,7 @@ static struct aw_pll_factor aw_a23_pll1_factors[] = {
PLLFACTOR(16, 1, 0, 0, 816000000),
PLLFACTOR(20, 1, 0, 0, 1008000000),
PLLFACTOR(24, 1, 0, 0, 1200000000),
PLLFACTOR(26, 1, 0, 0, 1296000000),
};
enum aw_pll_type {
@ -201,6 +202,7 @@ enum aw_pll_type {
AWPLL_A31_PLL6,
AWPLL_A64_PLLHSIC,
AWPLL_A80_PLL4,
AWPLL_H3_PLL1,
};
struct aw_pll_sc {
@ -626,6 +628,72 @@ a23_pll1_recalc(struct aw_pll_sc *sc, uint64_t *freq)
return (0);
}
static int
h3_pll1_set_freq(struct aw_pll_sc *sc, uint64_t fin, uint64_t *fout,
int flags)
{
struct aw_pll_factor *f;
uint32_t val, n, k, m, p;
int i;
f = NULL;
for (i = 0; i < nitems(aw_a23_pll1_factors); i++) {
if (aw_a23_pll1_factors[i].freq == *fout) {
f = &aw_a23_pll1_factors[i];
break;
}
}
if (f == NULL)
return (EINVAL);
DEVICE_LOCK(sc);
PLL_READ(sc, &val);
n = (val & A23_PLL1_FACTOR_N) >> A23_PLL1_FACTOR_N_SHIFT;
k = (val & A23_PLL1_FACTOR_K) >> A23_PLL1_FACTOR_K_SHIFT;
m = (val & A23_PLL1_FACTOR_M) >> A23_PLL1_FACTOR_M_SHIFT;
p = (val & A23_PLL1_FACTOR_P) >> A23_PLL1_FACTOR_P_SHIFT;
if (p < f->p) {
val &= ~A23_PLL1_FACTOR_P;
val |= (f->p << A23_PLL1_FACTOR_P_SHIFT);
PLL_WRITE(sc, val);
DELAY(2000);
}
if (m < f->m) {
val &= ~A23_PLL1_FACTOR_M;
val |= (f->m << A23_PLL1_FACTOR_M_SHIFT);
PLL_WRITE(sc, val);
DELAY(2000);
}
val &= ~(A23_PLL1_FACTOR_N|A23_PLL1_FACTOR_K);
val |= (f->n << A23_PLL1_FACTOR_N_SHIFT);
val |= (f->k << A23_PLL1_FACTOR_K_SHIFT);
PLL_WRITE(sc, val);
DELAY(2000);
if (m > f->m) {
val &= ~A23_PLL1_FACTOR_M;
val |= (f->m << A23_PLL1_FACTOR_M_SHIFT);
PLL_WRITE(sc, val);
DELAY(2000);
}
if (p > f->p) {
val &= ~A23_PLL1_FACTOR_P;
val |= (f->p << A23_PLL1_FACTOR_P_SHIFT);
PLL_WRITE(sc, val);
DELAY(2000);
}
DEVICE_UNLOCK(sc);
return (0);
}
static int
a31_pll1_recalc(struct aw_pll_sc *sc, uint64_t *freq)
{
@ -775,6 +843,7 @@ static struct aw_pll_funcs aw_pll_func[] = {
PLL(AWPLL_A31_PLL6, a31_pll6_recalc, NULL, a31_pll6_init),
PLL(AWPLL_A80_PLL4, a80_pll4_recalc, NULL, NULL),
PLL(AWPLL_A64_PLLHSIC, a64_pllhsic_recalc, NULL, a64_pllhsic_init),
PLL(AWPLL_H3_PLL1, a23_pll1_recalc, h3_pll1_set_freq, NULL),
};
static struct ofw_compat_data compat_data[] = {
@ -787,6 +856,7 @@ static struct ofw_compat_data compat_data[] = {
{ "allwinner,sun6i-a31-pll1-clk", AWPLL_A31_PLL1 },
{ "allwinner,sun6i-a31-pll6-clk", AWPLL_A31_PLL6 },
{ "allwinner,sun8i-a23-pll1-clk", AWPLL_A23_PLL1 },
{ "allwinner,sun8i-h3-pll1-clk", AWPLL_H3_PLL1 },
{ "allwinner,sun9i-a80-pll4-clk", AWPLL_A80_PLL4 },
{ "allwinner,sun50i-a64-pllhsic-clk", AWPLL_A64_PLLHSIC },
{ NULL, 0 }

View File

@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#define CLK_DIV_RATIO_MAX 3
static struct ofw_compat_data compat_data[] = {
{ "allwinner,sun8i-h3-ths-clk", 1 },
{ "allwinner,sun50i-a64-ths-clk", 1 },
{ NULL, 0 }
};

View File

@ -28,6 +28,7 @@ dev/usb/controller/generic_ohci.c optional ohci
dev/usb/controller/generic_usb_if.m optional ohci
arm/allwinner/aw_sid.c standard
arm/allwinner/aw_thermal.c standard
dev/iicbus/sy8106a.c optional sy8106a
#arm/allwinner/console.c standard
arm/allwinner/a10_fb.c optional vt
@ -52,4 +53,5 @@ arm/allwinner/clk/aw_modclk.c standard
arm/allwinner/clk/aw_mmcclk.c standard
arm/allwinner/clk/aw_oscclk.c standard
arm/allwinner/clk/aw_pll.c standard
arm/allwinner/clk/aw_thsclk.c standard
arm/allwinner/clk/aw_usbclk.c standard

View File

@ -369,7 +369,6 @@ minidumpsys(struct dumperinfo *di)
else
printf("\n** DUMP FAILED (ERROR %d) **\n", error);
return (error);
return (0);
}
void

View File

@ -81,6 +81,7 @@ device twsi
device rsb
device axp209 # AXP209 Power Management Unit
device axp81x # AXP813/818 Power Management Unit
device sy8106a # SY8106A Buck Regulator
# GPIO
device gpio

View File

@ -110,7 +110,7 @@
rtp: rtp@01c25000 {
compatible = "allwinner,sun50i-a64-ts";
reg = <0x01c25000 0x400>;
interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&bus_gates 72>, <&ths_clk>;
clock-names = "ahb", "ths";
resets = <&ahb_rst 136>;

View File

@ -0,0 +1,267 @@
/*-
* Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
* Copyright (c) 2010, Aleksandr Rybalko <ray@ddteam.net>
* All rights reserved.
*
* Developed by Semihalf.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of MARVELL nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* BHND attachment driver for the USB Enhanced Host Controller.
* Ported from ZRouter with insignificant adaptations for FreeBSD11.
*/
#include "opt_bus.h"
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/rman.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/linker_set.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/sysctl.h>
#include <sys/sx.h>
#include <sys/unistd.h>
#include <sys/callout.h>
#include <sys/malloc.h>
#include <sys/priv.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <dev/usb/controller/ehci.h>
#include <dev/usb/controller/ehcireg.h>
#include <dev/bhnd/bhnd.h>
#define EHCI_HC_DEVSTR "Broadcom EHCI"
#define USB_BRIDGE_INTR_CAUSE 0x210
#define USB_BRIDGE_INTR_MASK 0x214
static device_attach_t bhnd_ehci_attach;
static device_detach_t bhnd_ehci_detach;
static int bhnd_ehci_probe(device_t self);
static void bhnd_ehci_post_reset(struct ehci_softc *ehci_softc);
static int
bhnd_ehci_probe(device_t self)
{
device_set_desc(self, EHCI_HC_DEVSTR);
return (BUS_PROBE_DEFAULT);
}
static void
bhnd_ehci_post_reset(struct ehci_softc *ehci_softc)
{
uint32_t usbmode;
/* Force HOST mode */
usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_NOLPM);
usbmode &= ~EHCI_UM_CM;
usbmode |= EHCI_UM_CM_HOST;
EOWRITE4(ehci_softc, EHCI_USBMODE_NOLPM, usbmode);
}
static int
bhnd_ehci_attach(device_t self)
{
ehci_softc_t *sc;
int err;
int rid;
sc = device_get_softc(self);
/* initialise some bus fields */
sc->sc_bus.parent = self;
sc->sc_bus.devices = sc->sc_devices;
sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
sc->sc_bus.usbrev = USB_REV_2_0;
sc->sc_bus.dma_bits = 32;
/* get all DMA memory */
if ((err = usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self),
&ehci_iterate_hw_softc)) != 0) {
BHND_ERROR_DEV(self, "can't allocate DMA memory: %d", err);
return (ENOMEM);
}
rid = 0;
sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (!sc->sc_io_res) {
BHND_ERROR_DEV(self, "Could not map memory");
goto error;
}
sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
sc->sc_io_size = rman_get_size(sc->sc_io_res);
rid = 0;
sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE);
if (sc->sc_irq_res == NULL) {
BHND_ERROR_DEV(self, "Could not allocate error irq");
bhnd_ehci_detach(self);
return (ENXIO);
}
sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
if (!sc->sc_bus.bdev) {
BHND_ERROR_DEV(self, "Could not add USB device");
goto error;
}
device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR);
sprintf(sc->sc_vendor, "Broadcom");
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
if (err) {
BHND_ERROR_DEV(self, "Could not setup irq, %d", err);
sc->sc_intr_hdl = NULL;
goto error;
}
sc->sc_flags |= EHCI_SCFLG_LOSTINTRBUG;
sc->sc_vendor_post_reset = bhnd_ehci_post_reset;
err = ehci_init(sc);
if (!err) {
err = device_probe_and_attach(sc->sc_bus.bdev);
}
if (err) {
BHND_ERROR_DEV(self, "USB init failed err=%d", err);
goto error;
}
return (0);
error:
bhnd_ehci_detach(self);
return (ENXIO);
}
static int
bhnd_ehci_detach(device_t self)
{
ehci_softc_t *sc;
device_t bdev;
int err;
sc = device_get_softc(self);
if (sc->sc_bus.bdev) {
bdev = sc->sc_bus.bdev;
device_detach(bdev);
device_delete_child(self, bdev);
}
/* during module unload there are lots of children leftover */
device_delete_children(self);
/*
* disable interrupts that might have been switched on in ehci_init
*/
#ifdef notyet
if (sc->sc_io_res) {
EWRITE4(sc, EHCI_USBINTR, 0);
EWRITE4(sc, USB_BRIDGE_INTR_MASK, 0);
}
#endif
if (sc->sc_irq_res && sc->sc_intr_hdl) {
/*
* only call ehci_detach() after ehci_init()
*/
ehci_detach(sc);
err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
if (err)
/* XXX or should we panic? */
BHND_ERROR_DEV(self, "Could not tear down irq, %d", err);
sc->sc_intr_hdl = NULL;
}
if (sc->sc_irq_res) {
bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
sc->sc_irq_res = NULL;
}
if (sc->sc_io_res) {
bus_release_resource(self, SYS_RES_MEMORY, 0, sc->sc_io_res);
sc->sc_io_res = NULL;
}
usb_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
return (0);
}
static device_method_t ehci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, bhnd_ehci_probe),
DEVMETHOD(device_attach, bhnd_ehci_attach),
DEVMETHOD(device_detach, bhnd_ehci_detach),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
{0, 0}
};
static driver_t ehci_driver = {
"ehci",
ehci_methods,
sizeof(ehci_softc_t),
};
static devclass_t ehci_devclass;
DRIVER_MODULE(ehci, bhnd_usb, ehci_driver, ehci_devclass, 0, 0);
MODULE_DEPEND(ehci, usb, 1, 1, 1);

View File

@ -0,0 +1,228 @@
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 2010, Aleksandr Rybalko <ray@ddteam.net>
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Lennart Augustsson (augustss@carlstedt.se) at
* Carlstedt Research & Technology.
*
* 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* USB Open Host Controller driver.
*
* OHCI spec: http://www.intel.com/design/usb/ohci11d.pdf
*/
/* The low level controller code for OHCI has been split into
* SIBA probes and OHCI specific code. This was done to facilitate the
* sharing of code between *BSD's
*/
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/rman.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/linker_set.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/sysctl.h>
#include <sys/sx.h>
#include <sys/unistd.h>
#include <sys/callout.h>
#include <sys/malloc.h>
#include <sys/priv.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
#include <dev/usb/controller/ohci.h>
#include <dev/usb/controller/ohcireg.h>
static device_probe_t bhnd_ohci_probe;
static device_attach_t bhnd_ohci_attach;
static device_detach_t bhnd_ohci_detach;
static int
bhnd_ohci_probe(device_t self)
{
device_set_desc(self, "Broadcom OHCI");
return (0);
}
static int
bhnd_ohci_attach(device_t self)
{
ohci_softc_t *sc;
int rid;
int err;
sc = device_get_softc(self);
/* initialise some bus fields */
sc->sc_bus.parent = self;
sc->sc_bus.devices = sc->sc_devices;
sc->sc_bus.devices_max = OHCI_MAX_DEVICES;
sc->sc_bus.dma_bits = 32;
/* get all DMA memory */
if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self),
&ohci_iterate_hw_softc)) {
return (ENOMEM);
}
sc->sc_dev = self;
rid = 0;
sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
if (!sc->sc_io_res) {
device_printf(self, "Could not map memory\n");
goto error;
}
sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
sc->sc_io_size = rman_get_size(sc->sc_io_res);
rid = 0;
sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE);
if (sc->sc_irq_res == NULL) {
device_printf(self, "Could not allocate irq\n");
goto error;
}
sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
if (!sc->sc_bus.bdev) {
device_printf(self, "Could not add USB device\n");
goto error;
}
device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
strlcpy(sc->sc_vendor, "Broadcom", sizeof(sc->sc_vendor));
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
NULL, (driver_intr_t *)ohci_interrupt, sc, &sc->sc_intr_hdl);
if (err) {
device_printf(self, "Could not setup irq, %d\n", err);
sc->sc_intr_hdl = NULL;
goto error;
}
err = ohci_init(sc);
if (!err) {
err = device_probe_and_attach(sc->sc_bus.bdev);
}
if (err) {
device_printf(self, "USB init failed\n");
goto error;
}
return (0);
error:
bhnd_ohci_detach(self);
return (ENXIO);
}
static int
bhnd_ohci_detach(device_t self)
{
ohci_softc_t *sc;
device_t bdev;
sc = device_get_softc(self);
if (sc->sc_bus.bdev) {
bdev = sc->sc_bus.bdev;
device_detach(bdev);
device_delete_child(self, bdev);
}
/* during module unload there are lots of children leftover */
device_delete_children(self);
if (sc->sc_irq_res && sc->sc_intr_hdl) {
/*
* only call ohci_detach() after ohci_init()
*/
ohci_detach(sc);
int err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
if (err) {
/* XXX or should we panic? */
device_printf(self, "Could not tear down irq, %d\n",
err);
}
sc->sc_intr_hdl = NULL;
}
if (sc->sc_irq_res) {
bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
sc->sc_irq_res = NULL;
}
if (sc->sc_io_res) {
bus_release_resource(self, SYS_RES_MEMORY, 0,
sc->sc_io_res);
sc->sc_io_res = NULL;
}
usb_bus_mem_free_all(&sc->sc_bus, &ohci_iterate_hw_softc);
return (0);
}
static device_method_t bhnd_ohci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, bhnd_ohci_probe),
DEVMETHOD(device_attach, bhnd_ohci_attach),
DEVMETHOD(device_detach, bhnd_ohci_detach),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD_END
};
static driver_t ohci_driver = {
.name = "ohci",
.methods = bhnd_ohci_methods,
.size = sizeof(struct ohci_softc),
};
static devclass_t ohci_devclass;
DRIVER_MODULE(ohci, bhnd_usb, ohci_driver, ohci_devclass, 0, 0);
MODULE_DEPEND(ohci, usb, 1, 1, 1);

View File

@ -0,0 +1,487 @@
/*-
* Copyright (c) 2010, Aleksandr Rybalko <ray@ddteam.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Ported version of BroadCom USB core driver from ZRouter project
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/errno.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/malloc.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <dev/bhnd/bhnd.h>
#include <dev/bhnd/bhnd_core.h>
#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
#include "bhnd_usbvar.h"
/****************************** Variables ************************************/
static const struct bhnd_device bhnd_usb_devs[] = {
BHND_DEVICE(BCM, USB, "USB1.1 Host/Device core", NULL),
BHND_DEVICE(BCM, USB20H, "USB2.0 Host core", NULL),
BHND_DEVICE(BCM, USB20D, "USB2.0 Device core", NULL),
BHND_DEVICE(BCM, USB11H, "USB1.1 Host core", NULL),
BHND_DEVICE(BCM, USB11D, "USB1.1 Device core", NULL),
BHND_DEVICE_END
};
/****************************** Prototypes ***********************************/
static int bhnd_usb_attach(device_t);
static int bhnd_usb_probe(device_t);
static device_t bhnd_usb_add_child(device_t dev, u_int order, const char *name,
int unit);
static int bhnd_usb_print_all_resources(device_t dev);
static int bhnd_usb_print_child(device_t bus, device_t child);
static struct resource * bhnd_usb_alloc_resource(device_t bus,
device_t child, int type, int *rid,
rman_res_t start, rman_res_t end,
rman_res_t count, u_int flags);
static int bhnd_usb_release_resource(device_t dev,
device_t child, int type, int rid,
struct resource *r);
static struct resource_list * bhnd_usb_get_reslist(device_t dev,
device_t child);
static int
bhnd_usb_probe(device_t dev)
{
const struct bhnd_device *id;
id = bhnd_device_lookup(dev, bhnd_usb_devs, sizeof(bhnd_usb_devs[0]));
if (id == NULL)
return (ENXIO);
device_set_desc(dev, id->desc);
return (BUS_PROBE_DEFAULT);
}
static int
bhnd_usb_attach(device_t dev)
{
struct bhnd_usb_softc *sc;
int rid;
uint32_t tmp;
int tries, err;
sc = device_get_softc(dev);
BHND_BUS_RESET_CORE(device_get_parent(dev), dev, 0);
/*
* Allocate the resources which the parent bus has already
* determined for us.
* XXX: There are few windows (usually 2), RID should be chip-specific
*/
rid = 0;
sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
if (sc->sc_mem == NULL) {
BHND_ERROR_DEV(dev, "unable to allocate memory");
return (ENXIO);
}
sc->sc_bt = rman_get_bustag(sc->sc_mem);
sc->sc_bh = rman_get_bushandle(sc->sc_mem);
sc->sc_maddr = rman_get_start(sc->sc_mem);
sc->sc_msize = rman_get_size(sc->sc_mem);
rid = 0;
sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE);
if (sc->sc_irq == NULL) {
BHND_ERROR_DEV(dev, "unable to allocate IRQ");
return (ENXIO);
}
sc->sc_irqn = rman_get_start(sc->sc_irq);
sc->mem_rman.rm_start = sc->sc_maddr;
sc->mem_rman.rm_end = sc->sc_maddr + sc->sc_msize - 1;
sc->mem_rman.rm_type = RMAN_ARRAY;
sc->mem_rman.rm_descr = "BHND USB core I/O memory addresses";
if (rman_init(&sc->mem_rman) != 0 ||
rman_manage_region(&sc->mem_rman, sc->mem_rman.rm_start,
sc->mem_rman.rm_end) != 0) {
panic("%s: sc->mem_rman", __func__);
}
sc->irq_rman.rm_start = sc->sc_irqn;
sc->irq_rman.rm_end = sc->sc_irqn;
sc->irq_rman.rm_type = RMAN_ARRAY;
sc->irq_rman.rm_descr = "BHND USB core IRQ";
/*
* BHND USB share same IRQ between OHCI and EHCI
*/
if (rman_init(&sc->irq_rman) != 0 ||
rman_manage_region(&sc->irq_rman, sc->irq_rman.rm_start,
sc->irq_rman.rm_end) != 0)
panic("%s: failed to set up IRQ rman", __func__);
/* TODO: macros for registers */
bus_write_4(sc->sc_mem, 0x200, 0x7ff);
DELAY(100);
#define OHCI_CONTROL 0x04
bus_write_4(sc->sc_mem, OHCI_CONTROL, 0);
if ( bhnd_get_device(dev) == BHND_COREID_USB20H) {
uint32_t rev;
BHND_INFO_DEV(dev, "USB HOST 2.0 setup for rev %d", rev);
rev = bhnd_get_hwrev(dev);
if (rev == 1/* ? == 2 */) {
/* SiBa code */
/* Change Flush control reg */
tmp = bus_read_4(sc->sc_mem, 0x400) & ~0x8;
bus_write_4(sc->sc_mem, 0x400, tmp);
tmp = bus_read_4(sc->sc_mem, 0x400);
BHND_DEBUG_DEV(dev, "USB20H fcr: 0x%x", tmp);
/* Change Shim control reg */
tmp = bus_read_4(sc->sc_mem, 0x304) & ~0x100;
bus_write_4(sc->sc_mem, 0x304, tmp);
tmp = bus_read_4(sc->sc_mem, 0x304);
BHND_DEBUG_DEV(dev, "USB20H shim: 0x%x", tmp);
} else if (rev >= 5) {
/* BCMA code */
err = bhnd_alloc_pmu(dev);
if(err) {
BHND_ERROR_DEV(dev, "can't alloc pmu: %d", err);
return (err);
}
err = bhnd_request_ext_rsrc(dev, 1);
if(err) {
BHND_ERROR_DEV(dev, "can't req ext: %d", err);
return (err);
}
/* Take out of resets */
bus_write_4(sc->sc_mem, 0x200, 0x4ff);
DELAY(25);
bus_write_4(sc->sc_mem, 0x200, 0x6ff);
DELAY(25);
/* Make sure digital and AFE are locked in USB PHY */
bus_write_4(sc->sc_mem, 0x524, 0x6b);
DELAY(50);
bus_read_4(sc->sc_mem, 0x524);
DELAY(50);
bus_write_4(sc->sc_mem, 0x524, 0xab);
DELAY(50);
bus_read_4(sc->sc_mem, 0x524);
DELAY(50);
bus_write_4(sc->sc_mem, 0x524, 0x2b);
DELAY(50);
bus_read_4(sc->sc_mem, 0x524);
DELAY(50);
bus_write_4(sc->sc_mem, 0x524, 0x10ab);
DELAY(50);
bus_read_4(sc->sc_mem, 0x524);
tries = 10000;
for (;;) {
DELAY(10);
tmp = bus_read_4(sc->sc_mem, 0x528);
if (tmp & 0xc000)
break;
if (--tries != 0)
continue;
tmp = bus_read_4(sc->sc_mem, 0x528);
BHND_ERROR_DEV(dev, "USB20H mdio_rddata 0x%08x", tmp);
}
/* XXX: Puzzle code */
bus_write_4(sc->sc_mem, 0x528, 0x80000000);
bus_read_4(sc->sc_mem, 0x314);
DELAY(265);
bus_write_4(sc->sc_mem, 0x200, 0x7ff);
DELAY(10);
/* Take USB and HSIC out of non-driving modes */
bus_write_4(sc->sc_mem, 0x510, 0);
}
}
bus_generic_probe(dev);
if (bhnd_get_device(dev) == BHND_COREID_USB20H &&
( bhnd_get_hwrev(dev) > 0))
bhnd_usb_add_child(dev, 0, "ehci", -1);
bhnd_usb_add_child(dev, 1, "ohci", -1);
bus_generic_attach(dev);
return (0);
}
static struct resource *
bhnd_usb_alloc_resource(device_t bus, device_t child, int type, int *rid,
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
{
struct resource *rv;
struct resource_list *rl;
struct resource_list_entry *rle;
int isdefault, needactivate;
struct bhnd_usb_softc *sc = device_get_softc(bus);
isdefault = RMAN_IS_DEFAULT_RANGE(start,end);
needactivate = flags & RF_ACTIVE;
rl = BUS_GET_RESOURCE_LIST(bus, child);
rle = NULL;
if (isdefault) {
BHND_INFO_DEV(bus, "trying allocate def %d - %d for %s", type,
*rid, device_get_nameunit(child) );
rle = resource_list_find(rl, type, *rid);
if (rle == NULL)
return (NULL);
if (rle->res != NULL)
panic("%s: resource entry is busy", __func__);
start = rle->start;
end = rle->end;
count = rle->count;
} else {
BHND_INFO_DEV(bus, "trying allocate %d - %d (%jx-%jx) for %s", type,
*rid, start, end, device_get_nameunit(child) );
}
/*
* If the request is for a resource which we manage,
* attempt to satisfy the allocation ourselves.
*/
if (type == SYS_RES_MEMORY) {
rv = rman_reserve_resource(&sc->mem_rman, start, end, count,
flags, child);
if (rv == 0) {
BHND_ERROR_DEV(bus, "could not reserve resource");
return (0);
}
rman_set_rid(rv, *rid);
if (needactivate &&
bus_activate_resource(child, type, *rid, rv)) {
BHND_ERROR_DEV(bus, "could not activate resource");
rman_release_resource(rv);
return (0);
}
return (rv);
}
if (type == SYS_RES_IRQ) {
rv = rman_reserve_resource(&sc->irq_rman, start, end, count,
flags, child);
if (rv == 0) {
BHND_ERROR_DEV(bus, "could not reserve resource");
return (0);
}
rman_set_rid(rv, *rid);
if (needactivate &&
bus_activate_resource(child, type, *rid, rv)) {
BHND_ERROR_DEV(bus, "could not activate resource");
rman_release_resource(rv);
return (0);
}
return (rv);
}
/*
* Pass the request to the parent.
*/
return (resource_list_alloc(rl, bus, child, type, rid,
start, end, count, flags));
}
static struct resource_list *
bhnd_usb_get_reslist(device_t dev, device_t child)
{
struct bhnd_usb_devinfo *sdi;
sdi = device_get_ivars(child);
return (&sdi->sdi_rl);
}
static int
bhnd_usb_release_resource(device_t dev, device_t child, int type,
int rid, struct resource *r)
{
struct resource_list *rl;
struct resource_list_entry *rle;
rl = bhnd_usb_get_reslist(dev, child);
if (rl == NULL)
return (EINVAL);
rle = resource_list_find(rl, type, rid);
if (rle == NULL)
return (EINVAL);
rman_release_resource(r);
rle->res = NULL;
return (0);
}
static int
bhnd_usb_print_all_resources(device_t dev)
{
struct bhnd_usb_devinfo *sdi;
struct resource_list *rl;
int retval;
retval = 0;
sdi = device_get_ivars(dev);
rl = &sdi->sdi_rl;
if (STAILQ_FIRST(rl))
retval += printf(" at");
retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%jx");
retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
return (retval);
}
static int
bhnd_usb_print_child(device_t bus, device_t child)
{
int retval = 0;
retval += bus_print_child_header(bus, child);
retval += bhnd_usb_print_all_resources(child);
if (device_get_flags(child))
retval += printf(" flags %#x", device_get_flags(child));
retval += printf(" on %s\n", device_get_nameunit(bus));
return (retval);
}
static device_t
bhnd_usb_add_child(device_t dev, u_int order, const char *name, int unit)
{
struct bhnd_usb_softc *sc;
struct bhnd_usb_devinfo *sdi;
device_t child;
sc = device_get_softc(dev);
child = device_add_child_ordered(dev, order, name, unit);
if (child == NULL)
return (NULL);
sdi = malloc(sizeof(struct bhnd_usb_devinfo), M_DEVBUF, M_NOWAIT|M_ZERO);
if (sdi == NULL)
return (NULL);
if (strncmp(name, "ohci", 4) == 0)
{
sdi->sdi_maddr = sc->sc_maddr + 0x000;
sdi->sdi_msize = 0x200;
sdi->sdi_irq = sc->sc_irqn;
BHND_INFO_DEV(dev, "ohci: irq=%d maddr=0x%jx", sdi->sdi_irq,
sdi->sdi_maddr);
}
else if (strncmp(name, "ehci", 4) == 0)
{
sdi->sdi_maddr = sc->sc_maddr + 0x000;
sdi->sdi_msize = 0x1000;
sdi->sdi_irq = sc->sc_irqn;
BHND_INFO_DEV(dev, "ehci: irq=%d maddr=0x%jx", sdi->sdi_irq,
sdi->sdi_maddr);
}
else
{
panic("Unknown subdevice");
/* Unknown subdevice */
sdi->sdi_maddr = 1;
sdi->sdi_msize = 1;
sdi->sdi_irq = 1;
}
resource_list_init(&sdi->sdi_rl);
/*
* Determine memory window on bus and irq if one is needed.
*/
resource_list_add(&sdi->sdi_rl, SYS_RES_MEMORY, 0,
sdi->sdi_maddr, sdi->sdi_maddr + sdi->sdi_msize - 1, sdi->sdi_msize);
resource_list_add(&sdi->sdi_rl, SYS_RES_IRQ, 0,
sdi->sdi_irq, sdi->sdi_irq, 1);
device_set_ivars(child, sdi);
return (child);
}
static device_method_t bhnd_usb_methods[] = {
/* Device interface */
DEVMETHOD(device_attach, bhnd_usb_attach),
DEVMETHOD(device_probe, bhnd_usb_probe),
/* Bus interface */
DEVMETHOD(bus_add_child, bhnd_usb_add_child),
DEVMETHOD(bus_alloc_resource, bhnd_usb_alloc_resource),
DEVMETHOD(bus_get_resource_list, bhnd_usb_get_reslist),
DEVMETHOD(bus_print_child, bhnd_usb_print_child),
DEVMETHOD(bus_release_resource, bhnd_usb_release_resource),
/* Bus interface: generic part */
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD_END
};
static devclass_t bhnd_usb_devclass;
DEFINE_CLASS_0(bhnd_usb, bhnd_usb_driver, bhnd_usb_methods,
sizeof(struct bhnd_usb_softc));
DRIVER_MODULE(bhnd_usb, bhnd, bhnd_usb_driver, bhnd_usb_devclass, 0, 0);
MODULE_VERSION(bhnd_usb, 1);

View File

@ -0,0 +1,59 @@
/*-
* Copyright (c) 2010, Aleksandr Rybalko <ray@ddteam.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*
*/
#ifndef _BHND_USBVAR_H_
#define _BHND_USBVAR_H_
struct bhnd_usb_softc {
bus_space_tag_t sc_bt;
bus_space_handle_t sc_bh;
bus_addr_t sc_maddr;
bus_size_t sc_msize;
bus_addr_t sc_irqn;
struct intr_event *sc_events; /* IRQ events structs */
struct resource *sc_mem;
struct resource *sc_irq;
struct rman mem_rman;
struct rman irq_rman;
int devid;
};
struct bhnd_usb_devinfo {
struct resource_list sdi_rl;
uint8_t sdi_unit; /* core index on bus */
uint8_t sdi_irq;
char sdi_name[8];
rman_res_t sdi_maddr;
rman_res_t sdi_msize;
};
#endif /* _BHND_USBVAR_H_ */

View File

@ -742,32 +742,53 @@ hv_nv_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
{
const struct vmbus_chanpkt_rxbuf *pkt;
const struct hn_nvs_hdr *nvs_hdr;
int count = 0;
int i = 0;
int count, i, hlen;
if (__predict_false(VMBUS_CHANPKT_DATALEN(pkthdr) < sizeof(*nvs_hdr))) {
if_printf(rxr->hn_ifp, "invalid nvs RNDIS\n");
return;
}
nvs_hdr = VMBUS_CHANPKT_CONST_DATA(pkthdr);
/* Make sure that this is a RNDIS message. */
nvs_hdr = VMBUS_CHANPKT_CONST_DATA(pkthdr);
if (__predict_false(nvs_hdr->nvs_type != HN_NVS_TYPE_RNDIS)) {
if_printf(rxr->hn_ifp, "nvs type %u, not RNDIS\n",
nvs_hdr->nvs_type);
return;
}
hlen = VMBUS_CHANPKT_GETLEN(pkthdr->cph_hlen);
if (__predict_false(hlen < sizeof(*pkt))) {
if_printf(rxr->hn_ifp, "invalid rxbuf chanpkt\n");
return;
}
pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr;
if (pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID) {
if_printf(rxr->hn_ifp, "rxbuf_id %d is invalid!\n",
if (__predict_false(pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID)) {
if_printf(rxr->hn_ifp, "invalid rxbuf_id 0x%08x\n",
pkt->cp_rxbuf_id);
return;
}
count = pkt->cp_rxbuf_cnt;
if (__predict_false(hlen <
__offsetof(struct vmbus_chanpkt_rxbuf, cp_rxbuf[count]))) {
if_printf(rxr->hn_ifp, "invalid rxbuf_cnt %d\n", count);
return;
}
/* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */
for (i = 0; i < count; i++) {
hv_rf_on_receive(sc, rxr,
rxr->hn_rxbuf + pkt->cp_rxbuf[i].rb_ofs,
pkt->cp_rxbuf[i].rb_len);
for (i = 0; i < count; ++i) {
int ofs, len;
ofs = pkt->cp_rxbuf[i].rb_ofs;
len = pkt->cp_rxbuf[i].rb_len;
if (__predict_false(ofs + len > NETVSC_RECEIVE_BUFFER_SIZE)) {
if_printf(rxr->hn_ifp, "%dth RNDIS msg overflow rxbuf, "
"ofs %d, len %d\n", i, ofs, len);
continue;
}
hv_rf_on_receive(sc, rxr, rxr->hn_rxbuf + ofs, len);
}
/*
@ -816,7 +837,12 @@ hn_proc_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt)
{
const struct hn_nvs_hdr *hdr;
if (VMBUS_CHANPKT_DATALEN(pkt) < sizeof(*hdr)) {
if_printf(sc->hn_ifp, "invalid nvs notify\n");
return;
}
hdr = VMBUS_CHANPKT_CONST_DATA(pkt);
if (hdr->nvs_type == HN_NVS_TYPE_TXTBL_NOTE) {
/* Useless; ignore */
return;

View File

@ -72,7 +72,7 @@ __FBSDID("$FreeBSD$");
* Forward declarations
*/
static void hv_rf_receive_indicate_status(struct hn_softc *sc,
const rndis_msg *response);
const void *data, int dlen);
static void hv_rf_receive_data(struct hn_rx_ring *rxr,
const void *data, int dlen);
static int hv_rf_query_device_mac(struct hn_softc *sc, uint8_t *eaddr);
@ -131,21 +131,29 @@ hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
* RNDIS filter receive indicate status
*/
static void
hv_rf_receive_indicate_status(struct hn_softc *sc, const rndis_msg *response)
hv_rf_receive_indicate_status(struct hn_softc *sc, const void *data, int dlen)
{
const rndis_indicate_status *indicate = &response->msg.indicate_status;
switch(indicate->status) {
const struct rndis_status_msg *msg;
if (dlen < sizeof(*msg)) {
if_printf(sc->hn_ifp, "invalid RNDIS status\n");
return;
}
msg = data;
switch (msg->rm_status) {
case RNDIS_STATUS_MEDIA_CONNECT:
netvsc_linkstatus_callback(sc, 1);
break;
case RNDIS_STATUS_MEDIA_DISCONNECT:
netvsc_linkstatus_callback(sc, 0);
break;
default:
/* TODO: */
if_printf(sc->hn_ifp,
"unknown status %d received\n", indicate->status);
if_printf(sc->hn_ifp, "unknown RNDIS status 0x%08x\n",
msg->rm_status);
break;
}
}
@ -283,34 +291,41 @@ hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen)
/*
* RNDIS filter on receive
*/
int
void
hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
const void *data, int dlen)
{
const rndis_msg *rndis_hdr;
const struct rndis_comp_hdr *comp;
const struct rndis_msghdr *hdr;
rndis_hdr = data;
switch (rndis_hdr->ndis_msg_type) {
/* data message */
if (__predict_false(dlen < sizeof(*hdr))) {
if_printf(rxr->hn_ifp, "invalid RNDIS msg\n");
return;
}
hdr = data;
switch (hdr->rm_type) {
case REMOTE_NDIS_PACKET_MSG:
hv_rf_receive_data(rxr, data, dlen);
break;
/* completion messages */
case REMOTE_NDIS_INITIALIZE_CMPLT:
case REMOTE_NDIS_QUERY_CMPLT:
case REMOTE_NDIS_SET_CMPLT:
case REMOTE_NDIS_KEEPALIVE_CMPLT:
case REMOTE_NDIS_KEEPALIVE_CMPLT: /* unused */
if (dlen < sizeof(*comp)) {
if_printf(rxr->hn_ifp, "invalid RNDIS cmplt\n");
return;
}
comp = data;
KASSERT(comp->rm_rid > HN_RNDIS_RID_COMPAT_MAX,
("invalid rid 0x%08x\n", comp->rm_rid));
("invalid RNDIS rid 0x%08x\n", comp->rm_rid));
vmbus_xact_ctx_wakeup(sc->hn_xact, comp, dlen);
break;
/* notification message */
case REMOTE_NDIS_INDICATE_STATUS_MSG:
hv_rf_receive_indicate_status(sc, rndis_hdr);
hv_rf_receive_indicate_status(sc, data, dlen);
break;
case REMOTE_NDIS_RESET_CMPLT:
@ -321,15 +336,14 @@ hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
* RESET is not issued by hn(4), so this message should
* _not_ be observed.
*/
if_printf(sc->hn_ifp, "RESET CMPLT received\n");
if_printf(rxr->hn_ifp, "RESET cmplt received\n");
break;
default:
if_printf(sc->hn_ifp, "unknown RNDIS message 0x%x\n",
rndis_hdr->ndis_msg_type);
if_printf(rxr->hn_ifp, "unknown RNDIS msg 0x%x\n",
hdr->rm_type);
break;
}
return (0);
}
/*

View File

@ -40,7 +40,7 @@
*/
struct hn_rx_ring;
int hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
void hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
const void *data, int dlen);
void hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr);
int hv_rf_on_device_add(struct hn_softc *sc, void *additl_info, int *nchan,

View File

@ -721,7 +721,20 @@ vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0,
error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt));
if (error)
return error;
return (error);
if (__predict_false(pkt.cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) {
device_printf(chan->ch_dev, "invalid hlen %u\n",
pkt.cph_hlen);
/* XXX this channel is dead actually. */
return (EIO);
}
if (__predict_false(pkt.cph_hlen > pkt.cph_tlen)) {
device_printf(chan->ch_dev, "invalid hlen %u and tlen %u\n",
pkt.cph_hlen, pkt.cph_tlen);
/* XXX this channel is dead actually. */
return (EIO);
}
hlen = VMBUS_CHANPKT_GETLEN(pkt.cph_hlen);
dlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen) - hlen;
@ -729,7 +742,7 @@ vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0,
if (*dlen0 < dlen) {
/* Return the size of this packet's data. */
*dlen0 = dlen;
return ENOBUFS;
return (ENOBUFS);
}
*xactid = pkt.cph_xactid;
@ -739,7 +752,7 @@ vmbus_chan_recv(struct vmbus_channel *chan, void *data, int *dlen0,
error = vmbus_rxbr_read(&chan->ch_rxbr, data, dlen, hlen);
KASSERT(!error, ("vmbus_rxbr_read failed"));
return 0;
return (0);
}
int
@ -751,13 +764,26 @@ vmbus_chan_recv_pkt(struct vmbus_channel *chan,
error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt));
if (error)
return error;
return (error);
if (__predict_false(pkt.cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) {
device_printf(chan->ch_dev, "invalid hlen %u\n",
pkt.cph_hlen);
/* XXX this channel is dead actually. */
return (EIO);
}
if (__predict_false(pkt.cph_hlen > pkt.cph_tlen)) {
device_printf(chan->ch_dev, "invalid hlen %u and tlen %u\n",
pkt.cph_hlen, pkt.cph_tlen);
/* XXX this channel is dead actually. */
return (EIO);
}
pktlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen);
if (*pktlen0 < pktlen) {
/* Return the size of this packet. */
*pktlen0 = pktlen;
return ENOBUFS;
return (ENOBUFS);
}
*pktlen0 = pktlen;
@ -765,7 +791,7 @@ vmbus_chan_recv_pkt(struct vmbus_channel *chan,
error = vmbus_rxbr_read(&chan->ch_rxbr, pkt0, pktlen, 0);
KASSERT(!error, ("vmbus_rxbr_read failed"));
return 0;
return (0);
}
static void

View File

@ -153,6 +153,9 @@ do { \
#define VMBUS_CHANPKT_TOTLEN(tlen) \
roundup2((tlen), VMBUS_CHANPKT_SIZE_ALIGN)
#define VMBUS_CHANPKT_HLEN_MIN \
(sizeof(struct vmbus_chanpkt_hdr) >> VMBUS_CHANPKT_SIZE_SHIFT)
struct vmbus_chanpkt {
struct vmbus_chanpkt_hdr cp_hdr;
} __packed;

302
sys/dev/iicbus/sy8106a.c Normal file
View File

@ -0,0 +1,302 @@
/*-
* Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
* 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 ``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$
*/
/*
* Silergy Corp. SY8106A buck regulator
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/kernel.h>
#include <sys/reboot.h>
#include <sys/module.h>
#include <dev/iicbus/iicbus.h>
#include <dev/iicbus/iiconf.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/extres/regulator/regulator.h>
#include "iicbus_if.h"
#include "regdev_if.h"
#define VOUT1_SEL 0x01
#define SEL_GO (1 << 7)
#define SEL_VOLTAGE_MASK 0x7f
#define SEL_VOLTAGE_BASE 680000 /* uV */
#define SEL_VOLTAGE_STEP 10000 /* uV */
#define VOUT_COM 0x02
#define COM_DISABLE (1 << 0)
#define SYS_STATUS 0x06
static struct ofw_compat_data compat_data[] = {
{ "silergy,sy8106a", 1 },
{ NULL, 0 }
};
struct sy8106a_reg_sc {
struct regnode *regnode;
device_t base_dev;
phandle_t xref;
struct regnode_std_param *param;
};
struct sy8106a_softc {
uint16_t addr;
/* Regulator */
struct sy8106a_reg_sc *reg;
};
static int
sy8106a_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
{
struct sy8106a_softc *sc;
struct iic_msg msg[2];
sc = device_get_softc(dev);
msg[0].slave = sc->addr;
msg[0].flags = IIC_M_WR;
msg[0].len = 1;
msg[0].buf = &reg;
msg[1].slave = sc->addr;
msg[1].flags = IIC_M_RD;
msg[1].len = size;
msg[1].buf = data;
return (iicbus_transfer(dev, msg, 2));
}
static int
sy8106a_write(device_t dev, uint8_t reg, uint8_t val)
{
struct sy8106a_softc *sc;
struct iic_msg msg;
uint8_t buffer[2];
sc = device_get_softc(dev);
buffer[0] = reg;
buffer[1] = val;
msg.slave = sc->addr;
msg.flags = IIC_M_WR;
msg.len = 2;
msg.buf = buffer;
return (iicbus_transfer(dev, &msg, 1));
}
static int
sy8106a_regnode_init(struct regnode *regnode)
{
return (0);
}
static int
sy8106a_regnode_enable(struct regnode *regnode, bool enable, int *udelay)
{
struct sy8106a_reg_sc *sc;
uint8_t val;
sc = regnode_get_softc(regnode);
sy8106a_read(sc->base_dev, VOUT_COM, &val, 1);
if (enable)
val &= ~COM_DISABLE;
else
val |= COM_DISABLE;
sy8106a_write(sc->base_dev, VOUT_COM, val);
*udelay = sc->param->ramp_delay;
return (0);
}
static int
sy8106a_regnode_set_voltage(struct regnode *regnode, int min_uvolt,
int max_uvolt, int *udelay)
{
struct sy8106a_reg_sc *sc;
int cur_uvolt;
uint8_t val, oval;
sc = regnode_get_softc(regnode);
/* Get current voltage */
sy8106a_read(sc->base_dev, VOUT1_SEL, &oval, 1);
cur_uvolt = (oval & SEL_VOLTAGE_MASK) * SEL_VOLTAGE_STEP +
SEL_VOLTAGE_BASE;
/* Set new voltage */
val = SEL_GO | ((min_uvolt - SEL_VOLTAGE_BASE) / SEL_VOLTAGE_STEP);
sy8106a_write(sc->base_dev, VOUT1_SEL, val);
/* Time to delay is based on the number of voltage steps */
*udelay = sc->param->ramp_delay *
(abs(cur_uvolt - min_uvolt) / SEL_VOLTAGE_STEP);
return (0);
}
static int
sy8106a_regnode_get_voltage(struct regnode *regnode, int *uvolt)
{
struct sy8106a_reg_sc *sc;
uint8_t val;
sc = regnode_get_softc(regnode);
sy8106a_read(sc->base_dev, VOUT1_SEL, &val, 1);
*uvolt = (val & SEL_VOLTAGE_MASK) * SEL_VOLTAGE_STEP +
SEL_VOLTAGE_BASE;
return (0);
}
static regnode_method_t sy8106a_regnode_methods[] = {
/* Regulator interface */
REGNODEMETHOD(regnode_init, sy8106a_regnode_init),
REGNODEMETHOD(regnode_enable, sy8106a_regnode_enable),
REGNODEMETHOD(regnode_set_voltage, sy8106a_regnode_set_voltage),
REGNODEMETHOD(regnode_get_voltage, sy8106a_regnode_get_voltage),
REGNODEMETHOD_END
};
DEFINE_CLASS_1(sy8106a_regnode, sy8106a_regnode_class, sy8106a_regnode_methods,
sizeof(struct sy8106a_reg_sc), regnode_class);
static struct sy8106a_reg_sc *
sy8106a_reg_attach(device_t dev, phandle_t node)
{
struct sy8106a_reg_sc *reg_sc;
struct regnode_init_def initdef;
struct regnode *regnode;
memset(&initdef, 0, sizeof(initdef));
regulator_parse_ofw_stdparam(dev, node, &initdef);
initdef.id = 0;
initdef.ofw_node = node;
regnode = regnode_create(dev, &sy8106a_regnode_class, &initdef);
if (regnode == NULL) {
device_printf(dev, "cannot create regulator\n");
return (NULL);
}
reg_sc = regnode_get_softc(regnode);
reg_sc->regnode = regnode;
reg_sc->base_dev = dev;
reg_sc->xref = OF_xref_from_node(node);
reg_sc->param = regnode_get_stdparam(regnode);
regnode_register(regnode);
return (reg_sc);
}
static int
sy8106a_regdev_map(device_t dev, phandle_t xref, int ncells, pcell_t *cells,
intptr_t *num)
{
struct sy8106a_softc *sc;
sc = device_get_softc(dev);
if (sc->reg->xref != xref)
return (ENXIO);
*num = 0;
return (0);
}
static int
sy8106a_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
device_set_desc(dev, "Silergy SY8106A regulator");
return (BUS_PROBE_DEFAULT);
}
static int
sy8106a_attach(device_t dev)
{
struct sy8106a_softc *sc;
phandle_t node;
sc = device_get_softc(dev);
node = ofw_bus_get_node(dev);
sc->addr = iicbus_get_addr(dev);
sc->reg = sy8106a_reg_attach(dev, node);
if (sc->reg == NULL) {
device_printf(dev, "cannot attach regulator\n");
return (ENXIO);
}
return (0);
}
static device_method_t sy8106a_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, sy8106a_probe),
DEVMETHOD(device_attach, sy8106a_attach),
/* Regdev interface */
DEVMETHOD(regdev_map, sy8106a_regdev_map),
DEVMETHOD_END
};
static driver_t sy8106a_driver = {
"sy8106a",
sy8106a_methods,
sizeof(struct sy8106a_softc),
};
static devclass_t sy8106a_devclass;
EARLY_DRIVER_MODULE(sy8106a, iicbus, sy8106a_driver, sy8106a_devclass, 0, 0,
BUS_PASS_RESOURCE);
MODULE_VERSION(sy8106a, 1);
MODULE_DEPEND(sy8106a, iicbus, 1, 1, 1);

View File

@ -1245,7 +1245,7 @@ usb_temp_setup(struct usb_device *udev,
return (0);
/* Protect scratch area */
do_unlock = usbd_enum_lock(udev);
do_unlock = usbd_ctrl_lock(udev);
uts = udev->scratch.temp_setup;
@ -1324,7 +1324,7 @@ usb_temp_setup(struct usb_device *udev,
if (error)
usb_temp_unsetup(udev);
if (do_unlock)
usbd_enum_unlock(udev);
usbd_ctrl_unlock(udev);
return (error);
}

View File

@ -1585,6 +1585,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
/* initialise our SX-lock */
sx_init_flags(&udev->enum_sx, "USB config SX lock", SX_DUPOK);
sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS);
sx_init_flags(&udev->ctrl_sx, "USB control transfer SX lock", SX_DUPOK);
cv_init(&udev->ctrlreq_cv, "WCTRL");
cv_init(&udev->ref_cv, "UGONE");
@ -1770,7 +1771,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
*/
/* Protect scratch area */
do_unlock = usbd_enum_lock(udev);
do_unlock = usbd_ctrl_lock(udev);
scratch_ptr = udev->scratch.data;
@ -1821,7 +1822,7 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
}
if (do_unlock)
usbd_enum_unlock(udev);
usbd_ctrl_unlock(udev);
/* assume 100mA bus powered for now. Changed when configured. */
udev->power = USB_MIN_POWER;
@ -2195,6 +2196,7 @@ usb_free_device(struct usb_device *udev, uint8_t flag)
sx_destroy(&udev->enum_sx);
sx_destroy(&udev->sr_sx);
sx_destroy(&udev->ctrl_sx);
cv_destroy(&udev->ctrlreq_cv);
cv_destroy(&udev->ref_cv);
@ -2358,7 +2360,7 @@ usbd_set_device_strings(struct usb_device *udev)
uint8_t do_unlock;
/* Protect scratch area */
do_unlock = usbd_enum_lock(udev);
do_unlock = usbd_ctrl_lock(udev);
temp_ptr = (char *)udev->scratch.data;
temp_size = sizeof(udev->scratch.data);
@ -2418,7 +2420,7 @@ usbd_set_device_strings(struct usb_device *udev)
}
if (do_unlock)
usbd_enum_unlock(udev);
usbd_ctrl_unlock(udev);
}
/*
@ -2824,6 +2826,40 @@ usbd_enum_is_locked(struct usb_device *udev)
return (sx_xlocked(&udev->enum_sx));
}
/*
* The following function is used to serialize access to USB control
* transfers and the USB scratch area. If the lock is already grabbed
* this function returns zero. Else a value of one is returned.
*/
uint8_t
usbd_ctrl_lock(struct usb_device *udev)
{
if (sx_xlocked(&udev->ctrl_sx))
return (0);
sx_xlock(&udev->ctrl_sx);
/*
* We need to allow suspend and resume at this point, else the
* control transfer will timeout if the device is suspended!
*/
if (usbd_enum_is_locked(udev))
usbd_sr_unlock(udev);
return (1);
}
void
usbd_ctrl_unlock(struct usb_device *udev)
{
sx_xunlock(&udev->ctrl_sx);
/*
* Restore the suspend and resume lock after we have unlocked
* the USB control transfer lock to avoid LOR:
*/
if (usbd_enum_is_locked(udev))
usbd_sr_lock(udev);
}
/*
* The following function is used to set the per-interface specific
* plug and play information. The string referred to by the pnpinfo

View File

@ -162,7 +162,7 @@ struct usb_temp_setup {
/*
* The scratch area for USB devices. Access to this structure is
* protected by the enumeration SX lock.
* protected by the control SX lock.
*/
union usb_device_scratch {
struct usb_hw_ep_scratch hw_ep_scratch[1];
@ -183,6 +183,7 @@ struct usb_device {
struct usb_udev_msg cs_msg[2];
struct sx enum_sx;
struct sx sr_sx;
struct sx ctrl_sx;
struct mtx device_mtx;
struct cv ctrlreq_cv;
struct cv ref_cv;
@ -320,6 +321,8 @@ uint8_t usbd_enum_lock_sig(struct usb_device *);
void usbd_enum_unlock(struct usb_device *);
void usbd_sr_lock(struct usb_device *);
void usbd_sr_unlock(struct usb_device *);
uint8_t usbd_ctrl_lock(struct usb_device *);
void usbd_ctrl_unlock(struct usb_device *);
uint8_t usbd_enum_is_locked(struct usb_device *);
#if USB_HAVE_TT_SUPPORT

View File

@ -714,16 +714,16 @@ ugen_get_cdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
return (error);
}
/*
* This function is called having the enumeration SX locked which
* protects the scratch area used.
*/
static int
ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
{
void *ptr;
uint16_t size;
int error;
uint8_t do_unlock;
/* Protect scratch area */
do_unlock = usbd_ctrl_lock(f->udev);
ptr = f->udev->scratch.data;
size = sizeof(f->udev->scratch.data);
@ -744,6 +744,9 @@ ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
error = copyout(ptr, ugd->ugd_data, size);
}
if (do_unlock)
usbd_ctrl_unlock(f->udev);
return (error);
}

View File

@ -460,16 +460,9 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx,
}
/*
* Grab the USB device enumeration SX-lock serialization is
* achieved when multiple threads are involved:
* Serialize access to this function:
*/
do_unlock = usbd_enum_lock(udev);
/*
* We need to allow suspend and resume at this point, else the
* control transfer will timeout if the device is suspended!
*/
usbd_sr_unlock(udev);
do_unlock = usbd_ctrl_lock(udev);
hr_func = usbd_get_hr_func(udev);
@ -713,10 +706,8 @@ usbd_do_request_flags(struct usb_device *udev, struct mtx *mtx,
USB_XFER_UNLOCK(xfer);
done:
usbd_sr_lock(udev);
if (do_unlock)
usbd_enum_unlock(udev);
usbd_ctrl_unlock(udev);
if ((mtx != NULL) && (mtx != &Giant))
mtx_lock(mtx);

View File

@ -953,7 +953,7 @@ usbd_transfer_setup(struct usb_device *udev,
return (error);
/* Protect scratch area */
do_unlock = usbd_enum_lock(udev);
do_unlock = usbd_ctrl_lock(udev);
refcount = 0;
info = NULL;
@ -1274,7 +1274,7 @@ usbd_transfer_setup(struct usb_device *udev,
error = parm->err;
if (do_unlock)
usbd_enum_unlock(udev);
usbd_ctrl_unlock(udev);
return (error);
}

View File

@ -98,7 +98,7 @@ device_set_usb_desc(device_t dev)
}
/* Protect scratch area */
do_unlock = usbd_enum_lock(udev);
do_unlock = usbd_ctrl_lock(udev);
temp_p = (char *)udev->scratch.data;
@ -115,7 +115,7 @@ device_set_usb_desc(device_t dev)
}
if (do_unlock)
usbd_enum_unlock(udev);
usbd_ctrl_unlock(udev);
device_set_desc_copy(dev, temp_p);
device_printf(dev, "<%s> on %s\n", temp_p,

View File

@ -19,3 +19,8 @@ mips/broadcom/bcm_mipscore.c standard
# TODO: Replace with BCM47xx/57xx/etc-aware geom_map
geom/geom_flashmap.c standard
# USB bits
dev/bhnd/cores/usb/bhnd_usb.c optional usb
dev/bhnd/cores/usb/bhnd_ehci.c optional ehci
dev/bhnd/cores/usb/bhnd_ohci.c optional ohci

View File

@ -94,8 +94,16 @@ device miibus # attachments
# pci devices
# USB is not yet ready
#options USB_DEBUG # enable debug msgs
#device usb # USB Bus (required)
#device uhci # UHCI PCI->USB interface
#device ehci # EHCI PCI->USB interface (USB 2.0)
# USB
options USB_DEBUG # enable debug msgs
# taken from atheros
options USB_EHCI_BIG_ENDIAN_DESC # handle big-endian byte order
options USB_HOST_ALIGN=32 # AR71XX (MIPS in general?) requires this
device usb # USB Bus (required)
device ohci # OHCI interface
device ehci # EHCI interface (USB 2.0)
device scbus
device umass
device da

View File

@ -295,9 +295,28 @@ struct rndis_reset_comp {
uint32_t rm_adrreset;
};
/* 802.3 link-state or undefined message error. */
/* 802.3 link-state or undefined message error. Sent by device. */
#define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007
struct rndis_status_msg {
uint32_t rm_type;
uint32_t rm_len;
uint32_t rm_status;
uint32_t rm_stbuflen;
uint32_t rm_stbufoffset;
/* rndis_diag_info */
};
/*
* Immediately after rndis_status_msg.rm_stbufoffset, if a control
* message is malformatted, or a packet message contains inappropriate
* content.
*/
struct rndis_diag_info {
uint32_t rm_diagstatus;
uint32_t rm_erroffset;
};
/* Keepalive messsage. May be sent by device. */
#define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008
#define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008

View File

@ -2073,6 +2073,8 @@ pmap_page_is_mapped(vm_page_t m)
return (rv);
}
#define PMAP_TS_REFERENCED_MAX 5
/*
* Return a count of reference bits for a page, clearing those bits.
* It is not necessary for every reference bit to be cleared, but it
@ -2082,6 +2084,14 @@ pmap_page_is_mapped(vm_page_t m)
* XXX: The exact number of bits to check and clear is a matter that
* should be tested and standardized at some point in the future for
* optimal aging of shared pages.
*
* As an optimization, update the page's dirty field if a modified bit is
* found while counting reference bits. This opportunistic update can be
* performed at low cost and can eliminate the need for some future calls
* to pmap_is_modified(). However, since this function stops after
* finding PMAP_TS_REFERENCED_MAX reference bits, it may not detect some
* dirty pages. Those dirty pages will only be detected by a future call
* to pmap_is_modified().
*/
int
pmap_ts_referenced(vm_page_t m)
@ -2105,7 +2115,10 @@ pmap_ts_referenced(vm_page_t m)
if ((tp->tte_data & TD_PV) == 0)
continue;
data = atomic_clear_long(&tp->tte_data, TD_REF);
if ((data & TD_REF) != 0 && ++count > 4)
if ((data & TD_W) != 0)
vm_page_dirty(m);
if ((data & TD_REF) != 0 && ++count >=
PMAP_TS_REFERENCED_MAX)
break;
} while ((tp = tpn) != NULL && tp != tpf);
}

View File

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

View File

@ -69,7 +69,9 @@ static int namelength = 8;
#endif
/* TOP_JID_LEN based on max of 999999 */
#define TOP_JID_LEN 7
#define TOP_SWAP_LEN 6
static int jidlength;
static int swaplength;
static int cmdlengthdelta;
/* Prototypes for top internals */
@ -111,20 +113,20 @@ static char io_header[] =
"%5d%*s %-*.*s %6ld %6ld %6ld %6ld %6ld %6ld %6.2f%% %.*s"
static char smp_header_thr[] =
" PID%*s %-*.*s THR PRI NICE SIZE RES STATE C TIME %7s COMMAND";
" PID%*s %-*.*s THR PRI NICE SIZE RES%*s STATE C TIME %7s COMMAND";
static char smp_header[] =
" PID%*s %-*.*s " "PRI NICE SIZE RES STATE C TIME %7s COMMAND";
" PID%*s %-*.*s " "PRI NICE SIZE RES%*s STATE C TIME %7s COMMAND";
#define smp_Proc_format \
"%5d%*s %-*.*s %s%3d %4s%7s %6s %-6.6s %2d%7s %6.2f%% %.*s"
"%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s %2d%7s %6.2f%% %.*s"
static char up_header_thr[] =
" PID%*s %-*.*s THR PRI NICE SIZE RES STATE TIME %7s COMMAND";
" PID%*s %-*.*s THR PRI NICE SIZE RES%*s STATE TIME %7s COMMAND";
static char up_header[] =
" PID%*s %-*.*s " "PRI NICE SIZE RES STATE TIME %7s COMMAND";
" PID%*s %-*.*s " "PRI NICE SIZE RES%*s STATE TIME %7s COMMAND";
#define up_Proc_format \
"%5d%*s %-*.*s %s%3d %4s%7s %6s %-6.6s%.0d%7s %6.2f%% %.*s"
"%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s%.0d%7s %6.2f%% %.*s"
/* process state names for the "STATE" column of the display */
@ -227,6 +229,10 @@ static int pageshift; /* log base 2 of the pagesize */
#define pagetok(size) ((size) << pageshift)
/* swap usage */
#define ki_swap(kip) \
((kip)->ki_swrss > (kip)->ki_rssize ? (kip)->ki_swrss - (kip)->ki_rssize : 0)
/* useful externals */
long percentages();
@ -237,7 +243,7 @@ long percentages();
char *ordernames[] = {
"cpu", "size", "res", "time", "pri", "threads",
"total", "read", "write", "fault", "vcsw", "ivcsw",
"jid", "pid", NULL
"jid", "swap", "pid", NULL
};
#endif
@ -252,6 +258,7 @@ static long *pcpu_cp_old;
static long *pcpu_cp_diff;
static int *pcpu_cpu_states;
static int compare_swap(const void *a, const void *b);
static int compare_jid(const void *a, const void *b);
static int compare_pid(const void *a, const void *b);
static int compare_tid(const void *a, const void *b);
@ -412,6 +419,11 @@ format_header(char *uname_field)
else
jidlength = 0;
if (ps.swap)
swaplength = TOP_SWAP_LEN + 1; /* +1 for extra left space */
else
swaplength = 0;
switch (displaymode) {
case DISP_CPU:
/*
@ -426,6 +438,7 @@ format_header(char *uname_field)
snprintf(Header, sizeof(Header), prehead,
jidlength, ps.jail ? " JID" : "",
namelength, namelength, uname_field,
swaplength, ps.swap ? " SWAP" : "",
ps.wcpu ? "WCPU" : "CPU");
break;
case DISP_IO:
@ -902,7 +915,8 @@ format_next_process(caddr_t handle, char *(*get_userid)(int), int flags)
int cpu, state;
struct rusage ru, *rup;
long p_tot, s_tot;
char *proc_fmt, thr_buf[6], jid_buf[TOP_JID_LEN + 1];
char *proc_fmt, thr_buf[6];
char jid_buf[TOP_JID_LEN + 1], swap_buf[TOP_SWAP_LEN + 1];
char *cmdbuf = NULL;
char **args;
const int cmdlen = 128;
@ -1061,6 +1075,13 @@ format_next_process(caddr_t handle, char *(*get_userid)(int), int flags)
snprintf(jid_buf, sizeof(jid_buf), "%*d",
jidlength - 1, pp->ki_jid);
if (ps.swap == 0)
swap_buf[0] = '\0';
else
snprintf(swap_buf, sizeof(swap_buf), "%*s",
swaplength - 1,
format_k2(pagetok(ki_swap(pp)))); /* XXX */
if (displaymode == DISP_IO) {
oldp = get_old_proc(pp);
if (oldp != NULL) {
@ -1122,6 +1143,7 @@ format_next_process(caddr_t handle, char *(*get_userid)(int), int flags)
format_nice(pp),
format_k2(PROCSIZE(pp)),
format_k2(pagetok(pp->ki_rssize)),
swaplength, swaplength, swap_buf,
status,
cpu,
format_time(cputime),
@ -1309,6 +1331,12 @@ static int sorted_state[] = {
return (diff > 0 ? 1 : -1); \
} while (0)
#define ORDERKEY_SWAP(a, b) do { \
int diff = (int)ki_swap(b) - (int)ki_swap(a); \
if (diff != 0) \
return (diff > 0 ? 1 : -1); \
} while (0)
/* compare_cpu - the comparison function for sorting by cpu percentage */
int
@ -1357,6 +1385,7 @@ int (*compares[])() = {
compare_vcsw,
compare_ivcsw,
compare_jid,
compare_swap,
NULL
};
@ -1467,6 +1496,24 @@ compare_jid(const void *arg1, const void *arg2)
return (0);
}
/* compare_swap - the comparison function for sorting by swap */
static int
compare_swap(const void *arg1, const void *arg2)
{
struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
ORDERKEY_SWAP(p1, p2);
ORDERKEY_PCTCPU(p1, p2);
ORDERKEY_CPTICKS(p1, p2);
ORDERKEY_STATE(p1, p2);
ORDERKEY_PRIO(p1, p2);
ORDERKEY_RSSIZE(p1, p2);
ORDERKEY_MEM(p1, p2);
return (0);
}
#endif /* ORDER */
/* assorted comparison functions for sorting by i/o */

View File

@ -617,6 +617,20 @@ gpart_edit(struct gprovider *pp)
if (choice) /* Cancel pressed */
goto endedit;
/* If this is the root partition, check that this fs is bootable */
if (strcmp(items[2].text, "/") == 0 && !is_fs_bootable(scheme,
items[0].text)) {
char message[512];
sprintf(message, "This file system (%s) is not bootable "
"on this system. Are you sure you want to proceed?",
items[0].text);
dialog_vars.defaultno = TRUE;
choice = dialog_yesno("Warning", message, 0, 0);
dialog_vars.defaultno = FALSE;
if (choice == 1) /* cancel */
goto editpart;
}
/* Check if the label has a / in it */
if (strchr(items[3].text, '/') != NULL) {
dialog_msgbox("Error", "Label contains a /, which is not an "