Merge ^/head r305397 through r305430.
This commit is contained in:
commit
1839de1a4b
@ -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.
|
||||
|
@ -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.
|
222
contrib/libarchive/README.md
Normal file
222
contrib/libarchive/README.md
Normal 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.
|
||||
|
@ -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++;
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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 @@ restart:
|
||||
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');
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -369,7 +369,6 @@ fail:
|
||||
else
|
||||
printf("\n** DUMP FAILED (ERROR %d) **\n", error);
|
||||
return (error);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
|
267
sys/dev/bhnd/cores/usb/bhnd_ehci.c
Normal file
267
sys/dev/bhnd/cores/usb/bhnd_ehci.c
Normal 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);
|
228
sys/dev/bhnd/cores/usb/bhnd_ohci.c
Normal file
228
sys/dev/bhnd/cores/usb/bhnd_ohci.c
Normal 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);
|
487
sys/dev/bhnd/cores/usb/bhnd_usb.c
Normal file
487
sys/dev/bhnd/cores/usb/bhnd_usb.c
Normal 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);
|
59
sys/dev/bhnd/cores/usb/bhnd_usbvar.h
Normal file
59
sys/dev/bhnd/cores/usb/bhnd_usbvar.h
Normal 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_ */
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
302
sys/dev/iicbus/sy8106a.c
Normal 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 = ®
|
||||
|
||||
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);
|
@ -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 @@ done:
|
||||
if (error)
|
||||
usb_temp_unsetup(udev);
|
||||
if (do_unlock)
|
||||
usbd_enum_unlock(udev);
|
||||
usbd_ctrl_unlock(udev);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 @@ done:
|
||||
error = parm->err;
|
||||
|
||||
if (do_unlock)
|
||||
usbd_enum_unlock(udev);
|
||||
usbd_ctrl_unlock(udev);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -617,6 +617,20 @@ editpart:
|
||||
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 "
|
||||
|
Loading…
x
Reference in New Issue
Block a user