MFC
This commit is contained in:
commit
17028bb6ae
11
UPDATING
11
UPDATING
@ -26,6 +26,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10.x IS SLOW:
|
||||
disable the most expensive debugging functionality run
|
||||
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
||||
|
||||
20130301:
|
||||
The ctl device has been disabled in GENERIC for i386 and amd64.
|
||||
This was done due to the extra memory being allocated at system
|
||||
initialisation time by the ctl driver which was only used if
|
||||
a CAM target device was created. This makes a FreeBSD system
|
||||
unusable on 128MB or less of RAM.
|
||||
|
||||
20130208:
|
||||
A new compression method (lz4) has been merged to -HEAD. Please
|
||||
refer to zpool-features(7) for more information.
|
||||
@ -46,8 +53,8 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10.x IS SLOW:
|
||||
unlikely event that -M was the last option on the command line
|
||||
and the command line contained at least two files and a target
|
||||
directory the first file will have logs appended to it. The -M
|
||||
option served little practical purpose in the last decade so it's
|
||||
used expected to be extremely rare.
|
||||
option served little practical purpose in the last decade so its
|
||||
use is expected to be extremely rare.
|
||||
|
||||
20121223:
|
||||
After switching to Clang as the default compiler some users of ZFS
|
||||
|
@ -526,6 +526,39 @@ if the snapshot has been marked for deferred destroy by using the
|
||||
.Qq Nm Cm destroy -d
|
||||
command. Otherwise, the property is
|
||||
.Cm off .
|
||||
.It Sy logicalreferenced
|
||||
The amount of space that is
|
||||
.Qq logically
|
||||
accessible by this dataset.
|
||||
See the
|
||||
.Sy referenced
|
||||
property.
|
||||
The logical space ignores the effect of the
|
||||
.Sy compression
|
||||
and
|
||||
.Sy copies
|
||||
properties, giving a quantity closer to the amount of data that applications
|
||||
see.
|
||||
However, it does include space consumed by metadata.
|
||||
.Pp
|
||||
This property can also be referred to by its shortened column name,
|
||||
.Sy lrefer .
|
||||
.It Sy logicalused
|
||||
The amount of space that is
|
||||
.Qq logically
|
||||
consumed by this dataset and all its descendents.
|
||||
See the
|
||||
.Sy used
|
||||
property.
|
||||
The logical space ignores the effect of the
|
||||
.Sy compression
|
||||
and
|
||||
.Sy copies
|
||||
properties, giving a quantity closer to the amount of data that applications
|
||||
see.
|
||||
.Pp
|
||||
This property can also be referred to by its shortened column name,
|
||||
.Sy lused .
|
||||
.It Sy mounted
|
||||
For file systems, indicates whether the file system is currently mounted. This
|
||||
property can be either
|
||||
|
@ -24,6 +24,7 @@
|
||||
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2011 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _LIBFS_IMPL_H
|
||||
@ -216,6 +217,7 @@ extern void libzfs_fru_clear(libzfs_handle_t *, boolean_t);
|
||||
|
||||
#ifndef sun
|
||||
static int zfs_kernel_version = 0;
|
||||
static int zfs_ioctl_version = 0;
|
||||
|
||||
/*
|
||||
* This is FreeBSD version of ioctl, because Solaris' ioctl() updates
|
||||
@ -225,19 +227,34 @@ static int zfs_kernel_version = 0;
|
||||
static __inline int
|
||||
zcmd_ioctl(int fd, unsigned long cmd, zfs_cmd_t *zc)
|
||||
{
|
||||
size_t oldsize, zfs_kernel_version_size;
|
||||
size_t oldsize, zfs_kernel_version_size, zfs_ioctl_version_size;
|
||||
int version, ret, cflag = ZFS_CMD_COMPAT_NONE;
|
||||
|
||||
zfs_kernel_version_size = sizeof(zfs_kernel_version);
|
||||
if (zfs_kernel_version == 0) {
|
||||
sysctlbyname("vfs.zfs.version.spa", &zfs_kernel_version,
|
||||
&zfs_kernel_version_size, NULL, 0);
|
||||
zfs_ioctl_version_size = sizeof(zfs_ioctl_version);
|
||||
if (zfs_ioctl_version == 0) {
|
||||
sysctlbyname("vfs.zfs.version.ioctl", &zfs_ioctl_version,
|
||||
&zfs_ioctl_version_size, NULL, 0);
|
||||
}
|
||||
|
||||
if (zfs_kernel_version == SPA_VERSION_15 ||
|
||||
zfs_kernel_version == SPA_VERSION_14 ||
|
||||
zfs_kernel_version == SPA_VERSION_13)
|
||||
cflag = ZFS_CMD_COMPAT_V15;
|
||||
/*
|
||||
* If vfs.zfs.version.ioctl is not defined, assume we have v28
|
||||
* compatible binaries and use vfs.zfs.version.spa to test for v15
|
||||
*/
|
||||
if (zfs_ioctl_version < ZFS_IOCVER_DEADMAN) {
|
||||
cflag = ZFS_CMD_COMPAT_V28;
|
||||
zfs_kernel_version_size = sizeof(zfs_kernel_version);
|
||||
|
||||
if (zfs_kernel_version == 0) {
|
||||
sysctlbyname("vfs.zfs.version.spa",
|
||||
&zfs_kernel_version,
|
||||
&zfs_kernel_version_size, NULL, 0);
|
||||
}
|
||||
|
||||
if (zfs_kernel_version == SPA_VERSION_15 ||
|
||||
zfs_kernel_version == SPA_VERSION_14 ||
|
||||
zfs_kernel_version == SPA_VERSION_13)
|
||||
cflag = ZFS_CMD_COMPAT_V15;
|
||||
}
|
||||
|
||||
oldsize = zc->zc_nvlist_dst_size;
|
||||
ret = zcmd_ioctl_compat(fd, cmd, zc, cflag);
|
||||
|
@ -394,6 +394,7 @@ read_thread_wait(void)
|
||||
|
||||
mtx_lock(&adist_remote_mtx);
|
||||
if (adhost->adh_reset) {
|
||||
reset:
|
||||
adhost->adh_reset = false;
|
||||
if (trail_filefd(adist_trail) != -1)
|
||||
trail_close(adist_trail);
|
||||
@ -408,6 +409,14 @@ read_thread_wait(void)
|
||||
while (trail_filefd(adist_trail) == -1) {
|
||||
newfile = true;
|
||||
wait_for_dir();
|
||||
/*
|
||||
* We may have been disconnected and reconnected in the
|
||||
* meantime, check if reset is set.
|
||||
*/
|
||||
mtx_lock(&adist_remote_mtx);
|
||||
if (adhost->adh_reset)
|
||||
goto reset;
|
||||
mtx_unlock(&adist_remote_mtx);
|
||||
if (trail_filefd(adist_trail) == -1)
|
||||
trail_next(adist_trail);
|
||||
}
|
||||
|
@ -548,7 +548,7 @@
|
||||
43184:AUE_OPENAT:openat(2) - attr only:fa
|
||||
43185:AUE_POSIX_OPENPT:posix_openpt(2):ip
|
||||
43186:AUE_CAP_NEW:cap_new(2):fm
|
||||
43187:AUE_CAP_GETRIGHTS:cap_getrights(2):fm
|
||||
43187:AUE_CAP_RIGHTS_GET:cap_rights_get(2):fm
|
||||
43188:AUE_CAP_ENTER:cap_enter(2):pc
|
||||
43189:AUE_CAP_GETMODE:cap_getmode(2):pc
|
||||
43190:AUE_POSIX_SPAWN:posix_spawn(2):pc
|
||||
@ -563,6 +563,11 @@
|
||||
43199:AUE_PDGETPID:pdgetpid(2):pc
|
||||
43200:AUE_PDWAIT:pdwait(2):pc
|
||||
43201:AUE_WAIT6:wait6(2):pc
|
||||
43202:AUE_CAP_RIGHTS_LIMIT:cap_rights_limit(2):fm
|
||||
43203:AUE_CAP_IOCTLS_LIMIT:cap_ioctls_limit(2):fm
|
||||
43204:AUE_CAP_IOCTLS_GET:cap_ioctls_get(2):fm
|
||||
43205:AUE_CAP_FCNTLS_LIMIT:cap_fcntls_limit(2):fm
|
||||
43206:AUE_CAP_FCNTLS_GET:cap_fcntls_get(2):fm
|
||||
#
|
||||
# Solaris userspace events.
|
||||
#
|
||||
|
@ -16,6 +16,7 @@ SRCS+= __getosreldate.c \
|
||||
assert.c \
|
||||
auxv.c \
|
||||
basename.c \
|
||||
cap_sandboxed.c \
|
||||
check_utility_compat.c \
|
||||
clock.c \
|
||||
clock_getcpuclockid.c \
|
||||
@ -168,6 +169,7 @@ SYM_MAPS+=${.CURDIR}/gen/Symbol.map
|
||||
MAN+= alarm.3 \
|
||||
arc4random.3 \
|
||||
basename.3 \
|
||||
cap_sandboxed.3 \
|
||||
check_utility_compat.3 \
|
||||
clock.3 \
|
||||
clock_getcpuclockid.3 \
|
||||
|
70
lib/libc/gen/cap_sandboxed.3
Normal file
70
lib/libc/gen/cap_sandboxed.3
Normal file
@ -0,0 +1,70 @@
|
||||
.\" Copyright (c) 2012 The FreeBSD Foundation
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
|
||||
.\" from the FreeBSD Foundation.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 18, 2012
|
||||
.Dt CAP_SANDBOXED 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm cap_sandboxed
|
||||
.Nd Check if in a capability mode sandbox
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In sys/capability.h
|
||||
.In stdbool.h
|
||||
.Ft bool
|
||||
.Fn cap_sandboxed "void"
|
||||
.Sh DESCRIPTION
|
||||
.Fn cap_sandboxed
|
||||
returns
|
||||
.Va true
|
||||
if the process is in a capability mode sandbox or
|
||||
.Va false
|
||||
if it is not.
|
||||
This function is a more handy alternative to the
|
||||
.Xr cap_getmode 2
|
||||
system call as it always succeeds, so there is no need for error checking.
|
||||
If the support for capability mode is not compiled into the kernel,
|
||||
.Fn cap_sandboxed
|
||||
will always return
|
||||
.Va false .
|
||||
.Sh RETURN VALUES
|
||||
Function
|
||||
.Fn cap_sandboxed
|
||||
is always successful and will return either
|
||||
.Va true
|
||||
or
|
||||
.Va false .
|
||||
.Sh SEE ALSO
|
||||
.Xr cap_enter 2 ,
|
||||
.Xr capsicum 4
|
||||
.Sh AUTHORS
|
||||
This function was implemented and manual page was written by
|
||||
.An Pawel Jakub Dawidek Aq pawel@dawidek.net
|
||||
under sponsorship of the FreeBSD Foundation.
|
50
lib/libc/gen/cap_sandboxed.c
Normal file
50
lib/libc/gen/cap_sandboxed.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*-
|
||||
* Copyright (c) 2012 The FreeBSD Foundation
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by Pawel Jakub Dawidek under sponsorship from
|
||||
* the FreeBSD Foundation.
|
||||
*
|
||||
* 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 AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/capability.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool
|
||||
cap_sandboxed(void)
|
||||
{
|
||||
u_int mode;
|
||||
|
||||
if (cap_getmode(&mode) != 0) {
|
||||
assert(errno == ENOSYS);
|
||||
return (false);
|
||||
}
|
||||
assert(mode == 0 || mode == 1);
|
||||
return (mode == 1);
|
||||
}
|
@ -42,6 +42,8 @@ __sym_compat(__semctl, freebsd7___semctl, FBSD_1.0);
|
||||
__sym_compat(msgctl, freebsd7_msgctl, FBSD_1.0);
|
||||
__sym_compat(shmctl, freebsd7_shmctl, FBSD_1.0);
|
||||
|
||||
__sym_compat(cap_getrights, cap_rights_get, FBSD_1.2);
|
||||
|
||||
#undef __sym_compat
|
||||
|
||||
#endif /* __LIBC_COMPAT_H__ */
|
||||
|
@ -1212,7 +1212,7 @@ CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max)
|
||||
}
|
||||
cs->ranges = newranges;
|
||||
cs->ranges[cs->nranges].min = min;
|
||||
cs->ranges[cs->nranges].min = max;
|
||||
cs->ranges[cs->nranges].max = max;
|
||||
cs->nranges++;
|
||||
}
|
||||
|
||||
|
@ -260,7 +260,7 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
|
||||
if (ct->ct_addr.buf == NULL)
|
||||
goto err;
|
||||
memcpy(ct->ct_addr.buf, raddr->buf, raddr->len);
|
||||
ct->ct_addr.len = raddr->maxlen;
|
||||
ct->ct_addr.len = raddr->len;
|
||||
ct->ct_addr.maxlen = raddr->maxlen;
|
||||
|
||||
/*
|
||||
|
@ -93,7 +93,9 @@ MAN+= abort2.2 \
|
||||
bind.2 \
|
||||
brk.2 \
|
||||
cap_enter.2 \
|
||||
cap_new.2 \
|
||||
cap_fcntls_limit.2 \
|
||||
cap_ioctls_limit.2 \
|
||||
cap_rights_limit.2 \
|
||||
chdir.2 \
|
||||
chflags.2 \
|
||||
chmod.2 \
|
||||
@ -270,7 +272,9 @@ MLINKS+=access.2 eaccess.2 \
|
||||
access.2 faccessat.2
|
||||
MLINKS+=brk.2 sbrk.2
|
||||
MLINKS+=cap_enter.2 cap_getmode.2
|
||||
MLINKS+=cap_new.2 cap_getrights.2
|
||||
MLINKS+=cap_fcntls_limit.2 cap_fcntls_get.2
|
||||
MLINKS+=cap_ioctls_limit.2 cap_ioctls_get.2
|
||||
MLINKS+=cap_rights_limit.2 cap_rights_get.2
|
||||
MLINKS+=chdir.2 fchdir.2
|
||||
MLINKS+=chflags.2 fchflags.2 \
|
||||
chflags.2 lchflags.2
|
||||
|
@ -364,7 +364,6 @@ FBSD_1.2 {
|
||||
cap_enter;
|
||||
cap_getmode;
|
||||
cap_new;
|
||||
cap_getrights;
|
||||
getloginclass;
|
||||
pdfork;
|
||||
pdgetpid;
|
||||
@ -379,6 +378,13 @@ FBSD_1.2 {
|
||||
};
|
||||
|
||||
FBSD_1.3 {
|
||||
cap_fcntls_get;
|
||||
cap_fcntls_limit;
|
||||
cap_ioctls_get;
|
||||
cap_ioctls_limit;
|
||||
cap_rights_get;
|
||||
cap_rights_limit;
|
||||
cap_sandboxed;
|
||||
clock_getcpuclockid2;
|
||||
ffclock_getcounter;
|
||||
ffclock_getestimate;
|
||||
|
@ -58,8 +58,10 @@ or
|
||||
.Xr pdfork 2
|
||||
will be placed in capability mode from inception.
|
||||
.Pp
|
||||
When combined with capabilities created with
|
||||
.Xr cap_new 2 ,
|
||||
When combined with
|
||||
.Xr cap_rights_limit 2 ,
|
||||
.Xr cap_ioctls_limit 2 ,
|
||||
.Xr cap_fcntls_limit 2 ,
|
||||
.Fn cap_enter
|
||||
may be used to create kernel-enforced sandboxes in which
|
||||
appropriately-crafted applications or application components may be run.
|
||||
@ -71,11 +73,6 @@ sandbox.
|
||||
Creating effective process sandboxes is a tricky process that involves
|
||||
identifying the least possible rights required by the process and then
|
||||
passing those rights into the process in a safe manner.
|
||||
See the CAVEAT
|
||||
section of
|
||||
.Xr cap_new 2
|
||||
for why this is particularly tricky with UNIX file descriptors as the
|
||||
canonical representation of a right.
|
||||
Consumers of
|
||||
.Fn cap_enter
|
||||
should also be aware of other inherited rights, such as access to VM
|
||||
@ -87,9 +84,35 @@ to create a runtime environment inside the sandbox that has as few implicitly
|
||||
acquired rights as possible.
|
||||
.Sh RETURN VALUES
|
||||
.Rv -std cap_enter cap_getmode
|
||||
.Sh ERRORS
|
||||
The
|
||||
.Fn cap_enter
|
||||
and
|
||||
.Fn cap_getmode
|
||||
system calls
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er ENOSYS
|
||||
The kernel is compiled without:
|
||||
.Pp
|
||||
.Cd "options CAPABILITY_MODE"
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn cap_getmode
|
||||
system call may also return the following error:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EFAULT
|
||||
Pointer
|
||||
.Fa modep
|
||||
points outside the process's allocated address space.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr cap_new 2 ,
|
||||
.Xr cap_fcntls_limit 2 ,
|
||||
.Xr cap_ioctls_limit 2 ,
|
||||
.Xr cap_rights_limit 2 ,
|
||||
.Xr fexecve 2 ,
|
||||
.Xr cap_sandboxed 3 ,
|
||||
.Xr capsicum 4
|
||||
.Sh HISTORY
|
||||
Support for capabilities and capabilities mode was developed as part of the
|
||||
|
126
lib/libc/sys/cap_fcntls_limit.2
Normal file
126
lib/libc/sys/cap_fcntls_limit.2
Normal file
@ -0,0 +1,126 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2012 The FreeBSD Foundation
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
|
||||
.\" the FreeBSD Foundation.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 20, 2012
|
||||
.Dt CAP_FCNTLS_LIMIT 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm cap_fcntls_limit ,
|
||||
.Nm cap_fcntls_get
|
||||
.Nd manage allowed fcntl commands
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In sys/capability.h
|
||||
.Ft int
|
||||
.Fn cap_fcntls_limit "int fd" "uint32_t fcntlrights"
|
||||
.Ft int
|
||||
.Fn cap_fcntls_get "int fd" "uint32_t *fcntlrightsp"
|
||||
.Sh DESCRIPTION
|
||||
If a file descriptor is granted the
|
||||
.Dv CAP_FCNTL
|
||||
capability right, the list of allowed
|
||||
.Xr fcntl 2
|
||||
commands can be selectively reduced (but never expanded) with the
|
||||
.Fn cap_fcntls_limit
|
||||
system call.
|
||||
.Pp
|
||||
A bitmask of allowed fcntls commands for a given file descriptor can be obtained
|
||||
with the
|
||||
.Fn cap_fcntls_get
|
||||
system call.
|
||||
.Sh FLAGS
|
||||
The following flags may be specified in the
|
||||
.Fa fcntlrights
|
||||
argument or returned in the
|
||||
.Fa fcntlrightsp
|
||||
argument:
|
||||
.Bl -tag -width CAP_FCNTL_GETOWN
|
||||
.It Dv CAP_FCNTL_GETFL
|
||||
Permit
|
||||
.Dv F_GETFL
|
||||
command.
|
||||
.It Dv CAP_FCNTL_SETFL
|
||||
Permit
|
||||
.Dv F_SETFL
|
||||
command.
|
||||
.It Dv CAP_FCNTL_GETOWN
|
||||
Permit
|
||||
.Dv F_GETOWN
|
||||
command.
|
||||
.It Dv CAP_FCNTL_SETOWN
|
||||
Permit
|
||||
.Dv F_SETOWN
|
||||
command.
|
||||
.El
|
||||
.Sh RETURN VALUES
|
||||
.Rv -std
|
||||
.Sh ERRORS
|
||||
.Fn cap_fcntls_limit
|
||||
succeeds unless:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBADF
|
||||
The
|
||||
.Fa fd
|
||||
argument is not a valid descriptor.
|
||||
.It Bq Er EINVAL
|
||||
An invalid flag has been passed in
|
||||
.Fa fcntlrights .
|
||||
.It Bq Er ENOTCAPABLE
|
||||
.Fa fcntlrights
|
||||
would expand the list of allowed
|
||||
.Xr fcntl 2
|
||||
commands.
|
||||
.El
|
||||
.Pp
|
||||
.Fn cap_fcntls_get
|
||||
succeeds unless:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBADF
|
||||
The
|
||||
.Fa fd
|
||||
argument is not a valid descriptor.
|
||||
.It Bq Er EFAULT
|
||||
The
|
||||
.Fa fcntlrightsp
|
||||
argument points at an invalid address.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr cap_ioctls_limit 2 ,
|
||||
.Xr cap_rights_limit 2 ,
|
||||
.Xr fcntl 2
|
||||
.Sh HISTORY
|
||||
Support for capabilities and capabilities mode was developed as part of the
|
||||
.Tn TrustedBSD
|
||||
Project.
|
||||
.Sh AUTHORS
|
||||
This function was created by
|
||||
.An Pawel Jakub Dawidek Aq pawel@dawidek.net
|
||||
under sponsorship of the FreeBSD Foundation.
|
157
lib/libc/sys/cap_ioctls_limit.2
Normal file
157
lib/libc/sys/cap_ioctls_limit.2
Normal file
@ -0,0 +1,157 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2012 The FreeBSD Foundation
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
|
||||
.\" the FreeBSD Foundation.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 20, 2012
|
||||
.Dt CAP_IOCTLS_LIMIT 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm cap_ioctls_limit ,
|
||||
.Nm cap_ioctls_get
|
||||
.Nd manage allowed ioctl commands
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In sys/capability.h
|
||||
.Ft int
|
||||
.Fn cap_ioctls_limit "int fd" "const unsigned long *cmds" "size_t ncmds"
|
||||
.Ft ssize_t
|
||||
.Fn cap_ioctls_get "int fd" "unsigned long *cmds" "size_t maxcmds"
|
||||
.Sh DESCRIPTION
|
||||
If a file descriptor is granted the
|
||||
.Dv CAP_IOCTL
|
||||
capability right, the list of allowed
|
||||
.Xr ioctl 2
|
||||
commands can be selectively reduced (but never expanded) with the
|
||||
.Fn cap_ioctls_limit
|
||||
system call.
|
||||
The
|
||||
.Fa cmds
|
||||
argument is an array of
|
||||
.Xr ioctl 2
|
||||
commands and the
|
||||
.Fa ncmds
|
||||
argument specifies the number of elements in the array.
|
||||
There might be up to
|
||||
.Va 256
|
||||
elements in the array.
|
||||
.Pp
|
||||
The list of allowed ioctl commands for a given file descriptor can be obtained
|
||||
with the
|
||||
.Fn cap_ioctls_get
|
||||
system call.
|
||||
The
|
||||
.Fa cmds
|
||||
argument points at memory that can hold up to
|
||||
.Fa maxcmds
|
||||
values.
|
||||
The function populates the provided buffer with up to
|
||||
.Fa maxcmds
|
||||
elements, but always returns the total number of ioctl commands allowed for the
|
||||
given file descriptor.
|
||||
The total number of ioctls commands for the given file descriptor can be
|
||||
obtained by passing
|
||||
.Dv NULL as the
|
||||
.Fa cmds
|
||||
argument and
|
||||
.Va 0
|
||||
as the
|
||||
.Fa maxcmds
|
||||
argument.
|
||||
If all ioctl commands are allowed
|
||||
.Dv ( CAP_IOCTL
|
||||
capability right is assigned to the file descriptor and the
|
||||
.Fn cap_ioctls_limit
|
||||
system call was never called for this file descriptor), the
|
||||
.Fn cap_ioctls_get
|
||||
system call will return
|
||||
.Dv CAP_IOCTLS_ALL
|
||||
and won't modify the buffer pointed out by the
|
||||
.Fa cmds
|
||||
argument.
|
||||
.Sh RETURN VALUES
|
||||
.Rv -std cap_ioctls_limit
|
||||
.Pp
|
||||
The
|
||||
.Fn cap_ioctls_limit
|
||||
function, if successfull, returns the total number of allowed ioctl commands or
|
||||
the value
|
||||
.Dv INT_MAX
|
||||
if all ioctls commands are allowed.
|
||||
On failure the value
|
||||
.Va -1
|
||||
is returned and the global variable errno is set to indicate the error.
|
||||
.Sh ERRORS
|
||||
.Fn cap_ioctls_limit
|
||||
succeeds unless:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBADF
|
||||
The
|
||||
.Fa fd
|
||||
argument is not a valid descriptor.
|
||||
.It Bq Er EFAULT
|
||||
The
|
||||
.Fa cmds
|
||||
argument points at an invalid address.
|
||||
.It Bq Er EINVAL
|
||||
The
|
||||
.Fa ncmds
|
||||
argument is greater than
|
||||
.Va 256 .
|
||||
.It Bq Er ENOTCAPABLE
|
||||
.Fa cmds
|
||||
would expand the list of allowed
|
||||
.Xr ioctl 2
|
||||
commands.
|
||||
.El
|
||||
.Pp
|
||||
.Fn cap_ioctls_get
|
||||
succeeds unless:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBADF
|
||||
The
|
||||
.Fa fd
|
||||
argument is not a valid descriptor.
|
||||
.It Bq Er EFAULT
|
||||
The
|
||||
.Fa cmds
|
||||
argument points at invalid address.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr cap_fcntls_limit 2 ,
|
||||
.Xr cap_rights_limit 2 ,
|
||||
.Xr ioctl 2
|
||||
.Sh HISTORY
|
||||
Support for capabilities and capabilities mode was developed as part of the
|
||||
.Tn TrustedBSD
|
||||
Project.
|
||||
.Sh AUTHORS
|
||||
This function was created by
|
||||
.An Pawel Jakub Dawidek Aq pawel@dawidek.net
|
||||
under sponsorship of the FreeBSD Foundation.
|
@ -1,10 +1,14 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2008-2010 Robert N. M. Watson
|
||||
.\" Copyright (c) 2012-2013 The FreeBSD Foundation
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This software was developed at the University of Cambridge Computer
|
||||
.\" Laboratory with support from a grant from Google, Inc.
|
||||
.\"
|
||||
.\" Portions of this documentation were written by Pawel Jakub Dawidek
|
||||
.\" under sponsorship from the FreeBSD Foundation.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
@ -28,76 +32,48 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 20, 2011
|
||||
.Dt CAP_NEW 2
|
||||
.Dd February 23, 2013
|
||||
.Dt CAP_RIGHTS_LIMIT 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm cap_new ,
|
||||
.Nm cap_getrights
|
||||
.Nd System calls to manipulate capabilities
|
||||
.Nm cap_rights_limit ,
|
||||
.Nm cap_rights_get
|
||||
.Nd manage capability rights
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In sys/capability.h
|
||||
.Ft int
|
||||
.Fn cap_new "int fd" "cap_rights_t rights"
|
||||
.Fn cap_rights_limit "int fd" "cap_rights_t rights"
|
||||
.Ft int
|
||||
.Fn cap_getrights "int fd" "cap_rights_t *rightsp"
|
||||
.Fn cap_rights_get "int fd" "cap_rights_t *rightsp"
|
||||
.Sh DESCRIPTION
|
||||
Capabilities are special file descriptors derived from an existing file
|
||||
descriptor, such as one returned by
|
||||
When a file descriptor is created by a function such as
|
||||
.Xr fhopen 2 ,
|
||||
.Xr kqueue 2 ,
|
||||
.Xr mq_open 2 ,
|
||||
.Xr open 2 ,
|
||||
.Xr openat 2 ,
|
||||
.Xr pdfork 2 ,
|
||||
.Xr pipe 2 ,
|
||||
.Xr shm_open 2 ,
|
||||
.Xr socket 2 ,
|
||||
or
|
||||
.Xr socketpair 2 ,
|
||||
but with a restricted set of permitted operations determined by a rights
|
||||
mask set when the capability is created.
|
||||
These restricted rights cannot be changed after the capability is created,
|
||||
although further capabilities with yet more restricted rights may be created
|
||||
from an existing capability.
|
||||
In every other sense, a capability behaves in the same way as the file
|
||||
descriptor it was created from.
|
||||
it is assigned all capability rights.
|
||||
Those rights can be reduced (but never expanded) by using the
|
||||
.Fn cap_rights_limit
|
||||
system call.
|
||||
Once capability rights are reduced, operations on the file descriptor will be
|
||||
limited to those permitted by
|
||||
.Fa rights .
|
||||
.Pp
|
||||
.Fn cap_new
|
||||
creates a new capability for the existing file descriptor
|
||||
.Fa fd ,
|
||||
and returns a file descriptor for it.
|
||||
Operations on the capability will be limited to those permitted by
|
||||
.Fa rights ,
|
||||
which is static for the lifetime of the capability.
|
||||
If
|
||||
.Fa fd
|
||||
refers to an existing capability, then
|
||||
.Fa rights
|
||||
must be equal to or a subset of the rights on that capability.
|
||||
As with
|
||||
.Xr dup 2
|
||||
and
|
||||
.Xr dup2 2 ,
|
||||
many properties are shared between the new capability and the existing file
|
||||
descriptor, including open file flags, blocking disposition, and file offset.
|
||||
Many applications will prefer to use the
|
||||
.Xr cap_limitfd 3
|
||||
library call, part of
|
||||
.Xr libcapsicum 3 ,
|
||||
as it offers a more convenient interface.
|
||||
.Pp
|
||||
.Fn cap_getrights
|
||||
queries the rights associated with the capability referred to by file
|
||||
descriptor
|
||||
.Fa fd .
|
||||
.Pp
|
||||
These system calls, when combined with
|
||||
.Xr cap_enter 2 ,
|
||||
may be used to construct process sandboxes with highly granular rights
|
||||
assignment.
|
||||
A bitmask of capability rights assigned to a file descriptor can be obtained with
|
||||
the
|
||||
.Fn cap_rights_get
|
||||
system call.
|
||||
.Sh RIGHTS
|
||||
The following rights may be specified in a new capability rights mask:
|
||||
The following rights may be specified in a rights mask:
|
||||
.Bl -tag -width CAP_EXTATTR_DELETE
|
||||
.It Dv CAP_ACCEPT
|
||||
Permit
|
||||
@ -134,6 +110,13 @@ Permit
|
||||
also required for
|
||||
.Xr sendto 2
|
||||
with a non-NULL destination address.
|
||||
.It Dv CAP_CREATE
|
||||
Permit
|
||||
.Xr openat 2
|
||||
with the
|
||||
.Dv O_CREAT
|
||||
flag.
|
||||
.\" XXXPJD: Doesn't exist anymore.
|
||||
.It Dv CAP_EVENT
|
||||
Permit
|
||||
.Xr select 2 ,
|
||||
@ -143,7 +126,12 @@ and
|
||||
to be used in monitoring the file descriptor for events.
|
||||
.It Dv CAP_FEXECVE
|
||||
Permit
|
||||
.Xr fexecve 2 ;
|
||||
.Xr fexecve 2
|
||||
and
|
||||
.Xr openat 2
|
||||
with the
|
||||
.Dv O_EXEC
|
||||
flag;
|
||||
.Dv CAP_READ
|
||||
will also be required.
|
||||
.It Dv CAP_EXTATTR_DELETE
|
||||
@ -166,19 +154,49 @@ Permit
|
||||
.Xr fchflags 2 .
|
||||
.It Dv CAP_FCHMOD
|
||||
Permit
|
||||
.Xr fchmod 2 .
|
||||
.Xr fchmod 2
|
||||
and
|
||||
.Xr fchmodat 2 .
|
||||
.It Dv CAP_FCHMODAT
|
||||
An alias to
|
||||
.Dv CAP_FCHMOD .
|
||||
.It Dv CAP_FCHOWN
|
||||
Permit
|
||||
.Xr fchown 2 .
|
||||
.Xr fchown 2
|
||||
and
|
||||
.Xr fchownat 2 .
|
||||
.It Dv CAP_FCHOWNAT
|
||||
An alias to
|
||||
.Dv CAP_FCHOWN .
|
||||
.It Dv CAP_FCNTL
|
||||
Permit
|
||||
.Xr fcntl 2 ;
|
||||
be aware that this call provides indirect access to other operations, such as
|
||||
.Xr flock 2 .
|
||||
.Xr fcntl 2 .
|
||||
Note that only the
|
||||
.Dv F_GETFL ,
|
||||
.Dv F_SETFL ,
|
||||
.Dv F_GETOWN
|
||||
and
|
||||
.Dv F_SETOWN
|
||||
commands require this capability right.
|
||||
Also note that the list of permitted commands can be further limited with the
|
||||
.Xr cap_fcntls_limit 2
|
||||
system call.
|
||||
.It Dv CAP_FLOCK
|
||||
Permit
|
||||
.Xr flock 2
|
||||
and related calls.
|
||||
.Xr flock 2 ,
|
||||
.Xr fcntl 2
|
||||
(with
|
||||
.Dv F_GETLK ,
|
||||
.Dv F_SETLK
|
||||
or
|
||||
.Dv F_SETLKW
|
||||
flag) and
|
||||
.Xr openat 2
|
||||
(with
|
||||
.Dv O_EXLOCK
|
||||
or
|
||||
.Dv O_SHLOCK
|
||||
flag).
|
||||
.It Dv CAP_FPATHCONF
|
||||
Permit
|
||||
.Xr fpathconf 2 .
|
||||
@ -186,22 +204,42 @@ Permit
|
||||
Permit UFS background-fsck operations on the descriptor.
|
||||
.It Dv CAP_FSTAT
|
||||
Permit
|
||||
.Xr fstat 2 .
|
||||
.Xr fstat 2
|
||||
and
|
||||
.Xr fstatat 2 .
|
||||
.It Dv CAP_FSTATAT
|
||||
An alias to
|
||||
.Dv CAP_FSTAT .
|
||||
.It Dv CAP_FSTATFS
|
||||
Permit
|
||||
.Xr fstatfs 2 .
|
||||
.It Dv CAP_FSYNC
|
||||
Permit
|
||||
.Xr aio_fsync 2
|
||||
.Xr aio_fsync 2 ,
|
||||
.Xr fsync 2
|
||||
and
|
||||
.Xr fsync 2 .
|
||||
.Pp
|
||||
.Xr openat 2
|
||||
with
|
||||
.Dv O_FSYNC
|
||||
or
|
||||
.Dv O_SYNC
|
||||
flag.
|
||||
.It Dv CAP_FTRUNCATE
|
||||
Permit
|
||||
.Xr ftruncate 2 .
|
||||
.Xr ftruncate 2
|
||||
and
|
||||
.Xr openat 2
|
||||
with the
|
||||
.Dv O_TRUNC
|
||||
flag.
|
||||
.It Dv CAP_FUTIMES
|
||||
Permit
|
||||
.Xr futimes 2 .
|
||||
.Xr futimes 2
|
||||
and
|
||||
.Xr futimesat 2 .
|
||||
.It Dv CAP_FUTIMESAT
|
||||
An alias to
|
||||
.Dv CAP_FUTIMES .
|
||||
.It Dv CAP_GETPEERNAME
|
||||
Permit
|
||||
.Xr getpeername 2 .
|
||||
@ -216,42 +254,106 @@ Permit
|
||||
.Xr ioctl 2 .
|
||||
Be aware that this system call has enormous scope, including potentially
|
||||
global scope for some objects.
|
||||
The list of permitted ioctl commands can be further limited with the
|
||||
.Xr cap_ioctls_limit 2
|
||||
system call.
|
||||
.\" XXXPJD: Doesn't exist anymore.
|
||||
.It Dv CAP_KEVENT
|
||||
Permit
|
||||
.Xr kevent 2 ;
|
||||
.Dv CAP_EVENT
|
||||
is also required on file descriptors that will be monitored using
|
||||
.Xr kevent 2 .
|
||||
.It Dv CAP_LINKAT
|
||||
Permit
|
||||
.Xr linkat 2
|
||||
and
|
||||
.Xr renameat 2 .
|
||||
This right is required for the destination directory descriptor.
|
||||
.It Dv CAP_LISTEN
|
||||
Permit
|
||||
.Xr listen 2 ;
|
||||
not much use (generally) without
|
||||
.Dv CAP_BIND .
|
||||
.It Dv CAP_LOOKUP
|
||||
Permit the file descriptor to be used as a starting directory for calls such
|
||||
as
|
||||
Permit the file descriptor to be used as a starting directory for calls such as
|
||||
.Xr linkat 2 ,
|
||||
.Xr openat 2 ,
|
||||
and
|
||||
.Xr unlinkat 2 .
|
||||
Note that these calls are not available in capability mode as they manipulate
|
||||
a global name space; see
|
||||
.Xr cap_enter 2
|
||||
for details.
|
||||
.It Dv CAP_MAC_GET
|
||||
Permit
|
||||
.Xr mac_get_fd 3 .
|
||||
.It Dv CAP_MAC_SET
|
||||
Permit
|
||||
.Xr mac_set_fd 3 .
|
||||
.It Dv CAP_MKDIRAT
|
||||
Permit
|
||||
.Xr mkdirat 2 .
|
||||
.It Dv CAP_MKFIFOAT
|
||||
Permit
|
||||
.Xr mkfifoat 2 .
|
||||
.It Dv CAP_MKNODAT
|
||||
Permit
|
||||
.Xr mknodat 2 .
|
||||
.It Dv CAP_MMAP
|
||||
Permit
|
||||
.Xr mmap 2 ;
|
||||
specific invocations may also require
|
||||
.Xr mmap 2
|
||||
with the
|
||||
.Dv PROT_NONE
|
||||
protection.
|
||||
.It Dv CAP_MMAP_R
|
||||
Permit
|
||||
.Xr mmap 2
|
||||
with the
|
||||
.Dv PROT_READ
|
||||
protection.
|
||||
This also implies
|
||||
.Dv CAP_READ
|
||||
or
|
||||
.Dv CAP_WRITE .
|
||||
.Pp
|
||||
and
|
||||
.Dv CAP_SEEK
|
||||
rights.
|
||||
.It Dv CAP_MMAP_W
|
||||
Permit
|
||||
.Xr mmap 2
|
||||
with the
|
||||
.Dv PROT_WRITE
|
||||
protection.
|
||||
This also implies
|
||||
.Dv CAP_WRITE
|
||||
and
|
||||
.Dv CAP_SEEK
|
||||
rights.
|
||||
.It Dv CAP_MMAP_X
|
||||
Permit
|
||||
.Xr mmap 2
|
||||
with the
|
||||
.Dv PROT_EXEC
|
||||
protection.
|
||||
This also implies
|
||||
.Dv CAP_SEEK
|
||||
right.
|
||||
.It Dv CAP_MMAP_RW
|
||||
Implies
|
||||
.Dv CAP_MMAP_R
|
||||
and
|
||||
.Dv CAP_MMAP_W .
|
||||
.It Dv CAP_MMAP_RX
|
||||
Implies
|
||||
.Dv CAP_MMAP_R
|
||||
and
|
||||
.Dv CAP_MMAP_X .
|
||||
.It Dv CAP_MMAP_WX
|
||||
Implies
|
||||
.Dv CAP_MMAP_W
|
||||
and
|
||||
.Dv CAP_MMAP_X .
|
||||
.It Dv CAP_MMAP_RWX
|
||||
Implies
|
||||
.Dv CAP_MMAP_R ,
|
||||
.Dv CAP_MMAP_W
|
||||
and
|
||||
.Dv CAP_MMAP_X .
|
||||
.It Dv CAP_PDGETPID
|
||||
Permit
|
||||
.Xr pdgetpid 2 .
|
||||
@ -264,30 +366,46 @@ Permit
|
||||
.It Dv CAP_PEELOFF
|
||||
Permit
|
||||
.Xr sctp_peeloff 2 .
|
||||
.\" XXXPJD: Not documented.
|
||||
.It Dv CAP_POLL_EVENT
|
||||
.\" XXXPJD: Not documented.
|
||||
.It Dv CAP_POST_EVENT
|
||||
.It Dv CAP_PREAD
|
||||
Implies
|
||||
.Dv CAP_SEEK
|
||||
and
|
||||
.Dv CAP_READ .
|
||||
.It Dv CAP_PWRITE
|
||||
Implies
|
||||
.Dv CAP_SEEK
|
||||
and
|
||||
.Dv CAP_WRITE .
|
||||
.It Dv CAP_READ
|
||||
Allow
|
||||
.Xr aio_read 2 ,
|
||||
.Xr pread 2 ,
|
||||
.Xr openat
|
||||
with the
|
||||
.Dv O_RDONLY flag,
|
||||
.Xr read 2 ,
|
||||
.Xr recv 2 ,
|
||||
.Xr recvfrom 2 ,
|
||||
.Xr recvmsg 2 ,
|
||||
.Xr recvmsg 2
|
||||
and related system calls.
|
||||
.Pp
|
||||
For files and other seekable objects,
|
||||
.Dv CAP_SEEK
|
||||
may also be required.
|
||||
.It Dv CAP_REVOKE
|
||||
.It Dv CAP_RECV
|
||||
An alias to
|
||||
.Dv CAP_READ .
|
||||
.It Dv CAP_RENAMEAT
|
||||
Permit
|
||||
.Xr frevoke 2
|
||||
in certain ABI compatibility modes that support this system call.
|
||||
.Xr renameat 2 .
|
||||
This right is required for the source directory descriptor.
|
||||
.It Dv CAP_SEEK
|
||||
Permit operations that seek on the file descriptor, such as
|
||||
.Xr lseek 2 ,
|
||||
but also required for I/O system calls that modify the file offset, such as
|
||||
.Xr read 2
|
||||
but also required for I/O system calls that can read or write at any position
|
||||
in the file, such as
|
||||
.Xr pread 2
|
||||
and
|
||||
.Xr write 2 .
|
||||
.Xr pwrite 2 .
|
||||
.It Dv CAP_SEM_GETVALUE
|
||||
Permit
|
||||
.Xr sem_getvalue 3 .
|
||||
@ -299,6 +417,9 @@ Permit
|
||||
.Xr sem_wait 3
|
||||
and
|
||||
.Xr sem_trywait 3 .
|
||||
.It Dv CAP_SEND
|
||||
An alias to
|
||||
.Dv CAP_WRITE .
|
||||
.It Dv CAP_SETSOCKOPT
|
||||
Permit
|
||||
.Xr setsockopt 2 ;
|
||||
@ -308,49 +429,56 @@ connecting, and other behaviors with global scope.
|
||||
Permit explicit
|
||||
.Xr shutdown 2 ;
|
||||
closing the socket will also generally shut down any connections on it.
|
||||
.It Dv CAP_SYMLINKAT
|
||||
Permit
|
||||
.Xr symlinkat 2 .
|
||||
.It Dv CAP_TTYHOOK
|
||||
Allow configuration of TTY hooks, such as
|
||||
.Xr snp 4 ,
|
||||
on the file descriptor.
|
||||
.It Dv CAP_UNLINKAT
|
||||
Permit
|
||||
.Xr unlinkat 2
|
||||
and
|
||||
.Xr renameat 2 .
|
||||
This right is only required for
|
||||
.Xr renameat 2
|
||||
on the destination directory descriptor if the destination object already
|
||||
exists and will be removed by the rename.
|
||||
.It Dv CAP_WRITE
|
||||
Allow
|
||||
.Xr aio_write 2 ,
|
||||
.Xr pwrite 2 ,
|
||||
.Xr openat 2
|
||||
with
|
||||
.Dv O_WRONLY
|
||||
and
|
||||
.Dv O_APPEND
|
||||
flags,
|
||||
.Xr send 2 ,
|
||||
.Xr sendmsg 2 ,
|
||||
.Xr sendto 2 ,
|
||||
.Xr write 2 ,
|
||||
and related system calls.
|
||||
.Pp
|
||||
For files and other seekable objects,
|
||||
.Dv CAP_SEEK
|
||||
may also be required.
|
||||
.Pp
|
||||
For
|
||||
.Xr sendto 2
|
||||
with a non-NULL connection address,
|
||||
.Dv CAP_CONNECT
|
||||
is also required.
|
||||
For
|
||||
.Xr openat 2
|
||||
with the
|
||||
.Dv O_WRONLY
|
||||
flag, but without the
|
||||
.Dv O_APPEND
|
||||
flag,
|
||||
.Dv CAP_SEEK
|
||||
is also required.
|
||||
.El
|
||||
.Sh CAVEAT
|
||||
The
|
||||
.Fn cap_new
|
||||
system call and the capabilities it creates may be used to assign
|
||||
fine-grained rights to sandboxed processes running in capability mode.
|
||||
However, the semantics of objects accessed via file descriptors are complex,
|
||||
so caution should be exercised in passing object capabilities into sandboxes.
|
||||
.Sh RETURN VALUES
|
||||
If successful,
|
||||
.Fn cap_new
|
||||
returns a non-negative integer, termed a file descriptor.
|
||||
It returns -1 on failure, and sets
|
||||
.Va errno
|
||||
to indicate the error.
|
||||
.Pp
|
||||
.Rv -std cap_getrights
|
||||
.Rv -std
|
||||
.Sh ERRORS
|
||||
.Fn cap_new
|
||||
may return the following errors:
|
||||
.Fn cap_rights_limit
|
||||
succeeds unless:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBADF
|
||||
The
|
||||
@ -359,29 +487,23 @@ argument is not a valid active descriptor.
|
||||
.It Bq Er EINVAL
|
||||
An invalid right has been requested in
|
||||
.Fa rights .
|
||||
.It Bq Er EMFILE
|
||||
The process has already reached its limit for open file descriptors.
|
||||
.It Bq Er ENFILE
|
||||
The system file table is full.
|
||||
.It Bq Er EPERM
|
||||
.It Bq Er ENOTCAPABLE
|
||||
.Fa rights
|
||||
contains requested rights not present in the current rights mask associated
|
||||
with the capability referenced by
|
||||
.Fa fd ,
|
||||
if any.
|
||||
with the given file descriptor.
|
||||
.El
|
||||
.Pp
|
||||
.Fn cap_getrights
|
||||
may return the following errors:
|
||||
.Fn cap_rights_get
|
||||
succeeds unless:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBADF
|
||||
The
|
||||
.Fa fd
|
||||
argument is not a valid active descriptor.
|
||||
.It Bq Er EINVAL
|
||||
.It Bq Er EFAULT
|
||||
The
|
||||
.Fa fd
|
||||
argument is not a capability.
|
||||
.Fa rightsp
|
||||
argument points at an invalid address.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr accept 2 ,
|
||||
@ -390,6 +512,9 @@ argument is not a capability.
|
||||
.Xr aio_write 2 ,
|
||||
.Xr bind 2 ,
|
||||
.Xr cap_enter 2 ,
|
||||
.Xr cap_fcntls_limit 2 ,
|
||||
.Xr cap_ioctls_limit 2 ,
|
||||
.Xr cap_rights_limit 2 ,
|
||||
.Xr connect 2 ,
|
||||
.Xr dup 2 ,
|
||||
.Xr dup2 2 ,
|
||||
@ -421,6 +546,7 @@ argument is not a capability.
|
||||
.Xr mq_open 2 ,
|
||||
.Xr open 2 ,
|
||||
.Xr openat 2 ,
|
||||
.Xr pdfork 2 ,
|
||||
.Xr pdgetpid 2 ,
|
||||
.Xr pdkill 2 ,
|
||||
.Xr pdwait4 2 ,
|
||||
@ -432,6 +558,7 @@ argument is not a capability.
|
||||
.Xr recv 2 ,
|
||||
.Xr recvfrom 2 ,
|
||||
.Xr recvmsg 2 ,
|
||||
.Xr renameat 2 ,
|
||||
.Xr sctp_peeloff 2 ,
|
||||
.Xr select 2 ,
|
||||
.Xr send 2 ,
|
||||
@ -442,6 +569,7 @@ argument is not a capability.
|
||||
.Xr shutdown 2 ,
|
||||
.Xr socket 2 ,
|
||||
.Xr socketpair 2 ,
|
||||
.Xr symlinkat 2 ,
|
||||
.Xr unlinkat 2 ,
|
||||
.Xr write 2 ,
|
||||
.Xr acl_delete_fd_np 3 ,
|
||||
@ -463,10 +591,9 @@ Support for capabilities and capabilities mode was developed as part of the
|
||||
.Tn TrustedBSD
|
||||
Project.
|
||||
.Sh AUTHORS
|
||||
These functions and the capability facility were created by
|
||||
.An "Robert N. M. Watson"
|
||||
at the University of Cambridge Computer Laboratory with support from a grant
|
||||
from Google, Inc.
|
||||
This function was created by
|
||||
.An Pawel Jakub Dawidek Aq pawel@dawidek.net
|
||||
under sponsorship of the FreeBSD Foundation.
|
||||
.Sh BUGS
|
||||
This man page should list the set of permitted system calls more specifically
|
||||
for each capability right.
|
@ -115,11 +115,6 @@ and
|
||||
is a valid descriptor, then
|
||||
.Fn dup2
|
||||
is successful, and does nothing.
|
||||
.Pp
|
||||
The related
|
||||
.Xr cap_new 2
|
||||
system call allows file descriptors to be duplicated with restrictions on
|
||||
their use.
|
||||
.Sh RETURN VALUES
|
||||
The value -1 is returned if an error occurs in either call.
|
||||
The external variable
|
||||
@ -152,7 +147,6 @@ argument is negative or exceeds the maximum allowable descriptor number
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr accept 2 ,
|
||||
.Xr cap_new 2 ,
|
||||
.Xr close 2 ,
|
||||
.Xr fcntl 2 ,
|
||||
.Xr getdtablesize 2 ,
|
||||
|
@ -600,7 +600,6 @@ kinfo_fflags2fst(int kfflags)
|
||||
} kfflags2fst[] = {
|
||||
{ KF_FLAG_APPEND, PS_FST_FFLAG_APPEND },
|
||||
{ KF_FLAG_ASYNC, PS_FST_FFLAG_ASYNC },
|
||||
{ KF_FLAG_CAPABILITY, PS_FST_FFLAG_CAPABILITY },
|
||||
{ KF_FLAG_CREAT, PS_FST_FFLAG_CREAT },
|
||||
{ KF_FLAG_DIRECT, PS_FST_FFLAG_DIRECT },
|
||||
{ KF_FLAG_EXCL, PS_FST_FFLAG_EXCL },
|
||||
|
@ -88,7 +88,6 @@
|
||||
#define PS_FST_FFLAG_DIRECT 0x1000
|
||||
#define PS_FST_FFLAG_EXEC 0x2000
|
||||
#define PS_FST_FFLAG_HASLOCK 0x4000
|
||||
#define PS_FST_FFLAG_CAPABILITY 0x8000
|
||||
|
||||
struct procstat;
|
||||
struct filestat {
|
||||
|
@ -95,8 +95,7 @@ static off_t nandfs_seek(struct open_file *, off_t, int);
|
||||
static int nandfs_stat(struct open_file *, struct stat *);
|
||||
static int nandfs_readdir(struct open_file *, struct dirent *);
|
||||
|
||||
static int nandfs_buf_read(struct nandfs *, char **, size_t *);
|
||||
static struct nandfs_node *nandfs_lookup_inode(struct nandfs *, nandfs_daddr_t);
|
||||
static int nandfs_buf_read(struct nandfs *, void **, size_t *);
|
||||
static struct nandfs_node *nandfs_lookup_path(struct nandfs *, const char *);
|
||||
static int nandfs_read_inode(struct nandfs *, struct nandfs_node *,
|
||||
nandfs_lbn_t, u_int, void *, int);
|
||||
@ -125,6 +124,27 @@ struct fs_ops nandfs_fsops = {
|
||||
|
||||
#define NINDIR(fs) ((fs)->nf_blocksize / sizeof(nandfs_daddr_t))
|
||||
|
||||
/* from NetBSD's src/sys/net/if_ethersubr.c */
|
||||
static uint32_t
|
||||
nandfs_crc32(uint32_t crc, const uint8_t *buf, size_t len)
|
||||
{
|
||||
static const uint32_t crctab[] = {
|
||||
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
|
||||
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
||||
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
|
||||
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
|
||||
};
|
||||
size_t i;
|
||||
|
||||
crc = crc ^ ~0U;
|
||||
for (i = 0; i < len; i++) {
|
||||
crc ^= buf[i];
|
||||
crc = (crc >> 4) ^ crctab[crc & 0xf];
|
||||
crc = (crc >> 4) ^ crctab[crc & 0xf];
|
||||
}
|
||||
return (crc ^ ~0U);
|
||||
}
|
||||
|
||||
static int
|
||||
nandfs_check_fsdata_crc(struct nandfs_fsdata *fsdata)
|
||||
{
|
||||
@ -138,7 +158,7 @@ nandfs_check_fsdata_crc(struct nandfs_fsdata *fsdata)
|
||||
|
||||
/* Calculate */
|
||||
fsdata->f_sum = (0);
|
||||
comp_crc = crc32(0, (uint8_t *)fsdata, fsdata->f_bytes);
|
||||
comp_crc = nandfs_crc32(0, (uint8_t *)fsdata, fsdata->f_bytes);
|
||||
|
||||
/* Restore */
|
||||
fsdata->f_sum = fsdata_crc;
|
||||
@ -162,7 +182,7 @@ nandfs_check_superblock_crc(struct nandfs_fsdata *fsdata,
|
||||
|
||||
/* Calculate */
|
||||
super->s_sum = (0);
|
||||
comp_crc = crc32(0, (uint8_t *)super, fsdata->f_sbbytes);
|
||||
comp_crc = nandfs_crc32(0, (uint8_t *)super, fsdata->f_sbbytes);
|
||||
|
||||
/* Restore */
|
||||
super->s_sum = super_crc;
|
||||
@ -397,7 +417,7 @@ nandfs_open(const char *path, struct open_file *f)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
nandfs_free_node(struct nandfs_node *node)
|
||||
{
|
||||
struct bmap_buf *bmap, *tmp;
|
||||
@ -424,6 +444,7 @@ nandfs_close(struct open_file *f)
|
||||
nandfs_free_node(fs->nf_opened_node);
|
||||
free(fs->nf_sb);
|
||||
free(fs);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -431,7 +452,7 @@ nandfs_read(struct open_file *f, void *addr, size_t size, size_t *resid)
|
||||
{
|
||||
struct nandfs *fs = (struct nandfs *)f->f_fsdata;
|
||||
size_t csize, buf_size;
|
||||
uint8_t *buf;
|
||||
void *buf;
|
||||
int error = 0;
|
||||
|
||||
NANDFS_DEBUG("nandfs_read(file=%p, addr=%p, size=%d)\n", f, addr, size);
|
||||
@ -440,7 +461,7 @@ nandfs_read(struct open_file *f, void *addr, size_t size, size_t *resid)
|
||||
if (fs->nf_offset >= fs->nf_opened_node->inode->i_size)
|
||||
break;
|
||||
|
||||
error = nandfs_buf_read(fs, (void *)&buf, &buf_size);
|
||||
error = nandfs_buf_read(fs, &buf, &buf_size);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
@ -517,7 +538,7 @@ nandfs_readdir(struct open_file *f, struct dirent *d)
|
||||
{
|
||||
struct nandfs *fs = f->f_fsdata;
|
||||
struct nandfs_dir_entry *dirent;
|
||||
uint8_t *buf;
|
||||
void *buf;
|
||||
size_t buf_size;
|
||||
|
||||
NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)\n", f, d);
|
||||
@ -528,7 +549,7 @@ nandfs_readdir(struct open_file *f, struct dirent *d)
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
if (nandfs_buf_read(fs, (void *)&buf, &buf_size)) {
|
||||
if (nandfs_buf_read(fs, &buf, &buf_size)) {
|
||||
NANDFS_DEBUG("nandfs_readdir(file=%p, dirent=%p)"
|
||||
"buf_read failed\n", f, d);
|
||||
return (EIO);
|
||||
@ -546,7 +567,7 @@ nandfs_readdir(struct open_file *f, struct dirent *d)
|
||||
}
|
||||
|
||||
static int
|
||||
nandfs_buf_read(struct nandfs *fs, char **buf_p, size_t *size_p)
|
||||
nandfs_buf_read(struct nandfs *fs, void **buf_p, size_t *size_p)
|
||||
{
|
||||
nandfs_daddr_t blknr, blkoff;
|
||||
|
||||
@ -612,8 +633,8 @@ nandfs_lookup_path(struct nandfs *fs, const char *path)
|
||||
struct nandfs_node *node;
|
||||
struct nandfs_dir_entry *dirent;
|
||||
char *namebuf;
|
||||
uint64_t i, j, done, counter, pinode, inode;
|
||||
int nlinks = 0, len, link_len, nameidx;
|
||||
uint64_t i, done, pinode, inode;
|
||||
int nlinks = 0, counter, len, link_len, nameidx;
|
||||
uint8_t *buffer, *orig;
|
||||
char *strp, *lpath;
|
||||
|
||||
@ -650,7 +671,8 @@ nandfs_lookup_path(struct nandfs *fs, const char *path)
|
||||
buffer = orig;
|
||||
done = counter = 0;
|
||||
while (1) {
|
||||
dirent = (struct nandfs_dir_entry *)buffer;
|
||||
dirent =
|
||||
(struct nandfs_dir_entry *)(void *)buffer;
|
||||
NANDFS_DEBUG("%s: dirent.name = %s\n",
|
||||
__func__, dirent->name);
|
||||
NANDFS_DEBUG("%s: dirent.rec_len = %d\n",
|
||||
@ -746,9 +768,9 @@ static int
|
||||
nandfs_read_inode(struct nandfs *fs, struct nandfs_node *node,
|
||||
nandfs_daddr_t blknr, u_int nblks, void *buf, int raw)
|
||||
{
|
||||
int i;
|
||||
uint64_t *pblks;
|
||||
uint64_t *vblks;
|
||||
u_int i;
|
||||
int error;
|
||||
|
||||
pblks = malloc(nblks * sizeof(uint64_t));
|
||||
@ -777,7 +799,7 @@ nandfs_read_inode(struct nandfs *fs, struct nandfs_node *node,
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
buf += fs->nf_blocksize;
|
||||
buf = (void *)((uintptr_t)buf + fs->nf_blocksize);
|
||||
}
|
||||
|
||||
free(pblks);
|
||||
@ -859,8 +881,7 @@ nandfs_bmap_lookup(struct nandfs *fs, struct nandfs_node *node,
|
||||
{
|
||||
struct nandfs_inode *ino;
|
||||
nandfs_daddr_t ind_block_num;
|
||||
uint64_t *map, *indir;
|
||||
uint64_t idx0, idx1, vblk, tmp;
|
||||
uint64_t *map;
|
||||
int idx;
|
||||
int level;
|
||||
|
||||
@ -1006,7 +1027,7 @@ ioread(struct open_file *f, off_t pos, void *buf, u_int length)
|
||||
err = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, pos,
|
||||
nsec * bsize, buffer, NULL);
|
||||
|
||||
memcpy(buf, buffer + off, length);
|
||||
memcpy(buf, (void *)((uintptr_t)buffer + off), length);
|
||||
free(buffer);
|
||||
|
||||
return (err);
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 25, 2012
|
||||
.Dd March 1, 2013
|
||||
.Dt KINFO_GETPROC 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -37,7 +37,7 @@
|
||||
.In sys/types.h
|
||||
.In libutil.h
|
||||
.Ft struct kinfo_proc *
|
||||
.Fn kinfo_getproc "pid_t pid" "int *cntp"
|
||||
.Fn kinfo_getproc "pid_t pid"
|
||||
.Sh DESCRIPTION
|
||||
This function is used for obtaining process information from the kernel.
|
||||
.Pp
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 18, 2012
|
||||
.Dd February 27, 2013
|
||||
.Dt ARCMSR 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -108,6 +108,8 @@ ARC-1222
|
||||
.It
|
||||
ARC-1223
|
||||
.It
|
||||
ARC-1224
|
||||
.It
|
||||
ARC-1230
|
||||
.It
|
||||
ARC-1231
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2011 Alexander Motin <mav@FreeBSD.org>
|
||||
.\" Copyright (c) 2011-2013 Alexander Motin <mav@FreeBSD.org>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 14, 2011
|
||||
.Dd February 25, 2013
|
||||
.Dt EVENTTIMERS 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -36,7 +36,7 @@
|
||||
struct eventtimer;
|
||||
|
||||
typedef int et_start_t(struct eventtimer *et,
|
||||
struct bintime *first, struct bintime *period);
|
||||
sbintime_t first, sbintime_t period);
|
||||
typedef int et_stop_t(struct eventtimer *et);
|
||||
typedef void et_event_cb_t(struct eventtimer *et, void *arg);
|
||||
typedef int et_deregister_cb_t(struct eventtimer *et, void *arg);
|
||||
@ -53,8 +53,8 @@ struct eventtimer {
|
||||
int et_quality;
|
||||
int et_active;
|
||||
uint64_t et_frequency;
|
||||
struct bintime et_min_period;
|
||||
struct bintime et_max_period;
|
||||
sbintime_t et_min_period;
|
||||
sbintime_t et_max_period;
|
||||
et_start_t *et_start;
|
||||
et_stop_t *et_stop;
|
||||
et_event_cb_t *et_event_cb;
|
||||
@ -75,7 +75,7 @@ struct eventtimer {
|
||||
.Ft int
|
||||
.Fn et_init "struct eventtimer *et" "et_event_cb_t *event" "et_deregister_cb_t *deregister" "void *arg"
|
||||
.Ft int
|
||||
.Fn et_start "struct eventtimer *et" "struct bintime *first" "struct bintime *period"
|
||||
.Fn et_start "struct eventtimer *et" "sbintime_t first" "sbintime_t period"
|
||||
.Ft int
|
||||
.Fn et_stop "struct eventtimer *et"
|
||||
.Ft int
|
||||
|
@ -14,7 +14,7 @@ COMPILER_TYPE:= gcc
|
||||
. elif ${_COMPILER_VERSION:Mclang}
|
||||
COMPILER_TYPE:= clang
|
||||
. else
|
||||
.error Unable to determine compiler type for ${CC}
|
||||
.error Unable to determine compiler type for ${CC}. Consider setting COMPILER_TYPE.
|
||||
. endif
|
||||
. undef _COMPILER_VERSION
|
||||
. endif
|
||||
|
@ -658,7 +658,7 @@ cpu_halt(void)
|
||||
halt();
|
||||
}
|
||||
|
||||
void (*cpu_idle_hook)(void) = NULL; /* ACPI idle hook. */
|
||||
void (*cpu_idle_hook)(sbintime_t) = NULL; /* ACPI idle hook. */
|
||||
static int cpu_ident_amdc1e = 0; /* AMD C1E supported. */
|
||||
static int idle_mwait = 1; /* Use MONITOR/MWAIT for short idle. */
|
||||
TUNABLE_INT("machdep.idle_mwait", &idle_mwait);
|
||||
@ -670,7 +670,7 @@ SYSCTL_INT(_machdep, OID_AUTO, idle_mwait, CTLFLAG_RW, &idle_mwait,
|
||||
#define STATE_SLEEPING 0x2
|
||||
|
||||
static void
|
||||
cpu_idle_acpi(int busy)
|
||||
cpu_idle_acpi(sbintime_t sbt)
|
||||
{
|
||||
int *state;
|
||||
|
||||
@ -682,14 +682,14 @@ cpu_idle_acpi(int busy)
|
||||
if (sched_runnable())
|
||||
enable_intr();
|
||||
else if (cpu_idle_hook)
|
||||
cpu_idle_hook();
|
||||
cpu_idle_hook(sbt);
|
||||
else
|
||||
__asm __volatile("sti; hlt");
|
||||
*state = STATE_RUNNING;
|
||||
}
|
||||
|
||||
static void
|
||||
cpu_idle_hlt(int busy)
|
||||
cpu_idle_hlt(sbintime_t sbt)
|
||||
{
|
||||
int *state;
|
||||
|
||||
@ -730,7 +730,7 @@ cpu_idle_hlt(int busy)
|
||||
#define MWAIT_C4 0x30
|
||||
|
||||
static void
|
||||
cpu_idle_mwait(int busy)
|
||||
cpu_idle_mwait(sbintime_t sbt)
|
||||
{
|
||||
int *state;
|
||||
|
||||
@ -753,7 +753,7 @@ cpu_idle_mwait(int busy)
|
||||
}
|
||||
|
||||
static void
|
||||
cpu_idle_spin(int busy)
|
||||
cpu_idle_spin(sbintime_t sbt)
|
||||
{
|
||||
int *state;
|
||||
int i;
|
||||
@ -802,12 +802,13 @@ cpu_probe_amdc1e(void)
|
||||
}
|
||||
}
|
||||
|
||||
void (*cpu_idle_fn)(int) = cpu_idle_acpi;
|
||||
void (*cpu_idle_fn)(sbintime_t) = cpu_idle_acpi;
|
||||
|
||||
void
|
||||
cpu_idle(int busy)
|
||||
{
|
||||
uint64_t msr;
|
||||
sbintime_t sbt = -1;
|
||||
|
||||
CTR2(KTR_SPARE2, "cpu_idle(%d) at %d",
|
||||
busy, curcpu);
|
||||
@ -825,7 +826,7 @@ cpu_idle(int busy)
|
||||
/* If we have time - switch timers into idle mode. */
|
||||
if (!busy) {
|
||||
critical_enter();
|
||||
cpu_idleclock();
|
||||
sbt = cpu_idleclock();
|
||||
}
|
||||
|
||||
/* Apply AMD APIC timer C1E workaround. */
|
||||
@ -836,7 +837,7 @@ cpu_idle(int busy)
|
||||
}
|
||||
|
||||
/* Call main idle method. */
|
||||
cpu_idle_fn(busy);
|
||||
cpu_idle_fn(sbt);
|
||||
|
||||
/* Switch timers mack into active mode. */
|
||||
if (!busy) {
|
||||
|
@ -3665,7 +3665,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
|
||||
pv = get_pv_entry(pmap, &lock);
|
||||
pv->pv_va = va;
|
||||
CHANGE_PV_LIST_LOCK_TO_PHYS(&lock, pa);
|
||||
TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
|
||||
TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
|
||||
if ((newpte & PG_RW) != 0)
|
||||
vm_page_aflag_set(m, PGA_WRITEABLE);
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ device sa # Sequential Access (tape etc)
|
||||
device cd # CD
|
||||
device pass # Passthrough device (direct ATA/SCSI access)
|
||||
device ses # Enclosure Services (SES and SAF-TE)
|
||||
device ctl # CAM Target Layer
|
||||
#device ctl # CAM Target Layer
|
||||
|
||||
# RAID controllers interfaced to the SCSI subsystem
|
||||
device amr # AMI MegaRAID
|
||||
|
@ -17,5 +17,5 @@ arm/allwinner/timer.c standard
|
||||
arm/allwinner/aintc.c standard
|
||||
arm/allwinner/bus_space.c standard
|
||||
arm/allwinner/common.c standard
|
||||
arm/allwinner/console.c standard
|
||||
#arm/allwinner/console.c standard
|
||||
arm/allwinner/a10_machdep.c standard
|
||||
|
@ -95,7 +95,7 @@ int a10_timer_get_timerfreq(struct a10_timer_softc *);
|
||||
|
||||
static u_int a10_timer_get_timecount(struct timecounter *);
|
||||
static int a10_timer_timer_start(struct eventtimer *,
|
||||
struct bintime *, struct bintime *);
|
||||
sbintime_t first, sbintime_t period);
|
||||
static int a10_timer_timer_stop(struct eventtimer *);
|
||||
|
||||
static uint64_t timer_read_counter64(void);
|
||||
@ -193,12 +193,8 @@ a10_timer_attach(device_t dev)
|
||||
sc->et.et_name = "a10_timer Eventtimer";
|
||||
sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERIODIC;
|
||||
sc->et.et_quality = 1000;
|
||||
sc->et.et_min_period.sec = 0;
|
||||
sc->et.et_min_period.frac =
|
||||
((0x00000005LLU << 32) / sc->et.et_frequency) << 32;
|
||||
sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
|
||||
sc->et.et_max_period.frac =
|
||||
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
|
||||
sc->et.et_min_period = (0x00000005LLU << 32) / sc->et.et_frequency;
|
||||
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
|
||||
sc->et.et_start = a10_timer_timer_start;
|
||||
sc->et.et_stop = a10_timer_timer_stop;
|
||||
sc->et.et_priv = sc;
|
||||
@ -225,8 +221,8 @@ a10_timer_attach(device_t dev)
|
||||
}
|
||||
|
||||
static int
|
||||
a10_timer_timer_start(struct eventtimer *et, struct bintime *first,
|
||||
struct bintime *period)
|
||||
a10_timer_timer_start(struct eventtimer *et, sbintime_t first,
|
||||
sbintime_t period)
|
||||
{
|
||||
struct a10_timer_softc *sc;
|
||||
uint32_t count;
|
||||
@ -234,26 +230,21 @@ a10_timer_timer_start(struct eventtimer *et, struct bintime *first,
|
||||
|
||||
sc = (struct a10_timer_softc *)et->et_priv;
|
||||
|
||||
sc->sc_period = 0;
|
||||
|
||||
if (period != NULL) {
|
||||
sc->sc_period = (sc->et.et_frequency * (period->frac >> 32)) >> 32;
|
||||
sc->sc_period += sc->et.et_frequency * period->sec;
|
||||
}
|
||||
if (first == NULL)
|
||||
if (period != 0)
|
||||
sc->sc_period = ((uint32_t)et->et_frequency * period) >> 32;
|
||||
else
|
||||
sc->sc_period = 0;
|
||||
if (first != 0)
|
||||
count = ((uint32_t)et->et_frequency * first) >> 32;
|
||||
else
|
||||
count = sc->sc_period;
|
||||
else {
|
||||
count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
|
||||
if (first->sec != 0)
|
||||
count += sc->et.et_frequency * first->sec;
|
||||
}
|
||||
|
||||
/* Update timer values */
|
||||
timer_write_4(sc, SW_TIMER0_INT_VALUE_REG, sc->sc_period);
|
||||
timer_write_4(sc, SW_TIMER0_CUR_VALUE_REG, count);
|
||||
|
||||
val = timer_read_4(sc, SW_TIMER0_CTRL_REG);
|
||||
if (first == NULL) {
|
||||
if (period != 0) {
|
||||
/* periodic */
|
||||
val |= TIMER_AUTORELOAD;
|
||||
} else {
|
||||
|
@ -204,6 +204,7 @@ mmu_done:
|
||||
virt_done:
|
||||
mov r1, #20 /* loader info size is 20 bytes also second arg */
|
||||
subs sp, sp, r1 /* allocate arm_boot_params struct on stack */
|
||||
bic sp, sp, #7 /* align stack to 8 bytes */
|
||||
mov r0, sp /* loader info pointer is first arg */
|
||||
str r1, [r0] /* Store length of loader info */
|
||||
str r9, [r0, #4] /* Store r0 from boot loader */
|
||||
|
@ -167,31 +167,23 @@ arm_tmr_get_timecount(struct timecounter *tc)
|
||||
* Always returns 0
|
||||
*/
|
||||
static int
|
||||
arm_tmr_start(struct eventtimer *et, struct bintime *first,
|
||||
struct bintime *period)
|
||||
arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
|
||||
{
|
||||
struct arm_tmr_softc *sc = (struct arm_tmr_softc *)et->et_priv;
|
||||
uint32_t load, count;
|
||||
uint32_t ctrl;
|
||||
|
||||
ctrl = PRV_TIMER_CTRL_IRQ_ENABLE | PRV_TIMER_CTRL_TIMER_ENABLE;
|
||||
|
||||
if (period != NULL) {
|
||||
load = (et->et_frequency * (period->frac >> 32)) >> 32;
|
||||
if (period->sec > 0)
|
||||
load += et->et_frequency * period->sec;
|
||||
if (period != 0) {
|
||||
load = ((uint32_t)et->et_frequency * period) >> 32;
|
||||
ctrl |= PRV_TIMER_CTRL_AUTO_RELOAD;
|
||||
} else {
|
||||
} else
|
||||
load = 0;
|
||||
}
|
||||
|
||||
if (first != NULL) {
|
||||
count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
|
||||
if (first->sec != 0)
|
||||
count += sc->et.et_frequency * first->sec;
|
||||
} else {
|
||||
if (first != 0)
|
||||
count = ((uint32_t)et->et_frequency * first) >> 32;
|
||||
else
|
||||
count = load;
|
||||
}
|
||||
|
||||
tmr_prv_write_4(PRV_TIMER_LOAD, load);
|
||||
tmr_prv_write_4(PRV_TIMER_COUNT, count);
|
||||
@ -330,12 +322,8 @@ arm_tmr_attach(device_t dev)
|
||||
sc->et.et_quality = 1000;
|
||||
|
||||
sc->et.et_frequency = sc->clkfreq;
|
||||
sc->et.et_min_period.sec = 0;
|
||||
sc->et.et_min_period.frac =
|
||||
((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
|
||||
sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
|
||||
sc->et.et_max_period.frac =
|
||||
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
|
||||
sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
|
||||
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
|
||||
sc->et.et_start = arm_tmr_start;
|
||||
sc->et.et_stop = arm_tmr_stop;
|
||||
sc->et.et_priv = sc;
|
||||
|
727
sys/arm/broadcom/bcm2835/bcm2835_dma.c
Normal file
727
sys/arm/broadcom/bcm2835/bcm2835_dma.c
Normal file
@ -0,0 +1,727 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Daisuke Aoyama <aoyama@peach.ne.jp>
|
||||
* Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@bluezbox.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/pmap.h>
|
||||
|
||||
#include "bcm2835_dma.h"
|
||||
#include "bcm2835_vcbus.h"
|
||||
|
||||
#define MAX_REG 9
|
||||
|
||||
/* private flags */
|
||||
#define BCM_DMA_CH_USED 0x00000001
|
||||
#define BCM_DMA_CH_FREE 0x40000000
|
||||
#define BCM_DMA_CH_UNMAP 0x80000000
|
||||
|
||||
/* Register Map (4.2.1.2) */
|
||||
#define BCM_DMA_CS(n) (0x100*(n) + 0x00)
|
||||
#define CS_ACTIVE (1 << 0)
|
||||
#define CS_END (1 << 1)
|
||||
#define CS_INT (1 << 2)
|
||||
#define CS_DREQ (1 << 3)
|
||||
#define CS_ISPAUSED (1 << 4)
|
||||
#define CS_ISHELD (1 << 5)
|
||||
#define CS_ISWAIT (1 << 6)
|
||||
#define CS_ERR (1 << 8)
|
||||
#define CS_WAITWRT (1 << 28)
|
||||
#define CS_DISDBG (1 << 29)
|
||||
#define CS_ABORT (1 << 30)
|
||||
#define CS_RESET (1 << 31)
|
||||
#define BCM_DMA_CBADDR(n) (0x100*(n) + 0x04)
|
||||
#define BCM_DMA_INFO(n) (0x100*(n) + 0x08)
|
||||
#define INFO_INT_EN (1 << 0)
|
||||
#define INFO_TDMODE (1 << 1)
|
||||
#define INFO_WAIT_RESP (1 << 3)
|
||||
#define INFO_D_INC (1 << 4)
|
||||
#define INFO_D_WIDTH (1 << 5)
|
||||
#define INFO_D_DREQ (1 << 6)
|
||||
#define INFO_S_INC (1 << 8)
|
||||
#define INFO_S_WIDTH (1 << 9)
|
||||
#define INFO_S_DREQ (1 << 10)
|
||||
#define INFO_WAITS_SHIFT (21)
|
||||
#define INFO_PERMAP_SHIFT (16)
|
||||
#define INFO_PERMAP_MASK (0x1f << INFO_PERMAP_SHIFT)
|
||||
|
||||
#define BCM_DMA_SRC(n) (0x100*(n) + 0x0C)
|
||||
#define BCM_DMA_DST(n) (0x100*(n) + 0x10)
|
||||
#define BCM_DMA_LEN(n) (0x100*(n) + 0x14)
|
||||
#define BCM_DMA_STRIDE(n) (0x100*(n) + 0x18)
|
||||
#define BCM_DMA_CBNEXT(n) (0x100*(n) + 0x1C)
|
||||
#define BCM_DMA_DEBUG(n) (0x100*(n) + 0x20)
|
||||
#define DEBUG_ERROR_MASK (7)
|
||||
|
||||
#define BCM_DMA_INT_STATUS 0xfe0
|
||||
#define BCM_DMA_ENABLE 0xff0
|
||||
|
||||
/* relative offset from BCM_VC_DMA0_BASE (p.39) */
|
||||
#define BCM_DMA_CH(n) (0x100*(n))
|
||||
|
||||
/* DMA Control Block - 256bit aligned (p.40) */
|
||||
struct bcm_dma_cb {
|
||||
uint32_t info; /* Transfer Information */
|
||||
uint32_t src; /* Source Address */
|
||||
uint32_t dst; /* Destination Address */
|
||||
uint32_t len; /* Transfer Length */
|
||||
uint32_t stride; /* 2D Mode Stride */
|
||||
uint32_t next; /* Next Control Block Address */
|
||||
uint32_t rsvd1; /* Reserved */
|
||||
uint32_t rsvd2; /* Reserved */
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
static void bcm_dma_cb_dump(struct bcm_dma_cb *cb);
|
||||
static void bcm_dma_reg_dump(int ch);
|
||||
#endif
|
||||
|
||||
/* DMA channel private info */
|
||||
struct bcm_dma_ch {
|
||||
int ch;
|
||||
uint32_t flags;
|
||||
struct bcm_dma_cb * cb;
|
||||
uint32_t vc_cb;
|
||||
bus_dmamap_t dma_map;
|
||||
void (*intr_func)(int, void *);
|
||||
void * intr_arg;
|
||||
};
|
||||
|
||||
struct bcm_dma_softc {
|
||||
device_t sc_dev;
|
||||
struct mtx sc_mtx;
|
||||
struct resource * sc_mem;
|
||||
struct resource * sc_irq[BCM_DMA_CH_MAX];
|
||||
void * sc_intrhand[BCM_DMA_CH_MAX];
|
||||
struct bcm_dma_ch sc_dma_ch[BCM_DMA_CH_MAX];
|
||||
bus_dma_tag_t sc_dma_tag;
|
||||
};
|
||||
|
||||
static struct bcm_dma_softc *bcm_dma_sc = NULL;
|
||||
|
||||
static void
|
||||
bcm_dmamap_cb(void *arg, bus_dma_segment_t *segs,
|
||||
int nseg, int err)
|
||||
{
|
||||
bus_addr_t *addr;
|
||||
|
||||
if (err)
|
||||
return;
|
||||
|
||||
addr = (bus_addr_t*)arg;
|
||||
*addr = PHYS_TO_VCBUS(segs[0].ds_addr);
|
||||
}
|
||||
|
||||
static void
|
||||
bcm_dma_reset(device_t dev, int ch)
|
||||
{
|
||||
struct bcm_dma_softc *sc = device_get_softc(dev);
|
||||
struct bcm_dma_cb *cb;
|
||||
uint32_t cs;
|
||||
int count;
|
||||
|
||||
if (ch < 0 || ch >= BCM_DMA_CH_MAX)
|
||||
return;
|
||||
|
||||
cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch));
|
||||
|
||||
if (cs & CS_ACTIVE) {
|
||||
/* pause current task */
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_CS(ch), 0);
|
||||
|
||||
count = 1000;
|
||||
do {
|
||||
cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch));
|
||||
} while (!(cs & CS_ISPAUSED) && (count-- > 0));
|
||||
|
||||
if (!(cs & CS_ISPAUSED)) {
|
||||
device_printf(dev,
|
||||
"Can't abort DMA transfer at channel %d\n", ch);
|
||||
}
|
||||
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_CBNEXT(ch), 0);
|
||||
|
||||
/* Complete everything, clear interrupt */
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_CS(ch),
|
||||
CS_ABORT | CS_INT | CS_END| CS_ACTIVE);
|
||||
}
|
||||
|
||||
/* clear control blocks */
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_CBADDR(ch), 0);
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_CBNEXT(ch), 0);
|
||||
|
||||
/* Reset control block */
|
||||
cb = sc->sc_dma_ch[ch].cb;
|
||||
bzero(cb, sizeof(cb));
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_dma_init(device_t dev)
|
||||
{
|
||||
struct bcm_dma_softc *sc = device_get_softc(dev);
|
||||
uint32_t mask;
|
||||
struct bcm_dma_ch *ch;
|
||||
void *cb_virt;
|
||||
vm_paddr_t cb_phys;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
/* disable and clear interrupt status */
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, 0);
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_INT_STATUS, 0);
|
||||
|
||||
/* Allocate DMA chunks control blocks */
|
||||
/* p.40 of spec - control block should be 32-bit aligned */
|
||||
err = bus_dma_tag_create(bus_get_dma_tag(dev),
|
||||
1, 0, BUS_SPACE_MAXADDR_32BIT,
|
||||
BUS_SPACE_MAXADDR, NULL, NULL,
|
||||
sizeof(struct bcm_dma_cb), 1,
|
||||
sizeof(struct bcm_dma_cb),
|
||||
BUS_DMA_ALLOCNOW, NULL, NULL,
|
||||
&sc->sc_dma_tag);
|
||||
|
||||
if (err) {
|
||||
device_printf(dev, "failed allocate DMA tag");
|
||||
return (err);
|
||||
}
|
||||
|
||||
/* setup initial settings */
|
||||
for (i = 0; i < BCM_DMA_CH_MAX; i++) {
|
||||
ch = &sc->sc_dma_ch[i];
|
||||
|
||||
err = bus_dmamem_alloc(sc->sc_dma_tag, &cb_virt,
|
||||
BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO,
|
||||
&ch->dma_map);
|
||||
if (err) {
|
||||
device_printf(dev, "cannot allocate DMA memory\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Least alignment for busdma-allocated stuff is cache
|
||||
* line size, so just make sure nothing stupid happend
|
||||
* and we got properly aligned address
|
||||
*/
|
||||
if ((uintptr_t)cb_virt & 0x1f) {
|
||||
device_printf(dev,
|
||||
"DMA address is not 32-bytes aligned: %p\n",
|
||||
(void*)cb_virt);
|
||||
break;
|
||||
}
|
||||
|
||||
err = bus_dmamap_load(sc->sc_dma_tag, ch->dma_map, cb_virt,
|
||||
sizeof(struct bcm_dma_cb), bcm_dmamap_cb, &cb_phys,
|
||||
BUS_DMA_WAITOK);
|
||||
if (err) {
|
||||
device_printf(dev, "cannot load DMA memory\n");
|
||||
break;
|
||||
}
|
||||
|
||||
bzero(ch, sizeof(struct bcm_dma_ch));
|
||||
ch->ch = i;
|
||||
ch->cb = cb_virt;
|
||||
ch->vc_cb = cb_phys;
|
||||
ch->intr_func = NULL;
|
||||
ch->intr_arg = NULL;
|
||||
ch->flags = BCM_DMA_CH_UNMAP;
|
||||
|
||||
ch->cb->info = INFO_WAIT_RESP;
|
||||
|
||||
/* reset DMA engine */
|
||||
bcm_dma_reset(dev, i);
|
||||
}
|
||||
|
||||
/* now use DMA2/DMA3 only */
|
||||
sc->sc_dma_ch[2].flags = BCM_DMA_CH_FREE;
|
||||
sc->sc_dma_ch[3].flags = BCM_DMA_CH_FREE;
|
||||
|
||||
/* enable DMAs */
|
||||
mask = 0;
|
||||
|
||||
for (i = 0; i < BCM_DMA_CH_MAX; i++)
|
||||
if (sc->sc_dma_ch[i].flags & BCM_DMA_CH_FREE)
|
||||
mask |= (1 << i);
|
||||
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_ENABLE, mask);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate DMA channel for further use, returns channel # or
|
||||
* BCM_DMA_CH_INVALID
|
||||
*/
|
||||
int
|
||||
bcm_dma_allocate(int req_ch)
|
||||
{
|
||||
struct bcm_dma_softc *sc = bcm_dma_sc;
|
||||
int ch = BCM_DMA_CH_INVALID;
|
||||
int i;
|
||||
|
||||
if (req_ch >= BCM_DMA_CH_MAX)
|
||||
return (BCM_DMA_CH_INVALID);
|
||||
|
||||
/* Auto(req_ch < 0) or CH specified */
|
||||
mtx_lock(&sc->sc_mtx);
|
||||
|
||||
if (req_ch < 0) {
|
||||
for (i = 0; i < BCM_DMA_CH_MAX; i++) {
|
||||
if (sc->sc_dma_ch[i].flags & BCM_DMA_CH_FREE) {
|
||||
ch = i;
|
||||
sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_FREE;
|
||||
sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_USED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sc->sc_dma_ch[req_ch].flags & BCM_DMA_CH_FREE) {
|
||||
ch = req_ch;
|
||||
sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_FREE;
|
||||
sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_USED;
|
||||
}
|
||||
}
|
||||
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
return (ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Frees allocated channel. Returns 0 on success, -1 otherwise
|
||||
*/
|
||||
int
|
||||
bcm_dma_free(int ch)
|
||||
{
|
||||
struct bcm_dma_softc *sc = bcm_dma_sc;
|
||||
|
||||
if (ch < 0 || ch >= BCM_DMA_CH_MAX)
|
||||
return (-1);
|
||||
|
||||
mtx_lock(&sc->sc_mtx);
|
||||
if (sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED) {
|
||||
sc->sc_dma_ch[ch].flags |= BCM_DMA_CH_FREE;
|
||||
sc->sc_dma_ch[ch].flags &= ~BCM_DMA_CH_USED;
|
||||
sc->sc_dma_ch[ch].intr_func = NULL;
|
||||
sc->sc_dma_ch[ch].intr_arg = NULL;
|
||||
|
||||
/* reset DMA engine */
|
||||
bcm_dma_reset(sc->sc_dev, ch);
|
||||
}
|
||||
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Assign handler function for channel interrupt
|
||||
* Returns 0 on success, -1 otherwise
|
||||
*/
|
||||
int
|
||||
bcm_dma_setup_intr(int ch, void (*func)(int, void *), void *arg)
|
||||
{
|
||||
struct bcm_dma_softc *sc = bcm_dma_sc;
|
||||
struct bcm_dma_cb *cb;
|
||||
|
||||
if (ch < 0 || ch >= BCM_DMA_CH_MAX)
|
||||
return (-1);
|
||||
|
||||
if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
|
||||
return (-1);
|
||||
|
||||
sc->sc_dma_ch[ch].intr_func = func;
|
||||
sc->sc_dma_ch[ch].intr_arg = arg;
|
||||
cb = sc->sc_dma_ch[ch].cb;
|
||||
cb->info |= INFO_INT_EN;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup DMA source parameters
|
||||
* ch - channel number
|
||||
* dreq - hardware DREQ # or BCM_DMA_DREQ_NONE if
|
||||
* source is physical memory
|
||||
* inc_addr - BCM_DMA_INC_ADDR if source address
|
||||
* should be increased after each access or
|
||||
* BCM_DMA_SAME_ADDR if address should remain
|
||||
* the same
|
||||
* width - size of read operation, BCM_DMA_32BIT
|
||||
* for 32bit bursts, BCM_DMA_128BIT for 128 bits
|
||||
*
|
||||
* Returns 0 on success, -1 otherwise
|
||||
*/
|
||||
int
|
||||
bcm_dma_setup_src(int ch, int dreq, int inc_addr, int width)
|
||||
{
|
||||
struct bcm_dma_softc *sc = bcm_dma_sc;
|
||||
uint32_t info;
|
||||
|
||||
if (ch < 0 || ch >= BCM_DMA_CH_MAX)
|
||||
return (-1);
|
||||
|
||||
if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
|
||||
return (-1);
|
||||
|
||||
info = sc->sc_dma_ch[ch].cb->info;
|
||||
info &= ~INFO_PERMAP_MASK;
|
||||
info |= (dreq << INFO_PERMAP_SHIFT) & INFO_PERMAP_MASK;
|
||||
|
||||
if (dreq)
|
||||
info |= INFO_S_DREQ;
|
||||
else
|
||||
info &= ~INFO_S_DREQ;
|
||||
|
||||
if (width == BCM_DMA_128BIT)
|
||||
info |= INFO_S_WIDTH;
|
||||
else
|
||||
info &= ~INFO_S_WIDTH;
|
||||
|
||||
if (inc_addr == BCM_DMA_INC_ADDR)
|
||||
info |= INFO_S_INC;
|
||||
else
|
||||
info &= ~INFO_S_INC;
|
||||
|
||||
sc->sc_dma_ch[ch].cb->info = info;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup DMA destination parameters
|
||||
* ch - channel number
|
||||
* dreq - hardware DREQ # or BCM_DMA_DREQ_NONE if
|
||||
* destination is physical memory
|
||||
* inc_addr - BCM_DMA_INC_ADDR if source address
|
||||
* should be increased after each access or
|
||||
* BCM_DMA_SAME_ADDR if address should remain
|
||||
* the same
|
||||
* width - size of write operation, BCM_DMA_32BIT
|
||||
* for 32bit bursts, BCM_DMA_128BIT for 128 bits
|
||||
*
|
||||
* Returns 0 on success, -1 otherwise
|
||||
*/
|
||||
int
|
||||
bcm_dma_setup_dst(int ch, int dreq, int inc_addr, int width)
|
||||
{
|
||||
struct bcm_dma_softc *sc = bcm_dma_sc;
|
||||
uint32_t info;
|
||||
|
||||
if (ch < 0 || ch >= BCM_DMA_CH_MAX)
|
||||
return (-1);
|
||||
|
||||
if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
|
||||
return (-1);
|
||||
|
||||
info = sc->sc_dma_ch[ch].cb->info;
|
||||
info &= ~INFO_PERMAP_MASK;
|
||||
info |= (dreq << INFO_PERMAP_SHIFT) & INFO_PERMAP_MASK;
|
||||
|
||||
if (dreq)
|
||||
info |= INFO_D_DREQ;
|
||||
else
|
||||
info &= ~INFO_D_DREQ;
|
||||
|
||||
if (width == BCM_DMA_128BIT)
|
||||
info |= INFO_D_WIDTH;
|
||||
else
|
||||
info &= ~INFO_D_WIDTH;
|
||||
|
||||
if (inc_addr == BCM_DMA_INC_ADDR)
|
||||
info |= INFO_D_INC;
|
||||
else
|
||||
info &= ~INFO_D_INC;
|
||||
|
||||
sc->sc_dma_ch[ch].cb->info = info;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
bcm_dma_cb_dump(struct bcm_dma_cb *cb)
|
||||
{
|
||||
|
||||
printf("DMA CB ");
|
||||
printf("INFO: %8.8x ", cb->info);
|
||||
printf("SRC: %8.8x ", cb->src);
|
||||
printf("DST: %8.8x ", cb->dst);
|
||||
printf("LEN: %8.8x ", cb->len);
|
||||
printf("\n");
|
||||
printf("STRIDE: %8.8x ", cb->stride);
|
||||
printf("NEXT: %8.8x ", cb->next);
|
||||
printf("RSVD1: %8.8x ", cb->rsvd1);
|
||||
printf("RSVD2: %8.8x ", cb->rsvd2);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
bcm_dma_reg_dump(int ch)
|
||||
{
|
||||
struct bcm_dma_softc *sc = bcm_dma_sc;
|
||||
int i;
|
||||
uint32_t reg;
|
||||
|
||||
if (ch < 0 || ch >= BCM_DMA_CH_MAX)
|
||||
return;
|
||||
|
||||
printf("DMA%d: ", ch);
|
||||
for (i = 0; i < MAX_REG; i++) {
|
||||
reg = bus_read_4(sc->sc_mem, BCM_DMA_CH(ch) + i*4);
|
||||
printf("%8.8x ", reg);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Start DMA transaction
|
||||
* ch - channel number
|
||||
* src, dst - source and destination address in
|
||||
* ARM physical memory address space.
|
||||
* len - amount of bytes to be transfered
|
||||
*
|
||||
* Returns 0 on success, -1 otherwise
|
||||
*/
|
||||
int
|
||||
bcm_dma_start(int ch, vm_paddr_t src, vm_paddr_t dst, int len)
|
||||
{
|
||||
struct bcm_dma_softc *sc = bcm_dma_sc;
|
||||
struct bcm_dma_cb *cb;
|
||||
|
||||
if (ch < 0 || ch >= BCM_DMA_CH_MAX)
|
||||
return (-1);
|
||||
|
||||
if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
|
||||
return (-1);
|
||||
|
||||
cb = sc->sc_dma_ch[ch].cb;
|
||||
if (BCM2835_ARM_IS_IO(src))
|
||||
cb->src = IO_TO_VCBUS(src);
|
||||
else
|
||||
cb->src = PHYS_TO_VCBUS(src);
|
||||
if (BCM2835_ARM_IS_IO(dst))
|
||||
cb->dst = IO_TO_VCBUS(dst);
|
||||
else
|
||||
cb->dst = PHYS_TO_VCBUS(dst);
|
||||
cb->len = len;
|
||||
|
||||
bus_dmamap_sync(sc->sc_dma_tag,
|
||||
sc->sc_dma_ch[ch].dma_map, BUS_DMASYNC_PREWRITE);
|
||||
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_CBADDR(ch),
|
||||
sc->sc_dma_ch[ch].vc_cb);
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_CS(ch), CS_ACTIVE);
|
||||
|
||||
#ifdef DEBUG
|
||||
bcm_dma_cb_dump(sc->sc_dma_ch[ch].cb);
|
||||
bcm_dma_reg_dump(ch);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get length requested for DMA transaction
|
||||
* ch - channel number
|
||||
*
|
||||
* Returns size of transaction, 0 if channel is invalid
|
||||
*/
|
||||
uint32_t
|
||||
bcm_dma_length(int ch)
|
||||
{
|
||||
struct bcm_dma_softc *sc = bcm_dma_sc;
|
||||
struct bcm_dma_cb *cb;
|
||||
|
||||
if (ch < 0 || ch >= BCM_DMA_CH_MAX)
|
||||
return (0);
|
||||
|
||||
if (!(sc->sc_dma_ch[ch].flags & BCM_DMA_CH_USED))
|
||||
return (0);
|
||||
|
||||
cb = sc->sc_dma_ch[ch].cb;
|
||||
|
||||
return (cb->len);
|
||||
}
|
||||
|
||||
static void
|
||||
bcm_dma_intr(void *arg)
|
||||
{
|
||||
struct bcm_dma_softc *sc = bcm_dma_sc;
|
||||
struct bcm_dma_ch *ch = (struct bcm_dma_ch *)arg;
|
||||
uint32_t cs, debug;
|
||||
|
||||
/* my interrupt? */
|
||||
cs = bus_read_4(sc->sc_mem, BCM_DMA_CS(ch->ch));
|
||||
|
||||
if (!(cs & (CS_INT | CS_ERR)))
|
||||
return;
|
||||
|
||||
/* running? */
|
||||
if (!(ch->flags & BCM_DMA_CH_USED)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"unused DMA intr CH=%d, CS=%x\n", ch->ch, cs);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cs & CS_ERR) {
|
||||
debug = bus_read_4(sc->sc_mem, BCM_DMA_DEBUG(ch->ch));
|
||||
device_printf(sc->sc_dev, "DMA error %d on CH%d\n",
|
||||
debug & DEBUG_ERROR_MASK, ch->ch);
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_DEBUG(ch->ch),
|
||||
debug & DEBUG_ERROR_MASK);
|
||||
}
|
||||
|
||||
if (cs & CS_INT) {
|
||||
/* acknowledge interrupt */
|
||||
bus_write_4(sc->sc_mem, BCM_DMA_CS(ch->ch),
|
||||
CS_INT | CS_END);
|
||||
|
||||
/* Prepare for possible access to len field */
|
||||
bus_dmamap_sync(sc->sc_dma_tag, ch->dma_map,
|
||||
BUS_DMASYNC_POSTWRITE);
|
||||
|
||||
/* save callback function and argument */
|
||||
if (ch->intr_func)
|
||||
ch->intr_func(ch->ch, ch->intr_arg);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_dma_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-dma"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "BCM2835 DMA Controller");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_dma_attach(device_t dev)
|
||||
{
|
||||
struct bcm_dma_softc *sc = device_get_softc(dev);
|
||||
int rid, err = 0;
|
||||
int i;
|
||||
|
||||
sc->sc_dev = dev;
|
||||
|
||||
if (bcm_dma_sc)
|
||||
return (ENXIO);
|
||||
|
||||
for (i = 0; i < BCM_DMA_CH_MAX; i++) {
|
||||
sc->sc_irq[i] = NULL;
|
||||
sc->sc_intrhand[i] = NULL;
|
||||
}
|
||||
|
||||
/* DMA0 - DMA14 */
|
||||
rid = 0;
|
||||
sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
|
||||
if (sc->sc_mem == NULL) {
|
||||
device_printf(dev, "could not allocate memory resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* IRQ DMA0 - DMA11 XXX NOT USE DMA12(spurious?) */
|
||||
for (rid = 0; rid < BCM_DMA_CH_MAX; rid++) {
|
||||
sc->sc_irq[rid] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->sc_irq[rid] == NULL) {
|
||||
device_printf(dev, "cannot allocate interrupt\n");
|
||||
err = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
if (bus_setup_intr(dev, sc->sc_irq[rid], INTR_TYPE_MISC | INTR_MPSAFE,
|
||||
NULL, bcm_dma_intr, &sc->sc_dma_ch[rid],
|
||||
&sc->sc_intrhand[rid])) {
|
||||
device_printf(dev, "cannot setup interrupt handler\n");
|
||||
err = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
mtx_init(&sc->sc_mtx, "bcmdma", "bcmdma", MTX_DEF);
|
||||
bcm_dma_sc = sc;
|
||||
|
||||
err = bcm_dma_init(dev);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
return (err);
|
||||
|
||||
fail:
|
||||
if (sc->sc_mem)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem);
|
||||
|
||||
for (i = 0; i < BCM_DMA_CH_MAX; i++) {
|
||||
if (sc->sc_intrhand[i])
|
||||
bus_teardown_intr(dev, sc->sc_irq[i], sc->sc_intrhand[i]);
|
||||
if (sc->sc_irq[i])
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq[i]);
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
static device_method_t bcm_dma_methods[] = {
|
||||
DEVMETHOD(device_probe, bcm_dma_probe),
|
||||
DEVMETHOD(device_attach, bcm_dma_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t bcm_dma_driver = {
|
||||
"bcm_dma",
|
||||
bcm_dma_methods,
|
||||
sizeof(struct bcm_dma_softc),
|
||||
};
|
||||
|
||||
static devclass_t bcm_dma_devclass;
|
||||
|
||||
DRIVER_MODULE(bcm_dma, simplebus, bcm_dma_driver, bcm_dma_devclass, 0, 0);
|
||||
MODULE_VERSION(bcm_dma, 1);
|
62
sys/arm/broadcom/bcm2835/bcm2835_dma.h
Normal file
62
sys/arm/broadcom/bcm2835/bcm2835_dma.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Daisuke Aoyama <aoyama@peach.ne.jp>
|
||||
* Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@bluezbox.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BCM2835_DMA_H_
|
||||
#define _BCM2835_DMA_H_
|
||||
|
||||
#define BCM_DMA_BLOCK_SIZE 512
|
||||
|
||||
/* DMA0-DMA15 but DMA15 is special */
|
||||
#define BCM_DMA_CH_MAX 12
|
||||
|
||||
/* request CH for any nubmer */
|
||||
#define BCM_DMA_CH_INVALID (-1)
|
||||
#define BCM_DMA_CH_ANY (-1)
|
||||
#define BCM_DMA_CH_FAST1 (2)
|
||||
#define BCM_DMA_CH_FAST2 (3)
|
||||
|
||||
/* Peripheral DREQ Signals (4.2.1.3) */
|
||||
#define BCM_DMA_DREQ_NONE 0
|
||||
#define BCM_DMA_DREQ_EMMC 11
|
||||
#define BCM_DMA_DREQ_SDHOST 13
|
||||
|
||||
#define BCM_DMA_SAME_ADDR 0
|
||||
#define BCM_DMA_INC_ADDR 1
|
||||
|
||||
#define BCM_DMA_32BIT 0
|
||||
#define BCM_DMA_128BIT 1
|
||||
|
||||
int bcm_dma_allocate(int req_ch);
|
||||
int bcm_dma_free(int ch);
|
||||
int bcm_dma_setup_intr(int ch, void (*func)(int, void *), void *arg);
|
||||
int bcm_dma_setup_src(int ch, int dreq, int inc_addr, int width);
|
||||
int bcm_dma_setup_dst(int ch, int dreq, int inc_addr, int width);
|
||||
int bcm_dma_start(int ch, vm_paddr_t src, vm_paddr_t dst, int len);
|
||||
uint32_t bcm_dma_length(int ch);
|
||||
|
||||
#endif /* _BCM2835_DMA_H_ */
|
@ -67,8 +67,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/sdhci/sdhci.h>
|
||||
#include "sdhci_if.h"
|
||||
|
||||
#include "bcm2835_dma.h"
|
||||
#include "bcm2835_vcbus.h"
|
||||
|
||||
#define BCM2835_DEFAULT_SDHCI_FREQ 50
|
||||
|
||||
#define BCM_SDHCI_BUFFER_SIZE 512
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -85,9 +90,11 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
static int bcm2835_sdhci_min_freq = 400000;
|
||||
static int bcm2835_sdhci_hs = 1;
|
||||
static int bcm2835_sdhci_pio_mode = 0;
|
||||
|
||||
TUNABLE_INT("hw.bcm2835.sdhci.min_freq", &bcm2835_sdhci_min_freq);
|
||||
TUNABLE_INT("hw.bcm2835.sdhci.hs", &bcm2835_sdhci_hs);
|
||||
TUNABLE_INT("hw.bcm2835.sdhci.pio_mode", &bcm2835_sdhci_pio_mode);
|
||||
|
||||
struct bcm_sdhci_dmamap_arg {
|
||||
bus_addr_t sc_dma_busaddr;
|
||||
@ -111,23 +118,41 @@ struct bcm_sdhci_softc {
|
||||
int sc_xfer_done;
|
||||
int sc_bus_busy;
|
||||
struct sdhci_slot sc_slot;
|
||||
int sc_dma_inuse;
|
||||
int sc_dma_ch;
|
||||
bus_dma_tag_t sc_dma_tag;
|
||||
bus_dmamap_t sc_dma_map;
|
||||
void *sc_dma_buffer;
|
||||
vm_paddr_t sc_dma_buffer_phys;
|
||||
vm_paddr_t sc_sdhci_buffer_phys;;
|
||||
};
|
||||
|
||||
#define SD_MAX_BLOCKSIZE 1024
|
||||
/* XXX */
|
||||
|
||||
static int bcm_sdhci_probe(device_t);
|
||||
static int bcm_sdhci_attach(device_t);
|
||||
static int bcm_sdhci_detach(device_t);
|
||||
static void bcm_sdhci_intr(void *);
|
||||
|
||||
static int bcm_sdhci_get_ro(device_t, device_t);
|
||||
static void bcm_sdhci_dma_intr(int ch, void *arg);
|
||||
|
||||
#define bcm_sdhci_lock(_sc) \
|
||||
mtx_lock(&_sc->sc_mtx);
|
||||
#define bcm_sdhci_unlock(_sc) \
|
||||
mtx_unlock(&_sc->sc_mtx);
|
||||
|
||||
static void
|
||||
bcm_dmamap_cb(void *arg, bus_dma_segment_t *segs,
|
||||
int nseg, int err)
|
||||
{
|
||||
bus_addr_t *addr;
|
||||
|
||||
if (err)
|
||||
return;
|
||||
|
||||
addr = (bus_addr_t*)arg;
|
||||
*addr = segs[0].ds_addr;
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_sdhci_probe(device_t dev)
|
||||
{
|
||||
@ -146,9 +171,13 @@ bcm_sdhci_attach(device_t dev)
|
||||
phandle_t node;
|
||||
pcell_t cell;
|
||||
int default_freq;
|
||||
void *buffer;
|
||||
vm_paddr_t buffer_phys;
|
||||
void *va;
|
||||
|
||||
sc->sc_dev = dev;
|
||||
sc->sc_req = NULL;
|
||||
err = 0;
|
||||
|
||||
default_freq = BCM2835_DEFAULT_SDHCI_FREQ;
|
||||
node = ofw_bus_get_node(sc->sc_dev);
|
||||
@ -191,6 +220,9 @@ bcm_sdhci_attach(device_t dev)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!bcm2835_sdhci_pio_mode)
|
||||
sc->sc_slot.opt = SDHCI_PLATFORM_TRANSFER;
|
||||
|
||||
sc->sc_slot.caps = SDHCI_CAN_VDD_330 | SDHCI_CAN_VDD_180;
|
||||
if (bcm2835_sdhci_hs)
|
||||
sc->sc_slot.caps |= SDHCI_CAN_DO_HISPD;
|
||||
@ -201,6 +233,61 @@ bcm_sdhci_attach(device_t dev)
|
||||
|
||||
sdhci_init_slot(dev, &sc->sc_slot, 0);
|
||||
|
||||
sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_FAST1);
|
||||
if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
|
||||
sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_FAST2);
|
||||
if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
|
||||
sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_ANY);
|
||||
if (sc->sc_dma_ch == BCM_DMA_CH_INVALID)
|
||||
goto fail;
|
||||
|
||||
bcm_dma_setup_intr(sc->sc_dma_ch, bcm_sdhci_dma_intr, sc);
|
||||
|
||||
/* Allocate DMA buffers */
|
||||
err = bus_dma_tag_create(bus_get_dma_tag(dev),
|
||||
1, 0, BUS_SPACE_MAXADDR_32BIT,
|
||||
BUS_SPACE_MAXADDR, NULL, NULL,
|
||||
BCM_SDHCI_BUFFER_SIZE, 1, BCM_SDHCI_BUFFER_SIZE,
|
||||
BUS_DMA_ALLOCNOW, NULL, NULL,
|
||||
&sc->sc_dma_tag);
|
||||
|
||||
if (err) {
|
||||
device_printf(dev, "failed allocate DMA tag");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = bus_dmamem_alloc(sc->sc_dma_tag, &buffer,
|
||||
BUS_DMA_WAITOK | BUS_DMA_COHERENT| BUS_DMA_ZERO,
|
||||
&sc->sc_dma_map);
|
||||
|
||||
if (err) {
|
||||
device_printf(dev, "cannot allocate DMA memory\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, buffer,
|
||||
BCM_SDHCI_BUFFER_SIZE, bcm_dmamap_cb, &buffer_phys,
|
||||
BUS_DMA_WAITOK);
|
||||
if (err) {
|
||||
device_printf(dev, "cannot load DMA memory\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity check: two least bits of address should be zero
|
||||
*/
|
||||
if ((uintptr_t)buffer & 3) {
|
||||
device_printf(dev,
|
||||
"DMA address is not word-aligned\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sc->sc_dma_buffer = buffer;
|
||||
sc->sc_dma_buffer_phys = buffer_phys;
|
||||
va = (void*)rman_get_start(sc->sc_mem_res);
|
||||
sc->sc_sdhci_buffer_phys =
|
||||
pmap_kextract((vm_offset_t)va) + SDHCI_BUFFER;
|
||||
|
||||
bus_generic_probe(dev);
|
||||
bus_generic_attach(dev);
|
||||
|
||||
@ -354,6 +441,211 @@ bcm_sdhci_min_freq(device_t dev, struct sdhci_slot *slot)
|
||||
return bcm2835_sdhci_min_freq;
|
||||
}
|
||||
|
||||
static void
|
||||
bcm_sdhci_dma_intr(int ch, void *arg)
|
||||
{
|
||||
struct bcm_sdhci_softc *sc = (struct bcm_sdhci_softc *)arg;
|
||||
struct sdhci_slot *slot = &sc->sc_slot;
|
||||
uint32_t reg, mask;
|
||||
void *buffer;
|
||||
size_t len;
|
||||
int left;
|
||||
|
||||
mtx_lock(&slot->mtx);
|
||||
|
||||
/* copy DMA buffer to VA if READ */
|
||||
len = bcm_dma_length(sc->sc_dma_ch);
|
||||
if (slot->curcmd->data->flags & MMC_DATA_READ) {
|
||||
bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
|
||||
BUS_DMASYNC_POSTREAD);
|
||||
|
||||
mask = SDHCI_INT_DATA_AVAIL;
|
||||
/* all dma data in single or contiguous page */
|
||||
buffer = (uint8_t*)(slot->curcmd->data->data) + slot->offset;
|
||||
memcpy(buffer, sc->sc_dma_buffer, len);
|
||||
} else {
|
||||
bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
|
||||
BUS_DMASYNC_POSTWRITE);
|
||||
mask = SDHCI_INT_SPACE_AVAIL;
|
||||
}
|
||||
|
||||
slot->offset += len;
|
||||
sc->sc_dma_inuse = 0;
|
||||
|
||||
left = min(BCM_SDHCI_BUFFER_SIZE,
|
||||
slot->curcmd->data->len - slot->offset);
|
||||
|
||||
/* DATA END? */
|
||||
reg = bcm_sdhci_read_4(slot->bus, slot, SDHCI_INT_STATUS);
|
||||
|
||||
if (reg & SDHCI_INT_DATA_END) {
|
||||
/* ACK for all outstanding interrupts */
|
||||
bcm_sdhci_write_4(slot->bus, slot, SDHCI_INT_STATUS, reg);
|
||||
|
||||
/* enable INT */
|
||||
slot->intmask |= SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL
|
||||
| SDHCI_INT_DATA_END;
|
||||
bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE,
|
||||
slot->intmask);
|
||||
|
||||
/* finish this data */
|
||||
sdhci_finish_data(slot);
|
||||
}
|
||||
else {
|
||||
/* already available? */
|
||||
if (reg & mask) {
|
||||
sc->sc_dma_inuse = 1;
|
||||
|
||||
/* ACK for DATA_AVAIL or SPACE_AVAIL */
|
||||
bcm_sdhci_write_4(slot->bus, slot,
|
||||
SDHCI_INT_STATUS, mask);
|
||||
|
||||
/* continue next DMA transfer */
|
||||
if (slot->curcmd->data->flags & MMC_DATA_READ) {
|
||||
bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
|
||||
BUS_DMASYNC_PREREAD);
|
||||
|
||||
/* DMA start */
|
||||
if (bcm_dma_start(sc->sc_dma_ch,
|
||||
sc->sc_sdhci_buffer_phys,
|
||||
sc->sc_dma_buffer_phys, left) != 0)
|
||||
device_printf(sc->sc_dev, "failed DMA start\n");
|
||||
} else {
|
||||
buffer = (char*)slot->curcmd->data->data + slot->offset;
|
||||
memcpy(sc->sc_dma_buffer, buffer, left);
|
||||
|
||||
bus_dmamap_sync(sc->sc_dma_tag,
|
||||
sc->sc_dma_map, BUS_DMASYNC_PREWRITE);
|
||||
|
||||
/* DMA start */
|
||||
if (bcm_dma_start(sc->sc_dma_ch,
|
||||
sc->sc_dma_buffer_phys,
|
||||
sc->sc_sdhci_buffer_phys, left) != 0)
|
||||
device_printf(sc->sc_dev, "failed DMA start\n");
|
||||
}
|
||||
} else {
|
||||
/* wait for next data by INT */
|
||||
|
||||
/* enable INT */
|
||||
slot->intmask |= SDHCI_INT_DATA_AVAIL |
|
||||
SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_END;
|
||||
bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE,
|
||||
slot->intmask);
|
||||
}
|
||||
}
|
||||
|
||||
mtx_unlock(&slot->mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
bcm_sdhci_read_dma(struct sdhci_slot *slot)
|
||||
{
|
||||
struct bcm_sdhci_softc *sc = device_get_softc(slot->bus);
|
||||
size_t left;
|
||||
|
||||
if (sc->sc_dma_inuse) {
|
||||
device_printf(sc->sc_dev, "DMA in use\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_dma_inuse = 1;
|
||||
|
||||
left = min(BCM_SDHCI_BUFFER_SIZE,
|
||||
slot->curcmd->data->len - slot->offset);
|
||||
|
||||
KASSERT((left & 3) == 0,
|
||||
("%s: len = %d, not word-aligned", __func__, left));
|
||||
|
||||
bcm_dma_setup_src(sc->sc_dma_ch, BCM_DMA_DREQ_EMMC,
|
||||
BCM_DMA_SAME_ADDR, BCM_DMA_32BIT);
|
||||
bcm_dma_setup_dst(sc->sc_dma_ch, BCM_DMA_DREQ_NONE,
|
||||
BCM_DMA_INC_ADDR,
|
||||
(left & 0xf) ? BCM_DMA_32BIT : BCM_DMA_128BIT);
|
||||
|
||||
bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
|
||||
BUS_DMASYNC_PREREAD);
|
||||
|
||||
/* DMA start */
|
||||
if (bcm_dma_start(sc->sc_dma_ch, sc->sc_sdhci_buffer_phys,
|
||||
sc->sc_dma_buffer_phys, left) != 0)
|
||||
device_printf(sc->sc_dev, "failed DMA start\n");
|
||||
}
|
||||
|
||||
static void
|
||||
bcm_sdhci_write_dma(struct sdhci_slot *slot)
|
||||
{
|
||||
struct bcm_sdhci_softc *sc = device_get_softc(slot->bus);
|
||||
char *buffer;
|
||||
size_t left;
|
||||
|
||||
if (sc->sc_dma_inuse) {
|
||||
device_printf(sc->sc_dev, "DMA in use\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_dma_inuse = 1;
|
||||
|
||||
left = min(BCM_SDHCI_BUFFER_SIZE,
|
||||
slot->curcmd->data->len - slot->offset);
|
||||
|
||||
KASSERT((left & 3) == 0,
|
||||
("%s: len = %d, not word-aligned", __func__, left));
|
||||
|
||||
buffer = (char*)slot->curcmd->data->data + slot->offset;
|
||||
memcpy(sc->sc_dma_buffer, buffer, left);
|
||||
|
||||
bcm_dma_setup_src(sc->sc_dma_ch, BCM_DMA_DREQ_NONE,
|
||||
BCM_DMA_INC_ADDR,
|
||||
(left & 0xf) ? BCM_DMA_32BIT : BCM_DMA_128BIT);
|
||||
bcm_dma_setup_dst(sc->sc_dma_ch, BCM_DMA_DREQ_EMMC,
|
||||
BCM_DMA_SAME_ADDR, BCM_DMA_32BIT);
|
||||
|
||||
bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map,
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
|
||||
/* DMA start */
|
||||
if (bcm_dma_start(sc->sc_dma_ch, sc->sc_dma_buffer_phys,
|
||||
sc->sc_sdhci_buffer_phys, left) != 0)
|
||||
device_printf(sc->sc_dev, "failed DMA start\n");
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_sdhci_will_handle_transfer(device_t dev, struct sdhci_slot *slot)
|
||||
{
|
||||
size_t left;
|
||||
|
||||
/* Do not use DMA for transfers less then block size */
|
||||
left = min(BCM_DMA_BLOCK_SIZE,
|
||||
slot->curcmd->data->len - slot->offset);
|
||||
if (left < BCM_DMA_BLOCK_SIZE)
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
bcm_sdhci_start_transfer(device_t dev, struct sdhci_slot *slot,
|
||||
uint32_t *intmask)
|
||||
{
|
||||
|
||||
/* Disable INT */
|
||||
slot->intmask &= ~(SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_END);
|
||||
bcm_sdhci_write_4(dev, slot, SDHCI_SIGNAL_ENABLE, slot->intmask);
|
||||
|
||||
/* DMA transfer FIFO 1KB */
|
||||
if (slot->curcmd->data->flags & MMC_DATA_READ)
|
||||
bcm_sdhci_read_dma(slot);
|
||||
else
|
||||
bcm_sdhci_write_dma(slot);
|
||||
}
|
||||
|
||||
static void
|
||||
bcm_sdhci_finish_transfer(device_t dev, struct sdhci_slot *slot)
|
||||
{
|
||||
|
||||
sdhci_finish_data(slot);
|
||||
}
|
||||
|
||||
static device_method_t bcm_sdhci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bcm_sdhci_probe),
|
||||
@ -372,8 +664,12 @@ static device_method_t bcm_sdhci_methods[] = {
|
||||
DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host),
|
||||
DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host),
|
||||
|
||||
/* SDHCI registers accessors */
|
||||
DEVMETHOD(sdhci_min_freq, bcm_sdhci_min_freq),
|
||||
/* Platform transfer methods */
|
||||
DEVMETHOD(sdhci_platform_will_handle, bcm_sdhci_will_handle_transfer),
|
||||
DEVMETHOD(sdhci_platform_start_transfer, bcm_sdhci_start_transfer),
|
||||
DEVMETHOD(sdhci_platform_finish_transfer, bcm_sdhci_finish_transfer),
|
||||
/* SDHCI registers accessors */
|
||||
DEVMETHOD(sdhci_read_1, bcm_sdhci_read_1),
|
||||
DEVMETHOD(sdhci_read_2, bcm_sdhci_read_2),
|
||||
DEVMETHOD(sdhci_read_4, bcm_sdhci_read_4),
|
||||
|
@ -118,19 +118,16 @@ bcm_systimer_tc_get_timecount(struct timecounter *tc)
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_systimer_start(struct eventtimer *et, struct bintime *first,
|
||||
struct bintime *period)
|
||||
bcm_systimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
|
||||
{
|
||||
struct systimer *st = et->et_priv;
|
||||
uint32_t clo;
|
||||
uint32_t count;
|
||||
register_t s;
|
||||
|
||||
if (first != NULL) {
|
||||
if (first != 0) {
|
||||
|
||||
count = (st->et.et_frequency * (first->frac >> 32)) >> 32;
|
||||
if (first->sec != 0)
|
||||
count += st->et.et_frequency * first->sec;
|
||||
count = ((uint32_t)et->et_frequency * first) >> 32;
|
||||
|
||||
s = intr_disable();
|
||||
clo = bcm_systimer_tc_read_4(SYSTIMER_CLO);
|
||||
@ -238,12 +235,10 @@ bcm_systimer_attach(device_t dev)
|
||||
sc->st[DEFAULT_TIMER].et.et_flags = ET_FLAGS_ONESHOT;
|
||||
sc->st[DEFAULT_TIMER].et.et_quality = 1000;
|
||||
sc->st[DEFAULT_TIMER].et.et_frequency = sc->sysclk_freq;
|
||||
sc->st[DEFAULT_TIMER].et.et_min_period.sec = 0;
|
||||
sc->st[DEFAULT_TIMER].et.et_min_period.frac =
|
||||
((MIN_PERIOD << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) << 32;
|
||||
sc->st[DEFAULT_TIMER].et.et_max_period.sec = 0xfffffff0U / sc->st[DEFAULT_TIMER].et.et_frequency;
|
||||
sc->st[DEFAULT_TIMER].et.et_max_period.frac =
|
||||
((0xfffffffeLLU << 32) / sc->st[DEFAULT_TIMER].et.et_frequency) << 32;
|
||||
sc->st[DEFAULT_TIMER].et.et_min_period =
|
||||
(MIN_PERIOD << 32) / sc->st[DEFAULT_TIMER].et.et_frequency;
|
||||
sc->st[DEFAULT_TIMER].et.et_max_period =
|
||||
(0xfffffffeLLU << 32) / sc->st[DEFAULT_TIMER].et.et_frequency;
|
||||
sc->st[DEFAULT_TIMER].et.et_start = bcm_systimer_start;
|
||||
sc->st[DEFAULT_TIMER].et.et_stop = bcm_systimer_stop;
|
||||
sc->st[DEFAULT_TIMER].et.et_priv = &sc->st[DEFAULT_TIMER];
|
||||
|
@ -1,5 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
arm/broadcom/bcm2835/bcm2835_dma.c standard
|
||||
arm/broadcom/bcm2835/bcm2835_fb.c optional sc
|
||||
arm/broadcom/bcm2835/bcm2835_gpio.c optional gpio
|
||||
arm/broadcom/bcm2835/bcm2835_intr.c standard
|
||||
|
@ -87,8 +87,8 @@ options ROOTDEVNAME=\"ufs:/dev/da0s2\"
|
||||
#options ATA_STATIC_ID # Static device numbering
|
||||
|
||||
# Console and misc
|
||||
#device uart
|
||||
#device uart_ns8250
|
||||
device uart
|
||||
device uart_ns8250
|
||||
device pty
|
||||
device snp
|
||||
device md
|
||||
|
@ -117,4 +117,4 @@ options FDT
|
||||
# Note: DTB is normally loaded and modified by RPi boot loader, then
|
||||
# handed to kernel via U-Boot and ubldr.
|
||||
#options FDT_DTB_STATIC
|
||||
#makeoptions FDT_DTS_FILE=bcm2835-rpi-b.dts
|
||||
makeoptions FDT_DTS_FILE=bcm2835-rpi-b.dts
|
||||
|
@ -68,7 +68,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <machine/pmap.h>
|
||||
#include <machine/vmparam.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/undefined.h>
|
||||
|
@ -34,9 +34,32 @@
|
||||
#ifndef _MACHINE_VMPARAM_H_
|
||||
#define _MACHINE_VMPARAM_H_
|
||||
|
||||
/*
|
||||
* Machine dependent constants for ARM.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Virtual memory related constants, all in bytes
|
||||
*/
|
||||
#ifndef MAXTSIZ
|
||||
#define MAXTSIZ (64UL*1024*1024) /* max text size */
|
||||
#endif
|
||||
#ifndef DFLDSIZ
|
||||
#define DFLDSIZ (128UL*1024*1024) /* initial data size limit */
|
||||
#endif
|
||||
#ifndef MAXDSIZ
|
||||
#define MAXDSIZ (512UL*1024*1024) /* max data size */
|
||||
#endif
|
||||
#ifndef DFLSSIZ
|
||||
#define DFLSSIZ (2UL*1024*1024) /* initial stack size limit */
|
||||
#endif
|
||||
#ifndef MAXSSIZ
|
||||
#define MAXSSIZ (8UL*1024*1024) /* max stack size */
|
||||
#endif
|
||||
#ifndef SGROWSIZ
|
||||
#define SGROWSIZ (128UL*1024) /* amount to grow stack */
|
||||
#endif
|
||||
|
||||
/*#include <arm/arm32/vmparam.h>
|
||||
*/
|
||||
/*
|
||||
* Address space constants
|
||||
*/
|
||||
@ -153,23 +176,6 @@
|
||||
VM_MIN_KERNEL_ADDRESS + 1) * 2 / 5)
|
||||
#endif
|
||||
|
||||
#define MAXTSIZ (16*1024*1024)
|
||||
#ifndef DFLDSIZ
|
||||
#define DFLDSIZ (128*1024*1024)
|
||||
#endif
|
||||
#ifndef MAXDSIZ
|
||||
#define MAXDSIZ (512*1024*1024)
|
||||
#endif
|
||||
#ifndef DFLSSIZ
|
||||
#define DFLSSIZ (2*1024*1024)
|
||||
#endif
|
||||
#ifndef MAXSSIZ
|
||||
#define MAXSSIZ (8*1024*1024)
|
||||
#endif
|
||||
#ifndef SGROWSIZ
|
||||
#define SGROWSIZ (128*1024)
|
||||
#endif
|
||||
|
||||
#ifdef ARM_USE_SMALL_ALLOC
|
||||
#define UMA_MD_SMALL_ALLOC
|
||||
#endif /* ARM_USE_SMALL_ALLOC */
|
||||
@ -178,4 +184,8 @@ extern vm_offset_t vm_max_kernel_address;
|
||||
|
||||
#define ZERO_REGION_SIZE (64 * 1024) /* 64KB */
|
||||
|
||||
#ifndef VM_MAX_AUTOTUNE_MAXUSERS
|
||||
#define VM_MAX_AUTOTUNE_MAXUSERS 384
|
||||
#endif
|
||||
|
||||
#endif /* _MACHINE_VMPARAM_H_ */
|
||||
|
@ -72,8 +72,8 @@ static struct lpc_timer_softc *timer_softc = NULL;
|
||||
static int lpc_timer_initialized = 0;
|
||||
static int lpc_timer_probe(device_t);
|
||||
static int lpc_timer_attach(device_t);
|
||||
static int lpc_timer_start(struct eventtimer *, struct bintime *first,
|
||||
struct bintime *);
|
||||
static int lpc_timer_start(struct eventtimer *,
|
||||
sbintime_t first, sbintime_t period);
|
||||
static int lpc_timer_stop(struct eventtimer *et);
|
||||
static unsigned lpc_get_timecount(struct timecounter *);
|
||||
static int lpc_hardclock(void *);
|
||||
@ -173,12 +173,8 @@ lpc_timer_attach(device_t dev)
|
||||
sc->lt_et.et_name = "LPC32x0 Timer0";
|
||||
sc->lt_et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
|
||||
sc->lt_et.et_quality = 1000;
|
||||
sc->lt_et.et_min_period.sec = 0;
|
||||
sc->lt_et.et_min_period.frac =
|
||||
((0x00000002LLU << 32) / sc->lt_et.et_frequency) << 32;
|
||||
sc->lt_et.et_max_period.sec = 0xfffffff0U / sc->lt_et.et_frequency;
|
||||
sc->lt_et.et_max_period.frac =
|
||||
((0xfffffffeLLU << 32) / sc->lt_et.et_frequency) << 32;
|
||||
sc->lt_et.et_min_period = (0x00000002LLU << 32) / sc->lt_et.et_frequency;
|
||||
sc->lt_et.et_max_period = (0xfffffffeLLU << 32) / sc->lt_et.et_frequency;
|
||||
sc->lt_et.et_start = lpc_timer_start;
|
||||
sc->lt_et.et_stop = lpc_timer_stop;
|
||||
sc->lt_et.et_priv = sc;
|
||||
@ -199,27 +195,23 @@ lpc_timer_attach(device_t dev)
|
||||
}
|
||||
|
||||
static int
|
||||
lpc_timer_start(struct eventtimer *et, struct bintime *first,
|
||||
struct bintime *period)
|
||||
lpc_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
|
||||
{
|
||||
struct lpc_timer_softc *sc = (struct lpc_timer_softc *)et->et_priv;
|
||||
uint32_t ticks;
|
||||
|
||||
if (period == NULL)
|
||||
if (period == 0) {
|
||||
sc->lt_oneshot = 1;
|
||||
else {
|
||||
sc->lt_period = 0;
|
||||
} else {
|
||||
sc->lt_oneshot = 0;
|
||||
sc->lt_period = (sc->lt_et.et_frequency * (first->frac >> 32)) >> 32;
|
||||
sc->lt_period += sc->lt_et.et_frequency * first->sec;
|
||||
sc->lt_period = ((uint32_t)et->et_frequency * period) >> 32;
|
||||
}
|
||||
|
||||
if (first == NULL)
|
||||
if (first == 0)
|
||||
ticks = sc->lt_period;
|
||||
else {
|
||||
ticks = (sc->lt_et.et_frequency * (first->frac >> 32)) >> 32;
|
||||
if (first->sec != 0)
|
||||
ticks += sc->lt_et.et_frequency * first->sec;
|
||||
}
|
||||
else
|
||||
ticks = ((uint32_t)et->et_frequency * first) >> 32;
|
||||
|
||||
/* Reset timer */
|
||||
timer0_write_4(sc, LPC_TIMER_TCR, LPC_TIMER_TCR_RESET);
|
||||
|
@ -93,7 +93,7 @@ static void mv_watchdog_enable(void);
|
||||
static void mv_watchdog_disable(void);
|
||||
static void mv_watchdog_event(void *, unsigned int, int *);
|
||||
static int mv_timer_start(struct eventtimer *et,
|
||||
struct bintime *first, struct bintime *period);
|
||||
sbintime_t first, sbintime_t period);
|
||||
static int mv_timer_stop(struct eventtimer *et);
|
||||
static void mv_setup_timers(void);
|
||||
|
||||
@ -168,12 +168,8 @@ mv_timer_attach(device_t dev)
|
||||
sc->et.et_quality = 1000;
|
||||
|
||||
sc->et.et_frequency = MV_CLOCK_SRC;
|
||||
sc->et.et_min_period.sec = 0;
|
||||
sc->et.et_min_period.frac =
|
||||
((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
|
||||
sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
|
||||
sc->et.et_max_period.frac =
|
||||
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
|
||||
sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
|
||||
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
|
||||
sc->et.et_start = mv_timer_start;
|
||||
sc->et.et_stop = mv_timer_stop;
|
||||
sc->et.et_priv = sc;
|
||||
@ -394,25 +390,20 @@ mv_watchdog_event(void *arg, unsigned int cmd, int *error)
|
||||
}
|
||||
|
||||
static int
|
||||
mv_timer_start(struct eventtimer *et,
|
||||
struct bintime *first, struct bintime *period)
|
||||
mv_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
|
||||
{
|
||||
struct mv_timer_softc *sc;
|
||||
uint32_t val, val1;
|
||||
|
||||
/* Calculate dividers. */
|
||||
sc = (struct mv_timer_softc *)et->et_priv;
|
||||
if (period != NULL) {
|
||||
val = (sc->et.et_frequency * (period->frac >> 32)) >> 32;
|
||||
if (period->sec != 0)
|
||||
val += sc->et.et_frequency * period->sec;
|
||||
} else
|
||||
if (period != 0)
|
||||
val = ((uint32_t)sc->et.et_frequency * period) >> 32;
|
||||
else
|
||||
val = 0;
|
||||
if (first != NULL) {
|
||||
val1 = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
|
||||
if (first->sec != 0)
|
||||
val1 += sc->et.et_frequency * first->sec;
|
||||
} else
|
||||
if (first != 0)
|
||||
val1 = ((uint32_t)sc->et.et_frequency * first) >> 32;
|
||||
else
|
||||
val1 = val;
|
||||
|
||||
/* Apply configuration. */
|
||||
@ -420,7 +411,7 @@ mv_timer_start(struct eventtimer *et,
|
||||
mv_set_timer(0, val1);
|
||||
val = mv_get_timer_control();
|
||||
val |= CPU_TIMER0_EN;
|
||||
if (period != NULL)
|
||||
if (period != 0)
|
||||
val |= CPU_TIMER0_AUTO;
|
||||
else
|
||||
val &= ~CPU_TIMER0_AUTO;
|
||||
|
@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <machine/pmap.h>
|
||||
#include <machine/vmparam.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/undefined.h>
|
||||
|
@ -143,30 +143,24 @@ am335x_dmtimer_tc_get_timecount(struct timecounter *tc)
|
||||
}
|
||||
|
||||
static int
|
||||
am335x_dmtimer_start(struct eventtimer *et, struct bintime *first,
|
||||
struct bintime *period)
|
||||
am335x_dmtimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
|
||||
{
|
||||
struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)et->et_priv;
|
||||
uint32_t load, count;
|
||||
uint32_t tclr = 0;
|
||||
|
||||
if (period != NULL) {
|
||||
load = (et->et_frequency * (period->frac >> 32)) >> 32;
|
||||
if (period->sec > 0)
|
||||
load += et->et_frequency * period->sec;
|
||||
if (period != 0) {
|
||||
load = ((uint32_t)et->et_frequency * period) >> 32;
|
||||
tclr |= 2; /* autoreload bit */
|
||||
panic("periodic timer not implemented\n");
|
||||
} else {
|
||||
load = 0;
|
||||
}
|
||||
|
||||
if (first != NULL) {
|
||||
count = (tmr->et.et_frequency * (first->frac >> 32)) >> 32;
|
||||
if (first->sec != 0)
|
||||
count += tmr->et.et_frequency * first->sec;
|
||||
} else {
|
||||
if (first != 0)
|
||||
count = ((uint32_t)et->et_frequency * first) >> 32;
|
||||
else
|
||||
count = load;
|
||||
}
|
||||
|
||||
/* Reset Timer */
|
||||
am335x_dmtimer_et_write_4(DMTIMER_TSICR, 2);
|
||||
@ -316,12 +310,10 @@ am335x_dmtimer_attach(device_t dev)
|
||||
sc->t[3].et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
|
||||
sc->t[3].et.et_quality = 1000;
|
||||
sc->t[3].et.et_frequency = sc->sysclk_freq;
|
||||
sc->t[3].et.et_min_period.sec = 0;
|
||||
sc->t[3].et.et_min_period.frac =
|
||||
((0x00000002LLU << 32) / sc->t[3].et.et_frequency) << 32;
|
||||
sc->t[3].et.et_max_period.sec = 0xfffffff0U / sc->t[3].et.et_frequency;
|
||||
sc->t[3].et.et_max_period.frac =
|
||||
((0xfffffffeLLU << 32) / sc->t[3].et.et_frequency) << 32;
|
||||
sc->t[3].et.et_min_period =
|
||||
(0x00000002LLU << 32) / sc->t[3].et.et_frequency;
|
||||
sc->t[3].et.et_max_period =
|
||||
(0xfffffffeLLU << 32) / sc->t[3].et.et_frequency;
|
||||
sc->t[3].et.et_start = am335x_dmtimer_start;
|
||||
sc->t[3].et.et_stop = am335x_dmtimer_stop;
|
||||
sc->t[3].et.et_priv = &sc->t[3];
|
||||
|
@ -120,18 +120,15 @@ sp804_timer_tc_get_timecount(struct timecounter *tc)
|
||||
}
|
||||
|
||||
static int
|
||||
sp804_timer_start(struct eventtimer *et, struct bintime *first,
|
||||
struct bintime *period)
|
||||
sp804_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
|
||||
{
|
||||
struct sp804_timer_softc *sc = et->et_priv;
|
||||
uint32_t count, reg;
|
||||
|
||||
if (first != NULL) {
|
||||
if (first != 0) {
|
||||
sc->et_enabled = 1;
|
||||
|
||||
count = (sc->et.et_frequency * (first->frac >> 32)) >> 32;
|
||||
if (first->sec != 0)
|
||||
count += sc->et.et_frequency * first->sec;
|
||||
count = ((uint32_t)et->et_frequency * first) >> 32;
|
||||
|
||||
sp804_timer_tc_write_4(SP804_TIMER2_LOAD, count);
|
||||
reg = TIMER_CONTROL_32BIT | TIMER_CONTROL_INTREN |
|
||||
@ -142,7 +139,7 @@ sp804_timer_start(struct eventtimer *et, struct bintime *first,
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (period != NULL) {
|
||||
if (period != 0) {
|
||||
panic("period");
|
||||
}
|
||||
|
||||
@ -264,12 +261,8 @@ sp804_timer_attach(device_t dev)
|
||||
sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
|
||||
sc->et.et_quality = 1000;
|
||||
sc->et.et_frequency = sc->sysclk_freq / DEFAULT_DIVISOR;
|
||||
sc->et.et_min_period.sec = 0;
|
||||
sc->et.et_min_period.frac =
|
||||
((0x00000002LLU << 32) / sc->et.et_frequency) << 32;
|
||||
sc->et.et_max_period.sec = 0xfffffff0U / sc->et.et_frequency;
|
||||
sc->et.et_max_period.frac =
|
||||
((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32;
|
||||
sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
|
||||
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
|
||||
sc->et.et_start = sp804_timer_start;
|
||||
sc->et.et_stop = sp804_timer_stop;
|
||||
sc->et.et_priv = sc;
|
||||
|
@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <machine/pmap.h>
|
||||
#include <machine/vmparam.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/undefined.h>
|
||||
|
@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <machine/pmap.h>
|
||||
#include <machine/vmparam.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/undefined.h>
|
||||
|
@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <machine/pmap.h>
|
||||
#include <machine/vmparam.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/undefined.h>
|
||||
|
@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <machine/pmap.h>
|
||||
#include <machine/vmparam.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/undefined.h>
|
||||
|
@ -80,7 +80,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <machine/pmap.h>
|
||||
#include <machine/vmparam.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/undefined.h>
|
||||
|
@ -121,6 +121,8 @@
|
||||
interrupt-parent = <&AINTC>;
|
||||
current-speed = <115200>;
|
||||
clock-frequency = < 24000000 >;
|
||||
busy-detect = <1>;
|
||||
broken-txfifo = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -588,7 +588,7 @@
|
||||
#define AUE_OPENAT 43184 /* FreeBSD. */
|
||||
#define AUE_POSIX_OPENPT 43185 /* FreeBSD. */
|
||||
#define AUE_CAP_NEW 43186 /* TrustedBSD. */
|
||||
#define AUE_CAP_GETRIGHTS 43187 /* TrustedBSD. */
|
||||
#define AUE_CAP_RIGHTS_GET 43187 /* TrustedBSD. */
|
||||
#define AUE_CAP_ENTER 43188 /* TrustedBSD. */
|
||||
#define AUE_CAP_GETMODE 43189 /* TrustedBSD. */
|
||||
#define AUE_POSIX_SPAWN 43190 /* Darwin. */
|
||||
@ -603,6 +603,11 @@
|
||||
#define AUE_PDGETPID 43199 /* FreeBSD. */
|
||||
#define AUE_PDWAIT 43200 /* FreeBSD. */
|
||||
#define AUE_WAIT6 43201 /* FreeBSD. */
|
||||
#define AUE_CAP_RIGHTS_LIMIT 43202 /* TrustedBSD. */
|
||||
#define AUE_CAP_IOCTLS_LIMIT 43203 /* TrustedBSD. */
|
||||
#define AUE_CAP_IOCTLS_GET 43204 /* TrustedBSD. */
|
||||
#define AUE_CAP_FCNTLS_LIMIT 43205 /* TrustedBSD. */
|
||||
#define AUE_CAP_FCNTLS_GET 43206 /* TrustedBSD. */
|
||||
|
||||
/*
|
||||
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
|
||||
|
@ -39,15 +39,11 @@ typedef struct file file_t;
|
||||
#include <sys/capability.h>
|
||||
|
||||
static __inline file_t *
|
||||
getf(int fd)
|
||||
getf(int fd, cap_rights_t rights)
|
||||
{
|
||||
struct file *fp;
|
||||
|
||||
/*
|
||||
* We wouldn't need all of these rights on every invocation
|
||||
* if we had more information about intent.
|
||||
*/
|
||||
if (fget(curthread, fd, CAP_READ | CAP_WRITE | CAP_SEEK, &fp) == 0)
|
||||
if (fget(curthread, fd, rights, &fp) == 0)
|
||||
return (fp);
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2010 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
* Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
* Portions Copyright 2005, 2010, Oracle and/or its affiliates.
|
||||
* All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
@ -35,22 +35,100 @@
|
||||
#include <sys/zfs_ioctl.h>
|
||||
#include "zfs_ioctl_compat.h"
|
||||
|
||||
static int zfs_version_ioctl = ZFS_IOCVER_CURRENT;
|
||||
SYSCTL_DECL(_vfs_zfs_version);
|
||||
SYSCTL_INT(_vfs_zfs_version, OID_AUTO, ioctl, CTLFLAG_RD, &zfs_version_ioctl,
|
||||
0, "ZFS_IOCTL_VERSION");
|
||||
|
||||
/*
|
||||
* FreeBSD zfs_cmd compatibility with v15 and older binaries
|
||||
* FreeBSD zfs_cmd compatibility with older binaries
|
||||
* appropriately remap/extend the zfs_cmd_t structure
|
||||
*/
|
||||
void
|
||||
zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag)
|
||||
{
|
||||
zfs_cmd_v15_t *zc_c;
|
||||
zfs_cmd_v28_t *zc28_c;
|
||||
|
||||
if (cflag == ZFS_CMD_COMPAT_V15) {
|
||||
switch (cflag) {
|
||||
case ZFS_CMD_COMPAT_V28:
|
||||
zc28_c = (void *)addr;
|
||||
|
||||
/* zc */
|
||||
strlcpy(zc->zc_name, zc28_c->zc_name, MAXPATHLEN);
|
||||
strlcpy(zc->zc_value, zc28_c->zc_value, MAXPATHLEN * 2);
|
||||
strlcpy(zc->zc_string, zc28_c->zc_string, MAXPATHLEN);
|
||||
strlcpy(zc->zc_top_ds, zc28_c->zc_top_ds, MAXPATHLEN);
|
||||
zc->zc_guid = zc28_c->zc_guid;
|
||||
zc->zc_nvlist_conf = zc28_c->zc_nvlist_conf;
|
||||
zc->zc_nvlist_conf_size = zc28_c->zc_nvlist_conf_size;
|
||||
zc->zc_nvlist_src = zc28_c->zc_nvlist_src;
|
||||
zc->zc_nvlist_src_size = zc28_c->zc_nvlist_src_size;
|
||||
zc->zc_nvlist_dst = zc28_c->zc_nvlist_dst;
|
||||
zc->zc_nvlist_dst_size = zc28_c->zc_nvlist_dst_size;
|
||||
zc->zc_cookie = zc28_c->zc_cookie;
|
||||
zc->zc_objset_type = zc28_c->zc_objset_type;
|
||||
zc->zc_perm_action = zc28_c->zc_perm_action;
|
||||
zc->zc_history = zc28_c->zc_history;
|
||||
zc->zc_history_len = zc28_c->zc_history_len;
|
||||
zc->zc_history_offset = zc28_c->zc_history_offset;
|
||||
zc->zc_obj = zc28_c->zc_obj;
|
||||
zc->zc_iflags = zc28_c->zc_iflags;
|
||||
zc->zc_share = zc28_c->zc_share;
|
||||
zc->zc_jailid = zc28_c->zc_jailid;
|
||||
zc->zc_objset_stats = zc28_c->zc_objset_stats;
|
||||
zc->zc_begin_record = zc28_c->zc_begin_record;
|
||||
zc->zc_defer_destroy = zc28_c->zc_defer_destroy;
|
||||
zc->zc_temphold = zc28_c->zc_temphold;
|
||||
zc->zc_action_handle = zc28_c->zc_action_handle;
|
||||
zc->zc_cleanup_fd = zc28_c->zc_cleanup_fd;
|
||||
zc->zc_simple = zc28_c->zc_simple;
|
||||
bcopy(zc28_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad));
|
||||
zc->zc_sendobj = zc28_c->zc_sendobj;
|
||||
zc->zc_fromobj = zc28_c->zc_fromobj;
|
||||
zc->zc_createtxg = zc28_c->zc_createtxg;
|
||||
zc->zc_stat = zc28_c->zc_stat;
|
||||
|
||||
/* zc->zc_inject_record */
|
||||
zc->zc_inject_record.zi_objset =
|
||||
zc28_c->zc_inject_record.zi_objset;
|
||||
zc->zc_inject_record.zi_object =
|
||||
zc28_c->zc_inject_record.zi_object;
|
||||
zc->zc_inject_record.zi_start =
|
||||
zc28_c->zc_inject_record.zi_start;
|
||||
zc->zc_inject_record.zi_end =
|
||||
zc28_c->zc_inject_record.zi_end;
|
||||
zc->zc_inject_record.zi_guid =
|
||||
zc28_c->zc_inject_record.zi_guid;
|
||||
zc->zc_inject_record.zi_level =
|
||||
zc28_c->zc_inject_record.zi_level;
|
||||
zc->zc_inject_record.zi_error =
|
||||
zc28_c->zc_inject_record.zi_error;
|
||||
zc->zc_inject_record.zi_type =
|
||||
zc28_c->zc_inject_record.zi_type;
|
||||
zc->zc_inject_record.zi_freq =
|
||||
zc28_c->zc_inject_record.zi_freq;
|
||||
zc->zc_inject_record.zi_failfast =
|
||||
zc28_c->zc_inject_record.zi_failfast;
|
||||
strlcpy(zc->zc_inject_record.zi_func,
|
||||
zc28_c->zc_inject_record.zi_func, MAXNAMELEN);
|
||||
zc->zc_inject_record.zi_iotype =
|
||||
zc28_c->zc_inject_record.zi_iotype;
|
||||
zc->zc_inject_record.zi_duration =
|
||||
zc28_c->zc_inject_record.zi_duration;
|
||||
zc->zc_inject_record.zi_timer =
|
||||
zc28_c->zc_inject_record.zi_timer;
|
||||
zc->zc_inject_record.zi_cmd = ZINJECT_UNINITIALIZED;
|
||||
zc->zc_inject_record.zi_pad = 0;
|
||||
break;
|
||||
|
||||
case ZFS_CMD_COMPAT_V15:
|
||||
zc_c = (void *)addr;
|
||||
|
||||
/* zc */
|
||||
strlcpy(zc->zc_name,zc_c->zc_name,MAXPATHLEN);
|
||||
strlcpy(zc->zc_value,zc_c->zc_value,MAXPATHLEN);
|
||||
strlcpy(zc->zc_string,zc_c->zc_string,MAXPATHLEN);
|
||||
strlcpy(zc->zc_name, zc_c->zc_name, MAXPATHLEN);
|
||||
strlcpy(zc->zc_value, zc_c->zc_value, MAXPATHLEN);
|
||||
strlcpy(zc->zc_string, zc_c->zc_string, MAXPATHLEN);
|
||||
zc->zc_guid = zc_c->zc_guid;
|
||||
zc->zc_nvlist_conf = zc_c->zc_nvlist_conf;
|
||||
zc->zc_nvlist_conf_size = zc_c->zc_nvlist_conf_size;
|
||||
@ -91,6 +169,7 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag)
|
||||
zc_c->zc_inject_record.zi_freq;
|
||||
zc->zc_inject_record.zi_failfast =
|
||||
zc_c->zc_inject_record.zi_failfast;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,15 +177,84 @@ void
|
||||
zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_t addr, const int cflag)
|
||||
{
|
||||
zfs_cmd_v15_t *zc_c;
|
||||
zfs_cmd_v28_t *zc28_c;
|
||||
|
||||
switch (cflag) {
|
||||
case ZFS_CMD_COMPAT_V28:
|
||||
zc28_c = (void *)addr;
|
||||
|
||||
strlcpy(zc28_c->zc_name, zc->zc_name, MAXPATHLEN);
|
||||
strlcpy(zc28_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
|
||||
strlcpy(zc28_c->zc_string, zc->zc_string, MAXPATHLEN);
|
||||
strlcpy(zc28_c->zc_top_ds, zc->zc_top_ds, MAXPATHLEN);
|
||||
zc28_c->zc_guid = zc->zc_guid;
|
||||
zc28_c->zc_nvlist_conf = zc->zc_nvlist_conf;
|
||||
zc28_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
|
||||
zc28_c->zc_nvlist_src = zc->zc_nvlist_src;
|
||||
zc28_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
|
||||
zc28_c->zc_nvlist_dst = zc->zc_nvlist_dst;
|
||||
zc28_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
|
||||
zc28_c->zc_cookie = zc->zc_cookie;
|
||||
zc28_c->zc_objset_type = zc->zc_objset_type;
|
||||
zc28_c->zc_perm_action = zc->zc_perm_action;
|
||||
zc28_c->zc_history = zc->zc_history;
|
||||
zc28_c->zc_history_len = zc->zc_history_len;
|
||||
zc28_c->zc_history_offset = zc->zc_history_offset;
|
||||
zc28_c->zc_obj = zc->zc_obj;
|
||||
zc28_c->zc_iflags = zc->zc_iflags;
|
||||
zc28_c->zc_share = zc->zc_share;
|
||||
zc28_c->zc_jailid = zc->zc_jailid;
|
||||
zc28_c->zc_objset_stats = zc->zc_objset_stats;
|
||||
zc28_c->zc_begin_record = zc->zc_begin_record;
|
||||
zc28_c->zc_defer_destroy = zc->zc_defer_destroy;
|
||||
zc28_c->zc_temphold = zc->zc_temphold;
|
||||
zc28_c->zc_action_handle = zc->zc_action_handle;
|
||||
zc28_c->zc_cleanup_fd = zc->zc_cleanup_fd;
|
||||
zc28_c->zc_simple = zc->zc_simple;
|
||||
bcopy(zc->zc_pad, zc28_c->zc_pad, sizeof(zc28_c->zc_pad));
|
||||
zc28_c->zc_sendobj = zc->zc_sendobj;
|
||||
zc28_c->zc_fromobj = zc->zc_fromobj;
|
||||
zc28_c->zc_createtxg = zc->zc_createtxg;
|
||||
zc28_c->zc_stat = zc->zc_stat;
|
||||
|
||||
/* zc_inject_record */
|
||||
zc28_c->zc_inject_record.zi_objset =
|
||||
zc->zc_inject_record.zi_objset;
|
||||
zc28_c->zc_inject_record.zi_object =
|
||||
zc->zc_inject_record.zi_object;
|
||||
zc28_c->zc_inject_record.zi_start =
|
||||
zc->zc_inject_record.zi_start;
|
||||
zc28_c->zc_inject_record.zi_end =
|
||||
zc->zc_inject_record.zi_end;
|
||||
zc28_c->zc_inject_record.zi_guid =
|
||||
zc->zc_inject_record.zi_guid;
|
||||
zc28_c->zc_inject_record.zi_level =
|
||||
zc->zc_inject_record.zi_level;
|
||||
zc28_c->zc_inject_record.zi_error =
|
||||
zc->zc_inject_record.zi_error;
|
||||
zc28_c->zc_inject_record.zi_type =
|
||||
zc->zc_inject_record.zi_type;
|
||||
zc28_c->zc_inject_record.zi_freq =
|
||||
zc->zc_inject_record.zi_freq;
|
||||
zc28_c->zc_inject_record.zi_failfast =
|
||||
zc->zc_inject_record.zi_failfast;
|
||||
strlcpy(zc28_c->zc_inject_record.zi_func,
|
||||
zc->zc_inject_record.zi_func, MAXNAMELEN);
|
||||
zc28_c->zc_inject_record.zi_iotype =
|
||||
zc->zc_inject_record.zi_iotype;
|
||||
zc28_c->zc_inject_record.zi_duration =
|
||||
zc->zc_inject_record.zi_duration;
|
||||
zc28_c->zc_inject_record.zi_timer =
|
||||
zc->zc_inject_record.zi_timer;
|
||||
break;
|
||||
|
||||
case ZFS_CMD_COMPAT_V15:
|
||||
zc_c = (void *)addr;
|
||||
|
||||
/* zc */
|
||||
strlcpy(zc_c->zc_name,zc->zc_name,MAXPATHLEN);
|
||||
strlcpy(zc_c->zc_value,zc->zc_value,MAXPATHLEN);
|
||||
strlcpy(zc_c->zc_string,zc->zc_string,MAXPATHLEN);
|
||||
strlcpy(zc_c->zc_name, zc->zc_name, MAXPATHLEN);
|
||||
strlcpy(zc_c->zc_value, zc->zc_value, MAXPATHLEN);
|
||||
strlcpy(zc_c->zc_string, zc->zc_string, MAXPATHLEN);
|
||||
zc_c->zc_guid = zc->zc_guid;
|
||||
zc_c->zc_nvlist_conf = zc->zc_nvlist_conf;
|
||||
zc_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
|
||||
@ -260,7 +408,7 @@ zfs_ioctl_compat_fix_stats_nvlist(nvlist_t *nvl)
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int cflag)
|
||||
zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int nc)
|
||||
{
|
||||
nvlist_t *nv, *nvp = NULL;
|
||||
nvpair_t *elem;
|
||||
@ -270,7 +418,7 @@ zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int cflag)
|
||||
zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
|
||||
return (error);
|
||||
|
||||
if (cflag == 5) { /* ZFS_IOC_POOL_STATS */
|
||||
if (nc == 5) { /* ZFS_IOC_POOL_STATS */
|
||||
elem = NULL;
|
||||
while ((elem = nvlist_next_nvpair(nv, elem)) != NULL) {
|
||||
if (nvpair_value_nvlist(elem, &nvp) == 0)
|
||||
@ -334,17 +482,22 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
|
||||
void *zc_c;
|
||||
unsigned long ncmd;
|
||||
|
||||
if (cflag == ZFS_CMD_COMPAT_NONE) {
|
||||
switch (cflag) {
|
||||
case ZFS_CMD_COMPAT_NONE:
|
||||
ret = ioctl(fd, cmd, zc);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
if (cflag == ZFS_CMD_COMPAT_V15) {
|
||||
case ZFS_CMD_COMPAT_V28:
|
||||
zc_c = malloc(sizeof(zfs_cmd_v28_t));
|
||||
ncmd = _IOWR('Z', ZFS_IOC(cmd), struct zfs_cmd_v28);
|
||||
break;
|
||||
case ZFS_CMD_COMPAT_V15:
|
||||
nc = zfs_ioctl_v28_to_v15[ZFS_IOC(cmd)];
|
||||
zc_c = malloc(sizeof(zfs_cmd_v15_t));
|
||||
ncmd = _IOWR('Z', nc, struct zfs_cmd_v15);
|
||||
} else
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (ZFS_IOC(ncmd) == ZFS_IOC_COMPAT_FAIL)
|
||||
return (ENOTSUP);
|
||||
@ -358,16 +511,18 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
|
||||
zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag);
|
||||
free(zc_c);
|
||||
|
||||
switch (nc) {
|
||||
case 2: /* ZFS_IOC_POOL_IMPORT */
|
||||
case 4: /* ZFS_IOC_POOL_CONFIGS */
|
||||
case 5: /* ZFS_IOC_POOL_STATS */
|
||||
case 6: /* ZFS_IOC_POOL_TRYIMPORT */
|
||||
zfs_ioctl_compat_fix_stats(zc, nc);
|
||||
break;
|
||||
case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
|
||||
zfs_ioctl_compat_pool_get_props(zc);
|
||||
break;
|
||||
if (cflag == ZFS_CMD_COMPAT_V15) {
|
||||
switch (nc) {
|
||||
case 2: /* ZFS_IOC_POOL_IMPORT */
|
||||
case 4: /* ZFS_IOC_POOL_CONFIGS */
|
||||
case 5: /* ZFS_IOC_POOL_STATS */
|
||||
case 6: /* ZFS_IOC_POOL_TRYIMPORT */
|
||||
zfs_ioctl_compat_fix_stats(zc, nc);
|
||||
break;
|
||||
case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
|
||||
zfs_ioctl_compat_pool_get_props(zc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (ret);
|
||||
|
@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2010 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
* Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@ -40,11 +40,21 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ZFS_CMD_COMPAT_NONE 0
|
||||
#define ZFS_CMD_COMPAT_V15 1
|
||||
/*
|
||||
* Backwards ioctl compatibility
|
||||
*/
|
||||
|
||||
#define ZFS_IOC_COMPAT_PASS 254
|
||||
#define ZFS_IOC_COMPAT_FAIL 255
|
||||
/* ioctl versions for vfs.zfs.version.ioctl */
|
||||
#define ZFS_IOCVER_DEADMAN 1
|
||||
#define ZFS_IOCVER_CURRENT ZFS_IOCVER_DEADMAN
|
||||
|
||||
/* compatibility conversion flag */
|
||||
#define ZFS_CMD_COMPAT_NONE 0
|
||||
#define ZFS_CMD_COMPAT_V15 1
|
||||
#define ZFS_CMD_COMPAT_V28 2
|
||||
|
||||
#define ZFS_IOC_COMPAT_PASS 254
|
||||
#define ZFS_IOC_COMPAT_FAIL 255
|
||||
|
||||
typedef struct zinject_record_v15 {
|
||||
uint64_t zi_objset;
|
||||
@ -84,6 +94,60 @@ typedef struct zfs_cmd_v15 {
|
||||
zinject_record_v15_t zc_inject_record;
|
||||
} zfs_cmd_v15_t;
|
||||
|
||||
typedef struct zinject_record_v28 {
|
||||
uint64_t zi_objset;
|
||||
uint64_t zi_object;
|
||||
uint64_t zi_start;
|
||||
uint64_t zi_end;
|
||||
uint64_t zi_guid;
|
||||
uint32_t zi_level;
|
||||
uint32_t zi_error;
|
||||
uint64_t zi_type;
|
||||
uint32_t zi_freq;
|
||||
uint32_t zi_failfast;
|
||||
char zi_func[MAXNAMELEN];
|
||||
uint32_t zi_iotype;
|
||||
int32_t zi_duration;
|
||||
uint64_t zi_timer;
|
||||
} zinject_record_v28_t;
|
||||
|
||||
typedef struct zfs_cmd_v28 {
|
||||
char zc_name[MAXPATHLEN];
|
||||
char zc_value[MAXPATHLEN * 2];
|
||||
char zc_string[MAXNAMELEN];
|
||||
char zc_top_ds[MAXPATHLEN];
|
||||
uint64_t zc_guid;
|
||||
uint64_t zc_nvlist_conf; /* really (char *) */
|
||||
uint64_t zc_nvlist_conf_size;
|
||||
uint64_t zc_nvlist_src; /* really (char *) */
|
||||
uint64_t zc_nvlist_src_size;
|
||||
uint64_t zc_nvlist_dst; /* really (char *) */
|
||||
uint64_t zc_nvlist_dst_size;
|
||||
uint64_t zc_cookie;
|
||||
uint64_t zc_objset_type;
|
||||
uint64_t zc_perm_action;
|
||||
uint64_t zc_history; /* really (char *) */
|
||||
uint64_t zc_history_len;
|
||||
uint64_t zc_history_offset;
|
||||
uint64_t zc_obj;
|
||||
uint64_t zc_iflags; /* internal to zfs(7fs) */
|
||||
zfs_share_t zc_share;
|
||||
uint64_t zc_jailid;
|
||||
dmu_objset_stats_t zc_objset_stats;
|
||||
struct drr_begin zc_begin_record;
|
||||
zinject_record_v28_t zc_inject_record;
|
||||
boolean_t zc_defer_destroy;
|
||||
boolean_t zc_temphold;
|
||||
uint64_t zc_action_handle;
|
||||
int zc_cleanup_fd;
|
||||
uint8_t zc_simple;
|
||||
uint8_t zc_pad[3]; /* alignment */
|
||||
uint64_t zc_sendobj;
|
||||
uint64_t zc_fromobj;
|
||||
uint64_t zc_createtxg;
|
||||
zfs_stat_t zc_stat;
|
||||
} zfs_cmd_v28_t;
|
||||
|
||||
#ifdef _KERNEL
|
||||
unsigned static long zfs_ioctl_v15_to_v28[] = {
|
||||
0, /* 0 ZFS_IOC_POOL_CREATE */
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
*/
|
||||
|
||||
@ -350,6 +350,10 @@ zfs_prop_init(void)
|
||||
ZFS_TYPE_SNAPSHOT, "<count>", "USERREFS");
|
||||
zprop_register_number(ZFS_PROP_WRITTEN, "written", 0, PROP_READONLY,
|
||||
ZFS_TYPE_DATASET, "<size>", "WRITTEN");
|
||||
zprop_register_number(ZFS_PROP_LOGICALUSED, "logicalused", 0,
|
||||
PROP_READONLY, ZFS_TYPE_DATASET, "<size>", "LUSED");
|
||||
zprop_register_number(ZFS_PROP_LOGICALREFERENCED, "logicalreferenced",
|
||||
0, PROP_READONLY, ZFS_TYPE_DATASET, "<size>", "LREFER");
|
||||
|
||||
/* default number properties */
|
||||
zprop_register_number(ZFS_PROP_QUOTA, "quota", 0, PROP_DEFAULT,
|
||||
|
@ -2344,6 +2344,8 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
|
||||
(ds->ds_phys->ds_uncompressed_bytes * 100 /
|
||||
ds->ds_phys->ds_compressed_bytes);
|
||||
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio);
|
||||
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALREFERENCED,
|
||||
ds->ds_phys->ds_uncompressed_bytes);
|
||||
|
||||
if (ds->ds_phys->ds_next_snap_obj) {
|
||||
/*
|
||||
|
@ -541,6 +541,8 @@ dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv)
|
||||
dd->dd_phys->dd_compressed_bytes == 0 ? 100 :
|
||||
(dd->dd_phys->dd_uncompressed_bytes * 100 /
|
||||
dd->dd_phys->dd_compressed_bytes));
|
||||
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_LOGICALUSED,
|
||||
dd->dd_phys->dd_uncompressed_bytes);
|
||||
if (dd->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN) {
|
||||
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USEDSNAP,
|
||||
dd->dd_phys->dd_used_breakdown[DD_USED_SNAP]);
|
||||
|
@ -6018,7 +6018,7 @@ spa_sync_version(void *arg1, void *arg2, dmu_tx_t *tx)
|
||||
*/
|
||||
ASSERT(tx->tx_txg != TXG_INITIAL);
|
||||
|
||||
ASSERT(version <= SPA_VERSION);
|
||||
ASSERT(SPA_VERSION_IS_SUPPORTED(version));
|
||||
ASSERT(version >= spa_version(spa));
|
||||
|
||||
spa->spa_uberblock.ub_version = version;
|
||||
@ -6559,7 +6559,7 @@ spa_upgrade(spa_t *spa, uint64_t version)
|
||||
* future version would result in an unopenable pool, this shouldn't be
|
||||
* possible.
|
||||
*/
|
||||
ASSERT(spa->spa_uberblock.ub_version <= SPA_VERSION);
|
||||
ASSERT(SPA_VERSION_IS_SUPPORTED(spa->spa_uberblock.ub_version));
|
||||
ASSERT(version >= spa->spa_uberblock.ub_version);
|
||||
|
||||
spa->spa_uberblock.ub_version = version;
|
||||
|
@ -23,7 +23,7 @@
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||
* All rights reserved.
|
||||
* Portions Copyright 2011 Martin Matuska <mm@FreeBSD.org>
|
||||
* Copyright 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
@ -3822,7 +3822,7 @@ zfs_ioc_recv(zfs_cmd_t *zc)
|
||||
return (error);
|
||||
|
||||
fd = zc->zc_cookie;
|
||||
fp = getf(fd);
|
||||
fp = getf(fd, CAP_PREAD);
|
||||
if (fp == NULL) {
|
||||
nvlist_free(props);
|
||||
return (EBADF);
|
||||
@ -4079,7 +4079,7 @@ zfs_ioc_send(zfs_cmd_t *zc)
|
||||
error = dmu_send_estimate(tosnap, fromsnap, zc->zc_obj,
|
||||
&zc->zc_objset_type);
|
||||
} else {
|
||||
file_t *fp = getf(zc->zc_cookie);
|
||||
file_t *fp = getf(zc->zc_cookie, CAP_WRITE);
|
||||
if (fp == NULL) {
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
if (dsfrom)
|
||||
@ -4675,7 +4675,7 @@ zfs_ioc_diff(zfs_cmd_t *zc)
|
||||
return (error);
|
||||
}
|
||||
|
||||
fp = getf(zc->zc_cookie);
|
||||
fp = getf(zc->zc_cookie, CAP_WRITE);
|
||||
if (fp == NULL) {
|
||||
dmu_objset_rele(fromsnap, FTAG);
|
||||
dmu_objset_rele(tosnap, FTAG);
|
||||
@ -5331,12 +5331,14 @@ zfsdev_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
len = IOCPARM_LEN(cmd);
|
||||
|
||||
/*
|
||||
* Check if we have sufficient kernel memory allocated
|
||||
* for the zfs_cmd_t request. Bail out if not so we
|
||||
* will not access undefined memory region.
|
||||
* Check if we are talking to supported older binaries
|
||||
* and translate zfs_cmd if necessary
|
||||
*/
|
||||
if (len < sizeof(zfs_cmd_t))
|
||||
if (len == sizeof(zfs_cmd_v15_t)) {
|
||||
if (len == sizeof(zfs_cmd_v28_t)) {
|
||||
cflag = ZFS_CMD_COMPAT_V28;
|
||||
vec = ZFS_IOC(cmd);
|
||||
} else if (len == sizeof(zfs_cmd_v15_t)) {
|
||||
cflag = ZFS_CMD_COMPAT_V15;
|
||||
vec = zfs_ioctl_v15_to_v28[ZFS_IOC(cmd)];
|
||||
} else
|
||||
@ -5351,6 +5353,11 @@ zfsdev_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
return (ENOTSUP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we have sufficient kernel memory allocated
|
||||
* for the zfs_cmd_t request. Bail out if not so we
|
||||
* will not access undefined memory region.
|
||||
*/
|
||||
if (vec >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0]))
|
||||
return (EINVAL);
|
||||
|
||||
|
@ -124,7 +124,7 @@ zfs_onexit_fd_hold(int fd, minor_t *minorp)
|
||||
void *data;
|
||||
int error;
|
||||
|
||||
fp = getf(fd);
|
||||
fp = getf(fd, CAP_NONE);
|
||||
if (fp == NULL)
|
||||
return (EBADF);
|
||||
|
||||
|
@ -131,6 +131,8 @@ typedef enum {
|
||||
ZFS_PROP_REFRATIO,
|
||||
ZFS_PROP_WRITTEN,
|
||||
ZFS_PROP_CLONES,
|
||||
ZFS_PROP_LOGICALUSED,
|
||||
ZFS_PROP_LOGICALREFERENCED,
|
||||
ZFS_NUM_PROPS
|
||||
} zfs_prop_t;
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd
|
||||
*/
|
||||
|
||||
#ifndef _FREEBSD32_SYSPROTO_H_
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd
|
||||
*/
|
||||
|
||||
#define FREEBSD32_SYS_syscall 0
|
||||
@ -416,7 +416,7 @@
|
||||
#define FREEBSD32_SYS_freebsd32_shmctl 512
|
||||
#define FREEBSD32_SYS_lpathconf 513
|
||||
#define FREEBSD32_SYS_cap_new 514
|
||||
#define FREEBSD32_SYS_cap_getrights 515
|
||||
#define FREEBSD32_SYS_cap_rights_get 515
|
||||
#define FREEBSD32_SYS_cap_enter 516
|
||||
#define FREEBSD32_SYS_cap_getmode 517
|
||||
#define FREEBSD32_SYS_freebsd32_pselect 522
|
||||
@ -430,4 +430,9 @@
|
||||
#define FREEBSD32_SYS_freebsd32_posix_fallocate 530
|
||||
#define FREEBSD32_SYS_freebsd32_posix_fadvise 531
|
||||
#define FREEBSD32_SYS_freebsd32_wait6 532
|
||||
#define FREEBSD32_SYS_MAXSYSCALL 533
|
||||
#define FREEBSD32_SYS_cap_rights_limit 533
|
||||
#define FREEBSD32_SYS_cap_ioctls_limit 534
|
||||
#define FREEBSD32_SYS_cap_ioctls_get 535
|
||||
#define FREEBSD32_SYS_cap_fcntls_limit 536
|
||||
#define FREEBSD32_SYS_cap_fcntls_get 537
|
||||
#define FREEBSD32_SYS_MAXSYSCALL 538
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd
|
||||
*/
|
||||
|
||||
const char *freebsd32_syscallnames[] = {
|
||||
@ -538,7 +538,7 @@ const char *freebsd32_syscallnames[] = {
|
||||
"freebsd32_shmctl", /* 512 = freebsd32_shmctl */
|
||||
"lpathconf", /* 513 = lpathconf */
|
||||
"cap_new", /* 514 = cap_new */
|
||||
"cap_getrights", /* 515 = cap_getrights */
|
||||
"cap_rights_get", /* 515 = cap_rights_get */
|
||||
"cap_enter", /* 516 = cap_enter */
|
||||
"cap_getmode", /* 517 = cap_getmode */
|
||||
"#518", /* 518 = pdfork */
|
||||
@ -556,4 +556,9 @@ const char *freebsd32_syscallnames[] = {
|
||||
"freebsd32_posix_fallocate", /* 530 = freebsd32_posix_fallocate */
|
||||
"freebsd32_posix_fadvise", /* 531 = freebsd32_posix_fadvise */
|
||||
"freebsd32_wait6", /* 532 = freebsd32_wait6 */
|
||||
"cap_rights_limit", /* 533 = cap_rights_limit */
|
||||
"cap_ioctls_limit", /* 534 = cap_ioctls_limit */
|
||||
"cap_ioctls_get", /* 535 = cap_ioctls_get */
|
||||
"cap_fcntls_limit", /* 536 = cap_fcntls_limit */
|
||||
"cap_fcntls_get", /* 537 = cap_fcntls_get */
|
||||
};
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 242958 2012-11-13 12:52:31Z kib
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd
|
||||
*/
|
||||
|
||||
#include "opt_compat.h"
|
||||
@ -575,7 +575,7 @@ struct sysent freebsd32_sysent[] = {
|
||||
{ AS(freebsd32_shmctl_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 512 = freebsd32_shmctl */
|
||||
{ AS(lpathconf_args), (sy_call_t *)sys_lpathconf, AUE_LPATHCONF, NULL, 0, 0, 0, SY_THR_STATIC }, /* 513 = lpathconf */
|
||||
{ AS(cap_new_args), (sy_call_t *)sys_cap_new, AUE_CAP_NEW, NULL, 0, 0, 0, SY_THR_STATIC }, /* 514 = cap_new */
|
||||
{ AS(cap_getrights_args), (sy_call_t *)sys_cap_getrights, AUE_CAP_GETRIGHTS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 515 = cap_getrights */
|
||||
{ AS(cap_rights_get_args), (sy_call_t *)sys_cap_rights_get, AUE_CAP_RIGHTS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 515 = cap_rights_get */
|
||||
{ 0, (sy_call_t *)sys_cap_enter, AUE_CAP_ENTER, NULL, 0, 0, 0, SY_THR_STATIC }, /* 516 = cap_enter */
|
||||
{ AS(cap_getmode_args), (sy_call_t *)sys_cap_getmode, AUE_CAP_GETMODE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 517 = cap_getmode */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 518 = pdfork */
|
||||
@ -593,4 +593,9 @@ struct sysent freebsd32_sysent[] = {
|
||||
{ AS(freebsd32_posix_fallocate_args), (sy_call_t *)freebsd32_posix_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 530 = freebsd32_posix_fallocate */
|
||||
{ AS(freebsd32_posix_fadvise_args), (sy_call_t *)freebsd32_posix_fadvise, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 531 = freebsd32_posix_fadvise */
|
||||
{ AS(freebsd32_wait6_args), (sy_call_t *)freebsd32_wait6, AUE_WAIT6, NULL, 0, 0, 0, SY_THR_STATIC }, /* 532 = freebsd32_wait6 */
|
||||
{ AS(cap_rights_limit_args), (sy_call_t *)sys_cap_rights_limit, AUE_CAP_RIGHTS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 533 = cap_rights_limit */
|
||||
{ AS(cap_ioctls_limit_args), (sy_call_t *)sys_cap_ioctls_limit, AUE_CAP_IOCTLS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 534 = cap_ioctls_limit */
|
||||
{ AS(cap_ioctls_get_args), (sy_call_t *)sys_cap_ioctls_get, AUE_CAP_IOCTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 535 = cap_ioctls_get */
|
||||
{ AS(cap_fcntls_limit_args), (sy_call_t *)sys_cap_fcntls_limit, AUE_CAP_FCNTLS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 536 = cap_fcntls_limit */
|
||||
{ AS(cap_fcntls_get_args), (sy_call_t *)sys_cap_fcntls_get, AUE_CAP_FCNTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 537 = cap_fcntls_get */
|
||||
};
|
||||
|
@ -2956,9 +2956,9 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* cap_getrights */
|
||||
/* cap_rights_get */
|
||||
case 515: {
|
||||
struct cap_getrights_args *p = params;
|
||||
struct cap_rights_get_args *p = params;
|
||||
iarg[0] = p->fd; /* int */
|
||||
uarg[1] = (intptr_t) p->rightsp; /* uint64_t * */
|
||||
*n_args = 2;
|
||||
@ -3088,6 +3088,48 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
*n_args = 6;
|
||||
break;
|
||||
}
|
||||
/* cap_rights_limit */
|
||||
case 533: {
|
||||
struct cap_rights_limit_args *p = params;
|
||||
iarg[0] = p->fd; /* int */
|
||||
uarg[1] = p->rights; /* uint64_t */
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* cap_ioctls_limit */
|
||||
case 534: {
|
||||
struct cap_ioctls_limit_args *p = params;
|
||||
iarg[0] = p->fd; /* int */
|
||||
uarg[1] = (intptr_t) p->cmds; /* const u_long * */
|
||||
uarg[2] = p->ncmds; /* size_t */
|
||||
*n_args = 3;
|
||||
break;
|
||||
}
|
||||
/* cap_ioctls_get */
|
||||
case 535: {
|
||||
struct cap_ioctls_get_args *p = params;
|
||||
iarg[0] = p->fd; /* int */
|
||||
uarg[1] = (intptr_t) p->cmds; /* u_long * */
|
||||
uarg[2] = p->maxcmds; /* size_t */
|
||||
*n_args = 3;
|
||||
break;
|
||||
}
|
||||
/* cap_fcntls_limit */
|
||||
case 536: {
|
||||
struct cap_fcntls_limit_args *p = params;
|
||||
iarg[0] = p->fd; /* int */
|
||||
uarg[1] = p->fcntlrights; /* uint32_t */
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* cap_fcntls_get */
|
||||
case 537: {
|
||||
struct cap_fcntls_get_args *p = params;
|
||||
iarg[0] = p->fd; /* int */
|
||||
uarg[1] = (intptr_t) p->fcntlrightsp; /* uint32_t * */
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
*n_args = 0;
|
||||
break;
|
||||
@ -8002,7 +8044,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* cap_getrights */
|
||||
/* cap_rights_get */
|
||||
case 515:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
@ -8243,6 +8285,77 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* cap_rights_limit */
|
||||
case 533:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "int";
|
||||
break;
|
||||
case 1:
|
||||
p = "uint64_t";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* cap_ioctls_limit */
|
||||
case 534:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "int";
|
||||
break;
|
||||
case 1:
|
||||
p = "const u_long *";
|
||||
break;
|
||||
case 2:
|
||||
p = "size_t";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* cap_ioctls_get */
|
||||
case 535:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "int";
|
||||
break;
|
||||
case 1:
|
||||
p = "u_long *";
|
||||
break;
|
||||
case 2:
|
||||
p = "size_t";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* cap_fcntls_limit */
|
||||
case 536:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "int";
|
||||
break;
|
||||
case 1:
|
||||
p = "uint32_t";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* cap_fcntls_get */
|
||||
case 537:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "int";
|
||||
break;
|
||||
case 1:
|
||||
p = "uint32_t *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
@ -9938,7 +10051,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* cap_getrights */
|
||||
/* cap_rights_get */
|
||||
case 515:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
@ -10005,6 +10118,31 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* cap_rights_limit */
|
||||
case 533:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* cap_ioctls_limit */
|
||||
case 534:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* cap_ioctls_get */
|
||||
case 535:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "ssize_t";
|
||||
break;
|
||||
/* cap_fcntls_limit */
|
||||
case 536:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* cap_fcntls_get */
|
||||
case 537:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
@ -963,7 +963,7 @@
|
||||
struct shmid_ds32 *buf); }
|
||||
513 AUE_LPATHCONF NOPROTO { int lpathconf(char *path, int name); }
|
||||
514 AUE_CAP_NEW NOPROTO { int cap_new(int fd, uint64_t rights); }
|
||||
515 AUE_CAP_GETRIGHTS NOPROTO { int cap_getrights(int fd, \
|
||||
515 AUE_CAP_RIGHTS_GET NOPROTO { int cap_rights_get(int fd, \
|
||||
uint64_t *rightsp); }
|
||||
516 AUE_CAP_ENTER NOPROTO { int cap_enter(void); }
|
||||
517 AUE_CAP_GETMODE NOPROTO { int cap_getmode(u_int *modep); }
|
||||
@ -1005,3 +1005,13 @@
|
||||
struct wrusage32 *wrusage, \
|
||||
siginfo_t *info); }
|
||||
|
||||
533 AUE_CAP_RIGHTS_LIMIT NOPROTO { int cap_rights_limit(int fd, \
|
||||
uint64_t rights); }
|
||||
534 AUE_CAP_IOCTLS_LIMIT NOPROTO { int cap_ioctls_limit(int fd, \
|
||||
const u_long *cmds, size_t ncmds); }
|
||||
535 AUE_CAP_IOCTLS_GET NOPROTO { ssize_t cap_ioctls_get(int fd, \
|
||||
u_long *cmds, size_t maxcmds); }
|
||||
536 AUE_CAP_FCNTLS_LIMIT NOPROTO { int cap_fcntls_limit(int fd, \
|
||||
uint32_t fcntlrights); }
|
||||
537 AUE_CAP_FCNTLS_GET NOPROTO { int cap_fcntls_get(int fd, \
|
||||
uint32_t *fcntlrightsp); }
|
||||
|
@ -154,6 +154,7 @@ linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mod
|
||||
SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
|
||||
PROC_UNLOCK(p);
|
||||
sx_unlock(&proctree_lock);
|
||||
/* XXXPJD: Verify if TIOCSCTTY is allowed. */
|
||||
if (fp->f_type == DTYPE_VNODE)
|
||||
(void) fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0,
|
||||
td->td_ucred, td);
|
||||
@ -1038,11 +1039,11 @@ linux_pread(td, uap)
|
||||
error = sys_pread(td, &bsd);
|
||||
|
||||
if (error == 0) {
|
||||
/* This seems to violate POSIX but linux does it */
|
||||
if ((error = fgetvp(td, uap->fd, CAP_READ, &vp)) != 0)
|
||||
return (error);
|
||||
/* This seems to violate POSIX but linux does it */
|
||||
if ((error = fgetvp(td, uap->fd, CAP_PREAD, &vp)) != 0)
|
||||
return (error);
|
||||
if (vp->v_type == VDIR) {
|
||||
vrele(vp);
|
||||
vrele(vp);
|
||||
return (EISDIR);
|
||||
}
|
||||
vrele(vp);
|
||||
|
@ -566,7 +566,7 @@ ndis_convert_res(arg)
|
||||
return (ENOMEM);
|
||||
|
||||
rl->cprl_version = 5;
|
||||
rl->cprl_version = 1;
|
||||
rl->cprl_revision = 1;
|
||||
rl->cprl_count = sc->ndis_rescnt;
|
||||
prd = rl->cprl_partial_descs;
|
||||
|
||||
|
@ -265,14 +265,14 @@ fd_revoke(td, fd)
|
||||
/*
|
||||
* If we ever want to support Capsicum on SVR4 processes (unlikely)
|
||||
* or FreeBSD grows a native frevoke() (more likely), we will need a
|
||||
* CAP_REVOKE here.
|
||||
* CAP_FREVOKE here.
|
||||
*
|
||||
* In the meantime, use CAP_MASK_VALID: if a SVR4 process wants to
|
||||
* In the meantime, use CAP_ALL: if a SVR4 process wants to
|
||||
* do an frevoke(), it needs to do it on either a regular file
|
||||
* descriptor or a fully-privileged capability (which is effectively
|
||||
* the same as a non-capability-restricted file descriptor).
|
||||
*/
|
||||
if ((error = fgetvp(td, fd, CAP_MASK_VALID, &vp)) != 0)
|
||||
if ((error = fgetvp(td, fd, CAP_ALL, &vp)) != 0)
|
||||
return (error);
|
||||
|
||||
if (vp->v_type != VCHR && vp->v_type != VBLK) {
|
||||
|
@ -197,22 +197,24 @@ svr4_fil_ioctl(fp, td, retval, fd, cmd, data)
|
||||
u_long cmd;
|
||||
caddr_t data;
|
||||
{
|
||||
int error;
|
||||
int num;
|
||||
struct filedesc *fdp = td->td_proc->p_fd;
|
||||
struct filedescent *fde;
|
||||
int error, num;
|
||||
|
||||
*retval = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case SVR4_FIOCLEX:
|
||||
FILEDESC_XLOCK(fdp);
|
||||
fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
|
||||
fde = &fdp->fd_ofiles[fd];
|
||||
fde->fde_flags |= UF_EXCLOSE;
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
return 0;
|
||||
|
||||
case SVR4_FIONCLEX:
|
||||
FILEDESC_XLOCK(fdp);
|
||||
fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
|
||||
fde = &fdp->fd_ofiles[fd];
|
||||
fde->fde_flags &= ~UF_EXCLOSE;
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
return 0;
|
||||
|
||||
|
@ -247,10 +247,8 @@ svr4_sys_getdents64(td, uap)
|
||||
|
||||
DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n",
|
||||
uap->fd, uap->nbytes));
|
||||
if ((error = getvnode(td->td_proc->p_fd, uap->fd,
|
||||
CAP_READ | CAP_SEEK, &fp)) != 0) {
|
||||
if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
|
||||
return (error);
|
||||
}
|
||||
|
||||
if ((fp->f_flag & FREAD) == 0) {
|
||||
fdrop(fp, td);
|
||||
@ -426,8 +424,7 @@ svr4_sys_getdents(td, uap)
|
||||
if (uap->nbytes < 0)
|
||||
return (EINVAL);
|
||||
|
||||
if ((error = getvnode(td->td_proc->p_fd, uap->fd,
|
||||
CAP_READ | CAP_SEEK, &fp)) != 0)
|
||||
if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
|
||||
return (error);
|
||||
|
||||
if ((fp->f_flag & FREAD) == 0) {
|
||||
|
@ -1449,7 +1449,7 @@ svr4_sys_putmsg(td, uap)
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
if ((error = fget(td, uap->fd, CAP_WRITE, &fp)) != 0) {
|
||||
if ((error = fget(td, uap->fd, CAP_SEND, &fp)) != 0) {
|
||||
#ifdef DEBUG_SVR4
|
||||
uprintf("putmsg: bad fp\n");
|
||||
#endif
|
||||
@ -1621,7 +1621,7 @@ svr4_sys_getmsg(td, uap)
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
if ((error = fget(td, uap->fd, CAP_READ, &fp)) != 0) {
|
||||
if ((error = fget(td, uap->fd, CAP_RECV, &fp)) != 0) {
|
||||
#ifdef DEBUG_SVR4
|
||||
uprintf("getmsg: bad fp\n");
|
||||
#endif
|
||||
|
@ -23,7 +23,6 @@ PSM_DEBUG opt_psm.h
|
||||
PSM_HOOKRESUME opt_psm.h
|
||||
PSM_RESETAFTERSUSPEND opt_psm.h
|
||||
|
||||
DEBUGGER_ON_POWERFAIL opt_psycho.h
|
||||
PSYCHO_DEBUG opt_psycho.h
|
||||
|
||||
SCHIZO_DEBUG opt_schizo.h
|
||||
|
@ -117,7 +117,7 @@ static void aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command,
|
||||
static int aac_sa_get_mailbox(struct aac_softc *sc, int mb);
|
||||
static void aac_sa_set_interrupts(struct aac_softc *sc, int enable);
|
||||
|
||||
struct aac_interface aac_sa_interface = {
|
||||
const struct aac_interface aac_sa_interface = {
|
||||
aac_sa_get_fwstatus,
|
||||
aac_sa_qnotify,
|
||||
aac_sa_get_istatus,
|
||||
@ -142,7 +142,7 @@ static int aac_rx_send_command(struct aac_softc *sc, struct aac_command *cm);
|
||||
static int aac_rx_get_outb_queue(struct aac_softc *sc);
|
||||
static void aac_rx_set_outb_queue(struct aac_softc *sc, int index);
|
||||
|
||||
struct aac_interface aac_rx_interface = {
|
||||
const struct aac_interface aac_rx_interface = {
|
||||
aac_rx_get_fwstatus,
|
||||
aac_rx_qnotify,
|
||||
aac_rx_get_istatus,
|
||||
@ -169,7 +169,7 @@ static int aac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm);
|
||||
static int aac_rkt_get_outb_queue(struct aac_softc *sc);
|
||||
static void aac_rkt_set_outb_queue(struct aac_softc *sc, int index);
|
||||
|
||||
struct aac_interface aac_rkt_interface = {
|
||||
const struct aac_interface aac_rkt_interface = {
|
||||
aac_rkt_get_fwstatus,
|
||||
aac_rkt_qnotify,
|
||||
aac_rkt_get_istatus,
|
||||
@ -183,8 +183,8 @@ struct aac_interface aac_rkt_interface = {
|
||||
};
|
||||
|
||||
/* Debugging and Diagnostics */
|
||||
static void aac_describe_controller(struct aac_softc *sc);
|
||||
static char *aac_describe_code(struct aac_code_lookup *table,
|
||||
static void aac_describe_controller(struct aac_softc *sc);
|
||||
static const char *aac_describe_code(const struct aac_code_lookup *table,
|
||||
u_int32_t code);
|
||||
|
||||
/* Management Interface */
|
||||
@ -222,7 +222,7 @@ static struct cdevsw aac_cdevsw = {
|
||||
static MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for the AAC driver");
|
||||
|
||||
/* sysctl node */
|
||||
static SYSCTL_NODE(_hw, OID_AUTO, aac, CTLFLAG_RD, 0, "AAC driver parameters");
|
||||
SYSCTL_NODE(_hw, OID_AUTO, aac, CTLFLAG_RD, 0, "AAC driver parameters");
|
||||
|
||||
/*
|
||||
* Device Interface
|
||||
@ -634,8 +634,8 @@ aac_free(struct aac_softc *sc)
|
||||
if (sc->aac_intr)
|
||||
bus_teardown_intr(sc->aac_dev, sc->aac_irq, sc->aac_intr);
|
||||
if (sc->aac_irq != NULL)
|
||||
bus_release_resource(sc->aac_dev, SYS_RES_IRQ, sc->aac_irq_rid,
|
||||
sc->aac_irq);
|
||||
bus_release_resource(sc->aac_dev, SYS_RES_IRQ,
|
||||
rman_get_rid(sc->aac_irq), sc->aac_irq);
|
||||
|
||||
/* destroy data-transfer DMA tag */
|
||||
if (sc->aac_buffer_dmat)
|
||||
@ -648,10 +648,10 @@ aac_free(struct aac_softc *sc)
|
||||
/* release the register window mapping */
|
||||
if (sc->aac_regs_res0 != NULL)
|
||||
bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
|
||||
sc->aac_regs_rid0, sc->aac_regs_res0);
|
||||
rman_get_rid(sc->aac_regs_res0), sc->aac_regs_res0);
|
||||
if (sc->aac_hwif == AAC_HWIF_NARK && sc->aac_regs_res1 != NULL)
|
||||
bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
|
||||
sc->aac_regs_rid1, sc->aac_regs_res1);
|
||||
rman_get_rid(sc->aac_regs_res1), sc->aac_regs_res1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1333,9 +1333,6 @@ aac_bio_complete(struct aac_command *cm)
|
||||
} else {
|
||||
bp->bio_error = EIO;
|
||||
bp->bio_flags |= BIO_ERROR;
|
||||
/* pass an error string out to the disk layer */
|
||||
bp->bio_driver1 = aac_describe_code(aac_command_status_table,
|
||||
status);
|
||||
}
|
||||
aac_biodone(bp);
|
||||
}
|
||||
@ -1687,7 +1684,7 @@ static int
|
||||
aac_check_firmware(struct aac_softc *sc)
|
||||
{
|
||||
u_int32_t code, major, minor, options = 0, atu_size = 0;
|
||||
int status;
|
||||
int rid, status;
|
||||
time_t then;
|
||||
|
||||
fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
|
||||
@ -1765,7 +1762,7 @@ aac_check_firmware(struct aac_softc *sc)
|
||||
sc->flags |= AAC_FLAGS_SG_64BIT;
|
||||
}
|
||||
if ((options & AAC_SUPPORTED_NEW_COMM)
|
||||
&& sc->aac_if.aif_send_command)
|
||||
&& sc->aac_if->aif_send_command)
|
||||
sc->flags |= AAC_FLAGS_NEW_COMM;
|
||||
if (options & AAC_SUPPORTED_64BIT_ARRAYSIZE)
|
||||
sc->flags |= AAC_FLAGS_ARRAY_64BIT;
|
||||
@ -1776,17 +1773,15 @@ aac_check_firmware(struct aac_softc *sc)
|
||||
|
||||
/* Remap mem. resource, if required */
|
||||
if ((sc->flags & AAC_FLAGS_NEW_COMM) &&
|
||||
atu_size > rman_get_size(sc->aac_regs_res1)) {
|
||||
bus_release_resource(
|
||||
sc->aac_dev, SYS_RES_MEMORY,
|
||||
sc->aac_regs_rid1, sc->aac_regs_res1);
|
||||
sc->aac_regs_res1 = bus_alloc_resource(
|
||||
sc->aac_dev, SYS_RES_MEMORY, &sc->aac_regs_rid1,
|
||||
0ul, ~0ul, atu_size, RF_ACTIVE);
|
||||
atu_size > rman_get_size(sc->aac_regs_res1)) {
|
||||
rid = rman_get_rid(sc->aac_regs_res1);
|
||||
bus_release_resource(sc->aac_dev, SYS_RES_MEMORY, rid,
|
||||
sc->aac_regs_res1);
|
||||
sc->aac_regs_res1 = bus_alloc_resource(sc->aac_dev,
|
||||
SYS_RES_MEMORY, &rid, 0ul, ~0ul, atu_size, RF_ACTIVE);
|
||||
if (sc->aac_regs_res1 == NULL) {
|
||||
sc->aac_regs_res1 = bus_alloc_resource_any(
|
||||
sc->aac_dev, SYS_RES_MEMORY,
|
||||
&sc->aac_regs_rid1, RF_ACTIVE);
|
||||
sc->aac_dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
|
||||
if (sc->aac_regs_res1 == NULL) {
|
||||
device_printf(sc->aac_dev,
|
||||
"couldn't allocate register window\n");
|
||||
@ -1799,7 +1794,6 @@ aac_check_firmware(struct aac_softc *sc)
|
||||
|
||||
if (sc->aac_hwif == AAC_HWIF_NARK) {
|
||||
sc->aac_regs_res0 = sc->aac_regs_res1;
|
||||
sc->aac_regs_rid0 = sc->aac_regs_rid1;
|
||||
sc->aac_btag0 = sc->aac_btag1;
|
||||
sc->aac_bhandle0 = sc->aac_bhandle1;
|
||||
}
|
||||
@ -2003,14 +1997,7 @@ aac_init(struct aac_softc *sc)
|
||||
static int
|
||||
aac_setup_intr(struct aac_softc *sc)
|
||||
{
|
||||
sc->aac_irq_rid = 0;
|
||||
if ((sc->aac_irq = bus_alloc_resource_any(sc->aac_dev, SYS_RES_IRQ,
|
||||
&sc->aac_irq_rid,
|
||||
RF_SHAREABLE |
|
||||
RF_ACTIVE)) == NULL) {
|
||||
device_printf(sc->aac_dev, "can't allocate interrupt\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (sc->flags & AAC_FLAGS_NEW_COMM) {
|
||||
if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
|
||||
INTR_MPSAFE|INTR_TYPE_BIO, NULL,
|
||||
@ -2119,7 +2106,7 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
|
||||
* Note that the queue implementation here is a little funky; neither the PI or
|
||||
* CI will ever be zero. This behaviour is a controller feature.
|
||||
*/
|
||||
static struct {
|
||||
static const struct {
|
||||
int size;
|
||||
int notify;
|
||||
} aac_qinfo[] = {
|
||||
@ -2786,8 +2773,8 @@ aac_describe_controller(struct aac_softc *sc)
|
||||
* Look up a text description of a numeric error code and return a pointer to
|
||||
* same.
|
||||
*/
|
||||
static char *
|
||||
aac_describe_code(struct aac_code_lookup *table, u_int32_t code)
|
||||
static const char *
|
||||
aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -92,7 +92,7 @@ static device_method_t aac_pass_methods[] = {
|
||||
DEVMETHOD(device_probe, aac_cam_probe),
|
||||
DEVMETHOD(device_attach, aac_cam_attach),
|
||||
DEVMETHOD(device_detach, aac_cam_detach),
|
||||
{ 0, 0 }
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t aac_pass_driver = {
|
||||
@ -101,7 +101,7 @@ static driver_t aac_pass_driver = {
|
||||
sizeof(struct aac_cam)
|
||||
};
|
||||
|
||||
DRIVER_MODULE(aacp, aac, aac_pass_driver, aac_pass_devclass, 0, 0);
|
||||
DRIVER_MODULE(aacp, aac, aac_pass_driver, aac_pass_devclass, NULL, NULL);
|
||||
MODULE_DEPEND(aacp, cam, 1, 1, 1);
|
||||
|
||||
static MALLOC_DEFINE(M_AACCAM, "aaccam", "AAC CAM info");
|
||||
@ -685,4 +685,3 @@ aac_cam_term_io(struct cam_sim *sim, union ccb *ccb)
|
||||
{
|
||||
return (CAM_UA_TERMIO);
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ static device_method_t aac_disk_methods[] = {
|
||||
DEVMETHOD(device_probe, aac_disk_probe),
|
||||
DEVMETHOD(device_attach, aac_disk_attach),
|
||||
DEVMETHOD(device_detach, aac_disk_detach),
|
||||
{ 0, 0 }
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t aac_disk_driver = {
|
||||
@ -82,7 +82,7 @@ static driver_t aac_disk_driver = {
|
||||
sizeof(struct aac_disk)
|
||||
};
|
||||
|
||||
DRIVER_MODULE(aacd, aac, aac_disk_driver, aac_disk_devclass, 0, 0);
|
||||
DRIVER_MODULE(aacd, aac, aac_disk_driver, aac_disk_devclass, NULL, NULL);
|
||||
|
||||
/*
|
||||
* Handle open from generic layer.
|
||||
|
@ -60,6 +60,11 @@ __FBSDID("$FreeBSD$");
|
||||
static int aac_pci_probe(device_t dev);
|
||||
static int aac_pci_attach(device_t dev);
|
||||
|
||||
static int aac_enable_msi = 1;
|
||||
TUNABLE_INT("hw.aac.enable_msi", &aac_enable_msi);
|
||||
SYSCTL_INT(_hw_aac, OID_AUTO, enable_msi, CTLFLAG_RDTUN, &aac_enable_msi, 0,
|
||||
"Enable MSI interrupts");
|
||||
|
||||
static device_method_t aac_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, aac_pci_probe),
|
||||
@ -79,11 +84,10 @@ static driver_t aac_pci_driver = {
|
||||
|
||||
static devclass_t aac_devclass;
|
||||
|
||||
DRIVER_MODULE(aac, pci, aac_pci_driver, aac_devclass, 0, 0);
|
||||
DRIVER_MODULE(aac, pci, aac_pci_driver, aac_devclass, NULL, NULL);
|
||||
MODULE_DEPEND(aac, pci, 1, 1, 1);
|
||||
|
||||
|
||||
struct aac_ident
|
||||
static const struct aac_ident
|
||||
{
|
||||
u_int16_t vendor;
|
||||
u_int16_t device;
|
||||
@ -91,7 +95,7 @@ struct aac_ident
|
||||
u_int16_t subdevice;
|
||||
int hwif;
|
||||
int quirks;
|
||||
char *desc;
|
||||
const char *desc;
|
||||
} aac_identifiers[] = {
|
||||
{0x1028, 0x0001, 0x1028, 0x0001, AAC_HWIF_I960RX, 0,
|
||||
"Dell PERC 2/Si"},
|
||||
@ -139,7 +143,6 @@ struct aac_ident
|
||||
"Adaptec SCSI RAID 2230S"},
|
||||
{0x9005, 0x0286, 0x9005, 0x028d, AAC_HWIF_RKT, 0,
|
||||
"Adaptec SCSI RAID 2130S"},
|
||||
|
||||
{0x9005, 0x0285, 0x9005, 0x0287, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB |
|
||||
AAC_FLAGS_256FIBS, "Adaptec SCSI RAID 2200S"},
|
||||
{0x9005, 0x0285, 0x17aa, 0x0286, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB |
|
||||
@ -276,7 +279,8 @@ struct aac_ident
|
||||
"AOC-USAS-S8iR-LP"},
|
||||
{0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
struct aac_ident
|
||||
|
||||
static const struct aac_ident
|
||||
aac_family_identifiers[] = {
|
||||
{0x9005, 0x0285, 0, 0, AAC_HWIF_I960RX, 0,
|
||||
"Adaptec RAID Controller"},
|
||||
@ -285,10 +289,10 @@ aac_family_identifiers[] = {
|
||||
{0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static struct aac_ident *
|
||||
static const struct aac_ident *
|
||||
aac_find_ident(device_t dev)
|
||||
{
|
||||
struct aac_ident *m;
|
||||
const struct aac_ident *m;
|
||||
u_int16_t vendid, devid, sub_vendid, sub_devid;
|
||||
|
||||
vendid = pci_get_vendor(dev);
|
||||
@ -317,7 +321,7 @@ aac_find_ident(device_t dev)
|
||||
static int
|
||||
aac_pci_probe(device_t dev)
|
||||
{
|
||||
struct aac_ident *id;
|
||||
const struct aac_ident *id;
|
||||
|
||||
fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
|
||||
|
||||
@ -335,9 +339,8 @@ static int
|
||||
aac_pci_attach(device_t dev)
|
||||
{
|
||||
struct aac_softc *sc;
|
||||
struct aac_ident *id;
|
||||
int error;
|
||||
u_int32_t command;
|
||||
const struct aac_ident *id;
|
||||
int count, error, reg, rid;
|
||||
|
||||
fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
|
||||
|
||||
@ -345,7 +348,6 @@ aac_pci_attach(device_t dev)
|
||||
* Initialise softc.
|
||||
*/
|
||||
sc = device_get_softc(dev);
|
||||
bzero(sc, sizeof(*sc));
|
||||
sc->aac_dev = dev;
|
||||
|
||||
/* assume failure is 'not configured' */
|
||||
@ -354,55 +356,66 @@ aac_pci_attach(device_t dev)
|
||||
/*
|
||||
* Verify that the adapter is correctly set up in PCI space.
|
||||
*/
|
||||
command = pci_read_config(sc->aac_dev, PCIR_COMMAND, 2);
|
||||
command |= PCIM_CMD_BUSMASTEREN;
|
||||
pci_write_config(dev, PCIR_COMMAND, command, 2);
|
||||
command = pci_read_config(sc->aac_dev, PCIR_COMMAND, 2);
|
||||
if (!(command & PCIM_CMD_BUSMASTEREN)) {
|
||||
device_printf(sc->aac_dev, "can't enable bus-master feature\n");
|
||||
goto out;
|
||||
}
|
||||
if ((command & PCIM_CMD_MEMEN) == 0) {
|
||||
device_printf(sc->aac_dev, "memory window not available\n");
|
||||
pci_enable_busmaster(dev);
|
||||
if (!(pci_read_config(dev, PCIR_COMMAND, 2) & PCIM_CMD_BUSMASTEREN)) {
|
||||
device_printf(dev, "can't enable bus-master feature\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the PCI register window.
|
||||
* Allocate the PCI register window(s).
|
||||
*/
|
||||
sc->aac_regs_rid0 = PCIR_BAR(0);
|
||||
if ((sc->aac_regs_res0 = bus_alloc_resource_any(sc->aac_dev,
|
||||
SYS_RES_MEMORY, &sc->aac_regs_rid0, RF_ACTIVE)) == NULL) {
|
||||
device_printf(sc->aac_dev,
|
||||
"couldn't allocate register window 0\n");
|
||||
rid = PCIR_BAR(0);
|
||||
if ((sc->aac_regs_res0 = bus_alloc_resource_any(dev,
|
||||
SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) {
|
||||
device_printf(dev, "can't allocate register window 0\n");
|
||||
goto out;
|
||||
}
|
||||
sc->aac_btag0 = rman_get_bustag(sc->aac_regs_res0);
|
||||
sc->aac_bhandle0 = rman_get_bushandle(sc->aac_regs_res0);
|
||||
|
||||
if (sc->aac_hwif == AAC_HWIF_NARK) {
|
||||
sc->aac_regs_rid1 = PCIR_BAR(1);
|
||||
if ((sc->aac_regs_res1 = bus_alloc_resource_any(sc->aac_dev,
|
||||
SYS_RES_MEMORY, &sc->aac_regs_rid1, RF_ACTIVE)) == NULL) {
|
||||
device_printf(sc->aac_dev,
|
||||
"couldn't allocate register window 1\n");
|
||||
rid = PCIR_BAR(1);
|
||||
if ((sc->aac_regs_res1 = bus_alloc_resource_any(dev,
|
||||
SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) {
|
||||
device_printf(dev,
|
||||
"can't allocate register window 1\n");
|
||||
goto out;
|
||||
}
|
||||
sc->aac_btag1 = rman_get_bustag(sc->aac_regs_res1);
|
||||
sc->aac_bhandle1 = rman_get_bushandle(sc->aac_regs_res1);
|
||||
} else {
|
||||
sc->aac_regs_res1 = sc->aac_regs_res0;
|
||||
sc->aac_regs_rid1 = sc->aac_regs_rid0;
|
||||
sc->aac_btag1 = sc->aac_btag0;
|
||||
sc->aac_bhandle1 = sc->aac_bhandle0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the interrupt.
|
||||
*/
|
||||
rid = 0;
|
||||
count = 0;
|
||||
if (aac_enable_msi != 0 && pci_find_cap(dev, PCIY_MSI, ®) == 0) {
|
||||
count = pci_msi_count(dev);
|
||||
if (count > 1)
|
||||
count = 1;
|
||||
else
|
||||
count = 0;
|
||||
if (count == 1 && pci_alloc_msi(dev, &count) == 0)
|
||||
rid = 1;
|
||||
}
|
||||
if ((sc->aac_irq = bus_alloc_resource_any(sc->aac_dev, SYS_RES_IRQ,
|
||||
&rid, RF_ACTIVE | (count != 0 ? 0 : RF_SHAREABLE))) == NULL) {
|
||||
device_printf(dev, "can't allocate interrupt\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the parent bus DMA tag appropriate for our PCI interface.
|
||||
*
|
||||
* Note that some of these controllers are 64-bit capable.
|
||||
*/
|
||||
if (bus_dma_tag_create(bus_get_dma_tag(sc->aac_dev), /* parent */
|
||||
if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
|
||||
PAGE_SIZE, 0, /* algnmnt, boundary */
|
||||
BUS_SPACE_MAXADDR, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
@ -413,7 +426,7 @@ aac_pci_attach(device_t dev)
|
||||
0, /* flags */
|
||||
NULL, NULL, /* No locking needed */
|
||||
&sc->aac_parent_dmat)) {
|
||||
device_printf(sc->aac_dev, "can't allocate parent DMA tag\n");
|
||||
device_printf(dev, "can't allocate parent DMA tag\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -427,19 +440,19 @@ aac_pci_attach(device_t dev)
|
||||
case AAC_HWIF_I960RX:
|
||||
case AAC_HWIF_NARK:
|
||||
fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for i960Rx/NARK");
|
||||
sc->aac_if = aac_rx_interface;
|
||||
sc->aac_if = &aac_rx_interface;
|
||||
break;
|
||||
case AAC_HWIF_STRONGARM:
|
||||
fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for StrongARM");
|
||||
sc->aac_if = aac_sa_interface;
|
||||
sc->aac_if = &aac_sa_interface;
|
||||
break;
|
||||
case AAC_HWIF_RKT:
|
||||
fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for Rocket/MIPS");
|
||||
sc->aac_if = aac_rkt_interface;
|
||||
sc->aac_if = &aac_rkt_interface;
|
||||
break;
|
||||
default:
|
||||
sc->aac_hwif = AAC_HWIF_UNKNOWN;
|
||||
device_printf(sc->aac_dev, "unknown hardware type\n");
|
||||
device_printf(dev, "unknown hardware type\n");
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
}
|
||||
@ -472,7 +485,7 @@ static device_method_t aacch_methods[] = {
|
||||
DEVMETHOD(device_probe, aacch_probe),
|
||||
DEVMETHOD(device_attach, aacch_attach),
|
||||
DEVMETHOD(device_detach, aacch_detach),
|
||||
{ 0, 0 }
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
struct aacch_softc {
|
||||
@ -486,7 +499,7 @@ static driver_t aacch_driver = {
|
||||
};
|
||||
|
||||
static devclass_t aacch_devclass;
|
||||
DRIVER_MODULE(aacch, pci, aacch_driver, aacch_devclass, 0, 0);
|
||||
DRIVER_MODULE(aacch, pci, aacch_driver, aacch_devclass, NULL, NULL);
|
||||
|
||||
static int
|
||||
aacch_probe(device_t dev)
|
||||
|
@ -27,13 +27,14 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Status codes for block read/write commands, etc.
|
||||
*
|
||||
* XXX many of these would not normally be returned, as they are
|
||||
* relevant only to FSA operations.
|
||||
*/
|
||||
static struct aac_code_lookup aac_command_status_table[] = {
|
||||
static const struct aac_code_lookup aac_command_status_table[] = {
|
||||
{"OK", ST_OK},
|
||||
{"operation not permitted", ST_PERM},
|
||||
{"not found", ST_NOENT},
|
||||
@ -75,8 +76,9 @@ static struct aac_code_lookup aac_command_status_table[] = {
|
||||
};
|
||||
|
||||
#define AAC_COMMAND_STATUS(x) aac_describe_code(aac_command_status_table, x)
|
||||
#endif
|
||||
|
||||
static struct aac_code_lookup aac_cpu_variant[] = {
|
||||
static const struct aac_code_lookup aac_cpu_variant[] = {
|
||||
{"i960JX", CPUI960_JX},
|
||||
{"i960CX", CPUI960_CX},
|
||||
{"i960HX", CPUI960_HX},
|
||||
@ -93,7 +95,7 @@ static struct aac_code_lookup aac_cpu_variant[] = {
|
||||
{"Unknown processor", 0}
|
||||
};
|
||||
|
||||
static struct aac_code_lookup aac_battery_platform[] = {
|
||||
static const struct aac_code_lookup aac_battery_platform[] = {
|
||||
{"required battery present", PLATFORM_BAT_REQ_PRESENT},
|
||||
{"REQUIRED BATTERY NOT PRESENT", PLATFORM_BAT_REQ_NOTPRESENT},
|
||||
{"optional battery present", PLATFORM_BAT_OPT_PRESENT},
|
||||
@ -103,7 +105,7 @@ static struct aac_code_lookup aac_battery_platform[] = {
|
||||
{"unknown battery platform", 0}
|
||||
};
|
||||
|
||||
static struct aac_code_lookup aac_container_types[] = {
|
||||
static const struct aac_code_lookup aac_container_types[] = {
|
||||
{"Volume", CT_VOLUME},
|
||||
{"RAID 1 (Mirror)", CT_MIRROR},
|
||||
{"RAID 0 (Stripe)", CT_STRIPE},
|
||||
@ -126,4 +128,3 @@ static struct aac_code_lookup aac_container_types[] = {
|
||||
{NULL, 0},
|
||||
{"unknown", 0}
|
||||
};
|
||||
|
||||
|
@ -33,10 +33,13 @@
|
||||
#include <sys/callout.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <geom/geom_disk.h>
|
||||
|
||||
SYSCTL_DECL(_hw_aac);
|
||||
|
||||
#define AAC_TYPE_DEVO 1
|
||||
#define AAC_TYPE_ALPHA 2
|
||||
#define AAC_TYPE_BETA 3
|
||||
@ -242,28 +245,28 @@ struct aac_interface
|
||||
int (*aif_get_outb_queue)(struct aac_softc *sc);
|
||||
void (*aif_set_outb_queue)(struct aac_softc *sc, int index);
|
||||
};
|
||||
extern struct aac_interface aac_rx_interface;
|
||||
extern struct aac_interface aac_sa_interface;
|
||||
extern struct aac_interface aac_fa_interface;
|
||||
extern struct aac_interface aac_rkt_interface;
|
||||
extern const struct aac_interface aac_rx_interface;
|
||||
extern const struct aac_interface aac_sa_interface;
|
||||
extern const struct aac_interface aac_fa_interface;
|
||||
extern const struct aac_interface aac_rkt_interface;
|
||||
|
||||
#define AAC_GET_FWSTATUS(sc) ((sc)->aac_if.aif_get_fwstatus((sc)))
|
||||
#define AAC_QNOTIFY(sc, qbit) ((sc)->aac_if.aif_qnotify((sc), (qbit)))
|
||||
#define AAC_GET_ISTATUS(sc) ((sc)->aac_if.aif_get_istatus((sc)))
|
||||
#define AAC_CLEAR_ISTATUS(sc, mask) ((sc)->aac_if.aif_clr_istatus((sc), \
|
||||
#define AAC_GET_FWSTATUS(sc) ((sc)->aac_if->aif_get_fwstatus((sc)))
|
||||
#define AAC_QNOTIFY(sc, qbit) ((sc)->aac_if->aif_qnotify((sc), (qbit)))
|
||||
#define AAC_GET_ISTATUS(sc) ((sc)->aac_if->aif_get_istatus((sc)))
|
||||
#define AAC_CLEAR_ISTATUS(sc, mask) ((sc)->aac_if->aif_clr_istatus((sc), \
|
||||
(mask)))
|
||||
#define AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3) \
|
||||
((sc)->aac_if.aif_set_mailbox((sc), (command), (arg0), (arg1), (arg2), \
|
||||
((sc)->aac_if->aif_set_mailbox((sc), (command), (arg0), (arg1), (arg2), \
|
||||
(arg3)))
|
||||
#define AAC_GET_MAILBOX(sc, mb) ((sc)->aac_if.aif_get_mailbox((sc), \
|
||||
#define AAC_GET_MAILBOX(sc, mb) ((sc)->aac_if->aif_get_mailbox((sc), \
|
||||
(mb)))
|
||||
#define AAC_MASK_INTERRUPTS(sc) ((sc)->aac_if.aif_set_interrupts((sc), \
|
||||
#define AAC_MASK_INTERRUPTS(sc) ((sc)->aac_if->aif_set_interrupts((sc), \
|
||||
0))
|
||||
#define AAC_UNMASK_INTERRUPTS(sc) ((sc)->aac_if.aif_set_interrupts((sc), \
|
||||
#define AAC_UNMASK_INTERRUPTS(sc) ((sc)->aac_if->aif_set_interrupts((sc), \
|
||||
1))
|
||||
#define AAC_SEND_COMMAND(sc, cm) ((sc)->aac_if.aif_send_command((sc), (cm)))
|
||||
#define AAC_GET_OUTB_QUEUE(sc) ((sc)->aac_if.aif_get_outb_queue((sc)))
|
||||
#define AAC_SET_OUTB_QUEUE(sc, idx) ((sc)->aac_if.aif_set_outb_queue((sc), (idx)))
|
||||
#define AAC_SEND_COMMAND(sc, cm) ((sc)->aac_if->aif_send_command((sc), (cm)))
|
||||
#define AAC_GET_OUTB_QUEUE(sc) ((sc)->aac_if->aif_get_outb_queue((sc)))
|
||||
#define AAC_SET_OUTB_QUEUE(sc, idx) ((sc)->aac_if->aif_set_outb_queue((sc), (idx)))
|
||||
|
||||
#define AAC_MEM0_SETREG4(sc, reg, val) bus_space_write_4(sc->aac_btag0, \
|
||||
sc->aac_bhandle0, reg, val)
|
||||
@ -307,14 +310,12 @@ struct aac_softc
|
||||
/* bus connections */
|
||||
device_t aac_dev;
|
||||
struct resource *aac_regs_res0, *aac_regs_res1; /* reg. if. window */
|
||||
int aac_regs_rid0, aac_regs_rid1; /* resource ID */
|
||||
bus_space_handle_t aac_bhandle0, aac_bhandle1; /* bus space handle */
|
||||
bus_space_tag_t aac_btag0, aac_btag1; /* bus space tag */
|
||||
bus_dma_tag_t aac_parent_dmat; /* parent DMA tag */
|
||||
bus_dma_tag_t aac_buffer_dmat; /* data buffer/command
|
||||
* DMA tag */
|
||||
struct resource *aac_irq; /* interrupt */
|
||||
int aac_irq_rid;
|
||||
void *aac_intr; /* interrupt handle */
|
||||
eventhandler_tag eh;
|
||||
|
||||
@ -339,7 +340,7 @@ struct aac_softc
|
||||
* DMA map */
|
||||
struct aac_common *aac_common;
|
||||
u_int32_t aac_common_busaddr;
|
||||
struct aac_interface aac_if;
|
||||
const struct aac_interface *aac_if;
|
||||
|
||||
/* command/fib resources */
|
||||
bus_dma_tag_t aac_fib_dmat; /* DMA tag for allocing FIBs */
|
||||
@ -499,7 +500,7 @@ extern void aac_print_aif(struct aac_softc *sc,
|
||||
#endif
|
||||
|
||||
struct aac_code_lookup {
|
||||
char *string;
|
||||
const char *string;
|
||||
u_int32_t code;
|
||||
};
|
||||
|
||||
@ -581,7 +582,6 @@ aac_remove_ ## name (struct aac_command *cm) \
|
||||
cm->cm_flags &= ~AAC_ON_ ## index; \
|
||||
AACQ_REMOVE(cm->cm_sc, index); \
|
||||
} \
|
||||
struct hack
|
||||
|
||||
AACQ_COMMAND_QUEUE(free, AACQ_FREE);
|
||||
AACQ_COMMAND_QUEUE(ready, AACQ_READY);
|
||||
@ -644,4 +644,3 @@ aac_release_sync_fib(struct aac_softc *sc)
|
||||
|
||||
mtx_assert(&sc->aac_io_lock, MA_OWNED);
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ static int acpi_cpu_cx_cst(struct acpi_cpu_softc *sc);
|
||||
static void acpi_cpu_startup(void *arg);
|
||||
static void acpi_cpu_startup_cx(struct acpi_cpu_softc *sc);
|
||||
static void acpi_cpu_cx_list(struct acpi_cpu_softc *sc);
|
||||
static void acpi_cpu_idle(void);
|
||||
static void acpi_cpu_idle(sbintime_t sbt);
|
||||
static void acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context);
|
||||
static int acpi_cpu_quirks(void);
|
||||
static int acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
@ -954,13 +954,13 @@ acpi_cpu_startup_cx(struct acpi_cpu_softc *sc)
|
||||
* interrupts are re-enabled.
|
||||
*/
|
||||
static void
|
||||
acpi_cpu_idle()
|
||||
acpi_cpu_idle(sbintime_t sbt)
|
||||
{
|
||||
struct acpi_cpu_softc *sc;
|
||||
struct acpi_cx *cx_next;
|
||||
uint64_t cputicks;
|
||||
uint32_t start_time, end_time;
|
||||
int bm_active, cx_next_idx, i;
|
||||
int bm_active, cx_next_idx, i, us;
|
||||
|
||||
/*
|
||||
* Look up our CPU id to get our softc. If it's NULL, we'll use C1
|
||||
@ -980,13 +980,16 @@ acpi_cpu_idle()
|
||||
}
|
||||
|
||||
/* Find the lowest state that has small enough latency. */
|
||||
us = sc->cpu_prev_sleep;
|
||||
if (sbt >= 0 && us > (sbt >> 12))
|
||||
us = (sbt >> 12);
|
||||
cx_next_idx = 0;
|
||||
if (cpu_disable_deep_sleep)
|
||||
i = min(sc->cpu_cx_lowest, sc->cpu_non_c3);
|
||||
else
|
||||
i = sc->cpu_cx_lowest;
|
||||
for (; i >= 0; i--) {
|
||||
if (sc->cpu_cx_states[i].trans_lat * 3 <= sc->cpu_prev_sleep) {
|
||||
if (sc->cpu_cx_states[i].trans_lat * 3 <= us) {
|
||||
cx_next_idx = i;
|
||||
break;
|
||||
}
|
||||
|
@ -147,8 +147,7 @@ hpet_disable(struct hpet_softc *sc)
|
||||
}
|
||||
|
||||
static int
|
||||
hpet_start(struct eventtimer *et,
|
||||
struct bintime *first, struct bintime *period)
|
||||
hpet_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
|
||||
{
|
||||
struct hpet_timer *mt = (struct hpet_timer *)et->et_priv;
|
||||
struct hpet_timer *t;
|
||||
@ -156,20 +155,16 @@ hpet_start(struct eventtimer *et,
|
||||
uint32_t fdiv, now;
|
||||
|
||||
t = (mt->pcpu_master < 0) ? mt : &sc->t[mt->pcpu_slaves[curcpu]];
|
||||
if (period != NULL) {
|
||||
if (period != 0) {
|
||||
t->mode = 1;
|
||||
t->div = (sc->freq * (period->frac >> 32)) >> 32;
|
||||
if (period->sec != 0)
|
||||
t->div += sc->freq * period->sec;
|
||||
t->div = (sc->freq * period) >> 32;
|
||||
} else {
|
||||
t->mode = 2;
|
||||
t->div = 0;
|
||||
}
|
||||
if (first != NULL) {
|
||||
fdiv = (sc->freq * (first->frac >> 32)) >> 32;
|
||||
if (first->sec != 0)
|
||||
fdiv += sc->freq * first->sec;
|
||||
} else
|
||||
if (first != 0)
|
||||
fdiv = (sc->freq * first) >> 32;
|
||||
else
|
||||
fdiv = t->div;
|
||||
if (t->irq < 0)
|
||||
bus_write_4(sc->mem_res, HPET_ISR, 1 << t->num);
|
||||
@ -684,12 +679,9 @@ hpet_attach(device_t dev)
|
||||
if ((t->caps & HPET_TCAP_PER_INT) == 0)
|
||||
t->et.et_quality -= 10;
|
||||
t->et.et_frequency = sc->freq;
|
||||
t->et.et_min_period.sec = 0;
|
||||
t->et.et_min_period.frac =
|
||||
(((uint64_t)(HPET_MIN_CYCLES * 2) << 32) / sc->freq) << 32;
|
||||
t->et.et_max_period.sec = 0xfffffffeLLU / sc->freq;
|
||||
t->et.et_max_period.frac =
|
||||
((0xfffffffeLLU << 32) / sc->freq) << 32;
|
||||
t->et.et_min_period =
|
||||
((uint64_t)(HPET_MIN_CYCLES * 2) << 32) / sc->freq;
|
||||
t->et.et_max_period = (0xfffffffeLLU << 32) / sc->freq;
|
||||
t->et.et_start = hpet_start;
|
||||
t->et.et_stop = hpet_stop;
|
||||
t->et.et_priv = &sc->t[i];
|
||||
|
@ -1,16 +1,15 @@
|
||||
/*
|
||||
*****************************************************************************************
|
||||
** O.S : FreeBSD
|
||||
********************************************************************************
|
||||
** OS : FreeBSD
|
||||
** FILE NAME : arcmsr.c
|
||||
** BY : Erich Chen, Ching Huang
|
||||
** Description: SCSI RAID Device Driver for
|
||||
** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x) SATA/SAS RAID HOST Adapter
|
||||
** ARCMSR RAID Host adapter
|
||||
** [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set]
|
||||
******************************************************************************************
|
||||
************************************************************************
|
||||
** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x)
|
||||
** SATA/SAS RAID HOST Adapter
|
||||
********************************************************************************
|
||||
********************************************************************************
|
||||
**
|
||||
** Copyright (C) 2002 - 2010, Areca Technology Corporation All rights reserved.
|
||||
** Copyright (C) 2002 - 2012, Areca Technology Corporation All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
@ -33,7 +32,7 @@
|
||||
** 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.
|
||||
**************************************************************************
|
||||
********************************************************************************
|
||||
** History
|
||||
**
|
||||
** REV# DATE NAME DESCRIPTION
|
||||
@ -73,7 +72,7 @@
|
||||
** 1.20.00.23 01/30/2012 Ching Huang Fixed Request requeued and Retrying command
|
||||
** 1.20.00.24 06/11/2012 Ching Huang Fixed return sense data condition
|
||||
** 1.20.00.25 08/17/2012 Ching Huang Fixed hotplug device no function on type A adapter
|
||||
** 1.20.00.26 12/14/2012 Ching Huang Added support ARC1214
|
||||
** 1.20.00.26 12/14/2012 Ching Huang Added support ARC1214,1224
|
||||
******************************************************************************************
|
||||
*/
|
||||
|
||||
@ -145,7 +144,7 @@ __FBSDID("$FreeBSD$");
|
||||
#define arcmsr_callout_init(a) callout_init(a);
|
||||
#endif
|
||||
|
||||
#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.26 2012-12-14"
|
||||
#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.26 2013-01-08"
|
||||
#include <dev/arcmsr/arcmsr.h>
|
||||
/*
|
||||
**************************************************************************
|
||||
@ -168,7 +167,7 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_iop_init(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer);
|
||||
static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer);
|
||||
static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag);
|
||||
@ -212,7 +211,11 @@ static device_method_t arcmsr_methods[]={
|
||||
DEVMETHOD(device_suspend, arcmsr_suspend),
|
||||
DEVMETHOD(device_resume, arcmsr_resume),
|
||||
|
||||
#if __FreeBSD_version >= 803000
|
||||
DEVMETHOD_END
|
||||
#else
|
||||
{ 0, 0 }
|
||||
#endif
|
||||
};
|
||||
|
||||
static driver_t arcmsr_driver={
|
||||
@ -1381,13 +1384,61 @@ static void arcmsr_poll(struct cam_sim *psim)
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
*/
|
||||
static void arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
|
||||
static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb,
|
||||
struct QBUFFER *prbuffer) {
|
||||
|
||||
u_int8_t *pQbuffer;
|
||||
u_int8_t *buf1 = 0;
|
||||
u_int32_t *iop_data, *buf2 = 0;
|
||||
u_int32_t iop_len, data_len;
|
||||
|
||||
iop_data = (u_int32_t *)prbuffer->data;
|
||||
iop_len = (u_int32_t)prbuffer->data_len;
|
||||
if ( iop_len > 0 )
|
||||
{
|
||||
buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
buf2 = (u_int32_t *)buf1;
|
||||
if( buf1 == NULL)
|
||||
return (0);
|
||||
data_len = iop_len;
|
||||
while(data_len >= 4)
|
||||
{
|
||||
*buf2++ = *iop_data++;
|
||||
data_len -= 4;
|
||||
}
|
||||
if(data_len)
|
||||
*buf2 = *iop_data;
|
||||
buf2 = (u_int32_t *)buf1;
|
||||
}
|
||||
while (iop_len > 0) {
|
||||
pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
|
||||
*pQbuffer = *buf1;
|
||||
acb->rqbuf_lastindex++;
|
||||
/* if last, index number set it to 0 */
|
||||
acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
|
||||
buf1++;
|
||||
iop_len--;
|
||||
}
|
||||
if(buf2)
|
||||
free( (u_int8_t *)buf2, M_DEVBUF);
|
||||
/* let IOP know data has been read */
|
||||
arcmsr_iop_message_read(acb);
|
||||
return (1);
|
||||
}
|
||||
/*
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
*/
|
||||
static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
|
||||
struct QBUFFER *prbuffer) {
|
||||
|
||||
u_int8_t *pQbuffer;
|
||||
u_int8_t *iop_data;
|
||||
u_int32_t iop_len;
|
||||
|
||||
if(acb->adapter_type == ACB_ADAPTER_TYPE_D) {
|
||||
return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer));
|
||||
}
|
||||
iop_data = (u_int8_t *)prbuffer->data;
|
||||
iop_len = (u_int32_t)prbuffer->data_len;
|
||||
while (iop_len > 0) {
|
||||
@ -1401,6 +1452,7 @@ static void arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
|
||||
}
|
||||
/* let IOP know data has been read */
|
||||
arcmsr_iop_message_read(acb);
|
||||
return (1);
|
||||
}
|
||||
/*
|
||||
**************************************************************************
|
||||
@ -1417,7 +1469,8 @@ static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
|
||||
my_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) &
|
||||
(ARCMSR_MAX_QBUFFER-1);
|
||||
if(my_empty_len >= prbuffer->data_len) {
|
||||
arcmsr_Read_iop_rqbuffer_data(acb, prbuffer);
|
||||
if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
|
||||
acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
|
||||
} else {
|
||||
acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
|
||||
}
|
||||
@ -1427,6 +1480,50 @@ static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
*/
|
||||
static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb)
|
||||
{
|
||||
u_int8_t *pQbuffer;
|
||||
struct QBUFFER *pwbuffer;
|
||||
u_int8_t *buf1 = 0;
|
||||
u_int32_t *iop_data, *buf2 = 0;
|
||||
u_int32_t allxfer_len = 0, data_len;
|
||||
|
||||
if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
|
||||
buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
buf2 = (u_int32_t *)buf1;
|
||||
if( buf1 == NULL)
|
||||
return;
|
||||
|
||||
acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
|
||||
pwbuffer = arcmsr_get_iop_wqbuffer(acb);
|
||||
iop_data = (u_int32_t *)pwbuffer->data;
|
||||
while((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
|
||||
&& (allxfer_len < 124)) {
|
||||
pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
|
||||
*buf1 = *pQbuffer;
|
||||
acb->wqbuf_firstindex++;
|
||||
acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
|
||||
buf1++;
|
||||
allxfer_len++;
|
||||
}
|
||||
pwbuffer->data_len = allxfer_len;
|
||||
data_len = allxfer_len;
|
||||
buf1 = (u_int8_t *)buf2;
|
||||
while(data_len >= 4)
|
||||
{
|
||||
*iop_data++ = *buf2++;
|
||||
data_len -= 4;
|
||||
}
|
||||
if(data_len)
|
||||
*iop_data = *buf2;
|
||||
free( buf1, M_DEVBUF);
|
||||
arcmsr_iop_message_wrote(acb);
|
||||
}
|
||||
}
|
||||
/*
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
*/
|
||||
static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb)
|
||||
{
|
||||
u_int8_t *pQbuffer;
|
||||
@ -1434,6 +1531,10 @@ static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb)
|
||||
u_int8_t *iop_data;
|
||||
int32_t allxfer_len=0;
|
||||
|
||||
if(acb->adapter_type == ACB_ADAPTER_TYPE_D) {
|
||||
arcmsr_Write_data_2iop_wqbuffer_D(acb);
|
||||
return;
|
||||
}
|
||||
if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
|
||||
acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
|
||||
pwbuffer = arcmsr_get_iop_wqbuffer(acb);
|
||||
@ -2153,7 +2254,8 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c
|
||||
|
||||
acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
|
||||
prbuffer = arcmsr_get_iop_rqbuffer(acb);
|
||||
arcmsr_Read_iop_rqbuffer_data(acb, prbuffer);
|
||||
if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
|
||||
acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
|
||||
}
|
||||
pcmdmessagefld->cmdmessage.Length = allxfer_len;
|
||||
pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
|
||||
@ -2374,7 +2476,8 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *p
|
||||
|
||||
acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
|
||||
prbuffer = arcmsr_get_iop_rqbuffer(acb);
|
||||
arcmsr_Read_iop_rqbuffer_data(acb, prbuffer);
|
||||
if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
|
||||
acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
|
||||
}
|
||||
pcmdmessagefld->cmdmessage.Length = allxfer_len;
|
||||
pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
|
||||
|
@ -1,17 +1,14 @@
|
||||
/*
|
||||
***********************************************************************************************
|
||||
** O.S : FreeBSD
|
||||
********************************************************************************
|
||||
** OS : FreeBSD
|
||||
** FILE NAME : arcmsr.h
|
||||
** BY : Erich Chen, Ching Huang
|
||||
** Description: SCSI RAID Device Driver for
|
||||
** ARECA SATA/SAS RAID HOST Adapter
|
||||
** [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set]
|
||||
***********************************************************************************************
|
||||
************************************************************************
|
||||
** Copyright (C) 2002 - 2010, Areca Technology Corporation All rights reserved.
|
||||
**
|
||||
** Web site: www.areca.com.tw
|
||||
** E-mail: erich@areca.com.tw; ching2048@areca.com.tw
|
||||
** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x)
|
||||
** SATA/SAS RAID HOST Adapter
|
||||
********************************************************************************
|
||||
********************************************************************************
|
||||
** Copyright (C) 2002 - 2012, Areca Technology Corporation All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms,with or without
|
||||
** modification,are permitted provided that the following conditions
|
||||
|
@ -236,9 +236,9 @@ ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
|
||||
rate = rt->info[rc[i].rix].rateCode;
|
||||
|
||||
/*
|
||||
* XXX only do this for legacy rates?
|
||||
* Only enable short preamble for legacy rates
|
||||
*/
|
||||
if (bf->bf_state.bfs_shpream)
|
||||
if ((! IS_HT_RATE(rate)) && bf->bf_state.bfs_shpream)
|
||||
rate |= rt->info[rc[i].rix].shortPreamble;
|
||||
|
||||
/*
|
||||
@ -267,6 +267,19 @@ ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
|
||||
ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
|
||||
rc[i].flags |= ATH_RC_SGI_FLAG;
|
||||
|
||||
/*
|
||||
* If we have STBC TX enabled and the receiver
|
||||
* can receive (at least) 1 stream STBC, AND it's
|
||||
* MCS 0-7, AND we have at least two chains enabled,
|
||||
* enable STBC.
|
||||
*/
|
||||
if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
|
||||
ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
|
||||
(sc->sc_cur_txchainmask > 1) &&
|
||||
HT_RC_2_STREAMS(rate) == 1) {
|
||||
rc[i].flags |= ATH_RC_STBC_FLAG;
|
||||
}
|
||||
|
||||
/* XXX dual stream? and 3-stream? */
|
||||
}
|
||||
|
||||
@ -459,6 +472,9 @@ ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf)
|
||||
*
|
||||
* It, along with ath_buf_set_rate, must be called -after- a burst
|
||||
* or aggregate is setup.
|
||||
*
|
||||
* XXX TODO: it should use the rate series information from the
|
||||
* ath_buf, rather than recalculating it here!
|
||||
*/
|
||||
static void
|
||||
ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
@ -507,34 +523,6 @@ ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
*/
|
||||
series[i].ChSel = sc->sc_cur_txchainmask;
|
||||
|
||||
if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
|
||||
series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
|
||||
|
||||
/*
|
||||
* Transmit 40MHz frames only if the node has negotiated
|
||||
* it rather than whether the node is capable of it or not.
|
||||
* It's subtly different in the hostap case.
|
||||
*/
|
||||
if (ni->ni_chw == 40)
|
||||
series[i].RateFlags |= HAL_RATESERIES_2040;
|
||||
|
||||
/*
|
||||
* Set short-GI only if the node has advertised it
|
||||
* the channel width is suitable, and we support it.
|
||||
* We don't currently have a "negotiated" set of bits -
|
||||
* ni_htcap is what the remote end sends, not what this
|
||||
* node is capable of.
|
||||
*/
|
||||
if (ni->ni_chw == 40 &&
|
||||
ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
|
||||
ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
|
||||
series[i].RateFlags |= HAL_RATESERIES_HALFGI;
|
||||
|
||||
if (ni->ni_chw == 20 &&
|
||||
ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
|
||||
ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
|
||||
series[i].RateFlags |= HAL_RATESERIES_HALFGI;
|
||||
|
||||
/*
|
||||
* Setup rate and TX power cap for this series.
|
||||
*/
|
||||
@ -542,24 +530,56 @@ ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
series[i].RateIndex = rc[i].rix;
|
||||
series[i].tx_power_cap = 0x3f; /* XXX for now */
|
||||
|
||||
|
||||
/*
|
||||
* If we have STBC TX enabled and the receiver
|
||||
* can receive (at least) 1 stream STBC, AND it's
|
||||
* MCS 0-7, AND we have at least two chains enabled,
|
||||
* enable STBC.
|
||||
* Enable RTS/CTS as appropriate.
|
||||
*/
|
||||
if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
|
||||
ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
|
||||
(sc->sc_cur_txchainmask > 1) &&
|
||||
HT_RC_2_STREAMS(series[i].Rate) == 1) {
|
||||
series[i].RateFlags |= HAL_RATESERIES_STBC;
|
||||
if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
|
||||
series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
|
||||
|
||||
|
||||
if (IS_HT_RATE(rt->info[rc[i].rix].rateCode)) {
|
||||
/*
|
||||
* Transmit 40MHz frames only if the node has negotiated
|
||||
* it rather than whether the node is capable of it or not.
|
||||
* It's subtly different in the hostap case.
|
||||
*/
|
||||
if (ni->ni_chw == 40)
|
||||
series[i].RateFlags |= HAL_RATESERIES_2040;
|
||||
|
||||
/*
|
||||
* Set short-GI only if the node has advertised it
|
||||
* the channel width is suitable, and we support it.
|
||||
* We don't currently have a "negotiated" set of bits -
|
||||
* ni_htcap is what the remote end sends, not what this
|
||||
* node is capable of.
|
||||
*/
|
||||
if (ni->ni_chw == 40 &&
|
||||
ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
|
||||
ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
|
||||
series[i].RateFlags |= HAL_RATESERIES_HALFGI;
|
||||
|
||||
if (ni->ni_chw == 20 &&
|
||||
ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
|
||||
ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
|
||||
series[i].RateFlags |= HAL_RATESERIES_HALFGI;
|
||||
|
||||
/*
|
||||
* If we have STBC TX enabled and the receiver
|
||||
* can receive (at least) 1 stream STBC, AND it's
|
||||
* MCS 0-7, AND we have at least two chains enabled,
|
||||
* enable STBC.
|
||||
*/
|
||||
if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
|
||||
ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
|
||||
(sc->sc_cur_txchainmask > 1) &&
|
||||
HT_RC_2_STREAMS(series[i].Rate) == 1) {
|
||||
series[i].RateFlags |= HAL_RATESERIES_STBC;
|
||||
}
|
||||
/*
|
||||
* XXX TODO: LDPC if it's possible
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX TODO: LDPC if it's possible
|
||||
*/
|
||||
|
||||
/*
|
||||
* PktDuration doesn't include slot, ACK, RTS, etc timing -
|
||||
* it's just the packet duration
|
||||
|
@ -84,6 +84,8 @@ void ath_rate_detach(struct ath_ratectrl *);
|
||||
#define ATH_RC_SGI_FLAG 0x04 /* use short-GI */
|
||||
#define ATH_RC_HT_FLAG 0x08 /* use HT */
|
||||
#define ATH_RC_RTSCTS_FLAG 0x10 /* enable RTS/CTS protection */
|
||||
#define ATH_RC_STBC_FLAG 0x20 /* enable STBC */
|
||||
#define ATH_RC_LDPC_FLAG 0x40 /* enable STBC */
|
||||
|
||||
struct ath_rc_series {
|
||||
uint8_t rix; /* ratetable index, not rate code */
|
||||
|
@ -95,7 +95,7 @@ __FBSDID("$FreeBSD$");
|
||||
/****************************************************************************/
|
||||
#define BCE_DEVDESC_MAX 64
|
||||
|
||||
static struct bce_type bce_devs[] = {
|
||||
static const struct bce_type bce_devs[] = {
|
||||
/* BCM5706C Controllers and OEM boards. */
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x3101,
|
||||
"HP NC370T Multifunction Gigabit Server Adapter" },
|
||||
@ -161,7 +161,7 @@ static struct bce_type bce_devs[] = {
|
||||
/****************************************************************************/
|
||||
/* Supported Flash NVRAM device data. */
|
||||
/****************************************************************************/
|
||||
static struct flash_spec flash_table[] =
|
||||
static const struct flash_spec flash_table[] =
|
||||
{
|
||||
#define BUFFERED_FLAGS (BCE_NV_BUFFERED | BCE_NV_TRANSLATE)
|
||||
#define NONBUFFERED_FLAGS (BCE_NV_WREN)
|
||||
@ -258,7 +258,7 @@ static struct flash_spec flash_table[] =
|
||||
* logical-to-physical mapping is required in the
|
||||
* driver.
|
||||
*/
|
||||
static struct flash_spec flash_5709 = {
|
||||
static const struct flash_spec flash_5709 = {
|
||||
.flags = BCE_NV_BUFFERED,
|
||||
.page_bits = BCM5709_FLASH_PAGE_BITS,
|
||||
.page_size = BCM5709_FLASH_PAGE_SIZE,
|
||||
@ -481,8 +481,8 @@ MODULE_DEPEND(bce, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(bce, ether, 1, 1, 1);
|
||||
MODULE_DEPEND(bce, miibus, 1, 1, 1);
|
||||
|
||||
DRIVER_MODULE(bce, pci, bce_driver, bce_devclass, 0, 0);
|
||||
DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, 0, 0);
|
||||
DRIVER_MODULE(bce, pci, bce_driver, bce_devclass, NULL, NULL);
|
||||
DRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, NULL, NULL);
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
@ -647,7 +647,7 @@ SYSCTL_UINT(_hw_bce, OID_AUTO, rx_ticks, CTLFLAG_RDTUN,
|
||||
static int
|
||||
bce_probe(device_t dev)
|
||||
{
|
||||
struct bce_type *t;
|
||||
const struct bce_type *t;
|
||||
struct bce_softc *sc;
|
||||
char *descbuf;
|
||||
u16 vid = 0, did = 0, svid = 0, sdid = 0;
|
||||
@ -655,7 +655,6 @@ bce_probe(device_t dev)
|
||||
t = bce_devs;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
bzero(sc, sizeof(struct bce_softc));
|
||||
sc->bce_unit = device_get_unit(dev);
|
||||
sc->bce_dev = dev;
|
||||
|
||||
@ -1040,7 +1039,7 @@ bce_attach(device_t dev)
|
||||
struct bce_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
u32 val;
|
||||
int error, rid, rc = 0;
|
||||
int count, error, rc = 0, rid;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->bce_dev = dev;
|
||||
@ -1077,6 +1076,7 @@ bce_attach(device_t dev)
|
||||
bce_probe_pci_caps(dev, sc);
|
||||
|
||||
rid = 1;
|
||||
count = 0;
|
||||
#if 0
|
||||
/* Try allocating MSI-X interrupts. */
|
||||
if ((sc->bce_cap_flags & BCE_MSIX_CAPABLE_FLAG) &&
|
||||
@ -1084,14 +1084,14 @@ bce_attach(device_t dev)
|
||||
((sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&rid, RF_ACTIVE)) != NULL)) {
|
||||
|
||||
msi_needed = sc->bce_msi_count = 1;
|
||||
msi_needed = count = 1;
|
||||
|
||||
if (((error = pci_alloc_msix(dev, &sc->bce_msi_count)) != 0) ||
|
||||
(sc->bce_msi_count != msi_needed)) {
|
||||
if (((error = pci_alloc_msix(dev, &count)) != 0) ||
|
||||
(count != msi_needed)) {
|
||||
BCE_PRINTF("%s(%d): MSI-X allocation failed! Requested = %d,"
|
||||
"Received = %d, error = %d\n", __FILE__, __LINE__,
|
||||
msi_needed, sc->bce_msi_count, error);
|
||||
sc->bce_msi_count = 0;
|
||||
msi_needed, count, error);
|
||||
count = 0;
|
||||
pci_release_msi(dev);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, rid,
|
||||
sc->bce_res_irq);
|
||||
@ -1100,19 +1100,18 @@ bce_attach(device_t dev)
|
||||
DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI-X interrupt.\n",
|
||||
__FUNCTION__);
|
||||
sc->bce_flags |= BCE_USING_MSIX_FLAG;
|
||||
sc->bce_intr = bce_intr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Try allocating a MSI interrupt. */
|
||||
if ((sc->bce_cap_flags & BCE_MSI_CAPABLE_FLAG) &&
|
||||
(bce_msi_enable >= 1) && (sc->bce_msi_count == 0)) {
|
||||
sc->bce_msi_count = 1;
|
||||
if ((error = pci_alloc_msi(dev, &sc->bce_msi_count)) != 0) {
|
||||
(bce_msi_enable >= 1) && (count == 0)) {
|
||||
count = 1;
|
||||
if ((error = pci_alloc_msi(dev, &count)) != 0) {
|
||||
BCE_PRINTF("%s(%d): MSI allocation failed! "
|
||||
"error = %d\n", __FILE__, __LINE__, error);
|
||||
sc->bce_msi_count = 0;
|
||||
count = 0;
|
||||
pci_release_msi(dev);
|
||||
} else {
|
||||
DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI "
|
||||
@ -1120,23 +1119,19 @@ bce_attach(device_t dev)
|
||||
sc->bce_flags |= BCE_USING_MSI_FLAG;
|
||||
if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709)
|
||||
sc->bce_flags |= BCE_ONE_SHOT_MSI_FLAG;
|
||||
sc->bce_irq_rid = 1;
|
||||
sc->bce_intr = bce_intr;
|
||||
rid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try allocating a legacy interrupt. */
|
||||
if (sc->bce_msi_count == 0) {
|
||||
if (count == 0) {
|
||||
DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using INTx interrupt.\n",
|
||||
__FUNCTION__);
|
||||
rid = 0;
|
||||
sc->bce_intr = bce_intr;
|
||||
}
|
||||
|
||||
sc->bce_res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
|
||||
&rid, RF_SHAREABLE | RF_ACTIVE);
|
||||
|
||||
sc->bce_irq_rid = rid;
|
||||
&rid, RF_ACTIVE | (count != 0 ? 0 : RF_SHAREABLE));
|
||||
|
||||
/* Report any IRQ allocation errors. */
|
||||
if (sc->bce_res_irq == NULL) {
|
||||
@ -1635,7 +1630,7 @@ bce_shutdown(device_t dev)
|
||||
static u32
|
||||
bce_reg_rd(struct bce_softc *sc, u32 offset)
|
||||
{
|
||||
u32 val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, offset);
|
||||
u32 val = REG_RD(sc, offset);
|
||||
DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%08X\n",
|
||||
__FUNCTION__, offset, val);
|
||||
return val;
|
||||
@ -1653,7 +1648,7 @@ bce_reg_wr16(struct bce_softc *sc, u32 offset, u16 val)
|
||||
{
|
||||
DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%04X\n",
|
||||
__FUNCTION__, offset, val);
|
||||
bus_space_write_2(sc->bce_btag, sc->bce_bhandle, offset, val);
|
||||
REG_WR16(sc, offset, val);
|
||||
}
|
||||
|
||||
|
||||
@ -1668,7 +1663,7 @@ bce_reg_wr(struct bce_softc *sc, u32 offset, u32 val)
|
||||
{
|
||||
DBPRINT(sc, BCE_INSANE_REG, "%s(); offset = 0x%08X, val = 0x%08X\n",
|
||||
__FUNCTION__, offset, val);
|
||||
bus_space_write_4(sc->bce_btag, sc->bce_bhandle, offset, val);
|
||||
REG_WR(sc, offset, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1879,13 +1874,6 @@ bce_miibus_read_reg(device_t dev, int phy, int reg)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Make sure we are accessing the correct PHY address. */
|
||||
if (phy != sc->bce_phy_addr) {
|
||||
DBPRINT(sc, BCE_INSANE_PHY, "Invalid PHY address %d "
|
||||
"for PHY read!\n", phy);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* The 5709S PHY is an IEEE Clause 45 PHY
|
||||
* with special mappings to work with IEEE
|
||||
@ -1968,13 +1956,6 @@ bce_miibus_write_reg(device_t dev, int phy, int reg, int val)
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Make sure we are accessing the correct PHY address. */
|
||||
if (phy != sc->bce_phy_addr) {
|
||||
DBPRINT(sc, BCE_INSANE_PHY, "Invalid PHY address %d "
|
||||
"for PHY write!\n", phy);
|
||||
return(0);
|
||||
}
|
||||
|
||||
DB_PRINT_PHY_REG(reg, val);
|
||||
|
||||
/*
|
||||
@ -2535,7 +2516,7 @@ bce_init_nvram(struct bce_softc *sc)
|
||||
{
|
||||
u32 val;
|
||||
int j, entry_count, rc = 0;
|
||||
struct flash_spec *flash;
|
||||
const struct flash_spec *flash;
|
||||
|
||||
DBENTER(BCE_VERBOSE_NVRAM);
|
||||
|
||||
@ -3949,8 +3930,8 @@ bce_release_resources(struct bce_softc *sc)
|
||||
|
||||
if (sc->bce_res_irq != NULL) {
|
||||
DBPRINT(sc, BCE_INFO_RESET, "Releasing IRQ.\n");
|
||||
bus_release_resource(dev, SYS_RES_IRQ, sc->bce_irq_rid,
|
||||
sc->bce_res_irq);
|
||||
bus_release_resource(dev, SYS_RES_IRQ,
|
||||
rman_get_rid(sc->bce_res_irq), sc->bce_res_irq);
|
||||
}
|
||||
|
||||
if (sc->bce_flags & (BCE_USING_MSI_FLAG | BCE_USING_MSIX_FLAG)) {
|
||||
@ -11650,4 +11631,3 @@ bce_breakpoint(struct bce_softc *sc)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -622,7 +622,7 @@ struct bce_type {
|
||||
u_int16_t bce_did;
|
||||
u_int16_t bce_svid;
|
||||
u_int16_t bce_sdid;
|
||||
char *bce_name;
|
||||
const char *bce_name;
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
@ -716,7 +716,7 @@ struct flash_spec {
|
||||
u32 page_size;
|
||||
u32 addr_mask;
|
||||
u32 total_size;
|
||||
u8 *name;
|
||||
const u8 *name;
|
||||
};
|
||||
|
||||
|
||||
@ -2001,7 +2001,7 @@ struct l2_fhdr {
|
||||
#define BCE_MISC_ENABLE_CLR_BITS_UMP_ENABLE (1L<<27)
|
||||
#define BCE_MISC_ENABLE_CLR_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28)
|
||||
#define BCE_MISC_ENABLE_CLR_BITS_RSVD_FUTURE_ENABLE (0x7L<<29)
|
||||
|
||||
|
||||
#define BCE_MISC_ENABLE_CLR_DEFAULT 0x17ffffff
|
||||
|
||||
#define BCE_MISC_CLOCK_CONTROL_BITS 0x00000818
|
||||
@ -6318,19 +6318,19 @@ struct fw_info {
|
||||
u32 text_addr;
|
||||
u32 text_len;
|
||||
u32 text_index;
|
||||
u32 *text;
|
||||
const u32 *text;
|
||||
|
||||
/* Data section. */
|
||||
u32 data_addr;
|
||||
u32 data_len;
|
||||
u32 data_index;
|
||||
u32 *data;
|
||||
const u32 *data;
|
||||
|
||||
/* SBSS section. */
|
||||
u32 sbss_addr;
|
||||
u32 sbss_len;
|
||||
u32 sbss_index;
|
||||
u32 *sbss;
|
||||
const u32 *sbss;
|
||||
|
||||
/* BSS section. */
|
||||
u32 bss_addr;
|
||||
@ -6421,7 +6421,7 @@ struct fw_info {
|
||||
|
||||
struct bce_softc
|
||||
{
|
||||
/* Interface info. Must be first!! */
|
||||
/* Interface info */
|
||||
struct ifnet *bce_ifp;
|
||||
|
||||
/* Parent device handle */
|
||||
@ -6451,10 +6451,7 @@ struct bce_softc
|
||||
struct mtx bce_mtx;
|
||||
|
||||
/* Interrupt handler. */
|
||||
driver_intr_t *bce_intr;
|
||||
void *bce_intrhand;
|
||||
int bce_irq_rid;
|
||||
int bce_msi_count;
|
||||
|
||||
/* ASIC Chip ID. */
|
||||
u32 bce_chipid;
|
||||
@ -6509,7 +6506,7 @@ struct bce_softc
|
||||
u16 link_speed;
|
||||
|
||||
/* Flash NVRAM settings */
|
||||
struct flash_spec *bce_flash_info;
|
||||
const struct flash_spec *bce_flash_info;
|
||||
|
||||
/* Flash NVRAM size */
|
||||
u32 bce_flash_size;
|
||||
@ -6518,7 +6515,7 @@ struct bce_softc
|
||||
u32 bce_shmem_base;
|
||||
|
||||
/* Name string */
|
||||
char *bce_name;
|
||||
const char *bce_name;
|
||||
|
||||
/* Tracks the version of bootcode firmware. */
|
||||
char bce_bc_ver[32];
|
||||
@ -6834,4 +6831,3 @@ struct bce_softc
|
||||
};
|
||||
|
||||
#endif /* __BCEREG_H_DEFINED */
|
||||
|
||||
|
@ -824,7 +824,8 @@ cas_disable_rx(struct cas_softc *sc)
|
||||
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
|
||||
if (cas_bitwait(sc, CAS_MAC_RX_CONF, CAS_MAC_RX_CONF_EN, 0))
|
||||
return (1);
|
||||
device_printf(sc->sc_dev, "cannot disable RX MAC\n");
|
||||
if (bootverbose)
|
||||
device_printf(sc->sc_dev, "cannot disable RX MAC\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -838,7 +839,8 @@ cas_disable_tx(struct cas_softc *sc)
|
||||
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
|
||||
if (cas_bitwait(sc, CAS_MAC_TX_CONF, CAS_MAC_TX_CONF_EN, 0))
|
||||
return (1);
|
||||
device_printf(sc->sc_dev, "cannot disable TX MAC\n");
|
||||
if (bootverbose)
|
||||
device_printf(sc->sc_dev, "cannot disable TX MAC\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1041,7 +1043,8 @@ cas_init_locked(struct cas_softc *sc)
|
||||
/*
|
||||
* Enable infinite bursts for revisions without PCI issues if
|
||||
* applicable. Doing so greatly improves the TX performance on
|
||||
* !__sparc64__.
|
||||
* !__sparc64__ (on sparc64, setting CAS_INF_BURST improves TX
|
||||
* performance only marginally but hurts RX throughput quite a bit).
|
||||
*/
|
||||
CAS_WRITE_4(sc, CAS_INF_BURST,
|
||||
#if !defined(__sparc64__)
|
||||
@ -2691,7 +2694,10 @@ cas_pci_attach(device_t dev)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
pci_enable_busmaster(dev);
|
||||
/* PCI configuration */
|
||||
pci_write_config(dev, PCIR_COMMAND,
|
||||
pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_BUSMASTEREN |
|
||||
PCIM_CMD_MWRICEN | PCIM_CMD_PERRESPEN | PCIM_CMD_SERRESPEN, 2);
|
||||
|
||||
sc->sc_dev = dev;
|
||||
if (sc->sc_variant == CAS_CAS && pci_get_devid(dev) < 0x02)
|
||||
|
@ -182,6 +182,7 @@
|
||||
#define com_xoff1 6 /* XOFF 1 character (R/W) */
|
||||
#define com_xoff2 7 /* XOFF 2 character (R/W) */
|
||||
|
||||
#define DW_REG_USR 31 /* DesignWare derived Uart Status Reg */
|
||||
#define com_usr 39 /* Octeon 16750/16550 Uart Status Reg */
|
||||
#define REG_USR com_usr
|
||||
#define USR_TXFIFO_NOTFULL 2 /* Uart TX FIFO Not full */
|
||||
|
@ -387,11 +387,11 @@ i_setsoc(isc_session_t *sp, int fd, struct thread *td)
|
||||
if(sp->soc != NULL)
|
||||
isc_stop_receiver(sp);
|
||||
|
||||
error = fget(td, fd, CAP_SOCK_ALL, &sp->fp);
|
||||
error = fget(td, fd, CAP_SOCK_CLIENT, &sp->fp);
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
if((error = fgetsock(td, fd, CAP_SOCK_ALL, &sp->soc, 0)) == 0) {
|
||||
if((error = fgetsock(td, fd, CAP_SOCK_CLIENT, &sp->soc, 0)) == 0) {
|
||||
sp->td = td;
|
||||
isc_start_receiver(sp);
|
||||
}
|
||||
|
@ -2997,7 +2997,7 @@ mfi_stp_cmd(struct mfi_softc *sc, struct mfi_command *cm,caddr_t arg)
|
||||
cm->cm_frame->stp.sgl.sg64[i].len =
|
||||
ioc->mfi_sgl[i].iov_len;
|
||||
} else {
|
||||
cm->cm_frame->stp.sgl.sg32[i].len =
|
||||
cm->cm_frame->stp.sgl.sg32[i].addr =
|
||||
kern_sge[i].phys_addr;
|
||||
cm->cm_frame->stp.sgl.sg32[i].len =
|
||||
ioc->mfi_sgl[i].iov_len;
|
||||
|
@ -136,8 +136,8 @@ mps_diag_reset(struct mps_softc *sc,int sleep_flag)
|
||||
|
||||
/*Force NO_SLEEP for threads prohibited to sleep
|
||||
* e.a Thread from interrupt handler are prohibited to sleep.
|
||||
*/
|
||||
if(curthread->td_pflags & TDP_NOSLEEPING)
|
||||
*/
|
||||
if (curthread->td_no_sleeping != 0)
|
||||
sleep_flag = NO_SLEEP;
|
||||
|
||||
/* Push the magic sequence */
|
||||
@ -469,8 +469,8 @@ mps_request_sync(struct mps_softc *sc, void *req, MPI2_DEFAULT_REPLY *reply,
|
||||
uint16_t *data16;
|
||||
int i, count, ioc_sz, residual;
|
||||
int sleep_flags = CAN_SLEEP;
|
||||
|
||||
if(curthread->td_pflags & TDP_NOSLEEPING)
|
||||
|
||||
if (curthread->td_no_sleeping != 0)
|
||||
sleep_flags = NO_SLEEP;
|
||||
|
||||
/* Step 1 */
|
||||
|
@ -244,7 +244,6 @@ static const struct pci_quirk pci_quirks[] = {
|
||||
* but support MSI just fine. QEMU uses the Intel 82440.
|
||||
*/
|
||||
{ 0x12378086, PCI_QUIRK_ENABLE_MSI_VM, 0, 0 },
|
||||
{ 0x12751275, PCI_QUIRK_ENABLE_MSI_VM, 0, 0 }, /* bhyve */
|
||||
|
||||
/*
|
||||
* HPET MMIO base address may appear in Bar1 for AMD SB600 SMBus
|
||||
|
@ -769,7 +769,7 @@ const struct puc_cfg puc_pci_devices[] = {
|
||||
|
||||
{ 0x1415, 0x9538, 0xffff, 0,
|
||||
"Oxford Semiconductor OX16PCI958 UARTs",
|
||||
DEFAULT_RCLK * 10,
|
||||
DEFAULT_RCLK,
|
||||
PUC_PORT_8S, 0x18, 0, 8,
|
||||
},
|
||||
|
||||
@ -918,6 +918,7 @@ const struct puc_cfg puc_pci_devices[] = {
|
||||
DEFAULT_RCLK * 8,
|
||||
PUC_PORT_4S, 0x10, 0, 8,
|
||||
},
|
||||
|
||||
{ 0x14d2, 0xa004, 0xffff, 0,
|
||||
"Titan PCI-800H",
|
||||
DEFAULT_RCLK * 8,
|
||||
@ -1060,7 +1061,7 @@ const struct puc_cfg puc_pci_devices[] = {
|
||||
{ 0x9710, 0x9865, 0xa000, 0x3004,
|
||||
"NetMos NM9865 Quad UART",
|
||||
DEFAULT_RCLK,
|
||||
PUC_PORT_4S, 0x10, 4, 0,0
|
||||
PUC_PORT_4S, 0x10, 4, 0,
|
||||
},
|
||||
|
||||
{ 0x9710, 0x9865, 0xa000, 0x3011,
|
||||
@ -1420,26 +1421,26 @@ static int
|
||||
puc_config_timedia(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
|
||||
intptr_t *res)
|
||||
{
|
||||
static uint16_t dual[] = {
|
||||
static const uint16_t dual[] = {
|
||||
0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
|
||||
0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079,
|
||||
0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079,
|
||||
0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
|
||||
0xD079, 0
|
||||
};
|
||||
static uint16_t quad[] = {
|
||||
static const uint16_t quad[] = {
|
||||
0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157,
|
||||
0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159,
|
||||
0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
|
||||
0xB157, 0
|
||||
};
|
||||
static uint16_t octa[] = {
|
||||
static const uint16_t octa[] = {
|
||||
0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166,
|
||||
0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0
|
||||
};
|
||||
static struct {
|
||||
static const struct {
|
||||
int ports;
|
||||
uint16_t *ids;
|
||||
const uint16_t *ids;
|
||||
} subdevs[] = {
|
||||
{ 2, dual },
|
||||
{ 4, quad },
|
||||
|
@ -573,6 +573,13 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
|
||||
if (slot->quirks & SDHCI_QUIRK_FORCE_DMA)
|
||||
slot->opt |= SDHCI_HAVE_DMA;
|
||||
|
||||
/*
|
||||
* Use platform-provided transfer backend
|
||||
* with PIO as a fallback mechanism
|
||||
*/
|
||||
if (slot->opt & SDHCI_PLATFORM_TRANSFER)
|
||||
slot->opt &= ~SDHCI_HAVE_DMA;
|
||||
|
||||
if (bootverbose || sdhci_debug) {
|
||||
slot_printf(slot, "%uMHz%s 4bits%s%s%s %s\n",
|
||||
slot->max_clk / 1000000,
|
||||
@ -909,7 +916,7 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
|
||||
WR2(slot, SDHCI_BLOCK_COUNT, (data->len + 511) / 512);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
sdhci_finish_data(struct sdhci_slot *slot)
|
||||
{
|
||||
struct mmc_data *data = slot->curcmd->data;
|
||||
@ -1102,13 +1109,23 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
|
||||
}
|
||||
if (slot->curcmd->error) {
|
||||
/* No need to continue after any error. */
|
||||
sdhci_finish_data(slot);
|
||||
if (slot->flags & PLATFORM_DATA_STARTED) {
|
||||
slot->flags &= ~PLATFORM_DATA_STARTED;
|
||||
SDHCI_PLATFORM_FINISH_TRANSFER(slot->bus, slot);
|
||||
} else
|
||||
sdhci_finish_data(slot);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle PIO interrupt. */
|
||||
if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
|
||||
sdhci_transfer_pio(slot);
|
||||
if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) {
|
||||
if ((slot->opt & SDHCI_PLATFORM_TRANSFER) &&
|
||||
SDHCI_PLATFORM_WILL_HANDLE(slot->bus, slot)) {
|
||||
SDHCI_PLATFORM_START_TRANSFER(slot->bus, slot, &intmask);
|
||||
slot->flags |= PLATFORM_DATA_STARTED;
|
||||
} else
|
||||
sdhci_transfer_pio(slot);
|
||||
}
|
||||
/* Handle DMA border. */
|
||||
if (intmask & SDHCI_INT_DMA_END) {
|
||||
struct mmc_data *data = slot->curcmd->data;
|
||||
@ -1147,8 +1164,13 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
|
||||
WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr);
|
||||
}
|
||||
/* We have got all data. */
|
||||
if (intmask & SDHCI_INT_DATA_END)
|
||||
sdhci_finish_data(slot);
|
||||
if (intmask & SDHCI_INT_DATA_END) {
|
||||
if (slot->flags & PLATFORM_DATA_STARTED) {
|
||||
slot->flags &= ~PLATFORM_DATA_STARTED;
|
||||
SDHCI_PLATFORM_FINISH_TRANSFER(slot->bus, slot);
|
||||
} else
|
||||
sdhci_finish_data(slot);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -224,8 +224,9 @@ struct sdhci_slot {
|
||||
device_t dev; /* Slot device */
|
||||
u_char num; /* Slot number */
|
||||
u_char opt; /* Slot options */
|
||||
#define SDHCI_HAVE_DMA 1
|
||||
#define SDHCI_PLATFORM_TRANSFER 2
|
||||
u_char version;
|
||||
#define SDHCI_HAVE_DMA 1
|
||||
uint32_t max_clk; /* Max possible freq */
|
||||
uint32_t timeout_clk; /* Timeout freq */
|
||||
bus_dma_tag_t dmatag;
|
||||
@ -250,6 +251,7 @@ struct sdhci_slot {
|
||||
#define CMD_STARTED 1
|
||||
#define STOP_STARTED 2
|
||||
#define SDHCI_USE_DMA 4 /* Use DMA for this req. */
|
||||
#define PLATFORM_DATA_STARTED 8 /* Data transfer is handled by platform */
|
||||
struct mtx mtx; /* Slot mutex */
|
||||
};
|
||||
|
||||
@ -257,6 +259,8 @@ int sdhci_generic_read_ivar(device_t bus, device_t child, int which, uintptr_t *
|
||||
int sdhci_generic_write_ivar(device_t bus, device_t child, int which, uintptr_t value);
|
||||
int sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num);
|
||||
void sdhci_start_slot(struct sdhci_slot *slot);
|
||||
/* performs generic clean-up for platform transfers */
|
||||
void sdhci_finish_data(struct sdhci_slot *slot);
|
||||
int sdhci_cleanup_slot(struct sdhci_slot *slot);
|
||||
int sdhci_generic_suspend(struct sdhci_slot *slot);
|
||||
int sdhci_generic_resume(struct sdhci_slot *slot);
|
||||
|
@ -131,6 +131,22 @@ METHOD void write_multi_4 {
|
||||
bus_size_t count;
|
||||
}
|
||||
|
||||
METHOD int platform_will_handle {
|
||||
device_t brdev;
|
||||
struct sdhci_slot *slot;
|
||||
}
|
||||
|
||||
METHOD void platform_start_transfer {
|
||||
device_t brdev;
|
||||
struct sdhci_slot *slot;
|
||||
uint32_t *intmask;
|
||||
}
|
||||
|
||||
METHOD void platform_finish_transfer {
|
||||
device_t brdev;
|
||||
struct sdhci_slot *slot;
|
||||
}
|
||||
|
||||
METHOD uint32_t min_freq {
|
||||
device_t brdev;
|
||||
struct sdhci_slot *slot;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user