Merging ^/head r278224 through r278297.
This commit is contained in:
commit
bd9cc051b3
21
etc/Makefile
21
etc/Makefile
@ -44,7 +44,6 @@ BIN1= crontab \
|
||||
rc.bsdextended \
|
||||
rc.firewall \
|
||||
rc.initdiskless \
|
||||
rc.sendmail \
|
||||
rc.shutdown \
|
||||
rc.subr \
|
||||
remote \
|
||||
@ -144,6 +143,10 @@ BIN1+= portsnap.conf
|
||||
BIN1+= pf.os
|
||||
.endif
|
||||
|
||||
.if ${MK_SENDMAIL} != "no"
|
||||
BIN1+= rc.sendmail
|
||||
.endif
|
||||
|
||||
.if ${MK_TCSH} != "no"
|
||||
BIN1+= csh.cshrc csh.login csh.logout
|
||||
.endif
|
||||
@ -254,7 +257,9 @@ distribution:
|
||||
.endif
|
||||
${_+_}cd ${.CURDIR}/gss; ${MAKE} install
|
||||
${_+_}cd ${.CURDIR}/periodic; ${MAKE} install
|
||||
.if ${MK_PKGBOOTSTRAP} != "no"
|
||||
${_+_}cd ${.CURDIR}/pkg; ${MAKE} install
|
||||
.endif
|
||||
${_+_}cd ${.CURDIR}/rc.d; ${MAKE} install
|
||||
${_+_}cd ${.CURDIR}/../share/termcap; ${MAKE} etc-termcap
|
||||
${_+_}cd ${.CURDIR}/../usr.sbin/rmt; ${MAKE} etc-rmt
|
||||
@ -316,8 +321,10 @@ distribution:
|
||||
.endif
|
||||
${INSTALL} -o ${BINOWN} -g operator -m 664 /dev/null \
|
||||
${DESTDIR}/etc/dumpdates
|
||||
.if ${MK_LOCATE} != "no"
|
||||
${INSTALL} -o nobody -g ${BINGRP} -m 644 /dev/null \
|
||||
${DESTDIR}/var/db/locate.database
|
||||
.endif
|
||||
${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 ${.CURDIR}/minfree \
|
||||
${DESTDIR}/var/crash
|
||||
cd ${.CURDIR}/..; ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 \
|
||||
@ -385,6 +392,7 @@ distrib-dirs: ${MTREES:N/*}
|
||||
done; true
|
||||
.endif
|
||||
${INSTALL_SYMLINK} usr/src/sys ${DESTDIR}/sys
|
||||
.if ${MK_MAN} != "no"
|
||||
cd ${DESTDIR}/usr/share/man; \
|
||||
for mandir in man*; do \
|
||||
${INSTALL_SYMLINK} ../$$mandir \
|
||||
@ -392,23 +400,30 @@ distrib-dirs: ${MTREES:N/*}
|
||||
${INSTALL_SYMLINK} ../$$mandir \
|
||||
${DESTDIR}/usr/share/man/en.UTF-8/; \
|
||||
done
|
||||
.if ${MK_OPENSSL} != "no"
|
||||
cd ${DESTDIR}/usr/share/openssl/man; \
|
||||
for mandir in man*; do \
|
||||
${INSTALL_SYMLINK} ../$$mandir \
|
||||
${DESTDIR}/usr/share/openssl/man/en.ISO8859-1/; \
|
||||
done
|
||||
.endif
|
||||
set - `grep "^[a-zA-Z]" ${.CURDIR}/man.alias`; \
|
||||
while [ $$# -gt 0 ] ; do \
|
||||
${INSTALL_SYMLINK} "$$2" "${DESTDIR}/usr/share/man/$$1"; \
|
||||
${INSTALL_SYMLINK} "$$2" \
|
||||
"${DESTDIR}/usr/share/openssl/man/$$1"; \
|
||||
if [ "${MK_OPENSSL}" != "no" ]; then \
|
||||
${INSTALL_SYMLINK} "$$2" \
|
||||
"${DESTDIR}/usr/share/openssl/man/$$1"; \
|
||||
fi; \
|
||||
shift; shift; \
|
||||
done
|
||||
.endif
|
||||
.if ${MK_NLS} != "no"
|
||||
set - `grep "^[a-zA-Z]" ${.CURDIR}/nls.alias`; \
|
||||
while [ $$# -gt 0 ] ; do \
|
||||
${INSTALL_SYMLINK} "$$2" "${DESTDIR}/usr/share/nls/$$1"; \
|
||||
shift; shift; \
|
||||
done
|
||||
.endif
|
||||
|
||||
etc-examples:
|
||||
cd ${.CURDIR}; ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 \
|
||||
|
@ -19,7 +19,6 @@ FILES= DAEMON \
|
||||
auditdistd \
|
||||
bgfsck \
|
||||
${_bluetooth} \
|
||||
bootparams \
|
||||
bridge \
|
||||
${_bthidd} \
|
||||
${_casperd} \
|
||||
@ -35,7 +34,6 @@ FILES= DAEMON \
|
||||
dmesg \
|
||||
dumpon \
|
||||
fsck \
|
||||
ftpd \
|
||||
gbde \
|
||||
geli \
|
||||
geli2 \
|
||||
@ -46,7 +44,6 @@ FILES= DAEMON \
|
||||
hostid \
|
||||
hostid_save \
|
||||
hostname \
|
||||
inetd \
|
||||
ip6addrctl \
|
||||
ipfilter \
|
||||
ipfs \
|
||||
@ -72,7 +69,6 @@ FILES= DAEMON \
|
||||
mdconfig \
|
||||
mdconfig2 \
|
||||
mountd \
|
||||
moused \
|
||||
mroute6d \
|
||||
msgs \
|
||||
natd \
|
||||
@ -87,14 +83,11 @@ FILES= DAEMON \
|
||||
nisdomain \
|
||||
${_nscd} \
|
||||
nsswitch \
|
||||
ntpd \
|
||||
ntpdate \
|
||||
${_opensm} \
|
||||
othermta \
|
||||
pf \
|
||||
pflog \
|
||||
pfsync \
|
||||
powerd \
|
||||
ppp \
|
||||
pppoed \
|
||||
pwcheck \
|
||||
@ -124,17 +117,14 @@ FILES= DAEMON \
|
||||
stf \
|
||||
swap \
|
||||
swaplate \
|
||||
syscons \
|
||||
sysctl \
|
||||
syslogd \
|
||||
timed \
|
||||
tmp \
|
||||
${_ubthidhci} \
|
||||
ugidfw \
|
||||
${_unbound} \
|
||||
${_utx} \
|
||||
var \
|
||||
virecover \
|
||||
watchdogd \
|
||||
ypbind \
|
||||
yppasswdd \
|
||||
@ -153,6 +143,10 @@ FILES+= accounting
|
||||
FILES+= power_profile
|
||||
.endif
|
||||
|
||||
.if ${MK_ACPI} != "no" || ${MK_APM} != "no"
|
||||
FILES+= powerd
|
||||
.endif
|
||||
|
||||
.if ${MK_AMD} != "no"
|
||||
FILES+= amd
|
||||
.endif
|
||||
@ -175,6 +169,10 @@ _hcsecd= hcsecd
|
||||
_ubthidhci= ubthidhci
|
||||
.endif
|
||||
|
||||
.if ${MK_BOOTPARAMD} != "no"
|
||||
FILES+= bootparams
|
||||
.endif
|
||||
|
||||
.if ${MK_BSNMP} != "no"
|
||||
FILES+= bsnmpd
|
||||
.endif
|
||||
@ -187,10 +185,18 @@ _casperd= casperd
|
||||
FILES+= ccd
|
||||
.endif
|
||||
|
||||
.if ${MK_FTP} != "no"
|
||||
FILES+= ftpd
|
||||
.endif
|
||||
|
||||
.if ${MK_HAST} != "no"
|
||||
FILES+= hastd
|
||||
.endif
|
||||
|
||||
.if ${MK_INETD} != "no"
|
||||
FILES+= inetd
|
||||
.endif
|
||||
|
||||
.if ${MK_ISCSI} != "no"
|
||||
FILES+= iscsictl
|
||||
FILES+= iscsid
|
||||
@ -200,12 +206,13 @@ FILES+= iscsid
|
||||
FILES+= jail
|
||||
.endif
|
||||
|
||||
.if ${MK_LPR} != "no"
|
||||
FILES+= lpd
|
||||
.if ${MK_LEGACY_CONSOLE} != "no"
|
||||
FILES+= moused
|
||||
FILES+= syscons
|
||||
.endif
|
||||
|
||||
.if ${MK_NS_CACHING} != "no"
|
||||
_nscd= nscd
|
||||
.if ${MK_LPR} != "no"
|
||||
FILES+= lpd
|
||||
.endif
|
||||
|
||||
.if ${MK_KERBEROS} != "no"
|
||||
@ -217,6 +224,18 @@ _kfd= kfd
|
||||
_kpasswdd= kpasswdd
|
||||
.endif
|
||||
|
||||
.if ${MK_MAIL} != "no"
|
||||
FILES+= othermta
|
||||
.endif
|
||||
|
||||
.if ${MK_NS_CACHING} != "no"
|
||||
_nscd= nscd
|
||||
.endif
|
||||
|
||||
.if ${MK_NTP} != "no"
|
||||
FILES+= ntpd
|
||||
.endif
|
||||
|
||||
.if ${MK_OFED} != "no"
|
||||
_opensm= opensm
|
||||
.endif
|
||||
@ -237,6 +256,18 @@ FILES+= ftp-proxy
|
||||
FILES+= rwho
|
||||
.endif
|
||||
|
||||
.if ${MK_ROUTED} != "no"
|
||||
FILES+= routed
|
||||
.endif
|
||||
|
||||
.if ${MK_SENDMAIL} != "no"
|
||||
FILES+= sendmail
|
||||
.endif
|
||||
|
||||
.if ${MK_TIMED} != "no"
|
||||
FILES+= timed
|
||||
.endif
|
||||
|
||||
.if ${MK_UNBOUND} != "no"
|
||||
_unbound= local_unbound
|
||||
.endif
|
||||
@ -245,6 +276,10 @@ _unbound= local_unbound
|
||||
_utx= utx
|
||||
.endif
|
||||
|
||||
.if ${MK_VI} != "no"
|
||||
FILES+= virecover
|
||||
.endif
|
||||
|
||||
.if ${MK_WIRELESS} != "no"
|
||||
FILES+= hostapd
|
||||
FILES+= wpa_supplicant
|
||||
|
@ -34,7 +34,8 @@ BUILD_TRIPLE?= ${BUILD_ARCH:C/amd64/x86_64/:C/armv6hf/armv6/:C/arm64/aarch64/}-u
|
||||
CFLAGS+= -DLLVM_DEFAULT_TARGET_TRIPLE=\"${TARGET_TRIPLE}\" \
|
||||
-DLLVM_HOST_TRIPLE=\"${BUILD_TRIPLE}\" \
|
||||
-DDEFAULT_SYSROOT=\"${TOOLS_PREFIX}\"
|
||||
CXXFLAGS+= -std=c++11 -stdlib=libc++ -fno-exceptions -fno-rtti
|
||||
CXXFLAGS+= -std=c++11 -fno-exceptions -fno-rtti
|
||||
CXXFLAGS.clang+= -stdlib=libc++
|
||||
|
||||
.PATH: ${LLVM_SRCS}/${SRCDIR}
|
||||
|
||||
|
@ -9,6 +9,9 @@ CFLAGS+= -I${.CURDIR}/../common \
|
||||
-I${.CURDIR}/../../libc/include \
|
||||
-mlongcall
|
||||
|
||||
CC:= gcc
|
||||
COMPILER_TYPE:= gcc
|
||||
|
||||
all: ${OBJS}
|
||||
|
||||
CLEANFILES= ${OBJS}
|
||||
|
@ -4,6 +4,8 @@
|
||||
<!ENTITY % release PUBLIC "-//FreeBSD//ENTITIES Release Specification//EN"
|
||||
"http://www.FreeBSD.org/release/XML/release.ent">
|
||||
%release;
|
||||
<!ENTITY security SYSTEM "../../share/xml/security.xml">
|
||||
<!ENTITY errata SYSTEM "../../share/xml/errata.xml">
|
||||
]>
|
||||
|
||||
<article xmlns="http://docbook.org/ns/docbook"
|
||||
@ -17,7 +19,7 @@
|
||||
<pubdate>$FreeBSD$</pubdate>
|
||||
|
||||
<copyright>
|
||||
<year>2014</year>
|
||||
<year>2015</year>
|
||||
|
||||
<holder role="mailto:doc@FreeBSD.org">The &os; Documentation Project</holder>
|
||||
</copyright>
|
||||
@ -76,7 +78,13 @@
|
||||
<sect1 xml:id="security">
|
||||
<title>Security Advisories</title>
|
||||
|
||||
<para>No advisory.</para>
|
||||
&security;
|
||||
</sect1>
|
||||
|
||||
<sect1 xml:id="errata">
|
||||
<title>Errata Notices</title>
|
||||
|
||||
&errata;
|
||||
</sect1>
|
||||
|
||||
<sect1 xml:id="open-issues">
|
||||
|
@ -7,6 +7,8 @@
|
||||
%sponsor;
|
||||
<!ENTITY % vendor PUBLIC "-//FreeBSD//ENTITIES Vendor Specification//EN" "vendor.ent">
|
||||
%vendor;
|
||||
<!ENTITY security SYSTEM "../../share/xml/security.xml">
|
||||
<!ENTITY errata SYSTEM "../../share/xml/errata.xml">
|
||||
]>
|
||||
<article xmlns="http://docbook.org/ns/docbook"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0">
|
||||
@ -138,15 +140,13 @@
|
||||
<sect2 xml:id="security">
|
||||
<title>Security Advisories</title>
|
||||
|
||||
<para>No advisories.</para>
|
||||
|
||||
&security;
|
||||
</sect2>
|
||||
|
||||
<sect2 xml:id="errata">
|
||||
<title>Errata Notices</title>
|
||||
|
||||
<para>No errata notices.</para>
|
||||
|
||||
&errata;
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
|
28
release/doc/share/xml/errata.xml
Normal file
28
release/doc/share/xml/errata.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!--
|
||||
The FreeBSD Documentation Project
|
||||
|
||||
$FreeBSD$
|
||||
-->
|
||||
<informaltable frame="none" pgwide="1">
|
||||
<tgroup cols="3">
|
||||
<colspec colwidth="40%"/>
|
||||
<colspec colwidth="30%"/>
|
||||
<colspec colwidth="30%"/>
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Errata</entry>
|
||||
<entry>Date</entry>
|
||||
<entry>Topic</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><para>No errata notices.</para></entry>
|
||||
<entry><para> </para></entry>
|
||||
<entry><para> </para></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
@ -16,7 +16,7 @@
|
||||
<!-- The previous stable release, useful for pointing user's at the
|
||||
release they SHOULD be running if they don't want the bleeding
|
||||
edge. -->
|
||||
<!ENTITY release.prev.stable "9.2-RELEASE">
|
||||
<!ENTITY release.prev.stable "9.3-RELEASE">
|
||||
|
||||
<!-- The next version to be released, usually used for snapshots. -->
|
||||
<!ENTITY release.next "11.0-RELEASE">
|
||||
@ -25,7 +25,10 @@
|
||||
<!ENTITY release.branch "11-CURRENT">
|
||||
|
||||
<!-- The URL for obtaining this version of FreeBSD. -->
|
||||
<!ENTITY release.url "http://www.FreeBSD.org/snapshots/">
|
||||
<!ENTITY release.url "https://www.FreeBSD.org/snapshots/">
|
||||
|
||||
<!-- The URL for Security Advisories and Errata Notices. -->
|
||||
<!ENTITY security.url "https://www.FreeBSD.org/security/advisories">
|
||||
|
||||
<!-- The recommended mailing list to track. -->
|
||||
<!ENTITY release.maillist "current">
|
||||
@ -51,7 +54,7 @@
|
||||
<!ENTITY release ''>
|
||||
|
||||
<!-- The manpaths for man page references -->
|
||||
<!ENTITY release.man.url "http://www.FreeBSD.org/cgi/man.cgi">
|
||||
<!ENTITY release.man.url "https://www.FreeBSD.org/cgi/man.cgi">
|
||||
<!ENTITY release.manpath.xorg "7.5.1">
|
||||
<!ENTITY release.manpath.netbsd "5.1">
|
||||
<!ENTITY release.manpath.freebsd-ports "Ports">
|
||||
|
28
release/doc/share/xml/security.xml
Normal file
28
release/doc/share/xml/security.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!--
|
||||
The FreeBSD Documentation Project
|
||||
|
||||
$FreeBSD$
|
||||
-->
|
||||
<informaltable frame="none" pgwide="1">
|
||||
<tgroup cols="3">
|
||||
<colspec colwidth="40%"/>
|
||||
<colspec colwidth="30%"/>
|
||||
<colspec colwidth="30%"/>
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Advisory</entry>
|
||||
<entry>Date</entry>
|
||||
<entry>Topic</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><para>No advisories.</para></entry>
|
||||
<entry><para> </para></entry>
|
||||
<entry><para> </para></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
@ -61,6 +61,7 @@ struct format_opts {
|
||||
int bcwidth;
|
||||
int pcwidth;
|
||||
int show_counters;
|
||||
int show_time; /* show timestamp */
|
||||
uint32_t set_mask; /* enabled sets mask */
|
||||
uint32_t flags; /* request flags */
|
||||
uint32_t first; /* first rule to request */
|
||||
@ -2402,7 +2403,7 @@ list_static_range(struct cmdline_opts *co, struct format_opts *fo,
|
||||
for (n = seen = 0; n < rcnt; n++,
|
||||
rtlv = (ipfw_obj_tlv *)((caddr_t)rtlv + rtlv->length)) {
|
||||
|
||||
if (fo->show_counters != 0) {
|
||||
if ((fo->show_counters | fo->show_time) != 0) {
|
||||
cntr = (struct ip_fw_bcounter *)(rtlv + 1);
|
||||
r = (struct ip_fw_rule *)((caddr_t)cntr + cntr->size);
|
||||
} else {
|
||||
@ -2504,10 +2505,11 @@ ipfw_list(int ac, char *av[], int show_counters)
|
||||
/* get configuraion from kernel */
|
||||
cfg = NULL;
|
||||
sfo.show_counters = show_counters;
|
||||
sfo.show_time = co.do_time;
|
||||
sfo.flags = IPFW_CFG_GET_STATIC;
|
||||
if (co.do_dynamic != 0)
|
||||
sfo.flags |= IPFW_CFG_GET_STATES;
|
||||
if (sfo.show_counters != 0)
|
||||
if ((sfo.show_counters | sfo.show_time) != 0)
|
||||
sfo.flags |= IPFW_CFG_GET_COUNTERS;
|
||||
if (ipfw_get_config(&co, &sfo, &cfg, &sz) != 0)
|
||||
err(EX_OSERR, "retrieving config failed");
|
||||
|
@ -27,3 +27,23 @@ kern/kern_clocksource.c standard
|
||||
|
||||
dev/mbox/mbox_if.m standard
|
||||
dev/ofw/ofw_cpu.c standard
|
||||
|
||||
# VideoCore driver
|
||||
contrib/vchiq/interface/compat/vchi_bsd.c standard \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c standard \
|
||||
compile-with "${NORMAL_C} -Wno-unused -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_arm.c standard \
|
||||
compile-with "${NORMAL_C} -Wno-unused -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_connected.c standard \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_core.c standard \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c standard \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c standard \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_shim.c standard \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
contrib/vchiq/interface/vchiq_arm/vchiq_util.c standard \
|
||||
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
|
||||
|
@ -53,6 +53,10 @@ EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
|
||||
EFI_GUID mps = MPS_TABLE_GUID;
|
||||
EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
|
||||
EFI_GUID smbios = SMBIOS_TABLE_GUID;
|
||||
EFI_GUID dxe = DXE_SERVICES_TABLE_GUID;
|
||||
EFI_GUID hoblist = HOB_LIST_TABLE_GUID;
|
||||
EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID;
|
||||
EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
|
||||
|
||||
EFI_STATUS
|
||||
main(int argc, CHAR16 *argv[])
|
||||
@ -264,6 +268,14 @@ command_configuration(int argc, char *argv[])
|
||||
printf("ACPI 2.0 Table");
|
||||
else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
|
||||
printf("SMBIOS Table");
|
||||
else if (!memcmp(guid, &dxe, sizeof(EFI_GUID)))
|
||||
printf("DXE Table");
|
||||
else if (!memcmp(guid, &hoblist, sizeof(EFI_GUID)))
|
||||
printf("HOB List Table");
|
||||
else if (!memcmp(guid, &memtype, sizeof(EFI_GUID)))
|
||||
printf("Memory Type Information Table");
|
||||
else if (!memcmp(guid, &debugimg, sizeof(EFI_GUID)))
|
||||
printf("Debug Image Info Table");
|
||||
else
|
||||
printf("Unknown Table (%s)", guid_to_string(guid));
|
||||
printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
|
||||
@ -319,7 +331,7 @@ command_mode(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
printf("Choose the mode with \"col <mode number>\"\n");
|
||||
printf("Choose the mode with \"col <mode number>\"\n");
|
||||
|
||||
return (CMD_OK);
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ EFI_STATUS
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
typedef
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_SET_VIRTUAL_ADDRESS_MAP) (
|
||||
IN UINTN MemoryMapSize,
|
||||
@ -103,7 +103,7 @@ EFI_STATUS
|
||||
#define EFI_INTERNAL_PTR 0x00000004 // Pointer to internal runtime data
|
||||
|
||||
|
||||
typedef
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_CONVERT_POINTER) (
|
||||
IN UINTN DebugDisposition,
|
||||
@ -168,7 +168,7 @@ EFI_STATUS
|
||||
IN EFI_EVENT Event
|
||||
);
|
||||
|
||||
typedef
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_WAIT_FOR_EVENT) (
|
||||
IN UINTN NumberOfEvents,
|
||||
@ -194,8 +194,8 @@ EFI_STATUS
|
||||
|
||||
#define TPL_APPLICATION 4
|
||||
#define TPL_CALLBACK 8
|
||||
#define TPL_NOTIFY 16
|
||||
#define TPL_HIGH_LEVEL 31
|
||||
#define TPL_NOTIFY 16
|
||||
#define TPL_HIGH_LEVEL 31
|
||||
|
||||
typedef
|
||||
EFI_TPL
|
||||
@ -320,14 +320,14 @@ EFI_STATUS
|
||||
|
||||
// Image Entry prototype
|
||||
|
||||
typedef
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_IMAGE_ENTRY_POINT) (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN struct _EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
typedef
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_IMAGE_LOAD) (
|
||||
IN BOOLEAN BootPolicy,
|
||||
@ -338,7 +338,7 @@ EFI_STATUS
|
||||
OUT EFI_HANDLE *ImageHandle
|
||||
);
|
||||
|
||||
typedef
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_IMAGE_START) (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
@ -355,7 +355,7 @@ EFI_STATUS
|
||||
IN CHAR16 *ExitData OPTIONAL
|
||||
);
|
||||
|
||||
typedef
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_IMAGE_UNLOAD) (
|
||||
IN EFI_HANDLE ImageHandle
|
||||
@ -491,7 +491,7 @@ EFI_STATUS
|
||||
);
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_REGISTER_PROTOCOL_NOTIFY) (
|
||||
IN EFI_GUID *Protocol,
|
||||
IN EFI_EVENT Event,
|
||||
@ -535,7 +535,7 @@ EFI_STATUS
|
||||
);
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_CONNECT_CONTROLLER) (
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE *DriverImageHandle OPTIONAL,
|
||||
@ -544,19 +544,19 @@ EFI_STATUS
|
||||
);
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_DISCONNECT_CONTROLLER)(
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE DriverImageHandle, OPTIONAL
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL
|
||||
);
|
||||
);
|
||||
|
||||
#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001
|
||||
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002
|
||||
#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004
|
||||
#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008
|
||||
#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010
|
||||
#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020
|
||||
#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001
|
||||
#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002
|
||||
#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004
|
||||
#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008
|
||||
#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010
|
||||
#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020
|
||||
|
||||
typedef
|
||||
EFI_STATUS
|
||||
@ -804,7 +804,7 @@ typedef struct {
|
||||
//
|
||||
EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle;
|
||||
EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer;
|
||||
EFI_LOCATE_PROTOCOL LocateProtocol;
|
||||
EFI_LOCATE_PROTOCOL LocateProtocol;
|
||||
|
||||
EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces;
|
||||
EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces;
|
||||
@ -845,6 +845,18 @@ typedef struct {
|
||||
#define FDT_TABLE_GUID \
|
||||
{ 0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 }
|
||||
|
||||
#define DXE_SERVICES_TABLE_GUID \
|
||||
{ 0x5ad34ba, 0x6f02, 0x4214, 0x95, 0x2e, 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9 }
|
||||
|
||||
#define HOB_LIST_TABLE_GUID \
|
||||
{ 0x7739f24c, 0x93d7, 0x11d4, 0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }
|
||||
|
||||
#define MEMORY_TYPE_INFORMATION_TABLE_GUID \
|
||||
{ 0x4c19049f, 0x4137, 0x4dd3, 0x9c, 0x10, 0x8b, 0x97, 0xa8, 0x3f, 0xfd, 0xfa }
|
||||
|
||||
#define DEBUG_IMAGE_INFO_TABLE_GUID \
|
||||
{ 0x49152e77, 0x1ada, 0x4764, 0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b }
|
||||
|
||||
typedef struct _EFI_CONFIGURATION_TABLE {
|
||||
EFI_GUID VendorGuid;
|
||||
VOID *VendorTable;
|
||||
|
@ -1147,6 +1147,7 @@ struct ccb_dev_advinfo {
|
||||
#define CDAI_TYPE_SERIAL_NUM 2
|
||||
#define CDAI_TYPE_PHYS_PATH 3
|
||||
#define CDAI_TYPE_RCAPLONG 4
|
||||
#define CDAI_TYPE_EXT_INQ 5
|
||||
off_t bufsiz; /* IN: Size of external buffer */
|
||||
#define CAM_SCSI_DEVID_MAXLEN 65536 /* length in buffer is an uint16_t */
|
||||
off_t provsiz; /* OUT: Size required/used */
|
||||
|
@ -4795,6 +4795,7 @@ xpt_release_device(struct cam_ed *device)
|
||||
*/
|
||||
free(device->supported_vpds, M_CAMXPT);
|
||||
free(device->device_id, M_CAMXPT);
|
||||
free(device->ext_inq, M_CAMXPT);
|
||||
free(device->physpath, M_CAMXPT);
|
||||
free(device->rcap_buf, M_CAMXPT);
|
||||
free(device->serial_num, M_CAMXPT);
|
||||
|
@ -83,6 +83,8 @@ struct cam_ed {
|
||||
uint8_t supported_vpds_len;
|
||||
uint32_t device_id_len;
|
||||
uint8_t *device_id;
|
||||
uint32_t ext_inq_len;
|
||||
uint8_t *ext_inq;
|
||||
uint8_t physpath_len;
|
||||
uint8_t *physpath; /* physical path string form */
|
||||
uint32_t rcap_len;
|
||||
|
@ -139,6 +139,7 @@ typedef enum {
|
||||
PROBE_MODE_SENSE,
|
||||
PROBE_SUPPORTED_VPD_LIST,
|
||||
PROBE_DEVICE_ID,
|
||||
PROBE_EXTENDED_INQUIRY,
|
||||
PROBE_SERIAL_NUM,
|
||||
PROBE_TUR_FOR_NEGOTIATION,
|
||||
PROBE_INQUIRY_BASIC_DV1,
|
||||
@ -156,6 +157,7 @@ static char *probe_action_text[] = {
|
||||
"PROBE_MODE_SENSE",
|
||||
"PROBE_SUPPORTED_VPD_LIST",
|
||||
"PROBE_DEVICE_ID",
|
||||
"PROBE_EXTENDED_INQUIRY",
|
||||
"PROBE_SERIAL_NUM",
|
||||
"PROBE_TUR_FOR_NEGOTIATION",
|
||||
"PROBE_INQUIRY_BASIC_DV1",
|
||||
@ -923,6 +925,34 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
case PROBE_EXTENDED_INQUIRY:
|
||||
{
|
||||
struct scsi_vpd_extended_inquiry_data *ext_inq;
|
||||
|
||||
ext_inq = NULL;
|
||||
if (scsi_vpd_supported_page(periph, SVPD_EXTENDED_INQUIRY_DATA))
|
||||
ext_inq = malloc(sizeof(*ext_inq), M_CAMXPT,
|
||||
M_NOWAIT | M_ZERO);
|
||||
|
||||
if (ext_inq != NULL) {
|
||||
scsi_inquiry(csio,
|
||||
/*retries*/4,
|
||||
probedone,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
(uint8_t *)ext_inq,
|
||||
sizeof(*ext_inq),
|
||||
/*evpd*/TRUE,
|
||||
SVPD_EXTENDED_INQUIRY_DATA,
|
||||
SSD_MIN_SIZE,
|
||||
/*timeout*/60 * 1000);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* We'll have to do without, let our probedone
|
||||
* routine finish up for us.
|
||||
*/
|
||||
goto done;
|
||||
}
|
||||
case PROBE_SERIAL_NUM:
|
||||
{
|
||||
struct scsi_vpd_unit_serial_number *serial_buf;
|
||||
@ -1454,6 +1484,50 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
if (devid && length == 0)
|
||||
free(devid, M_CAMXPT);
|
||||
xpt_release_ccb(done_ccb);
|
||||
PROBE_SET_ACTION(softc, PROBE_EXTENDED_INQUIRY);
|
||||
xpt_schedule(periph, priority);
|
||||
goto out;
|
||||
}
|
||||
case PROBE_EXTENDED_INQUIRY: {
|
||||
struct scsi_vpd_extended_inquiry_data *ext_inq;
|
||||
struct ccb_scsiio *csio;
|
||||
int32_t length = 0;
|
||||
|
||||
csio = &done_ccb->csio;
|
||||
ext_inq = (struct scsi_vpd_extended_inquiry_data *)
|
||||
csio->data_ptr;
|
||||
if (path->device->ext_inq != NULL) {
|
||||
path->device->ext_inq_len = 0;
|
||||
free(path->device->ext_inq, M_CAMXPT);
|
||||
path->device->ext_inq = NULL;
|
||||
}
|
||||
|
||||
if (ext_inq == NULL) {
|
||||
/* Don't process the command as it was never sent */
|
||||
} else if (CCB_COMPLETED_OK(csio->ccb_h)) {
|
||||
length = scsi_2btoul(ext_inq->page_length) +
|
||||
__offsetof(struct scsi_vpd_extended_inquiry_data,
|
||||
flags1);
|
||||
length = min(length, sizeof(*ext_inq));
|
||||
length -= csio->resid;
|
||||
if (length > 0) {
|
||||
path->device->ext_inq_len = length;
|
||||
path->device->ext_inq = (uint8_t *)ext_inq;
|
||||
}
|
||||
} else if (cam_periph_error(done_ccb, 0,
|
||||
SF_RETRY_UA,
|
||||
&softc->saved_ccb) == ERESTART) {
|
||||
return;
|
||||
} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
|
||||
/* Don't wedge the queue */
|
||||
xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
|
||||
/*run_queue*/TRUE);
|
||||
}
|
||||
|
||||
/* Free the device id space if we don't use it */
|
||||
if (ext_inq && length <= 0)
|
||||
free(ext_inq, M_CAMXPT);
|
||||
xpt_release_ccb(done_ccb);
|
||||
PROBE_SET_ACTION(softc, PROBE_SERIAL_NUM);
|
||||
xpt_schedule(periph, priority);
|
||||
goto out;
|
||||
@ -2477,6 +2551,21 @@ scsi_dev_advinfo(union ccb *start_ccb)
|
||||
memcpy(cdai->buf, device->rcap_buf, amt);
|
||||
}
|
||||
break;
|
||||
case CDAI_TYPE_EXT_INQ:
|
||||
/*
|
||||
* We fetch extended inquiry data during probe, if
|
||||
* available. We don't allow changing it.
|
||||
*/
|
||||
if (cdai->flags & CDAI_FLAG_STORE)
|
||||
return;
|
||||
cdai->provsiz = device->ext_inq_len;
|
||||
if (device->ext_inq_len == 0)
|
||||
break;
|
||||
amt = device->ext_inq_len;
|
||||
if (cdai->provsiz > cdai->bufsiz)
|
||||
amt = cdai->bufsiz;
|
||||
memcpy(cdai->buf, device->ext_inq, amt);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -159,6 +159,14 @@ INLINE_LIMIT?= 8000
|
||||
#
|
||||
CFLAGS+= -ffreestanding
|
||||
|
||||
#
|
||||
# The C standard leaves signed integer overflow behavior undefined.
|
||||
# gcc and clang opimizers take advantage of this. The kernel makes
|
||||
# use of signed integer wraparound mechanics so we need the compiler
|
||||
# to treat it as a wraparound and not take shortcuts.
|
||||
#
|
||||
CFLAGS+= -fwrapv
|
||||
|
||||
#
|
||||
# GCC SSP support
|
||||
#
|
||||
|
@ -79,6 +79,9 @@ INCLUDES+= -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal
|
||||
# ... and the same for the NgATM stuff
|
||||
INCLUDES+= -I$S/contrib/ngatm
|
||||
|
||||
# ... and the same for vchiq
|
||||
INCLUDES+= -I$S/contrib/vchiq
|
||||
|
||||
# ... and the same for twa
|
||||
INCLUDES+= -I$S/dev/twa
|
||||
|
||||
|
@ -129,6 +129,7 @@ GEOM_SHSEC opt_geom.h
|
||||
GEOM_STRIPE opt_geom.h
|
||||
GEOM_SUNLABEL opt_geom.h
|
||||
GEOM_UNCOMPRESS opt_geom.h
|
||||
GEOM_UNCOMPRESS_DEBUG opt_geom.h
|
||||
GEOM_UZIP opt_geom.h
|
||||
GEOM_VINUM opt_geom.h
|
||||
GEOM_VIRSTOR opt_geom.h
|
||||
@ -209,7 +210,7 @@ SW_WATCHDOG opt_watchdog.h
|
||||
TURNSTILE_PROFILING
|
||||
UMTX_PROFILING
|
||||
VFS_AIO
|
||||
VERBOSE_SYSINIT opt_global.h
|
||||
VERBOSE_SYSINIT
|
||||
WLCACHE opt_wavelan.h
|
||||
WLDEBUG opt_wavelan.h
|
||||
|
||||
|
256
sys/contrib/vchiq/interface/compat/list.h
Normal file
256
sys/contrib/vchiq/interface/compat/list.h
Normal file
@ -0,0 +1,256 @@
|
||||
/* $NetBSD: list.h,v 1.5 2014/08/20 15:26:52 riastradh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2013 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Taylor R. Campbell.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Notes on porting:
|
||||
*
|
||||
* - LIST_HEAD(x) means a declaration `struct list_head x =
|
||||
* LIST_HEAD_INIT(x)' in Linux, but something else in NetBSD.
|
||||
* Replace by the expansion.
|
||||
*
|
||||
* - The `_rcu' routines here are not actually pserialize(9)-safe.
|
||||
* They need dependent read memory barriers added. Please fix this
|
||||
* if you need to use them with pserialize(9).
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_LIST_H_
|
||||
#define _LINUX_LIST_H_
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#define container_of(ptr, type, member) \
|
||||
({ \
|
||||
__typeof(((type *)0)->member) *_p = (ptr); \
|
||||
(type *)((char *)_p - offsetof(type, member)); \
|
||||
})
|
||||
|
||||
/*
|
||||
* Doubly-linked lists.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *prev;
|
||||
struct list_head *next;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { .prev = &(name), .next = &(name) }
|
||||
|
||||
static inline void
|
||||
INIT_LIST_HEAD(struct list_head *head)
|
||||
{
|
||||
head->prev = head;
|
||||
head->next = head;
|
||||
}
|
||||
|
||||
static inline struct list_head *
|
||||
list_first(const struct list_head *head)
|
||||
{
|
||||
return head->next;
|
||||
}
|
||||
|
||||
static inline struct list_head *
|
||||
list_last(const struct list_head *head)
|
||||
{
|
||||
return head->prev;
|
||||
}
|
||||
|
||||
static inline struct list_head *
|
||||
list_next(const struct list_head *node)
|
||||
{
|
||||
return node->next;
|
||||
}
|
||||
|
||||
static inline struct list_head *
|
||||
list_prev(const struct list_head *node)
|
||||
{
|
||||
return node->prev;
|
||||
}
|
||||
|
||||
static inline int
|
||||
list_empty(const struct list_head *head)
|
||||
{
|
||||
return (head->next == head);
|
||||
}
|
||||
|
||||
static inline int
|
||||
list_is_singular(const struct list_head *head)
|
||||
{
|
||||
|
||||
if (list_empty(head))
|
||||
return false;
|
||||
if (head->next != head->prev)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__list_add_between(struct list_head *prev, struct list_head *node,
|
||||
struct list_head *next)
|
||||
{
|
||||
prev->next = node;
|
||||
node->prev = prev;
|
||||
node->next = next;
|
||||
next->prev = node;
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_add(struct list_head *node, struct list_head *head)
|
||||
{
|
||||
__list_add_between(head, node, head->next);
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_add_tail(struct list_head *node, struct list_head *head)
|
||||
{
|
||||
__list_add_between(head->prev, node, head);
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_del(struct list_head *entry)
|
||||
{
|
||||
entry->prev->next = entry->next;
|
||||
entry->next->prev = entry->prev;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__list_splice_between(struct list_head *prev, const struct list_head *list,
|
||||
struct list_head *next)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
struct list_head *last = list->prev;
|
||||
|
||||
first->prev = prev;
|
||||
prev->next = first;
|
||||
|
||||
last->next = next;
|
||||
next->prev = last;
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_splice(const struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice_between(head, list, head->next);
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_splice_tail(const struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice_between(head->prev, list, head);
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_move(struct list_head *node, struct list_head *head)
|
||||
{
|
||||
list_del(node);
|
||||
list_add(node, head);
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_move_tail(struct list_head *node, struct list_head *head)
|
||||
{
|
||||
list_del(node);
|
||||
list_add_tail(node, head);
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_replace(struct list_head *old, struct list_head *new)
|
||||
{
|
||||
new->prev = old->prev;
|
||||
old->prev->next = new;
|
||||
new->next = old->next;
|
||||
old->next->prev = new;
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_del_init(struct list_head *node)
|
||||
{
|
||||
list_del(node);
|
||||
INIT_LIST_HEAD(node);
|
||||
}
|
||||
|
||||
#define list_entry(PTR, TYPE, FIELD) container_of(PTR, TYPE, FIELD)
|
||||
#define list_first_entry(PTR, TYPE, FIELD) \
|
||||
list_entry(list_first((PTR)), TYPE, FIELD)
|
||||
#define list_last_entry(PTR, TYPE, FIELD) \
|
||||
list_entry(list_last((PTR)), TYPE, FIELD)
|
||||
#define list_next_entry(ENTRY, FIELD) \
|
||||
list_entry(list_next(&(ENTRY)->FIELD), typeof(*(ENTRY)), FIELD)
|
||||
#define list_prev_entry(ENTRY, FIELD) \
|
||||
list_entry(list_prev(&(ENTRY)->FIELD), typeof(*(ENTRY)), FIELD)
|
||||
|
||||
#define list_for_each(VAR, HEAD) \
|
||||
for ((VAR) = list_first((HEAD)); \
|
||||
(VAR) != (HEAD); \
|
||||
(VAR) = list_next((VAR)))
|
||||
|
||||
#define list_for_each_safe(VAR, NEXT, HEAD) \
|
||||
for ((VAR) = list_first((HEAD)); \
|
||||
((VAR) != (HEAD)) && ((NEXT) = list_next((VAR)), 1); \
|
||||
(VAR) = (NEXT))
|
||||
|
||||
#define list_for_each_entry(VAR, HEAD, FIELD) \
|
||||
for ((VAR) = list_entry(list_first((HEAD)), typeof(*(VAR)), FIELD); \
|
||||
&(VAR)->FIELD != (HEAD); \
|
||||
(VAR) = list_entry(list_next(&(VAR)->FIELD), typeof(*(VAR)), \
|
||||
FIELD))
|
||||
|
||||
#define list_for_each_entry_reverse(VAR, HEAD, FIELD) \
|
||||
for ((VAR) = list_entry(list_last((HEAD)), typeof(*(VAR)), FIELD); \
|
||||
&(VAR)->FIELD != (HEAD); \
|
||||
(VAR) = list_entry(list_prev(&(VAR)->FIELD), typeof(*(VAR)), \
|
||||
FIELD))
|
||||
|
||||
#define list_for_each_entry_safe(VAR, NEXT, HEAD, FIELD) \
|
||||
for ((VAR) = list_entry(list_first((HEAD)), typeof(*(VAR)), FIELD); \
|
||||
(&(VAR)->FIELD != (HEAD)) && \
|
||||
((NEXT) = list_entry(list_next(&(VAR)->FIELD), \
|
||||
typeof(*(VAR)), FIELD), 1); \
|
||||
(VAR) = (NEXT))
|
||||
|
||||
#define list_for_each_entry_continue(VAR, HEAD, FIELD) \
|
||||
for ((VAR) = list_next_entry((VAR), FIELD); \
|
||||
&(VAR)->FIELD != (HEAD); \
|
||||
(VAR) = list_next_entry((VAR), FIELD))
|
||||
|
||||
#define list_for_each_entry_continue_reverse(VAR, HEAD, FIELD) \
|
||||
for ((VAR) = list_prev_entry((VAR), FIELD); \
|
||||
&(VAR)->FIELD != (HEAD); \
|
||||
(VAR) = list_prev_entry((VAR), FIELD))
|
||||
|
||||
#define list_for_each_entry_safe_from(VAR, NEXT, HEAD, FIELD) \
|
||||
for (; \
|
||||
(&(VAR)->FIELD != (HEAD)) && \
|
||||
((NEXT) = list_next_entry((VAR), FIELD)); \
|
||||
(VAR) = (NEXT))
|
||||
|
||||
#endif /* _LINUX_LIST_H_ */
|
532
sys/contrib/vchiq/interface/compat/vchi_bsd.c
Normal file
532
sys/contrib/vchiq/interface/compat/vchi_bsd.c
Normal file
@ -0,0 +1,532 @@
|
||||
/*-
|
||||
* Copyright (c) 2010 Max Khon <fjoe@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed by Max Khon under sponsorship from
|
||||
* the FreeBSD Foundation and Ethon Technologies GmbH.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id: bsd-compat.c 9253 2010-09-02 10:12:09Z fjoe $
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/firmware.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/taskqueue.h>
|
||||
|
||||
#include <machine/stdarg.h>
|
||||
|
||||
#include "mbox_if.h"
|
||||
|
||||
#include <interface/compat/vchi_bsd.h>
|
||||
|
||||
MALLOC_DEFINE(M_VCHI, "VCHI", "VCHI");
|
||||
|
||||
/*
|
||||
* Timer API
|
||||
*/
|
||||
static void
|
||||
run_timer(void *arg)
|
||||
{
|
||||
struct timer_list *t = (struct timer_list *) arg;
|
||||
void (*function)(unsigned long);
|
||||
|
||||
mtx_lock_spin(&t->mtx);
|
||||
if (callout_pending(&t->callout)) {
|
||||
/* callout was reset */
|
||||
mtx_unlock_spin(&t->mtx);
|
||||
return;
|
||||
}
|
||||
if (!callout_active(&t->callout)) {
|
||||
/* callout was stopped */
|
||||
mtx_unlock_spin(&t->mtx);
|
||||
return;
|
||||
}
|
||||
callout_deactivate(&t->callout);
|
||||
|
||||
function = t->function;
|
||||
mtx_unlock_spin(&t->mtx);
|
||||
|
||||
function(t->data);
|
||||
}
|
||||
|
||||
void
|
||||
init_timer(struct timer_list *t)
|
||||
{
|
||||
mtx_init(&t->mtx, "dahdi timer lock", NULL, MTX_SPIN);
|
||||
callout_init(&t->callout, CALLOUT_MPSAFE);
|
||||
t->expires = 0;
|
||||
/*
|
||||
* function and data are not initialized intentionally:
|
||||
* they are not initialized by Linux implementation too
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
setup_timer(struct timer_list *t, void (*function)(unsigned long), unsigned long data)
|
||||
{
|
||||
t->function = function;
|
||||
t->data = data;
|
||||
init_timer(t);
|
||||
}
|
||||
|
||||
void
|
||||
mod_timer(struct timer_list *t, unsigned long expires)
|
||||
{
|
||||
mtx_lock_spin(&t->mtx);
|
||||
callout_reset(&t->callout, expires - jiffies, run_timer, t);
|
||||
mtx_unlock_spin(&t->mtx);
|
||||
}
|
||||
|
||||
void
|
||||
add_timer(struct timer_list *t)
|
||||
{
|
||||
mod_timer(t, t->expires);
|
||||
}
|
||||
|
||||
int
|
||||
del_timer_sync(struct timer_list *t)
|
||||
{
|
||||
mtx_lock_spin(&t->mtx);
|
||||
callout_stop(&t->callout);
|
||||
mtx_unlock_spin(&t->mtx);
|
||||
|
||||
mtx_destroy(&t->mtx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
del_timer(struct timer_list *t)
|
||||
{
|
||||
del_timer_sync(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Completion API
|
||||
*/
|
||||
void
|
||||
init_completion(struct completion *c)
|
||||
{
|
||||
cv_init(&c->cv, "VCHI completion cv");
|
||||
mtx_init(&c->lock, "VCHI completion lock", "condvar", MTX_DEF);
|
||||
c->done = 0;
|
||||
}
|
||||
|
||||
void
|
||||
destroy_completion(struct completion *c)
|
||||
{
|
||||
cv_destroy(&c->cv);
|
||||
mtx_destroy(&c->lock);
|
||||
}
|
||||
|
||||
void
|
||||
complete(struct completion *c)
|
||||
{
|
||||
mtx_lock(&c->lock);
|
||||
|
||||
if (c->done >= 0) {
|
||||
KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
|
||||
c->done++;
|
||||
cv_signal(&c->cv);
|
||||
} else {
|
||||
KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
|
||||
}
|
||||
|
||||
mtx_unlock(&c->lock);
|
||||
}
|
||||
|
||||
void
|
||||
complete_all(struct completion *c)
|
||||
{
|
||||
mtx_lock(&c->lock);
|
||||
|
||||
if (c->done >= 0) {
|
||||
KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
|
||||
c->done = -1;
|
||||
cv_broadcast(&c->cv);
|
||||
} else {
|
||||
KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
|
||||
}
|
||||
|
||||
mtx_unlock(&c->lock);
|
||||
}
|
||||
|
||||
void
|
||||
INIT_COMPLETION_locked(struct completion *c)
|
||||
{
|
||||
mtx_lock(&c->lock);
|
||||
|
||||
c->done = 0;
|
||||
|
||||
mtx_unlock(&c->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
_completion_claim(struct completion *c)
|
||||
{
|
||||
|
||||
KASSERT(mtx_owned(&c->lock),
|
||||
("_completion_claim should be called with acquired lock"));
|
||||
KASSERT(c->done != 0, ("_completion_claim on non-waited completion"));
|
||||
if (c->done > 0)
|
||||
c->done--;
|
||||
else
|
||||
KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
|
||||
}
|
||||
|
||||
void
|
||||
wait_for_completion(struct completion *c)
|
||||
{
|
||||
mtx_lock(&c->lock);
|
||||
if (!c->done)
|
||||
cv_wait(&c->cv, &c->lock);
|
||||
c->done--;
|
||||
mtx_unlock(&c->lock);
|
||||
}
|
||||
|
||||
int
|
||||
try_wait_for_completion(struct completion *c)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
mtx_lock(&c->lock);
|
||||
if (!c->done)
|
||||
res = 1;
|
||||
else
|
||||
c->done--;
|
||||
mtx_unlock(&c->lock);
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
int
|
||||
wait_for_completion_interruptible_timeout(struct completion *c, unsigned long timeout)
|
||||
{
|
||||
int res = 0;
|
||||
unsigned long start, now;
|
||||
start = jiffies;
|
||||
|
||||
mtx_lock(&c->lock);
|
||||
while (c->done == 0) {
|
||||
res = cv_timedwait_sig(&c->cv, &c->lock, timeout);
|
||||
if (res)
|
||||
goto out;
|
||||
now = jiffies;
|
||||
if (timeout < (now - start)) {
|
||||
res = EWOULDBLOCK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
timeout -= (now - start);
|
||||
start = now;
|
||||
}
|
||||
|
||||
_completion_claim(c);
|
||||
res = 0;
|
||||
|
||||
out:
|
||||
mtx_unlock(&c->lock);
|
||||
|
||||
if (res == EWOULDBLOCK) {
|
||||
return 0;
|
||||
} else if ((res == EINTR) || (res == ERESTART)) {
|
||||
return -ERESTART;
|
||||
} else {
|
||||
KASSERT((res == 0), ("res = %d", res));
|
||||
return timeout;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
wait_for_completion_interruptible(struct completion *c)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
mtx_lock(&c->lock);
|
||||
while (c->done == 0) {
|
||||
res = cv_wait_sig(&c->cv, &c->lock);
|
||||
if (res)
|
||||
goto out;
|
||||
}
|
||||
|
||||
_completion_claim(c);
|
||||
|
||||
out:
|
||||
mtx_unlock(&c->lock);
|
||||
|
||||
if ((res == EINTR) || (res == ERESTART))
|
||||
res = -ERESTART;
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
wait_for_completion_killable(struct completion *c)
|
||||
{
|
||||
|
||||
return wait_for_completion_interruptible(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Semaphore API
|
||||
*/
|
||||
|
||||
void sema_sysinit(void *arg)
|
||||
{
|
||||
struct semaphore *s = arg;
|
||||
|
||||
printf("sema_sysinit\n");
|
||||
_sema_init(s, 1);
|
||||
}
|
||||
|
||||
void
|
||||
_sema_init(struct semaphore *s, int value)
|
||||
{
|
||||
bzero(s, sizeof(*s));
|
||||
mtx_init(&s->mtx, "sema lock", "VCHIQ sepmaphore backing lock",
|
||||
MTX_DEF | MTX_NOWITNESS | MTX_QUIET);
|
||||
cv_init(&s->cv, "sema cv");
|
||||
s->value = value;
|
||||
}
|
||||
|
||||
void
|
||||
_sema_destroy(struct semaphore *s)
|
||||
{
|
||||
mtx_destroy(&s->mtx);
|
||||
cv_destroy(&s->cv);
|
||||
}
|
||||
|
||||
void
|
||||
down(struct semaphore *s)
|
||||
{
|
||||
|
||||
mtx_lock(&s->mtx);
|
||||
while (s->value == 0) {
|
||||
s->waiters++;
|
||||
cv_wait(&s->cv, &s->mtx);
|
||||
s->waiters--;
|
||||
}
|
||||
|
||||
s->value--;
|
||||
mtx_unlock(&s->mtx);
|
||||
}
|
||||
|
||||
int
|
||||
down_interruptible(struct semaphore *s)
|
||||
{
|
||||
int ret ;
|
||||
|
||||
ret = 0;
|
||||
|
||||
mtx_lock(&s->mtx);
|
||||
|
||||
while (s->value == 0) {
|
||||
s->waiters++;
|
||||
ret = cv_wait_sig(&s->cv, &s->mtx);
|
||||
s->waiters--;
|
||||
|
||||
if (ret == EINTR) {
|
||||
mtx_unlock(&s->mtx);
|
||||
return (-EINTR);
|
||||
}
|
||||
|
||||
if (ret == ERESTART)
|
||||
continue;
|
||||
}
|
||||
|
||||
s->value--;
|
||||
mtx_unlock(&s->mtx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
down_trylock(struct semaphore *s)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
|
||||
mtx_lock(&s->mtx);
|
||||
|
||||
if (s->value > 0) {
|
||||
/* Success. */
|
||||
s->value--;
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
|
||||
mtx_unlock(&s->mtx);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
up(struct semaphore *s)
|
||||
{
|
||||
mtx_lock(&s->mtx);
|
||||
s->value++;
|
||||
if (s->waiters && s->value > 0)
|
||||
cv_signal(&s->cv);
|
||||
|
||||
mtx_unlock(&s->mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Logging API
|
||||
*/
|
||||
void
|
||||
rlprintf(int pps, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
static struct timeval last_printf;
|
||||
static int count;
|
||||
|
||||
if (ppsratecheck(&last_printf, &count, pps)) {
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
device_rlprintf(int pps, device_t dev, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
static struct timeval last_printf;
|
||||
static int count;
|
||||
|
||||
if (ppsratecheck(&last_printf, &count, pps)) {
|
||||
va_start(ap, fmt);
|
||||
device_print_prettyname(dev);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Signals API
|
||||
*/
|
||||
|
||||
void
|
||||
flush_signals(VCHIQ_THREAD_T thr)
|
||||
{
|
||||
printf("Implement ME: %s\n", __func__);
|
||||
}
|
||||
|
||||
int
|
||||
fatal_signal_pending(VCHIQ_THREAD_T thr)
|
||||
{
|
||||
printf("Implement ME: %s\n", __func__);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* kthread API
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a hack to avoid memory leak
|
||||
*/
|
||||
#define MAX_THREAD_DATA_SLOTS 32
|
||||
static int thread_data_slot = 0;
|
||||
|
||||
struct thread_data {
|
||||
void *data;
|
||||
int (*threadfn)(void *);
|
||||
};
|
||||
|
||||
static struct thread_data thread_slots[MAX_THREAD_DATA_SLOTS];
|
||||
|
||||
static void
|
||||
kthread_wrapper(void *data)
|
||||
{
|
||||
struct thread_data *slot;
|
||||
|
||||
slot = data;
|
||||
slot->threadfn(slot->data);
|
||||
}
|
||||
|
||||
VCHIQ_THREAD_T
|
||||
vchiq_thread_create(int (*threadfn)(void *data),
|
||||
void *data,
|
||||
const char namefmt[], ...)
|
||||
{
|
||||
VCHIQ_THREAD_T newp;
|
||||
va_list ap;
|
||||
char name[MAXCOMLEN+1];
|
||||
struct thread_data *slot;
|
||||
|
||||
if (thread_data_slot >= MAX_THREAD_DATA_SLOTS) {
|
||||
printf("kthread_create: out of thread data slots\n");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
slot = &thread_slots[thread_data_slot];
|
||||
slot->data = data;
|
||||
slot->threadfn = threadfn;
|
||||
|
||||
va_start(ap, namefmt);
|
||||
vsnprintf(name, sizeof(name), namefmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
newp = NULL;
|
||||
if (kproc_create(kthread_wrapper, (void*)slot, &newp, 0, 0,
|
||||
"%s", name) != 0) {
|
||||
/* Just to be sure */
|
||||
newp = NULL;
|
||||
}
|
||||
else
|
||||
thread_data_slot++;
|
||||
|
||||
return newp;
|
||||
}
|
||||
|
||||
void
|
||||
set_user_nice(VCHIQ_THREAD_T thr, int nice)
|
||||
{
|
||||
/* NOOP */
|
||||
}
|
||||
|
||||
void
|
||||
wake_up_process(VCHIQ_THREAD_T thr)
|
||||
{
|
||||
/* NOOP */
|
||||
}
|
||||
|
||||
void
|
||||
bcm_mbox_write(int channel, uint32_t data)
|
||||
{
|
||||
device_t mbox;
|
||||
|
||||
mbox = devclass_get_device(devclass_find("mbox"), 0);
|
||||
|
||||
if (mbox)
|
||||
MBOX_WRITE(mbox, channel, data);
|
||||
}
|
434
sys/contrib/vchiq/interface/compat/vchi_bsd.h
Normal file
434
sys/contrib/vchiq/interface/compat/vchi_bsd.h
Normal file
@ -0,0 +1,434 @@
|
||||
/*-
|
||||
* Copyright (c) 2010 Max Khon <fjoe@freebsd.org>
|
||||
* Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@bluezbox.com>
|
||||
* Copyright (c) 2013 Jared D. McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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.
|
||||
*/
|
||||
#ifndef __VCHI_BSD_H__
|
||||
#define __VCHI_BSD_H__
|
||||
|
||||
#include <sys/systm.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/sema.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioccom.h>
|
||||
|
||||
/*
|
||||
* Copy from/to user API
|
||||
*/
|
||||
#define copy_from_user(to, from, n) copyin((from), (to), (n))
|
||||
#define copy_to_user(to, from, n) copyout((from), (to), (n))
|
||||
|
||||
/*
|
||||
* Bit API
|
||||
*/
|
||||
|
||||
static __inline int
|
||||
test_and_set_bit(int nr, volatile void *addr)
|
||||
{
|
||||
int val;
|
||||
|
||||
do {
|
||||
val = *(volatile int *) addr;
|
||||
} while (atomic_cmpset_int(addr, val, val | (1 << nr)) == 0);
|
||||
return (val & (1 << nr));
|
||||
}
|
||||
|
||||
static __inline__
|
||||
int test_and_clear_bit(int nr, volatile void *addr)
|
||||
{
|
||||
int val;
|
||||
|
||||
do {
|
||||
val = *(volatile int *) addr;
|
||||
} while (atomic_cmpset_int(addr, val, val & ~(1 << nr)) == 0);
|
||||
return (val & (1 << nr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomic API
|
||||
*/
|
||||
typedef volatile unsigned atomic_t;
|
||||
|
||||
#define atomic_set(p, v) (*(p) = (v))
|
||||
#define atomic_read(p) (*(p))
|
||||
#define atomic_inc(p) atomic_add_int(p, 1)
|
||||
#define atomic_dec(p) atomic_subtract_int(p, 1)
|
||||
#define atomic_dec_and_test(p) (atomic_fetchadd_int(p, -1) == 1)
|
||||
#define atomic_inc_return(v) atomic_add_return(1, (v))
|
||||
#define atomic_dec_return(v) atomic_sub_return(1, (v))
|
||||
#define atomic_add(v, p) atomic_add_int(p, v)
|
||||
#define atomic_sub(v, p) atomic_subtract_int(p, v)
|
||||
|
||||
#define ATOMIC_INIT(v) (v)
|
||||
|
||||
static inline int
|
||||
atomic_add_return(int i, atomic_t *v)
|
||||
{
|
||||
return i + atomic_fetchadd_int(v, i);
|
||||
}
|
||||
|
||||
static inline int
|
||||
atomic_sub_return(int i, atomic_t *v)
|
||||
{
|
||||
return atomic_fetchadd_int(v, -i) - i;
|
||||
}
|
||||
|
||||
static inline int
|
||||
atomic_cmpxchg(atomic_t *v, int oldv, int newv)
|
||||
{
|
||||
if (atomic_cmpset_rel_int(v, oldv, newv))
|
||||
return newv;
|
||||
else
|
||||
return *v;
|
||||
}
|
||||
|
||||
static inline int
|
||||
atomic_xchg(atomic_t *v, int newv)
|
||||
{
|
||||
int oldv;
|
||||
if (newv == 0)
|
||||
return atomic_readandclear_int(v);
|
||||
else {
|
||||
do {
|
||||
oldv = atomic_load_acq_int(v);
|
||||
} while (!atomic_cmpset_rel_int(v, oldv, newv));
|
||||
}
|
||||
|
||||
return (oldv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Spinlock API
|
||||
*/
|
||||
typedef struct mtx spinlock_t;
|
||||
|
||||
#define DEFINE_SPINLOCK(name) \
|
||||
struct mtx name
|
||||
#define spin_lock_init(lock) mtx_init(lock, "VCHI spinlock " # lock, NULL, MTX_DEF)
|
||||
#define spin_lock_destroy(lock) mtx_destroy(lock)
|
||||
#define spin_lock(lock) mtx_lock(lock)
|
||||
#define spin_unlock(lock) mtx_unlock(lock)
|
||||
#define spin_lock_bh(lock) spin_lock(lock)
|
||||
#define spin_unlock_bh(lock) spin_unlock(lock)
|
||||
|
||||
/*
|
||||
* Mutex API
|
||||
*/
|
||||
struct mutex {
|
||||
struct mtx mtx;
|
||||
};
|
||||
|
||||
#define lmutex_init(lock) mtx_init(&(lock)->mtx, #lock, NULL, MTX_DEF)
|
||||
#define lmutex_lock(lock) mtx_lock(&(lock)->mtx)
|
||||
#define lmutex_lock_interruptible(lock) (mtx_lock(&(lock)->mtx),0)
|
||||
#define lmutex_unlock(lock) mtx_unlock(&(lock)->mtx)
|
||||
#define lmutex_destroy(lock) mtx_destroy(&(lock)->mtx)
|
||||
|
||||
/*
|
||||
* Rwlock API
|
||||
*/
|
||||
typedef struct sx rwlock_t;
|
||||
|
||||
#if defined(SX_ADAPTIVESPIN) && !defined(SX_NOADAPTIVE)
|
||||
#define SX_NOADAPTIVE SX_ADAPTIVESPIN
|
||||
#endif
|
||||
|
||||
#define DEFINE_RWLOCK(name) \
|
||||
struct sx name; \
|
||||
SX_SYSINIT(name, &name, #name)
|
||||
#define rwlock_init(rwlock) sx_init_flags(rwlock, "VCHI rwlock", SX_NOADAPTIVE)
|
||||
#define read_lock(rwlock) sx_slock(rwlock)
|
||||
#define read_unlock(rwlock) sx_sunlock(rwlock)
|
||||
|
||||
#define write_lock(rwlock) sx_xlock(rwlock)
|
||||
#define write_unlock(rwlock) sx_xunlock(rwlock)
|
||||
#define write_lock_irqsave(rwlock, flags) \
|
||||
do { \
|
||||
sx_xlock(rwlock); \
|
||||
(void) &(flags); \
|
||||
} while (0)
|
||||
#define write_unlock_irqrestore(rwlock, flags) \
|
||||
sx_xunlock(rwlock)
|
||||
|
||||
#define read_lock_bh(rwlock) sx_slock(rwlock)
|
||||
#define read_unlock_bh(rwlock) sx_sunlock(rwlock)
|
||||
#define write_lock_bh(rwlock) sx_xlock(rwlock)
|
||||
#define write_unlock_bh(rwlock) sx_xunlock(rwlock)
|
||||
|
||||
/*
|
||||
* Timer API
|
||||
*/
|
||||
struct timer_list {
|
||||
struct mtx mtx;
|
||||
struct callout callout;
|
||||
|
||||
unsigned long expires;
|
||||
void (*function)(unsigned long);
|
||||
unsigned long data;
|
||||
};
|
||||
|
||||
void init_timer(struct timer_list *t);
|
||||
void setup_timer(struct timer_list *t, void (*function)(unsigned long), unsigned long data);
|
||||
void mod_timer(struct timer_list *t, unsigned long expires);
|
||||
void add_timer(struct timer_list *t);
|
||||
int del_timer(struct timer_list *t);
|
||||
int del_timer_sync(struct timer_list *t);
|
||||
|
||||
/*
|
||||
* Completion API
|
||||
*/
|
||||
struct completion {
|
||||
struct cv cv;
|
||||
struct mtx lock;
|
||||
int done;
|
||||
};
|
||||
|
||||
void init_completion(struct completion *c);
|
||||
void destroy_completion(struct completion *c);
|
||||
int try_wait_for_completion(struct completion *);
|
||||
int wait_for_completion_interruptible(struct completion *);
|
||||
int wait_for_completion_interruptible_timeout(struct completion *, unsigned long ticks);
|
||||
int wait_for_completion_killable(struct completion *);
|
||||
void wait_for_completion(struct completion *c);
|
||||
void complete(struct completion *c);
|
||||
void complete_all(struct completion *c);
|
||||
void INIT_COMPLETION_locked(struct completion *c);
|
||||
|
||||
#define INIT_COMPLETION(x) INIT_COMPLETION_locked(&(x))
|
||||
|
||||
/*
|
||||
* Semaphore API
|
||||
*/
|
||||
struct semaphore {
|
||||
struct mtx mtx;
|
||||
struct cv cv;
|
||||
int value;
|
||||
int waiters;
|
||||
};
|
||||
|
||||
#define DEFINE_SEMAPHORE(name) \
|
||||
struct semaphore name; \
|
||||
SYSINIT(name##_sema_sysinit, SI_SUB_LOCK, SI_ORDER_MIDDLE, \
|
||||
sema_sysinit, &name); \
|
||||
SYSUNINIT(name##_sema_sysuninit, SI_SUB_LOCK, SI_ORDER_MIDDLE, \
|
||||
_sema_destroy, __DEVOLATILE(void *, &(name)))
|
||||
|
||||
void sema_sysinit(void *arg);
|
||||
void _sema_init(struct semaphore *s, int value);
|
||||
void _sema_destroy(struct semaphore *s);
|
||||
void down(struct semaphore *s);
|
||||
int down_interruptible(struct semaphore *s);
|
||||
int down_trylock(struct semaphore *s);
|
||||
void up(struct semaphore *s);
|
||||
|
||||
/*
|
||||
* Logging and assertions API
|
||||
*/
|
||||
void rlprintf(int pps, const char *fmt, ...)
|
||||
__printflike(2, 3);
|
||||
|
||||
void
|
||||
device_rlprintf(int pps, device_t dev, const char *fmt, ...)
|
||||
__printflike(3, 4);
|
||||
|
||||
#define might_sleep()
|
||||
|
||||
#define WARN(condition, msg) \
|
||||
({ \
|
||||
int __ret_warn_on = !!(condition); \
|
||||
if (unlikely(__ret_warn_on)) \
|
||||
printf((msg)); \
|
||||
unlikely(__ret_warn_on); \
|
||||
})
|
||||
|
||||
|
||||
|
||||
#define WARN_ON(condition) \
|
||||
({ \
|
||||
int __ret_warn_on = !!(condition); \
|
||||
if (unlikely(__ret_warn_on)) \
|
||||
printf("WARN_ON: " #condition "\n"); \
|
||||
unlikely(__ret_warn_on); \
|
||||
})
|
||||
|
||||
#define WARN_ON_ONCE(condition) ({ \
|
||||
static int __warned; \
|
||||
int __ret_warn_once = !!(condition); \
|
||||
\
|
||||
if (unlikely(__ret_warn_once)) \
|
||||
if (WARN_ON(!__warned)) \
|
||||
__warned = 1; \
|
||||
unlikely(__ret_warn_once); \
|
||||
})
|
||||
|
||||
#define BUG_ON(cond) \
|
||||
do { \
|
||||
if (cond) \
|
||||
panic("BUG_ON: " #cond); \
|
||||
} while (0)
|
||||
|
||||
#define BUG() \
|
||||
do { \
|
||||
panic("BUG: %s:%d", __FILE__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
#define vchiq_static_assert(cond) CTASSERT(cond)
|
||||
|
||||
#define KERN_EMERG "<0>" /* system is unusable */
|
||||
#define KERN_ALERT "<1>" /* action must be taken immediately */
|
||||
#define KERN_CRIT "<2>" /* critical conditions */
|
||||
#define KERN_ERR "<3>" /* error conditions */
|
||||
#define KERN_WARNING "<4>" /* warning conditions */
|
||||
#define KERN_NOTICE "<5>" /* normal but significant condition */
|
||||
#define KERN_INFO "<6>" /* informational */
|
||||
#define KERN_DEBUG "<7>" /* debug-level messages */
|
||||
#define KERN_CONT ""
|
||||
|
||||
#define printk(fmt, args...) printf(fmt, ##args)
|
||||
#define vprintk(fmt, args) vprintf(fmt, args)
|
||||
|
||||
/*
|
||||
* Malloc API
|
||||
*/
|
||||
#define GFP_KERNEL 0
|
||||
#define GFP_ATOMIC 0
|
||||
|
||||
MALLOC_DECLARE(M_VCHI);
|
||||
|
||||
#define kmalloc(size, flags) malloc((size), M_VCHI, M_NOWAIT | M_ZERO)
|
||||
#define kcalloc(n, size, flags) malloc((n) * (size), M_VCHI, M_NOWAIT | M_ZERO)
|
||||
#define kzalloc(a, b) kcalloc(1, (a), (b))
|
||||
#define kfree(p) free(p, M_VCHI)
|
||||
|
||||
/*
|
||||
* Kernel module API
|
||||
*/
|
||||
#define __init
|
||||
#define __exit
|
||||
#define __devinit
|
||||
#define __devexit
|
||||
#define __devinitdata
|
||||
|
||||
/*
|
||||
* Time API
|
||||
*/
|
||||
#if 1
|
||||
/* emulate jiffies */
|
||||
static inline unsigned long
|
||||
_jiffies(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
microuptime(&tv);
|
||||
return tvtohz(&tv);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
msecs_to_jiffies(unsigned long msecs)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = msecs / 1000000UL;
|
||||
tv.tv_usec = msecs % 1000000UL;
|
||||
return tvtohz(&tv);
|
||||
}
|
||||
|
||||
#define jiffies _jiffies()
|
||||
#else
|
||||
#define jiffies ticks
|
||||
#endif
|
||||
#define HZ hz
|
||||
|
||||
#define udelay(usec) DELAY(usec)
|
||||
#define mdelay(msec) DELAY((msec) * 1000)
|
||||
|
||||
#define schedule_timeout(jiff) pause("dhdslp", jiff)
|
||||
|
||||
#if defined(msleep)
|
||||
#undef msleep
|
||||
#endif
|
||||
#define msleep(msec) mdelay(msec)
|
||||
|
||||
#define time_after(a, b) ((a) > (b))
|
||||
#define time_after_eq(a, b) ((a) >= (b))
|
||||
#define time_before(a, b) time_after((b), (a))
|
||||
|
||||
/*
|
||||
* kthread API (we use proc)
|
||||
*/
|
||||
typedef struct proc * VCHIQ_THREAD_T;
|
||||
|
||||
VCHIQ_THREAD_T vchiq_thread_create(int (*threadfn)(void *data),
|
||||
void *data,
|
||||
const char namefmt[], ...);
|
||||
void set_user_nice(VCHIQ_THREAD_T p, int nice);
|
||||
void wake_up_process(VCHIQ_THREAD_T p);
|
||||
|
||||
/*
|
||||
* Proc APIs
|
||||
*/
|
||||
void flush_signals(VCHIQ_THREAD_T);
|
||||
int fatal_signal_pending(VCHIQ_THREAD_T);
|
||||
|
||||
/*
|
||||
* mbox API
|
||||
*/
|
||||
void bcm_mbox_write(int channel, uint32_t data);
|
||||
|
||||
/*
|
||||
* Misc API
|
||||
*/
|
||||
|
||||
#define ENODATA EINVAL
|
||||
|
||||
#define __user
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#define current curproc
|
||||
#define EXPORT_SYMBOL(x)
|
||||
#define PAGE_ALIGN(addr) round_page(addr)
|
||||
|
||||
typedef void irqreturn_t;
|
||||
typedef off_t loff_t;
|
||||
|
||||
#define BCM2835_MBOX_CHAN_VCHIQ 3
|
||||
|
||||
#define smp_mb wmb
|
||||
#define smp_rmb rmb
|
||||
#define smp_wmb wmb
|
||||
|
||||
#define device_print_prettyname(dev) device_printf((dev), "")
|
||||
|
||||
#endif /* __VCHI_BSD_H__ */
|
324
sys/contrib/vchiq/interface/vchi/connections/connection.h
Normal file
324
sys/contrib/vchiq/interface/vchi/connections/connection.h
Normal file
@ -0,0 +1,324 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef CONNECTION_H_
|
||||
#define CONNECTION_H_
|
||||
|
||||
#include "interface/vchi/vchi_cfg_internal.h"
|
||||
#include "interface/vchi/vchi_common.h"
|
||||
#include "interface/vchi/message_drivers/message.h"
|
||||
|
||||
/******************************************************************************
|
||||
Global defs
|
||||
*****************************************************************************/
|
||||
|
||||
// Opaque handle for a connection / service pair
|
||||
typedef struct opaque_vchi_connection_connected_service_handle_t *VCHI_CONNECTION_SERVICE_HANDLE_T;
|
||||
|
||||
// opaque handle to the connection state information
|
||||
typedef struct opaque_vchi_connection_info_t VCHI_CONNECTION_STATE_T;
|
||||
|
||||
typedef struct vchi_connection_t VCHI_CONNECTION_T;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
API
|
||||
*****************************************************************************/
|
||||
|
||||
// Routine to init a connection with a particular low level driver
|
||||
typedef VCHI_CONNECTION_STATE_T * (*VCHI_CONNECTION_INIT_T)( struct vchi_connection_t * connection,
|
||||
const VCHI_MESSAGE_DRIVER_T * driver );
|
||||
|
||||
// Routine to control CRC enabling at a connection level
|
||||
typedef int32_t (*VCHI_CONNECTION_CRC_CONTROL_T)( VCHI_CONNECTION_STATE_T *state_handle,
|
||||
VCHI_CRC_CONTROL_T control );
|
||||
|
||||
// Routine to create a service
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_CONNECT_T)( VCHI_CONNECTION_STATE_T *state_handle,
|
||||
int32_t service_id,
|
||||
uint32_t rx_fifo_size,
|
||||
uint32_t tx_fifo_size,
|
||||
int server,
|
||||
VCHI_CALLBACK_T callback,
|
||||
void *callback_param,
|
||||
int32_t want_crc,
|
||||
int32_t want_unaligned_bulk_rx,
|
||||
int32_t want_unaligned_bulk_tx,
|
||||
VCHI_CONNECTION_SERVICE_HANDLE_T *service_handle );
|
||||
|
||||
// Routine to close a service
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_DISCONNECT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle );
|
||||
|
||||
// Routine to queue a message
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
const void *data,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *msg_handle );
|
||||
|
||||
// scatter-gather (vector) message queueing
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
VCHI_MSG_VECTOR_T *vector,
|
||||
uint32_t count,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *msg_handle );
|
||||
|
||||
// Routine to dequeue a message
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void *data,
|
||||
uint32_t max_data_size_to_read,
|
||||
uint32_t *actual_msg_size,
|
||||
VCHI_FLAGS_T flags );
|
||||
|
||||
// Routine to peek at a message
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void **data,
|
||||
uint32_t *msg_size,
|
||||
VCHI_FLAGS_T flags );
|
||||
|
||||
// Routine to hold a message
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void **data,
|
||||
uint32_t *msg_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void **message_handle );
|
||||
|
||||
// Routine to initialise a received message iterator
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
VCHI_MSG_ITER_T *iter,
|
||||
VCHI_FLAGS_T flags );
|
||||
|
||||
// Routine to release a held message
|
||||
typedef int32_t (*VCHI_CONNECTION_HELD_MSG_RELEASE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void *message_handle );
|
||||
|
||||
// Routine to get info on a held message
|
||||
typedef int32_t (*VCHI_CONNECTION_HELD_MSG_INFO_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void *message_handle,
|
||||
void **data,
|
||||
int32_t *msg_size,
|
||||
uint32_t *tx_timestamp,
|
||||
uint32_t *rx_timestamp );
|
||||
|
||||
// Routine to check whether the iterator has a next message
|
||||
typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
|
||||
const VCHI_MSG_ITER_T *iter );
|
||||
|
||||
// Routine to advance the iterator
|
||||
typedef int32_t (*VCHI_CONNECTION_MSG_ITER_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
|
||||
VCHI_MSG_ITER_T *iter,
|
||||
void **data,
|
||||
uint32_t *msg_size );
|
||||
|
||||
// Routine to remove the last message returned by the iterator
|
||||
typedef int32_t (*VCHI_CONNECTION_MSG_ITER_REMOVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
|
||||
VCHI_MSG_ITER_T *iter );
|
||||
|
||||
// Routine to hold the last message returned by the iterator
|
||||
typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HOLD_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
|
||||
VCHI_MSG_ITER_T *iter,
|
||||
void **msg_handle );
|
||||
|
||||
// Routine to transmit bulk data
|
||||
typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
const void *data_src,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *bulk_handle );
|
||||
|
||||
// Routine to receive data
|
||||
typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
|
||||
void *data_dst,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *bulk_handle );
|
||||
|
||||
// Routine to report if a server is available
|
||||
typedef int32_t (*VCHI_CONNECTION_SERVER_PRESENT)( VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t peer_flags );
|
||||
|
||||
// Routine to report the number of RX slots available
|
||||
typedef int (*VCHI_CONNECTION_RX_SLOTS_AVAILABLE)( const VCHI_CONNECTION_STATE_T *state );
|
||||
|
||||
// Routine to report the RX slot size
|
||||
typedef uint32_t (*VCHI_CONNECTION_RX_SLOT_SIZE)( const VCHI_CONNECTION_STATE_T *state );
|
||||
|
||||
// Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO
|
||||
typedef void (*VCHI_CONNECTION_RX_BULK_BUFFER_ADDED)(VCHI_CONNECTION_STATE_T *state,
|
||||
int32_t service,
|
||||
uint32_t length,
|
||||
MESSAGE_TX_CHANNEL_T channel,
|
||||
uint32_t channel_params,
|
||||
uint32_t data_length,
|
||||
uint32_t data_offset);
|
||||
|
||||
// Callback to inform a service that a Xon or Xoff message has been received
|
||||
typedef void (*VCHI_CONNECTION_FLOW_CONTROL)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, int32_t xoff);
|
||||
|
||||
// Callback to inform a service that a server available reply message has been received
|
||||
typedef void (*VCHI_CONNECTION_SERVER_AVAILABLE_REPLY)(VCHI_CONNECTION_STATE_T *state, int32_t service_id, uint32_t flags);
|
||||
|
||||
// Callback to indicate that bulk auxiliary messages have arrived
|
||||
typedef void (*VCHI_CONNECTION_BULK_AUX_RECEIVED)(VCHI_CONNECTION_STATE_T *state);
|
||||
|
||||
// Callback to indicate that bulk auxiliary messages have arrived
|
||||
typedef void (*VCHI_CONNECTION_BULK_AUX_TRANSMITTED)(VCHI_CONNECTION_STATE_T *state, void *handle);
|
||||
|
||||
// Callback with all the connection info you require
|
||||
typedef void (*VCHI_CONNECTION_INFO)(VCHI_CONNECTION_STATE_T *state, uint32_t protocol_version, uint32_t slot_size, uint32_t num_slots, uint32_t min_bulk_size);
|
||||
|
||||
// Callback to inform of a disconnect
|
||||
typedef void (*VCHI_CONNECTION_DISCONNECT)(VCHI_CONNECTION_STATE_T *state, uint32_t flags);
|
||||
|
||||
// Callback to inform of a power control request
|
||||
typedef void (*VCHI_CONNECTION_POWER_CONTROL)(VCHI_CONNECTION_STATE_T *state, MESSAGE_TX_CHANNEL_T channel, int32_t enable);
|
||||
|
||||
// allocate memory suitably aligned for this connection
|
||||
typedef void * (*VCHI_BUFFER_ALLOCATE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, uint32_t * length);
|
||||
|
||||
// free memory allocated by buffer_allocate
|
||||
typedef void (*VCHI_BUFFER_FREE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, void * address);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
System driver struct
|
||||
*****************************************************************************/
|
||||
|
||||
struct opaque_vchi_connection_api_t
|
||||
{
|
||||
// Routine to init the connection
|
||||
VCHI_CONNECTION_INIT_T init;
|
||||
|
||||
// Connection-level CRC control
|
||||
VCHI_CONNECTION_CRC_CONTROL_T crc_control;
|
||||
|
||||
// Routine to connect to or create service
|
||||
VCHI_CONNECTION_SERVICE_CONNECT_T service_connect;
|
||||
|
||||
// Routine to disconnect from a service
|
||||
VCHI_CONNECTION_SERVICE_DISCONNECT_T service_disconnect;
|
||||
|
||||
// Routine to queue a message
|
||||
VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T service_queue_msg;
|
||||
|
||||
// scatter-gather (vector) message queue
|
||||
VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T service_queue_msgv;
|
||||
|
||||
// Routine to dequeue a message
|
||||
VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T service_dequeue_msg;
|
||||
|
||||
// Routine to peek at a message
|
||||
VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T service_peek_msg;
|
||||
|
||||
// Routine to hold a message
|
||||
VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T service_hold_msg;
|
||||
|
||||
// Routine to initialise a received message iterator
|
||||
VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T service_look_ahead_msg;
|
||||
|
||||
// Routine to release a message
|
||||
VCHI_CONNECTION_HELD_MSG_RELEASE_T held_msg_release;
|
||||
|
||||
// Routine to get information on a held message
|
||||
VCHI_CONNECTION_HELD_MSG_INFO_T held_msg_info;
|
||||
|
||||
// Routine to check for next message on iterator
|
||||
VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T msg_iter_has_next;
|
||||
|
||||
// Routine to get next message on iterator
|
||||
VCHI_CONNECTION_MSG_ITER_NEXT_T msg_iter_next;
|
||||
|
||||
// Routine to remove the last message returned by iterator
|
||||
VCHI_CONNECTION_MSG_ITER_REMOVE_T msg_iter_remove;
|
||||
|
||||
// Routine to hold the last message returned by iterator
|
||||
VCHI_CONNECTION_MSG_ITER_HOLD_T msg_iter_hold;
|
||||
|
||||
// Routine to transmit bulk data
|
||||
VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T bulk_queue_transmit;
|
||||
|
||||
// Routine to receive data
|
||||
VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T bulk_queue_receive;
|
||||
|
||||
// Routine to report the available servers
|
||||
VCHI_CONNECTION_SERVER_PRESENT server_present;
|
||||
|
||||
// Routine to report the number of RX slots available
|
||||
VCHI_CONNECTION_RX_SLOTS_AVAILABLE connection_rx_slots_available;
|
||||
|
||||
// Routine to report the RX slot size
|
||||
VCHI_CONNECTION_RX_SLOT_SIZE connection_rx_slot_size;
|
||||
|
||||
// Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO
|
||||
VCHI_CONNECTION_RX_BULK_BUFFER_ADDED rx_bulk_buffer_added;
|
||||
|
||||
// Callback to inform a service that a Xon or Xoff message has been received
|
||||
VCHI_CONNECTION_FLOW_CONTROL flow_control;
|
||||
|
||||
// Callback to inform a service that a server available reply message has been received
|
||||
VCHI_CONNECTION_SERVER_AVAILABLE_REPLY server_available_reply;
|
||||
|
||||
// Callback to indicate that bulk auxiliary messages have arrived
|
||||
VCHI_CONNECTION_BULK_AUX_RECEIVED bulk_aux_received;
|
||||
|
||||
// Callback to indicate that a bulk auxiliary message has been transmitted
|
||||
VCHI_CONNECTION_BULK_AUX_TRANSMITTED bulk_aux_transmitted;
|
||||
|
||||
// Callback to provide information about the connection
|
||||
VCHI_CONNECTION_INFO connection_info;
|
||||
|
||||
// Callback to notify that peer has requested disconnect
|
||||
VCHI_CONNECTION_DISCONNECT disconnect;
|
||||
|
||||
// Callback to notify that peer has requested power change
|
||||
VCHI_CONNECTION_POWER_CONTROL power_control;
|
||||
|
||||
// allocate memory suitably aligned for this connection
|
||||
VCHI_BUFFER_ALLOCATE buffer_allocate;
|
||||
|
||||
// free memory allocated by buffer_allocate
|
||||
VCHI_BUFFER_FREE buffer_free;
|
||||
|
||||
};
|
||||
|
||||
struct vchi_connection_t {
|
||||
const VCHI_CONNECTION_API_T *api;
|
||||
VCHI_CONNECTION_STATE_T *state;
|
||||
#ifdef VCHI_COARSE_LOCKING
|
||||
struct semaphore sem;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif /* CONNECTION_H_ */
|
||||
|
||||
/****************************** End of file **********************************/
|
200
sys/contrib/vchiq/interface/vchi/message_drivers/message.h
Normal file
200
sys/contrib/vchiq/interface/vchi/message_drivers/message.h
Normal file
@ -0,0 +1,200 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef _VCHI_MESSAGE_H_
|
||||
#define _VCHI_MESSAGE_H_
|
||||
|
||||
#include "interface/vchi/vchi_cfg_internal.h"
|
||||
#include "interface/vchi/vchi_common.h"
|
||||
|
||||
|
||||
typedef enum message_event_type {
|
||||
MESSAGE_EVENT_NONE,
|
||||
MESSAGE_EVENT_NOP,
|
||||
MESSAGE_EVENT_MESSAGE,
|
||||
MESSAGE_EVENT_SLOT_COMPLETE,
|
||||
MESSAGE_EVENT_RX_BULK_PAUSED,
|
||||
MESSAGE_EVENT_RX_BULK_COMPLETE,
|
||||
MESSAGE_EVENT_TX_COMPLETE,
|
||||
MESSAGE_EVENT_MSG_DISCARDED
|
||||
} MESSAGE_EVENT_TYPE_T;
|
||||
|
||||
typedef enum vchi_msg_flags
|
||||
{
|
||||
VCHI_MSG_FLAGS_NONE = 0x0,
|
||||
VCHI_MSG_FLAGS_TERMINATE_DMA = 0x1
|
||||
} VCHI_MSG_FLAGS_T;
|
||||
|
||||
typedef enum message_tx_channel
|
||||
{
|
||||
MESSAGE_TX_CHANNEL_MESSAGE = 0,
|
||||
MESSAGE_TX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards
|
||||
} MESSAGE_TX_CHANNEL_T;
|
||||
|
||||
// Macros used for cycling through bulk channels
|
||||
#define MESSAGE_TX_CHANNEL_BULK_PREV(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION-1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION)
|
||||
#define MESSAGE_TX_CHANNEL_BULK_NEXT(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION)
|
||||
|
||||
typedef enum message_rx_channel
|
||||
{
|
||||
MESSAGE_RX_CHANNEL_MESSAGE = 0,
|
||||
MESSAGE_RX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards
|
||||
} MESSAGE_RX_CHANNEL_T;
|
||||
|
||||
// Message receive slot information
|
||||
typedef struct rx_msg_slot_info {
|
||||
|
||||
struct rx_msg_slot_info *next;
|
||||
//struct slot_info *prev;
|
||||
#if !defined VCHI_COARSE_LOCKING
|
||||
struct semaphore sem;
|
||||
#endif
|
||||
|
||||
uint8_t *addr; // base address of slot
|
||||
uint32_t len; // length of slot in bytes
|
||||
|
||||
uint32_t write_ptr; // hardware causes this to advance
|
||||
uint32_t read_ptr; // this module does the reading
|
||||
int active; // is this slot in the hardware dma fifo?
|
||||
uint32_t msgs_parsed; // count how many messages are in this slot
|
||||
uint32_t msgs_released; // how many messages have been released
|
||||
void *state; // connection state information
|
||||
uint8_t ref_count[VCHI_MAX_SERVICES_PER_CONNECTION]; // reference count for slots held by services
|
||||
} RX_MSG_SLOTINFO_T;
|
||||
|
||||
// The message driver no longer needs to know about the fields of RX_BULK_SLOTINFO_T - sort this out.
|
||||
// In particular, it mustn't use addr and len - they're the client buffer, but the message
|
||||
// driver will be tasked with sending the aligned core section.
|
||||
typedef struct rx_bulk_slotinfo_t {
|
||||
struct rx_bulk_slotinfo_t *next;
|
||||
|
||||
struct semaphore *blocking;
|
||||
|
||||
// needed by DMA
|
||||
void *addr;
|
||||
uint32_t len;
|
||||
|
||||
// needed for the callback
|
||||
void *service;
|
||||
void *handle;
|
||||
VCHI_FLAGS_T flags;
|
||||
} RX_BULK_SLOTINFO_T;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* each connection driver will have a pool of the following struct.
|
||||
*
|
||||
* the pool will be managed by vchi_qman_*
|
||||
* this means there will be multiple queues (single linked lists)
|
||||
* a given struct message_info will be on exactly one of these queues
|
||||
* at any one time
|
||||
* -------------------------------------------------------------------- */
|
||||
typedef struct rx_message_info {
|
||||
|
||||
struct message_info *next;
|
||||
//struct message_info *prev;
|
||||
|
||||
uint8_t *addr;
|
||||
uint32_t len;
|
||||
RX_MSG_SLOTINFO_T *slot; // points to whichever slot contains this message
|
||||
uint32_t tx_timestamp;
|
||||
uint32_t rx_timestamp;
|
||||
|
||||
} RX_MESSAGE_INFO_T;
|
||||
|
||||
typedef struct {
|
||||
MESSAGE_EVENT_TYPE_T type;
|
||||
|
||||
struct {
|
||||
// for messages
|
||||
void *addr; // address of message
|
||||
uint16_t slot_delta; // whether this message indicated slot delta
|
||||
uint32_t len; // length of message
|
||||
RX_MSG_SLOTINFO_T *slot; // slot this message is in
|
||||
int32_t service; // service id this message is destined for
|
||||
uint32_t tx_timestamp; // timestamp from the header
|
||||
uint32_t rx_timestamp; // timestamp when we parsed it
|
||||
} message;
|
||||
|
||||
// FIXME: cleanup slot reporting...
|
||||
RX_MSG_SLOTINFO_T *rx_msg;
|
||||
RX_BULK_SLOTINFO_T *rx_bulk;
|
||||
void *tx_handle;
|
||||
MESSAGE_TX_CHANNEL_T tx_channel;
|
||||
|
||||
} MESSAGE_EVENT_T;
|
||||
|
||||
|
||||
// callbacks
|
||||
typedef void VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T( void *state );
|
||||
|
||||
typedef struct {
|
||||
VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T *event_callback;
|
||||
} VCHI_MESSAGE_DRIVER_OPEN_T;
|
||||
|
||||
|
||||
// handle to this instance of message driver (as returned by ->open)
|
||||
typedef struct opaque_mhandle_t *VCHI_MDRIVER_HANDLE_T;
|
||||
|
||||
struct opaque_vchi_message_driver_t {
|
||||
VCHI_MDRIVER_HANDLE_T *(*open)( VCHI_MESSAGE_DRIVER_OPEN_T *params, void *state );
|
||||
int32_t (*suspending)( VCHI_MDRIVER_HANDLE_T *handle );
|
||||
int32_t (*resumed)( VCHI_MDRIVER_HANDLE_T *handle );
|
||||
int32_t (*power_control)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T, int32_t enable );
|
||||
int32_t (*add_msg_rx_slot)( VCHI_MDRIVER_HANDLE_T *handle, RX_MSG_SLOTINFO_T *slot ); // rx message
|
||||
int32_t (*add_bulk_rx)( VCHI_MDRIVER_HANDLE_T *handle, void *data, uint32_t len, RX_BULK_SLOTINFO_T *slot ); // rx data (bulk)
|
||||
int32_t (*send)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, VCHI_MSG_FLAGS_T flags, void *send_handle ); // tx (message & bulk)
|
||||
void (*next_event)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_EVENT_T *event ); // get the next event from message_driver
|
||||
int32_t (*enable)( VCHI_MDRIVER_HANDLE_T *handle );
|
||||
int32_t (*form_message)( VCHI_MDRIVER_HANDLE_T *handle, int32_t service_id, VCHI_MSG_VECTOR_T *vector, uint32_t count, void
|
||||
*address, uint32_t length_avail, uint32_t max_total_length, int32_t pad_to_fill, int32_t allow_partial );
|
||||
|
||||
int32_t (*update_message)( VCHI_MDRIVER_HANDLE_T *handle, void *dest, int16_t *slot_count );
|
||||
int32_t (*buffer_aligned)( VCHI_MDRIVER_HANDLE_T *handle, int tx, int uncached, const void *address, const uint32_t length );
|
||||
void * (*allocate_buffer)( VCHI_MDRIVER_HANDLE_T *handle, uint32_t *length );
|
||||
void (*free_buffer)( VCHI_MDRIVER_HANDLE_T *handle, void *address );
|
||||
int (*rx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size );
|
||||
int (*tx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size );
|
||||
|
||||
int32_t (*tx_supports_terminate)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
|
||||
uint32_t (*tx_bulk_chunk_size)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
|
||||
int (*tx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
|
||||
int (*rx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_RX_CHANNEL_T channel );
|
||||
void (*form_bulk_aux)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, uint32_t chunk_size, const void **aux_data, int32_t *aux_len );
|
||||
void (*debug)( VCHI_MDRIVER_HANDLE_T *handle );
|
||||
};
|
||||
|
||||
|
||||
#endif // _VCHI_MESSAGE_H_
|
||||
|
||||
/****************************** End of file ***********************************/
|
373
sys/contrib/vchiq/interface/vchi/vchi.h
Normal file
373
sys/contrib/vchiq/interface/vchi/vchi.h
Normal file
@ -0,0 +1,373 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHI_H_
|
||||
#define VCHI_H_
|
||||
|
||||
#include "interface/vchi/vchi_cfg.h"
|
||||
#include "interface/vchi/vchi_common.h"
|
||||
#include "interface/vchi/connections/connection.h"
|
||||
#include "vchi_mh.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Global defs
|
||||
*****************************************************************************/
|
||||
|
||||
#define VCHI_BULK_ROUND_UP(x) ((((unsigned long)(x))+VCHI_BULK_ALIGN-1) & ~(VCHI_BULK_ALIGN-1))
|
||||
#define VCHI_BULK_ROUND_DOWN(x) (((unsigned long)(x)) & ~(VCHI_BULK_ALIGN-1))
|
||||
#define VCHI_BULK_ALIGN_NBYTES(x) (VCHI_BULK_ALIGNED(x) ? 0 : (VCHI_BULK_ALIGN - ((unsigned long)(x) & (VCHI_BULK_ALIGN-1))))
|
||||
|
||||
#ifdef USE_VCHIQ_ARM
|
||||
#define VCHI_BULK_ALIGNED(x) 1
|
||||
#else
|
||||
#define VCHI_BULK_ALIGNED(x) (((unsigned long)(x) & (VCHI_BULK_ALIGN-1)) == 0)
|
||||
#endif
|
||||
|
||||
struct vchi_version {
|
||||
uint32_t version;
|
||||
uint32_t version_min;
|
||||
};
|
||||
#define VCHI_VERSION(v_) { v_, v_ }
|
||||
#define VCHI_VERSION_EX(v_, m_) { v_, m_ }
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VCHI_VEC_POINTER,
|
||||
VCHI_VEC_HANDLE,
|
||||
VCHI_VEC_LIST
|
||||
} VCHI_MSG_VECTOR_TYPE_T;
|
||||
|
||||
typedef struct vchi_msg_vector_ex {
|
||||
|
||||
VCHI_MSG_VECTOR_TYPE_T type;
|
||||
union
|
||||
{
|
||||
// a memory handle
|
||||
struct
|
||||
{
|
||||
VCHI_MEM_HANDLE_T handle;
|
||||
uint32_t offset;
|
||||
int32_t vec_len;
|
||||
} handle;
|
||||
|
||||
// an ordinary data pointer
|
||||
struct
|
||||
{
|
||||
const void *vec_base;
|
||||
int32_t vec_len;
|
||||
} ptr;
|
||||
|
||||
// a nested vector list
|
||||
struct
|
||||
{
|
||||
struct vchi_msg_vector_ex *vec;
|
||||
uint32_t vec_len;
|
||||
} list;
|
||||
} u;
|
||||
} VCHI_MSG_VECTOR_EX_T;
|
||||
|
||||
|
||||
// Construct an entry in a msg vector for a pointer (p) of length (l)
|
||||
#define VCHI_VEC_POINTER(p,l) VCHI_VEC_POINTER, { { (VCHI_MEM_HANDLE_T)(p), (l) } }
|
||||
|
||||
// Construct an entry in a msg vector for a message handle (h), starting at offset (o) of length (l)
|
||||
#define VCHI_VEC_HANDLE(h,o,l) VCHI_VEC_HANDLE, { { (h), (o), (l) } }
|
||||
|
||||
// Macros to manipulate 'FOURCC' values
|
||||
#define MAKE_FOURCC(x) ((int32_t)( (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3] ))
|
||||
#define FOURCC_TO_CHAR(x) (x >> 24) & 0xFF,(x >> 16) & 0xFF,(x >> 8) & 0xFF, x & 0xFF
|
||||
|
||||
|
||||
// Opaque service information
|
||||
struct opaque_vchi_service_t;
|
||||
|
||||
// Descriptor for a held message. Allocated by client, initialised by vchi_msg_hold,
|
||||
// vchi_msg_iter_hold or vchi_msg_iter_hold_next. Fields are for internal VCHI use only.
|
||||
typedef struct
|
||||
{
|
||||
struct opaque_vchi_service_t *service;
|
||||
void *message;
|
||||
} VCHI_HELD_MSG_T;
|
||||
|
||||
|
||||
|
||||
// structure used to provide the information needed to open a server or a client
|
||||
typedef struct {
|
||||
struct vchi_version version;
|
||||
int32_t service_id;
|
||||
VCHI_CONNECTION_T *connection;
|
||||
uint32_t rx_fifo_size;
|
||||
uint32_t tx_fifo_size;
|
||||
VCHI_CALLBACK_T callback;
|
||||
void *callback_param;
|
||||
/* client intends to receive bulk transfers of
|
||||
odd lengths or into unaligned buffers */
|
||||
int32_t want_unaligned_bulk_rx;
|
||||
/* client intends to transmit bulk transfers of
|
||||
odd lengths or out of unaligned buffers */
|
||||
int32_t want_unaligned_bulk_tx;
|
||||
/* client wants to check CRCs on (bulk) xfers.
|
||||
Only needs to be set at 1 end - will do both directions. */
|
||||
int32_t want_crc;
|
||||
} SERVICE_CREATION_T;
|
||||
|
||||
// Opaque handle for a VCHI instance
|
||||
typedef struct opaque_vchi_instance_handle_t *VCHI_INSTANCE_T;
|
||||
|
||||
// Opaque handle for a server or client
|
||||
typedef struct opaque_vchi_service_handle_t *VCHI_SERVICE_HANDLE_T;
|
||||
|
||||
// Service registration & startup
|
||||
typedef void (*VCHI_SERVICE_INIT)(VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections);
|
||||
|
||||
typedef struct service_info_tag {
|
||||
const char * const vll_filename; /* VLL to load to start this service. This is an empty string if VLL is "static" */
|
||||
VCHI_SERVICE_INIT init; /* Service initialisation function */
|
||||
void *vll_handle; /* VLL handle; NULL when unloaded or a "static VLL" in build */
|
||||
} SERVICE_INFO_T;
|
||||
|
||||
/******************************************************************************
|
||||
Global funcs - implementation is specific to which side you are on (local / remote)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern /*@observer@*/ VCHI_CONNECTION_T * vchi_create_connection( const VCHI_CONNECTION_API_T * function_table,
|
||||
const VCHI_MESSAGE_DRIVER_T * low_level);
|
||||
|
||||
|
||||
// Routine used to initialise the vchi on both local + remote connections
|
||||
extern int32_t vchi_initialise( VCHI_INSTANCE_T *instance_handle );
|
||||
|
||||
extern int32_t vchi_exit( void );
|
||||
|
||||
extern int32_t vchi_connect( VCHI_CONNECTION_T **connections,
|
||||
const uint32_t num_connections,
|
||||
VCHI_INSTANCE_T instance_handle );
|
||||
|
||||
//When this is called, ensure that all services have no data pending.
|
||||
//Bulk transfers can remain 'queued'
|
||||
extern int32_t vchi_disconnect( VCHI_INSTANCE_T instance_handle );
|
||||
|
||||
// Global control over bulk CRC checking
|
||||
extern int32_t vchi_crc_control( VCHI_CONNECTION_T *connection,
|
||||
VCHI_CRC_CONTROL_T control );
|
||||
|
||||
// helper functions
|
||||
extern void * vchi_allocate_buffer(VCHI_SERVICE_HANDLE_T handle, uint32_t *length);
|
||||
extern void vchi_free_buffer(VCHI_SERVICE_HANDLE_T handle, void *address);
|
||||
extern uint32_t vchi_current_time(VCHI_INSTANCE_T instance_handle);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Global service API
|
||||
*****************************************************************************/
|
||||
// Routine to create a named service
|
||||
extern int32_t vchi_service_create( VCHI_INSTANCE_T instance_handle,
|
||||
SERVICE_CREATION_T *setup,
|
||||
VCHI_SERVICE_HANDLE_T *handle );
|
||||
|
||||
// Routine to destory a service
|
||||
extern int32_t vchi_service_destroy( const VCHI_SERVICE_HANDLE_T handle );
|
||||
|
||||
// Routine to open a named service
|
||||
extern int32_t vchi_service_open( VCHI_INSTANCE_T instance_handle,
|
||||
SERVICE_CREATION_T *setup,
|
||||
VCHI_SERVICE_HANDLE_T *handle);
|
||||
|
||||
extern int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle,
|
||||
short *peer_version );
|
||||
|
||||
// Routine to close a named service
|
||||
extern int32_t vchi_service_close( const VCHI_SERVICE_HANDLE_T handle );
|
||||
|
||||
// Routine to increment ref count on a named service
|
||||
extern int32_t vchi_service_use( const VCHI_SERVICE_HANDLE_T handle );
|
||||
|
||||
// Routine to decrement ref count on a named service
|
||||
extern int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle );
|
||||
|
||||
// Routine to send a message accross a service
|
||||
extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle,
|
||||
const void *data,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *msg_handle );
|
||||
|
||||
// scatter-gather (vector) and send message
|
||||
int32_t vchi_msg_queuev_ex( VCHI_SERVICE_HANDLE_T handle,
|
||||
VCHI_MSG_VECTOR_EX_T *vector,
|
||||
uint32_t count,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *msg_handle );
|
||||
|
||||
// legacy scatter-gather (vector) and send message, only handles pointers
|
||||
int32_t vchi_msg_queuev( VCHI_SERVICE_HANDLE_T handle,
|
||||
VCHI_MSG_VECTOR_T *vector,
|
||||
uint32_t count,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *msg_handle );
|
||||
|
||||
// Routine to receive a msg from a service
|
||||
// Dequeue is equivalent to hold, copy into client buffer, release
|
||||
extern int32_t vchi_msg_dequeue( VCHI_SERVICE_HANDLE_T handle,
|
||||
void *data,
|
||||
uint32_t max_data_size_to_read,
|
||||
uint32_t *actual_msg_size,
|
||||
VCHI_FLAGS_T flags );
|
||||
|
||||
// Routine to look at a message in place.
|
||||
// The message is not dequeued, so a subsequent call to peek or dequeue
|
||||
// will return the same message.
|
||||
extern int32_t vchi_msg_peek( VCHI_SERVICE_HANDLE_T handle,
|
||||
void **data,
|
||||
uint32_t *msg_size,
|
||||
VCHI_FLAGS_T flags );
|
||||
|
||||
// Routine to remove a message after it has been read in place with peek
|
||||
// The first message on the queue is dequeued.
|
||||
extern int32_t vchi_msg_remove( VCHI_SERVICE_HANDLE_T handle );
|
||||
|
||||
// Routine to look at a message in place.
|
||||
// The message is dequeued, so the caller is left holding it; the descriptor is
|
||||
// filled in and must be released when the user has finished with the message.
|
||||
extern int32_t vchi_msg_hold( VCHI_SERVICE_HANDLE_T handle,
|
||||
void **data, // } may be NULL, as info can be
|
||||
uint32_t *msg_size, // } obtained from HELD_MSG_T
|
||||
VCHI_FLAGS_T flags,
|
||||
VCHI_HELD_MSG_T *message_descriptor );
|
||||
|
||||
// Initialise an iterator to look through messages in place
|
||||
extern int32_t vchi_msg_look_ahead( VCHI_SERVICE_HANDLE_T handle,
|
||||
VCHI_MSG_ITER_T *iter,
|
||||
VCHI_FLAGS_T flags );
|
||||
|
||||
/******************************************************************************
|
||||
Global service support API - operations on held messages and message iterators
|
||||
*****************************************************************************/
|
||||
|
||||
// Routine to get the address of a held message
|
||||
extern void *vchi_held_msg_ptr( const VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Routine to get the size of a held message
|
||||
extern int32_t vchi_held_msg_size( const VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Routine to get the transmit timestamp as written into the header by the peer
|
||||
extern uint32_t vchi_held_msg_tx_timestamp( const VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Routine to get the reception timestamp, written as we parsed the header
|
||||
extern uint32_t vchi_held_msg_rx_timestamp( const VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Routine to release a held message after it has been processed
|
||||
extern int32_t vchi_held_msg_release( VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Indicates whether the iterator has a next message.
|
||||
extern int32_t vchi_msg_iter_has_next( const VCHI_MSG_ITER_T *iter );
|
||||
|
||||
// Return the pointer and length for the next message and advance the iterator.
|
||||
extern int32_t vchi_msg_iter_next( VCHI_MSG_ITER_T *iter,
|
||||
void **data,
|
||||
uint32_t *msg_size );
|
||||
|
||||
// Remove the last message returned by vchi_msg_iter_next.
|
||||
// Can only be called once after each call to vchi_msg_iter_next.
|
||||
extern int32_t vchi_msg_iter_remove( VCHI_MSG_ITER_T *iter );
|
||||
|
||||
// Hold the last message returned by vchi_msg_iter_next.
|
||||
// Can only be called once after each call to vchi_msg_iter_next.
|
||||
extern int32_t vchi_msg_iter_hold( VCHI_MSG_ITER_T *iter,
|
||||
VCHI_HELD_MSG_T *message );
|
||||
|
||||
// Return information for the next message, and hold it, advancing the iterator.
|
||||
extern int32_t vchi_msg_iter_hold_next( VCHI_MSG_ITER_T *iter,
|
||||
void **data, // } may be NULL
|
||||
uint32_t *msg_size, // }
|
||||
VCHI_HELD_MSG_T *message );
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Global bulk API
|
||||
*****************************************************************************/
|
||||
|
||||
// Routine to prepare interface for a transfer from the other side
|
||||
extern int32_t vchi_bulk_queue_receive( VCHI_SERVICE_HANDLE_T handle,
|
||||
void *data_dst,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *transfer_handle );
|
||||
|
||||
|
||||
// Prepare interface for a transfer from the other side into relocatable memory.
|
||||
int32_t vchi_bulk_queue_receive_reloc( const VCHI_SERVICE_HANDLE_T handle,
|
||||
VCHI_MEM_HANDLE_T h_dst,
|
||||
uint32_t offset,
|
||||
uint32_t data_size,
|
||||
const VCHI_FLAGS_T flags,
|
||||
void * const bulk_handle );
|
||||
|
||||
// Routine to queue up data ready for transfer to the other (once they have signalled they are ready)
|
||||
extern int32_t vchi_bulk_queue_transmit( VCHI_SERVICE_HANDLE_T handle,
|
||||
void *data_src,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *transfer_handle );
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Configuration plumbing
|
||||
*****************************************************************************/
|
||||
|
||||
// function prototypes for the different mid layers (the state info gives the different physical connections)
|
||||
extern const VCHI_CONNECTION_API_T *single_get_func_table( void );
|
||||
//extern const VCHI_CONNECTION_API_T *local_server_get_func_table( void );
|
||||
//extern const VCHI_CONNECTION_API_T *local_client_get_func_table( void );
|
||||
|
||||
// declare all message drivers here
|
||||
const VCHI_MESSAGE_DRIVER_T *vchi_mphi_message_driver_func_table( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern int32_t vchi_bulk_queue_transmit_reloc( VCHI_SERVICE_HANDLE_T handle,
|
||||
VCHI_MEM_HANDLE_T h_src,
|
||||
uint32_t offset,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *transfer_handle );
|
||||
#endif /* VCHI_H_ */
|
||||
|
||||
/****************************** End of file **********************************/
|
224
sys/contrib/vchiq/interface/vchi/vchi_cfg.h
Normal file
224
sys/contrib/vchiq/interface/vchi/vchi_cfg.h
Normal file
@ -0,0 +1,224 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHI_CFG_H_
|
||||
#define VCHI_CFG_H_
|
||||
|
||||
/****************************************************************************************
|
||||
* Defines in this first section are part of the VCHI API and may be examined by VCHI
|
||||
* services.
|
||||
***************************************************************************************/
|
||||
|
||||
/* Required alignment of base addresses for bulk transfer, if unaligned transfers are not enabled */
|
||||
/* Really determined by the message driver, and should be available from a run-time call. */
|
||||
#ifndef VCHI_BULK_ALIGN
|
||||
# if __VCCOREVER__ >= 0x04000000
|
||||
# define VCHI_BULK_ALIGN 32 // Allows for the need to do cache cleans
|
||||
# else
|
||||
# define VCHI_BULK_ALIGN 16
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Required length multiple for bulk transfers, if unaligned transfers are not enabled */
|
||||
/* May be less than or greater than VCHI_BULK_ALIGN */
|
||||
/* Really determined by the message driver, and should be available from a run-time call. */
|
||||
#ifndef VCHI_BULK_GRANULARITY
|
||||
# if __VCCOREVER__ >= 0x04000000
|
||||
# define VCHI_BULK_GRANULARITY 32 // Allows for the need to do cache cleans
|
||||
# else
|
||||
# define VCHI_BULK_GRANULARITY 16
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The largest possible message to be queued with vchi_msg_queue. */
|
||||
#ifndef VCHI_MAX_MSG_SIZE
|
||||
# if defined VCHI_LOCAL_HOST_PORT
|
||||
# define VCHI_MAX_MSG_SIZE 16384 // makes file transfers fast, but should they be using bulk?
|
||||
# else
|
||||
# define VCHI_MAX_MSG_SIZE 4096 // NOTE: THIS MUST BE LARGER THAN OR EQUAL TO THE SIZE OF THE KHRONOS MERGE BUFFER!!
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/******************************************************************************************
|
||||
* Defines below are system configuration options, and should not be used by VCHI services.
|
||||
*****************************************************************************************/
|
||||
|
||||
/* How many connections can we support? A localhost implementation uses 2 connections,
|
||||
* 1 for host-app, 1 for VMCS, and these are hooked together by a loopback MPHI VCFW
|
||||
* driver. */
|
||||
#ifndef VCHI_MAX_NUM_CONNECTIONS
|
||||
# define VCHI_MAX_NUM_CONNECTIONS 3
|
||||
#endif
|
||||
|
||||
/* How many services can we open per connection? Extending this doesn't cost processing time, just a small
|
||||
* amount of static memory. */
|
||||
#ifndef VCHI_MAX_SERVICES_PER_CONNECTION
|
||||
# define VCHI_MAX_SERVICES_PER_CONNECTION 36
|
||||
#endif
|
||||
|
||||
/* Adjust if using a message driver that supports more logical TX channels */
|
||||
#ifndef VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION
|
||||
# define VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION 9 // 1 MPHI + 8 CCP2 logical channels
|
||||
#endif
|
||||
|
||||
/* Adjust if using a message driver that supports more logical RX channels */
|
||||
#ifndef VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION
|
||||
# define VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION 1 // 1 MPHI
|
||||
#endif
|
||||
|
||||
/* How many receive slots do we use. This times VCHI_MAX_MSG_SIZE gives the effective
|
||||
* receive queue space, less message headers. */
|
||||
#ifndef VCHI_NUM_READ_SLOTS
|
||||
# if defined(VCHI_LOCAL_HOST_PORT)
|
||||
# define VCHI_NUM_READ_SLOTS 4
|
||||
# else
|
||||
# define VCHI_NUM_READ_SLOTS 48
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Do we utilise overrun facility for receive message slots? Can aid peer transmit
|
||||
* performance. Only define on VideoCore end, talking to host.
|
||||
*/
|
||||
//#define VCHI_MSG_RX_OVERRUN
|
||||
|
||||
/* How many transmit slots do we use. Generally don't need many, as the hardware driver
|
||||
* underneath VCHI will usually have its own buffering. */
|
||||
#ifndef VCHI_NUM_WRITE_SLOTS
|
||||
# define VCHI_NUM_WRITE_SLOTS 4
|
||||
#endif
|
||||
|
||||
/* If a service has held or queued received messages in VCHI_XOFF_THRESHOLD or more slots,
|
||||
* then it's taking up too much buffer space, and the peer service will be told to stop
|
||||
* transmitting with an XOFF message. For this to be effective, the VCHI_NUM_READ_SLOTS
|
||||
* needs to be considerably bigger than VCHI_NUM_WRITE_SLOTS, or the transmit latency
|
||||
* is too high. */
|
||||
#ifndef VCHI_XOFF_THRESHOLD
|
||||
# define VCHI_XOFF_THRESHOLD (VCHI_NUM_READ_SLOTS / 2)
|
||||
#endif
|
||||
|
||||
/* After we've sent an XOFF, the peer will be told to resume transmission once the local
|
||||
* service has dequeued/released enough messages that it's now occupying
|
||||
* VCHI_XON_THRESHOLD slots or fewer. */
|
||||
#ifndef VCHI_XON_THRESHOLD
|
||||
# define VCHI_XON_THRESHOLD (VCHI_NUM_READ_SLOTS / 4)
|
||||
#endif
|
||||
|
||||
/* A size below which a bulk transfer omits the handshake completely and always goes
|
||||
* via the message channel, if bulk auxiliary is being sent on that service. (The user
|
||||
* can guarantee this by enabling unaligned transmits).
|
||||
* Not API. */
|
||||
#ifndef VCHI_MIN_BULK_SIZE
|
||||
# define VCHI_MIN_BULK_SIZE ( VCHI_MAX_MSG_SIZE / 2 < 4096 ? VCHI_MAX_MSG_SIZE / 2 : 4096 )
|
||||
#endif
|
||||
|
||||
/* Maximum size of bulk transmission chunks, for each interface type. A trade-off between
|
||||
* speed and latency; the smaller the chunk size the better change of messages and other
|
||||
* bulk transmissions getting in when big bulk transfers are happening. Set to 0 to not
|
||||
* break transmissions into chunks.
|
||||
*/
|
||||
#ifndef VCHI_MAX_BULK_CHUNK_SIZE_MPHI
|
||||
# define VCHI_MAX_BULK_CHUNK_SIZE_MPHI (16 * 1024)
|
||||
#endif
|
||||
|
||||
/* NB Chunked CCP2 transmissions violate the letter of the CCP2 spec by using "JPEG8" mode
|
||||
* with multiple-line frames. Only use if the receiver can cope. */
|
||||
#ifndef VCHI_MAX_BULK_CHUNK_SIZE_CCP2
|
||||
# define VCHI_MAX_BULK_CHUNK_SIZE_CCP2 0
|
||||
#endif
|
||||
|
||||
/* How many TX messages can we have pending in our transmit slots. Once exhausted,
|
||||
* vchi_msg_queue will be blocked. */
|
||||
#ifndef VCHI_TX_MSG_QUEUE_SIZE
|
||||
# define VCHI_TX_MSG_QUEUE_SIZE 256
|
||||
#endif
|
||||
|
||||
/* How many RX messages can we have parsed in the receive slots. Once exhausted, parsing
|
||||
* will be suspended until older messages are dequeued/released. */
|
||||
#ifndef VCHI_RX_MSG_QUEUE_SIZE
|
||||
# define VCHI_RX_MSG_QUEUE_SIZE 256
|
||||
#endif
|
||||
|
||||
/* Really should be able to cope if we run out of received message descriptors, by
|
||||
* suspending parsing as the comment above says, but we don't. This sweeps the issue
|
||||
* under the carpet. */
|
||||
#if VCHI_RX_MSG_QUEUE_SIZE < (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS
|
||||
# undef VCHI_RX_MSG_QUEUE_SIZE
|
||||
# define VCHI_RX_MSG_QUEUE_SIZE (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS
|
||||
#endif
|
||||
|
||||
/* How many bulk transmits can we have pending. Once exhausted, vchi_bulk_queue_transmit
|
||||
* will be blocked. */
|
||||
#ifndef VCHI_TX_BULK_QUEUE_SIZE
|
||||
# define VCHI_TX_BULK_QUEUE_SIZE 64
|
||||
#endif
|
||||
|
||||
/* How many bulk receives can we have pending. Once exhausted, vchi_bulk_queue_receive
|
||||
* will be blocked. */
|
||||
#ifndef VCHI_RX_BULK_QUEUE_SIZE
|
||||
# define VCHI_RX_BULK_QUEUE_SIZE 64
|
||||
#endif
|
||||
|
||||
/* A limit on how many outstanding bulk requests we expect the peer to give us. If
|
||||
* the peer asks for more than this, VCHI will fail and assert. The number is determined
|
||||
* by the peer's hardware - it's the number of outstanding requests that can be queued
|
||||
* on all bulk channels. VC3's MPHI peripheral allows 16. */
|
||||
#ifndef VCHI_MAX_PEER_BULK_REQUESTS
|
||||
# define VCHI_MAX_PEER_BULK_REQUESTS 32
|
||||
#endif
|
||||
|
||||
/* Define VCHI_CCP2TX_MANUAL_POWER if the host tells us when to turn the CCP2
|
||||
* transmitter on and off.
|
||||
*/
|
||||
/*#define VCHI_CCP2TX_MANUAL_POWER*/
|
||||
|
||||
#ifndef VCHI_CCP2TX_MANUAL_POWER
|
||||
|
||||
/* Timeout (in milliseconds) for putting the CCP2TX interface into IDLE state. Set
|
||||
* negative for no IDLE.
|
||||
*/
|
||||
# ifndef VCHI_CCP2TX_IDLE_TIMEOUT
|
||||
# define VCHI_CCP2TX_IDLE_TIMEOUT 5
|
||||
# endif
|
||||
|
||||
/* Timeout (in milliseconds) for putting the CCP2TX interface into OFF state. Set
|
||||
* negative for no OFF.
|
||||
*/
|
||||
# ifndef VCHI_CCP2TX_OFF_TIMEOUT
|
||||
# define VCHI_CCP2TX_OFF_TIMEOUT 1000
|
||||
# endif
|
||||
|
||||
#endif /* VCHI_CCP2TX_MANUAL_POWER */
|
||||
|
||||
#endif /* VCHI_CFG_H_ */
|
||||
|
||||
/****************************** End of file **********************************/
|
71
sys/contrib/vchiq/interface/vchi/vchi_cfg_internal.h
Normal file
71
sys/contrib/vchiq/interface/vchi/vchi_cfg_internal.h
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHI_CFG_INTERNAL_H_
|
||||
#define VCHI_CFG_INTERNAL_H_
|
||||
|
||||
/****************************************************************************************
|
||||
* Control optimisation attempts.
|
||||
***************************************************************************************/
|
||||
|
||||
// Don't use lots of short-term locks - use great long ones, reducing the overall locks-per-second
|
||||
#define VCHI_COARSE_LOCKING
|
||||
|
||||
// Avoid lock then unlock on exit from blocking queue operations (msg tx, bulk rx/tx)
|
||||
// (only relevant if VCHI_COARSE_LOCKING)
|
||||
#define VCHI_ELIDE_BLOCK_EXIT_LOCK
|
||||
|
||||
// Avoid lock on non-blocking peek
|
||||
// (only relevant if VCHI_COARSE_LOCKING)
|
||||
#define VCHI_AVOID_PEEK_LOCK
|
||||
|
||||
// Use one slot-handler thread per connection, rather than 1 thread dealing with all connections in rotation.
|
||||
#define VCHI_MULTIPLE_HANDLER_THREADS
|
||||
|
||||
// Put free descriptors onto the head of the free queue, rather than the tail, so that we don't thrash
|
||||
// our way through the pool of descriptors.
|
||||
#define VCHI_PUSH_FREE_DESCRIPTORS_ONTO_HEAD
|
||||
|
||||
// Don't issue a MSG_AVAILABLE callback for every single message. Possibly only safe if VCHI_COARSE_LOCKING.
|
||||
#define VCHI_FEWER_MSG_AVAILABLE_CALLBACKS
|
||||
|
||||
// Don't use message descriptors for TX messages that don't need them
|
||||
#define VCHI_MINIMISE_TX_MSG_DESCRIPTORS
|
||||
|
||||
// Nano-locks for multiqueue
|
||||
//#define VCHI_MQUEUE_NANOLOCKS
|
||||
|
||||
// Lock-free(er) dequeuing
|
||||
//#define VCHI_RX_NANOLOCKS
|
||||
|
||||
#endif /*VCHI_CFG_INTERNAL_H_*/
|
163
sys/contrib/vchiq/interface/vchi/vchi_common.h
Normal file
163
sys/contrib/vchiq/interface/vchi/vchi_common.h
Normal file
@ -0,0 +1,163 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHI_COMMON_H_
|
||||
#define VCHI_COMMON_H_
|
||||
|
||||
|
||||
//flags used when sending messages (must be bitmapped)
|
||||
typedef enum
|
||||
{
|
||||
VCHI_FLAGS_NONE = 0x0,
|
||||
VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE = 0x1, // waits for message to be received, or sent (NB. not the same as being seen on other side)
|
||||
VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2, // run a callback when message sent
|
||||
VCHI_FLAGS_BLOCK_UNTIL_QUEUED = 0x4, // return once the transfer is in a queue ready to go
|
||||
VCHI_FLAGS_ALLOW_PARTIAL = 0x8,
|
||||
VCHI_FLAGS_BLOCK_UNTIL_DATA_READ = 0x10,
|
||||
VCHI_FLAGS_CALLBACK_WHEN_DATA_READ = 0x20,
|
||||
|
||||
VCHI_FLAGS_ALIGN_SLOT = 0x000080, // internal use only
|
||||
VCHI_FLAGS_BULK_AUX_QUEUED = 0x010000, // internal use only
|
||||
VCHI_FLAGS_BULK_AUX_COMPLETE = 0x020000, // internal use only
|
||||
VCHI_FLAGS_BULK_DATA_QUEUED = 0x040000, // internal use only
|
||||
VCHI_FLAGS_BULK_DATA_COMPLETE = 0x080000, // internal use only
|
||||
VCHI_FLAGS_INTERNAL = 0xFF0000
|
||||
} VCHI_FLAGS_T;
|
||||
|
||||
// constants for vchi_crc_control()
|
||||
typedef enum {
|
||||
VCHI_CRC_NOTHING = -1,
|
||||
VCHI_CRC_PER_SERVICE = 0,
|
||||
VCHI_CRC_EVERYTHING = 1,
|
||||
} VCHI_CRC_CONTROL_T;
|
||||
|
||||
//callback reasons when an event occurs on a service
|
||||
typedef enum
|
||||
{
|
||||
VCHI_CALLBACK_REASON_MIN,
|
||||
|
||||
//This indicates that there is data available
|
||||
//handle is the msg id that was transmitted with the data
|
||||
// When a message is received and there was no FULL message available previously, send callback
|
||||
// Tasks get kicked by the callback, reset their event and try and read from the fifo until it fails
|
||||
VCHI_CALLBACK_MSG_AVAILABLE,
|
||||
VCHI_CALLBACK_MSG_SENT,
|
||||
VCHI_CALLBACK_MSG_SPACE_AVAILABLE, // XXX not yet implemented
|
||||
|
||||
// This indicates that a transfer from the other side has completed
|
||||
VCHI_CALLBACK_BULK_RECEIVED,
|
||||
//This indicates that data queued up to be sent has now gone
|
||||
//handle is the msg id that was used when sending the data
|
||||
VCHI_CALLBACK_BULK_SENT,
|
||||
VCHI_CALLBACK_BULK_RX_SPACE_AVAILABLE, // XXX not yet implemented
|
||||
VCHI_CALLBACK_BULK_TX_SPACE_AVAILABLE, // XXX not yet implemented
|
||||
|
||||
VCHI_CALLBACK_SERVICE_CLOSED,
|
||||
|
||||
// this side has sent XOFF to peer due to lack of data consumption by service
|
||||
// (suggests the service may need to take some recovery action if it has
|
||||
// been deliberately holding off consuming data)
|
||||
VCHI_CALLBACK_SENT_XOFF,
|
||||
VCHI_CALLBACK_SENT_XON,
|
||||
|
||||
// indicates that a bulk transfer has finished reading the source buffer
|
||||
VCHI_CALLBACK_BULK_DATA_READ,
|
||||
|
||||
// power notification events (currently host side only)
|
||||
VCHI_CALLBACK_PEER_OFF,
|
||||
VCHI_CALLBACK_PEER_SUSPENDED,
|
||||
VCHI_CALLBACK_PEER_ON,
|
||||
VCHI_CALLBACK_PEER_RESUMED,
|
||||
VCHI_CALLBACK_FORCED_POWER_OFF,
|
||||
|
||||
#ifdef USE_VCHIQ_ARM
|
||||
// some extra notifications provided by vchiq_arm
|
||||
VCHI_CALLBACK_SERVICE_OPENED,
|
||||
VCHI_CALLBACK_BULK_RECEIVE_ABORTED,
|
||||
VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,
|
||||
#endif
|
||||
|
||||
VCHI_CALLBACK_REASON_MAX
|
||||
} VCHI_CALLBACK_REASON_T;
|
||||
|
||||
//Calback used by all services / bulk transfers
|
||||
typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param
|
||||
VCHI_CALLBACK_REASON_T reason,
|
||||
void *handle ); //for transmitting msg's only
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Define vector struct for scatter-gather (vector) operations
|
||||
* Vectors can be nested - if a vector element has negative length, then
|
||||
* the data pointer is treated as pointing to another vector array, with
|
||||
* '-vec_len' elements. Thus to append a header onto an existing vector,
|
||||
* you can do this:
|
||||
*
|
||||
* void foo(const VCHI_MSG_VECTOR_T *v, int n)
|
||||
* {
|
||||
* VCHI_MSG_VECTOR_T nv[2];
|
||||
* nv[0].vec_base = my_header;
|
||||
* nv[0].vec_len = sizeof my_header;
|
||||
* nv[1].vec_base = v;
|
||||
* nv[1].vec_len = -n;
|
||||
* ...
|
||||
*
|
||||
*/
|
||||
typedef struct vchi_msg_vector {
|
||||
const void *vec_base;
|
||||
int32_t vec_len;
|
||||
} VCHI_MSG_VECTOR_T;
|
||||
|
||||
// Opaque type for a connection API
|
||||
typedef struct opaque_vchi_connection_api_t VCHI_CONNECTION_API_T;
|
||||
|
||||
// Opaque type for a message driver
|
||||
typedef struct opaque_vchi_message_driver_t VCHI_MESSAGE_DRIVER_T;
|
||||
|
||||
|
||||
// Iterator structure for reading ahead through received message queue. Allocated by client,
|
||||
// initialised by vchi_msg_look_ahead. Fields are for internal VCHI use only.
|
||||
// Iterates over messages in queue at the instant of the call to vchi_msg_lookahead -
|
||||
// will not proceed to messages received since. Behaviour is undefined if an iterator
|
||||
// is used again after messages for that service are removed/dequeued by any
|
||||
// means other than vchi_msg_iter_... calls on the iterator itself.
|
||||
typedef struct {
|
||||
struct opaque_vchi_service_t *service;
|
||||
void *last;
|
||||
void *next;
|
||||
void *remove;
|
||||
} VCHI_MSG_ITER_T;
|
||||
|
||||
|
||||
#endif // VCHI_COMMON_H_
|
42
sys/contrib/vchiq/interface/vchi/vchi_mh.h
Normal file
42
sys/contrib/vchiq/interface/vchi/vchi_mh.h
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHI_MH_H_
|
||||
#define VCHI_MH_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef int32_t VCHI_MEM_HANDLE_T;
|
||||
#define VCHI_MEM_HANDLE_INVALID 0
|
||||
|
||||
#endif
|
41
sys/contrib/vchiq/interface/vchiq_arm/vchiq.h
Normal file
41
sys/contrib/vchiq/interface/vchiq_arm/vchiq.h
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_VCHIQ_H
|
||||
#define VCHIQ_VCHIQ_H
|
||||
|
||||
#include "vchiq_if.h"
|
||||
#include "vchiq_util.h"
|
||||
|
||||
#endif
|
||||
|
42
sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835.h
Normal file
42
sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835.h
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_2835_H
|
||||
#define VCHIQ_2835_H
|
||||
|
||||
#include "vchiq_pagelist.h"
|
||||
|
||||
#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0
|
||||
#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1
|
||||
|
||||
#endif /* VCHIQ_2835_H */
|
580
sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
Normal file
580
sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
Normal file
@ -0,0 +1,580 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <interface/compat/vchi_bsd.h>
|
||||
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rwlock.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <vm/vm_map.h>
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vm_pager.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/vm_phys.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <arm/broadcom/bcm2835/bcm2835_mbox.h>
|
||||
#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
|
||||
|
||||
MALLOC_DEFINE(M_VCPAGELIST, "vcpagelist", "VideoCore pagelist memory");
|
||||
|
||||
#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32)
|
||||
|
||||
#define VCHIQ_DOORBELL_IRQ IRQ_ARM_DOORBELL_0
|
||||
#define VCHIQ_ARM_ADDRESS(x) ((void *)PHYS_TO_VCBUS(pmap_kextract((vm_offset_t)(x))))
|
||||
|
||||
#include "vchiq_arm.h"
|
||||
#include "vchiq_2835.h"
|
||||
#include "vchiq_connected.h"
|
||||
|
||||
#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2)
|
||||
|
||||
typedef struct vchiq_2835_state_struct {
|
||||
int inited;
|
||||
VCHIQ_ARM_STATE_T arm_state;
|
||||
} VCHIQ_2835_ARM_STATE_T;
|
||||
|
||||
static char *g_slot_mem;
|
||||
static int g_slot_mem_size;
|
||||
vm_paddr_t g_slot_phys;
|
||||
/* BSD DMA */
|
||||
bus_dma_tag_t bcm_slots_dma_tag;
|
||||
bus_dmamap_t bcm_slots_dma_map;
|
||||
|
||||
static FRAGMENTS_T *g_fragments_base;
|
||||
static FRAGMENTS_T *g_free_fragments;
|
||||
struct semaphore g_free_fragments_sema;
|
||||
|
||||
static DEFINE_SEMAPHORE(g_free_fragments_mutex);
|
||||
|
||||
typedef struct bulkinfo_struct {
|
||||
PAGELIST_T *pagelist;
|
||||
bus_dma_tag_t pagelist_dma_tag;
|
||||
bus_dmamap_t pagelist_dma_map;
|
||||
void *buf;
|
||||
size_t size;
|
||||
} BULKINFO_T;
|
||||
|
||||
static int
|
||||
create_pagelist(char __user *buf, size_t count, unsigned short type,
|
||||
struct proc *p, BULKINFO_T *bi);
|
||||
|
||||
static void
|
||||
free_pagelist(BULKINFO_T *bi, int actual);
|
||||
|
||||
static void
|
||||
vchiq_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);
|
||||
}
|
||||
|
||||
int __init
|
||||
vchiq_platform_init(VCHIQ_STATE_T *state)
|
||||
{
|
||||
VCHIQ_SLOT_ZERO_T *vchiq_slot_zero;
|
||||
int frag_mem_size;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
/* Allocate space for the channels in coherent memory */
|
||||
g_slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
|
||||
frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS);
|
||||
|
||||
err = bus_dma_tag_create(
|
||||
NULL,
|
||||
PAGE_SIZE, 0, /* alignment, boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
g_slot_mem_size + frag_mem_size, 1, /* maxsize, nsegments */
|
||||
g_slot_mem_size + frag_mem_size, 0, /* maxsegsize, flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&bcm_slots_dma_tag);
|
||||
|
||||
err = bus_dmamem_alloc(bcm_slots_dma_tag, (void **)&g_slot_mem,
|
||||
BUS_DMA_COHERENT | BUS_DMA_WAITOK, &bcm_slots_dma_map);
|
||||
if (err) {
|
||||
vchiq_log_error(vchiq_core_log_level, "Unable to allocate channel memory");
|
||||
err = -ENOMEM;
|
||||
goto failed_alloc;
|
||||
}
|
||||
|
||||
err = bus_dmamap_load(bcm_slots_dma_tag, bcm_slots_dma_map, g_slot_mem,
|
||||
g_slot_mem_size + frag_mem_size, vchiq_dmamap_cb,
|
||||
&g_slot_phys, 0);
|
||||
|
||||
if (err) {
|
||||
vchiq_log_error(vchiq_core_log_level, "cannot load DMA map");
|
||||
err = -ENOMEM;
|
||||
goto failed_load;
|
||||
}
|
||||
|
||||
WARN_ON(((int)g_slot_mem & (PAGE_SIZE - 1)) != 0);
|
||||
|
||||
vchiq_slot_zero = vchiq_init_slots(g_slot_mem, g_slot_mem_size);
|
||||
if (!vchiq_slot_zero) {
|
||||
err = -EINVAL;
|
||||
goto failed_init_slots;
|
||||
}
|
||||
|
||||
vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] =
|
||||
(int)g_slot_phys + g_slot_mem_size;
|
||||
vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] =
|
||||
MAX_FRAGMENTS;
|
||||
|
||||
g_fragments_base = (FRAGMENTS_T *)(g_slot_mem + g_slot_mem_size);
|
||||
g_slot_mem_size += frag_mem_size;
|
||||
|
||||
g_free_fragments = g_fragments_base;
|
||||
for (i = 0; i < (MAX_FRAGMENTS - 1); i++) {
|
||||
*(FRAGMENTS_T **)&g_fragments_base[i] =
|
||||
&g_fragments_base[i + 1];
|
||||
}
|
||||
*(FRAGMENTS_T **)&g_fragments_base[i] = NULL;
|
||||
_sema_init(&g_free_fragments_sema, MAX_FRAGMENTS);
|
||||
|
||||
if (vchiq_init_state(state, vchiq_slot_zero, 0/*slave*/) !=
|
||||
VCHIQ_SUCCESS) {
|
||||
err = -EINVAL;
|
||||
goto failed_vchiq_init;
|
||||
}
|
||||
|
||||
bcm_mbox_write(BCM2835_MBOX_CHAN_VCHIQ, (unsigned int)g_slot_phys);
|
||||
|
||||
vchiq_log_info(vchiq_arm_log_level,
|
||||
"vchiq_init - done (slots %x, phys %x)",
|
||||
(unsigned int)vchiq_slot_zero, g_slot_phys);
|
||||
|
||||
vchiq_call_connected_callbacks();
|
||||
|
||||
return 0;
|
||||
|
||||
failed_vchiq_init:
|
||||
failed_init_slots:
|
||||
failed_load:
|
||||
bus_dmamap_unload(bcm_slots_dma_tag, bcm_slots_dma_map);
|
||||
failed_alloc:
|
||||
bus_dmamap_destroy(bcm_slots_dma_tag, bcm_slots_dma_map);
|
||||
bus_dma_tag_destroy(bcm_slots_dma_tag);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void __exit
|
||||
vchiq_platform_exit(VCHIQ_STATE_T *state)
|
||||
{
|
||||
|
||||
bus_dmamap_unload(bcm_slots_dma_tag, bcm_slots_dma_map);
|
||||
bus_dmamap_destroy(bcm_slots_dma_tag, bcm_slots_dma_map);
|
||||
bus_dma_tag_destroy(bcm_slots_dma_tag);
|
||||
}
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_platform_init_state(VCHIQ_STATE_T *state)
|
||||
{
|
||||
VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
|
||||
state->platform_state = kzalloc(sizeof(VCHIQ_2835_ARM_STATE_T), GFP_KERNEL);
|
||||
((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 1;
|
||||
status = vchiq_arm_init_state(state, &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state);
|
||||
if(status != VCHIQ_SUCCESS)
|
||||
{
|
||||
((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited = 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
VCHIQ_ARM_STATE_T*
|
||||
vchiq_platform_get_arm_state(VCHIQ_STATE_T *state)
|
||||
{
|
||||
if(!((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->inited)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
return &((VCHIQ_2835_ARM_STATE_T*)state->platform_state)->arm_state;
|
||||
}
|
||||
|
||||
int
|
||||
vchiq_copy_from_user(void *dst, const void *src, int size)
|
||||
{
|
||||
|
||||
if (((vm_offset_t)(src)) < VM_MIN_KERNEL_ADDRESS) {
|
||||
int error = copyin(src, dst, size);
|
||||
return error ? VCHIQ_ERROR : VCHIQ_SUCCESS;
|
||||
}
|
||||
else
|
||||
bcopy(src, dst, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle,
|
||||
void *offset, int size, int dir)
|
||||
{
|
||||
PAGELIST_T *pagelist;
|
||||
BULKINFO_T *bi;
|
||||
int ret;
|
||||
|
||||
WARN_ON(memhandle != VCHI_MEM_HANDLE_INVALID);
|
||||
bi = malloc(sizeof(*bi), M_VCPAGELIST, M_WAITOK | M_ZERO);
|
||||
if (bi == NULL)
|
||||
return VCHIQ_ERROR;
|
||||
|
||||
ret = create_pagelist((char __user *)offset, size,
|
||||
(dir == VCHIQ_BULK_RECEIVE)
|
||||
? PAGELIST_READ
|
||||
: PAGELIST_WRITE,
|
||||
current,
|
||||
bi);
|
||||
if (ret != 0)
|
||||
return VCHIQ_ERROR;
|
||||
|
||||
bulk->handle = memhandle;
|
||||
bulk->data = VCHIQ_ARM_ADDRESS(bi->pagelist);
|
||||
|
||||
/* Store the pagelist address in remote_data, which isn't used by the
|
||||
slave. */
|
||||
bulk->remote_data = bi;
|
||||
|
||||
return VCHIQ_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
vchiq_complete_bulk(VCHIQ_BULK_T *bulk)
|
||||
{
|
||||
if (bulk && bulk->remote_data && bulk->actual)
|
||||
free_pagelist((BULKINFO_T *)bulk->remote_data, bulk->actual);
|
||||
}
|
||||
|
||||
void
|
||||
vchiq_transfer_bulk(VCHIQ_BULK_T *bulk)
|
||||
{
|
||||
/*
|
||||
* This should only be called on the master (VideoCore) side, but
|
||||
* provide an implementation to avoid the need for ifdefery.
|
||||
*/
|
||||
BUG();
|
||||
}
|
||||
|
||||
void
|
||||
vchiq_dump_platform_state(void *dump_context)
|
||||
{
|
||||
char buf[80];
|
||||
int len;
|
||||
len = snprintf(buf, sizeof(buf),
|
||||
" Platform: 2835 (VC master)");
|
||||
vchiq_dump(dump_context, buf, len + 1);
|
||||
}
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_platform_suspend(VCHIQ_STATE_T *state)
|
||||
{
|
||||
return VCHIQ_ERROR;
|
||||
}
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_platform_resume(VCHIQ_STATE_T *state)
|
||||
{
|
||||
return VCHIQ_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
vchiq_platform_paused(VCHIQ_STATE_T *state)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
vchiq_platform_resumed(VCHIQ_STATE_T *state)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
vchiq_platform_videocore_wanted(VCHIQ_STATE_T* state)
|
||||
{
|
||||
return 1; // autosuspend not supported - videocore always wanted
|
||||
}
|
||||
|
||||
int
|
||||
vchiq_platform_use_suspend_timer(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
vchiq_dump_platform_use_state(VCHIQ_STATE_T *state)
|
||||
{
|
||||
vchiq_log_info(vchiq_arm_log_level, "Suspend timer not in use");
|
||||
}
|
||||
void
|
||||
vchiq_platform_handle_timeout(VCHIQ_STATE_T *state)
|
||||
{
|
||||
(void)state;
|
||||
}
|
||||
/*
|
||||
* Local functions
|
||||
*/
|
||||
|
||||
/* There is a potential problem with partial cache lines (pages?)
|
||||
** at the ends of the block when reading. If the CPU accessed anything in
|
||||
** the same line (page?) then it may have pulled old data into the cache,
|
||||
** obscuring the new data underneath. We can solve this by transferring the
|
||||
** partial cache lines separately, and allowing the ARM to copy into the
|
||||
** cached area.
|
||||
|
||||
** N.B. This implementation plays slightly fast and loose with the Linux
|
||||
** driver programming rules, e.g. its use of __virt_to_bus instead of
|
||||
** dma_map_single, but it isn't a multi-platform driver and it benefits
|
||||
** from increased speed as a result.
|
||||
*/
|
||||
|
||||
static int
|
||||
create_pagelist(char __user *buf, size_t count, unsigned short type,
|
||||
struct proc *p, BULKINFO_T *bi)
|
||||
{
|
||||
PAGELIST_T *pagelist;
|
||||
vm_page_t* pages;
|
||||
unsigned long *addrs;
|
||||
unsigned int num_pages, i;
|
||||
vm_offset_t offset;
|
||||
int pagelist_size;
|
||||
char *addr, *base_addr, *next_addr;
|
||||
int run, addridx, actual_pages;
|
||||
int err;
|
||||
vm_paddr_t pagelist_phys;
|
||||
|
||||
offset = (vm_offset_t)buf & (PAGE_SIZE - 1);
|
||||
num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
|
||||
bi->pagelist = NULL;
|
||||
bi->buf = buf;
|
||||
bi->size = count;
|
||||
|
||||
/* Allocate enough storage to hold the page pointers and the page
|
||||
** list
|
||||
*/
|
||||
pagelist_size = sizeof(PAGELIST_T) +
|
||||
(num_pages * sizeof(unsigned long)) +
|
||||
(num_pages * sizeof(pages[0]));
|
||||
|
||||
err = bus_dma_tag_create(
|
||||
NULL,
|
||||
PAGE_SIZE, 0, /* alignment, boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
pagelist_size, 1, /* maxsize, nsegments */
|
||||
pagelist_size, 0, /* maxsegsize, flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&bi->pagelist_dma_tag);
|
||||
|
||||
|
||||
|
||||
err = bus_dmamem_alloc(bi->pagelist_dma_tag, (void **)&pagelist,
|
||||
BUS_DMA_COHERENT | BUS_DMA_WAITOK, &bi->pagelist_dma_map);
|
||||
if (err) {
|
||||
vchiq_log_error(vchiq_core_log_level, "Unable to allocate pagelist memory");
|
||||
err = -ENOMEM;
|
||||
goto failed_alloc;
|
||||
}
|
||||
|
||||
err = bus_dmamap_load(bi->pagelist_dma_tag, bi->pagelist_dma_map, pagelist,
|
||||
pagelist_size, vchiq_dmamap_cb,
|
||||
&pagelist_phys, 0);
|
||||
|
||||
if (err) {
|
||||
vchiq_log_error(vchiq_core_log_level, "cannot load DMA map for pagelist memory");
|
||||
err = -ENOMEM;
|
||||
goto failed_load;
|
||||
}
|
||||
|
||||
vchiq_log_trace(vchiq_arm_log_level,
|
||||
"create_pagelist - %x", (unsigned int)pagelist);
|
||||
if (!pagelist)
|
||||
return -ENOMEM;
|
||||
|
||||
addrs = pagelist->addrs;
|
||||
pages = (vm_page_t*)(addrs + num_pages);
|
||||
|
||||
actual_pages = vm_fault_quick_hold_pages(&p->p_vmspace->vm_map,
|
||||
(vm_offset_t)buf, count,
|
||||
(type == PAGELIST_READ ? VM_PROT_WRITE : 0 ) | VM_PROT_READ, pages, num_pages);
|
||||
|
||||
if (actual_pages != num_pages) {
|
||||
vm_page_unhold_pages(pages, actual_pages);
|
||||
free(pagelist, M_VCPAGELIST);
|
||||
return (-ENOMEM);
|
||||
}
|
||||
|
||||
pagelist->length = count;
|
||||
pagelist->type = type;
|
||||
pagelist->offset = offset;
|
||||
|
||||
/* Group the pages into runs of contiguous pages */
|
||||
|
||||
base_addr = (void *)PHYS_TO_VCBUS(VM_PAGE_TO_PHYS(pages[0]));
|
||||
next_addr = base_addr + PAGE_SIZE;
|
||||
addridx = 0;
|
||||
run = 0;
|
||||
|
||||
for (i = 1; i < num_pages; i++) {
|
||||
addr = (void *)PHYS_TO_VCBUS(VM_PAGE_TO_PHYS(pages[i]));
|
||||
if ((addr == next_addr) && (run < (PAGE_SIZE - 1))) {
|
||||
next_addr += PAGE_SIZE;
|
||||
run++;
|
||||
} else {
|
||||
addrs[addridx] = (unsigned long)base_addr + run;
|
||||
addridx++;
|
||||
base_addr = addr;
|
||||
next_addr = addr + PAGE_SIZE;
|
||||
run = 0;
|
||||
}
|
||||
}
|
||||
|
||||
addrs[addridx] = (unsigned long)base_addr + run;
|
||||
addridx++;
|
||||
|
||||
/* Partial cache lines (fragments) require special measures */
|
||||
if ((type == PAGELIST_READ) &&
|
||||
((pagelist->offset & (CACHE_LINE_SIZE - 1)) ||
|
||||
((pagelist->offset + pagelist->length) &
|
||||
(CACHE_LINE_SIZE - 1)))) {
|
||||
FRAGMENTS_T *fragments;
|
||||
|
||||
if (down_interruptible(&g_free_fragments_sema) != 0) {
|
||||
free(pagelist, M_VCPAGELIST);
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
WARN_ON(g_free_fragments == NULL);
|
||||
|
||||
down(&g_free_fragments_mutex);
|
||||
fragments = (FRAGMENTS_T *) g_free_fragments;
|
||||
WARN_ON(fragments == NULL);
|
||||
g_free_fragments = *(FRAGMENTS_T **) g_free_fragments;
|
||||
up(&g_free_fragments_mutex);
|
||||
pagelist->type =
|
||||
PAGELIST_READ_WITH_FRAGMENTS + (fragments -
|
||||
g_fragments_base);
|
||||
}
|
||||
|
||||
/* XXX: optimize? INV operation for read WBINV for write? */
|
||||
cpu_dcache_wbinv_range((vm_offset_t)buf, count);
|
||||
|
||||
bi->pagelist = pagelist;
|
||||
|
||||
return 0;
|
||||
|
||||
failed_load:
|
||||
bus_dmamap_unload(bi->pagelist_dma_tag, bi->pagelist_dma_map);
|
||||
failed_alloc:
|
||||
bus_dmamap_destroy(bi->pagelist_dma_tag, bi->pagelist_dma_map);
|
||||
bus_dma_tag_destroy(bi->pagelist_dma_tag);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
free_pagelist(BULKINFO_T *bi, int actual)
|
||||
{
|
||||
vm_page_t*pages;
|
||||
unsigned int num_pages, i;
|
||||
void *page_address;
|
||||
PAGELIST_T *pagelist;
|
||||
|
||||
pagelist = bi->pagelist;
|
||||
|
||||
vchiq_log_trace(vchiq_arm_log_level,
|
||||
"free_pagelist - %x, %d", (unsigned int)pagelist, actual);
|
||||
|
||||
num_pages =
|
||||
(pagelist->length + pagelist->offset + PAGE_SIZE - 1) /
|
||||
PAGE_SIZE;
|
||||
|
||||
pages = (vm_page_t*)(pagelist->addrs + num_pages);
|
||||
|
||||
/* Deal with any partial cache lines (fragments) */
|
||||
if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) {
|
||||
FRAGMENTS_T *fragments = g_fragments_base +
|
||||
(pagelist->type - PAGELIST_READ_WITH_FRAGMENTS);
|
||||
int head_bytes, tail_bytes;
|
||||
head_bytes = (CACHE_LINE_SIZE - pagelist->offset) &
|
||||
(CACHE_LINE_SIZE - 1);
|
||||
tail_bytes = (pagelist->offset + actual) &
|
||||
(CACHE_LINE_SIZE - 1);
|
||||
|
||||
if ((actual >= 0) && (head_bytes != 0)) {
|
||||
if (head_bytes > actual)
|
||||
head_bytes = actual;
|
||||
|
||||
memcpy((char *)bi->buf,
|
||||
fragments->headbuf,
|
||||
head_bytes);
|
||||
}
|
||||
|
||||
if ((actual >= 0) && (head_bytes < actual) &&
|
||||
(tail_bytes != 0)) {
|
||||
memcpy((char *)bi->buf + actual - tail_bytes,
|
||||
fragments->tailbuf, tail_bytes);
|
||||
}
|
||||
|
||||
down(&g_free_fragments_mutex);
|
||||
*(FRAGMENTS_T **) fragments = g_free_fragments;
|
||||
g_free_fragments = fragments;
|
||||
up(&g_free_fragments_mutex);
|
||||
up(&g_free_fragments_sema);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
if (pagelist->type != PAGELIST_WRITE)
|
||||
vm_page_dirty(pages[i]);
|
||||
}
|
||||
|
||||
vm_page_unhold_pages(pages, num_pages);
|
||||
|
||||
bus_dmamap_unload(bi->pagelist_dma_tag, bi->pagelist_dma_map);
|
||||
bus_dmamem_free(bi->pagelist_dma_tag, bi->pagelist, bi->pagelist_dma_map);
|
||||
bus_dmamap_destroy(bi->pagelist_dma_tag, bi->pagelist_dma_map);
|
||||
bus_dma_tag_destroy(bi->pagelist_dma_tag);
|
||||
|
||||
free(bi, M_VCPAGELIST);
|
||||
}
|
2810
sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c
Normal file
2810
sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.c
Normal file
File diff suppressed because it is too large
Load Diff
200
sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.h
Normal file
200
sys/contrib/vchiq/interface/vchiq_arm/vchiq_arm.h
Normal file
@ -0,0 +1,200 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_ARM_H
|
||||
#define VCHIQ_ARM_H
|
||||
|
||||
#include "vchiq_core.h"
|
||||
|
||||
|
||||
enum vc_suspend_status {
|
||||
VC_SUSPEND_FORCE_CANCELED = -3, /* Force suspend canceled, too busy */
|
||||
VC_SUSPEND_REJECTED = -2, /* Videocore rejected suspend request */
|
||||
VC_SUSPEND_FAILED = -1, /* Videocore suspend failed */
|
||||
VC_SUSPEND_IDLE = 0, /* VC active, no suspend actions */
|
||||
VC_SUSPEND_REQUESTED, /* User has requested suspend */
|
||||
VC_SUSPEND_IN_PROGRESS, /* Slot handler has recvd suspend request */
|
||||
VC_SUSPEND_SUSPENDED /* Videocore suspend succeeded */
|
||||
};
|
||||
|
||||
enum vc_resume_status {
|
||||
VC_RESUME_FAILED = -1, /* Videocore resume failed */
|
||||
VC_RESUME_IDLE = 0, /* VC suspended, no resume actions */
|
||||
VC_RESUME_REQUESTED, /* User has requested resume */
|
||||
VC_RESUME_IN_PROGRESS, /* Slot handler has received resume request */
|
||||
VC_RESUME_RESUMED /* Videocore resumed successfully (active) */
|
||||
};
|
||||
|
||||
|
||||
enum USE_TYPE_E {
|
||||
USE_TYPE_SERVICE,
|
||||
USE_TYPE_SERVICE_NO_RESUME,
|
||||
USE_TYPE_VCHIQ
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef struct vchiq_arm_state_struct {
|
||||
/* Keepalive-related data */
|
||||
VCHIQ_THREAD_T ka_thread;
|
||||
struct completion ka_evt;
|
||||
atomic_t ka_use_count;
|
||||
atomic_t ka_use_ack_count;
|
||||
atomic_t ka_release_count;
|
||||
|
||||
struct completion vc_suspend_complete;
|
||||
struct completion vc_resume_complete;
|
||||
|
||||
rwlock_t susp_res_lock;
|
||||
enum vc_suspend_status vc_suspend_state;
|
||||
enum vc_resume_status vc_resume_state;
|
||||
|
||||
unsigned int wake_address;
|
||||
|
||||
struct timer_list suspend_timer;
|
||||
int suspend_timer_timeout;
|
||||
int suspend_timer_running;
|
||||
|
||||
/* Global use count for videocore.
|
||||
** This is equal to the sum of the use counts for all services. When
|
||||
** this hits zero the videocore suspend procedure will be initiated.
|
||||
*/
|
||||
int videocore_use_count;
|
||||
|
||||
/* Use count to track requests from videocore peer.
|
||||
** This use count is not associated with a service, so needs to be
|
||||
** tracked separately with the state.
|
||||
*/
|
||||
int peer_use_count;
|
||||
|
||||
/* Flag to indicate whether resume is blocked. This happens when the
|
||||
** ARM is suspending
|
||||
*/
|
||||
struct completion resume_blocker;
|
||||
int resume_blocked;
|
||||
struct completion blocked_blocker;
|
||||
int blocked_count;
|
||||
|
||||
int autosuspend_override;
|
||||
|
||||
/* Flag to indicate that the first vchiq connect has made it through.
|
||||
** This means that both sides should be fully ready, and we should
|
||||
** be able to suspend after this point.
|
||||
*/
|
||||
int first_connect;
|
||||
|
||||
unsigned long long suspend_start_time;
|
||||
unsigned long long sleep_start_time;
|
||||
unsigned long long resume_start_time;
|
||||
unsigned long long last_wake_time;
|
||||
|
||||
} VCHIQ_ARM_STATE_T;
|
||||
|
||||
extern int vchiq_arm_log_level;
|
||||
extern int vchiq_susp_log_level;
|
||||
|
||||
extern int __init
|
||||
vchiq_platform_init(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void __exit
|
||||
vchiq_platform_exit(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATE_T *
|
||||
vchiq_get_state(void);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_arm_vcsuspend(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_arm_force_suspend(VCHIQ_STATE_T *state);
|
||||
|
||||
extern int
|
||||
vchiq_arm_allow_resume(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_arm_vcresume(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state);
|
||||
|
||||
extern int
|
||||
vchiq_check_resume(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_check_suspend(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_platform_suspend(VCHIQ_STATE_T *state);
|
||||
|
||||
extern int
|
||||
vchiq_platform_videocore_wanted(VCHIQ_STATE_T *state);
|
||||
|
||||
extern int
|
||||
vchiq_platform_use_suspend_timer(void);
|
||||
|
||||
extern void
|
||||
vchiq_dump_platform_use_state(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_dump_service_use_state(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_ARM_STATE_T*
|
||||
vchiq_platform_get_arm_state(VCHIQ_STATE_T *state);
|
||||
|
||||
extern int
|
||||
vchiq_videocore_wanted(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
|
||||
enum USE_TYPE_E use_type);
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service);
|
||||
|
||||
void
|
||||
set_suspend_state(VCHIQ_ARM_STATE_T *arm_state,
|
||||
enum vc_suspend_status new_state);
|
||||
|
||||
void
|
||||
set_resume_state(VCHIQ_ARM_STATE_T *arm_state,
|
||||
enum vc_resume_status new_state);
|
||||
|
||||
void
|
||||
start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state);
|
||||
|
||||
extern int vchiq_proc_init(void);
|
||||
extern void vchiq_proc_deinit(void);
|
||||
extern struct proc_dir_entry *vchiq_proc_top(void);
|
||||
extern struct proc_dir_entry *vchiq_clients_top(void);
|
||||
|
||||
|
||||
#endif /* VCHIQ_ARM_H */
|
37
sys/contrib/vchiq/interface/vchiq_arm/vchiq_build_info.h
Normal file
37
sys/contrib/vchiq/interface/vchiq_arm/vchiq_build_info.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
const char *vchiq_get_build_hostname(void);
|
||||
const char *vchiq_get_build_version(void);
|
||||
const char *vchiq_get_build_time(void);
|
||||
const char *vchiq_get_build_date(void);
|
60
sys/contrib/vchiq/interface/vchiq_arm/vchiq_cfg.h
Normal file
60
sys/contrib/vchiq/interface/vchiq_arm/vchiq_cfg.h
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_CFG_H
|
||||
#define VCHIQ_CFG_H
|
||||
|
||||
#define VCHIQ_MAGIC VCHIQ_MAKE_FOURCC('V', 'C', 'H', 'I')
|
||||
/* The version of VCHIQ - change with any non-trivial change */
|
||||
#define VCHIQ_VERSION 6
|
||||
/* The minimum compatible version - update to match VCHIQ_VERSION with any
|
||||
** incompatible change */
|
||||
#define VCHIQ_VERSION_MIN 3
|
||||
|
||||
#define VCHIQ_MAX_STATES 1
|
||||
#define VCHIQ_MAX_SERVICES 4096
|
||||
#define VCHIQ_MAX_SLOTS 128
|
||||
#define VCHIQ_MAX_SLOTS_PER_SIDE 64
|
||||
|
||||
#define VCHIQ_NUM_CURRENT_BULKS 32
|
||||
#define VCHIQ_NUM_SERVICE_BULKS 4
|
||||
|
||||
#ifndef VCHIQ_ENABLE_DEBUG
|
||||
#define VCHIQ_ENABLE_DEBUG 1
|
||||
#endif
|
||||
|
||||
#ifndef VCHIQ_ENABLE_STATS
|
||||
#define VCHIQ_ENABLE_STATS 1
|
||||
#endif
|
||||
|
||||
#endif /* VCHIQ_CFG_H */
|
117
sys/contrib/vchiq/interface/vchiq_arm/vchiq_connected.c
Normal file
117
sys/contrib/vchiq/interface/vchiq_arm/vchiq_connected.c
Normal file
@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 "vchiq_connected.h"
|
||||
#include "vchiq_core.h"
|
||||
|
||||
#define MAX_CALLBACKS 10
|
||||
|
||||
static int g_connected;
|
||||
static int g_num_deferred_callbacks;
|
||||
static VCHIQ_CONNECTED_CALLBACK_T g_deferred_callback[MAX_CALLBACKS];
|
||||
static int g_once_init;
|
||||
static struct mutex g_connected_mutex;
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Function to initialize our lock.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
static void connected_init(void)
|
||||
{
|
||||
if (!g_once_init) {
|
||||
lmutex_init(&g_connected_mutex);
|
||||
g_once_init = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* This function is used to defer initialization until the vchiq stack is
|
||||
* initialized. If the stack is already initialized, then the callback will
|
||||
* be made immediately, otherwise it will be deferred until
|
||||
* vchiq_call_connected_callbacks is called.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback)
|
||||
{
|
||||
connected_init();
|
||||
|
||||
if (lmutex_lock_interruptible(&g_connected_mutex) != 0)
|
||||
return;
|
||||
|
||||
if (g_connected)
|
||||
/* We're already connected. Call the callback immediately. */
|
||||
|
||||
callback();
|
||||
else {
|
||||
if (g_num_deferred_callbacks >= MAX_CALLBACKS)
|
||||
vchiq_log_error(vchiq_core_log_level,
|
||||
"There are already %d callbacks registered - "
|
||||
"please increase MAX_CALLBACKS",
|
||||
g_num_deferred_callbacks);
|
||||
else {
|
||||
g_deferred_callback[g_num_deferred_callbacks] =
|
||||
callback;
|
||||
g_num_deferred_callbacks++;
|
||||
}
|
||||
}
|
||||
lmutex_unlock(&g_connected_mutex);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* This function is called by the vchiq stack once it has been connected to
|
||||
* the videocore and clients can start to use the stack.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
void vchiq_call_connected_callbacks(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
connected_init();
|
||||
|
||||
if (lmutex_lock_interruptible(&g_connected_mutex) != 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < g_num_deferred_callbacks; i++)
|
||||
g_deferred_callback[i]();
|
||||
|
||||
g_num_deferred_callbacks = 0;
|
||||
g_connected = 1;
|
||||
lmutex_unlock(&g_connected_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_add_connected_callback);
|
51
sys/contrib/vchiq/interface/vchiq_arm/vchiq_connected.h
Normal file
51
sys/contrib/vchiq/interface/vchiq_arm/vchiq_connected.h
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_CONNECTED_H
|
||||
#define VCHIQ_CONNECTED_H
|
||||
|
||||
/* ---- Include Files ----------------------------------------------------- */
|
||||
|
||||
/* ---- Constants and Types ---------------------------------------------- */
|
||||
|
||||
typedef void (*VCHIQ_CONNECTED_CALLBACK_T)(void);
|
||||
|
||||
/* ---- Variable Externs ------------------------------------------------- */
|
||||
|
||||
/* ---- Function Prototypes ---------------------------------------------- */
|
||||
|
||||
void vchiq_add_connected_callback(VCHIQ_CONNECTED_CALLBACK_T callback);
|
||||
void vchiq_call_connected_callbacks(void);
|
||||
|
||||
#endif /* VCHIQ_CONNECTED_H */
|
||||
|
3842
sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.c
Normal file
3842
sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.c
Normal file
File diff suppressed because it is too large
Load Diff
710
sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.h
Normal file
710
sys/contrib/vchiq/interface/vchiq_arm/vchiq_core.h
Normal file
@ -0,0 +1,710 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_CORE_H
|
||||
#define VCHIQ_CORE_H
|
||||
|
||||
#include <interface/compat/vchi_bsd.h>
|
||||
#include <interface/compat/list.h>
|
||||
|
||||
#include "vchiq_cfg.h"
|
||||
|
||||
#include "vchiq.h"
|
||||
|
||||
/* Run time control of log level, based on KERN_XXX level. */
|
||||
#ifndef VCHIQ_LOG_DEFAULT
|
||||
#define VCHIQ_LOG_DEFAULT 4
|
||||
#endif
|
||||
#define VCHIQ_LOG_ERROR 3
|
||||
#define VCHIQ_LOG_WARNING 4
|
||||
#define VCHIQ_LOG_INFO 6
|
||||
#define VCHIQ_LOG_TRACE 7
|
||||
|
||||
#define VCHIQ_LOG_PREFIX "vchiq: "
|
||||
|
||||
#ifndef vchiq_log_error
|
||||
#define vchiq_log_error(cat, fmt, ...) \
|
||||
do { if (cat >= VCHIQ_LOG_ERROR) \
|
||||
printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
|
||||
#endif
|
||||
#ifndef vchiq_log_warning
|
||||
#define vchiq_log_warning(cat, fmt, ...) \
|
||||
do { if (cat >= VCHIQ_LOG_WARNING) \
|
||||
printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
|
||||
#endif
|
||||
#ifndef vchiq_log_info
|
||||
#define vchiq_log_info(cat, fmt, ...) \
|
||||
do { if (cat >= VCHIQ_LOG_INFO) \
|
||||
printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
|
||||
#endif
|
||||
#ifndef vchiq_log_trace
|
||||
#define vchiq_log_trace(cat, fmt, ...) \
|
||||
do { if (cat >= VCHIQ_LOG_TRACE) \
|
||||
printf(VCHIQ_LOG_PREFIX fmt "\n", ##__VA_ARGS__); } while (0)
|
||||
#endif
|
||||
|
||||
#define vchiq_loud_error(...) \
|
||||
vchiq_log_error(vchiq_core_log_level, "===== " __VA_ARGS__)
|
||||
|
||||
#ifndef vchiq_static_assert
|
||||
#define vchiq_static_assert(cond) __attribute__((unused)) \
|
||||
extern int vchiq_static_assert[(cond) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
#define IS_POW2(x) (x && ((x & (x - 1)) == 0))
|
||||
|
||||
/* Ensure that the slot size and maximum number of slots are powers of 2 */
|
||||
vchiq_static_assert(IS_POW2(VCHIQ_SLOT_SIZE));
|
||||
vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS));
|
||||
vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS_PER_SIDE));
|
||||
|
||||
#define VCHIQ_SLOT_MASK (VCHIQ_SLOT_SIZE - 1)
|
||||
#define VCHIQ_SLOT_QUEUE_MASK (VCHIQ_MAX_SLOTS_PER_SIDE - 1)
|
||||
#define VCHIQ_SLOT_ZERO_SLOTS ((sizeof(VCHIQ_SLOT_ZERO_T) + \
|
||||
VCHIQ_SLOT_SIZE - 1) / VCHIQ_SLOT_SIZE)
|
||||
|
||||
#define VCHIQ_MSG_PADDING 0 /* - */
|
||||
#define VCHIQ_MSG_CONNECT 1 /* - */
|
||||
#define VCHIQ_MSG_OPEN 2 /* + (srcport, -), fourcc, client_id */
|
||||
#define VCHIQ_MSG_OPENACK 3 /* + (srcport, dstport) */
|
||||
#define VCHIQ_MSG_CLOSE 4 /* + (srcport, dstport) */
|
||||
#define VCHIQ_MSG_DATA 5 /* + (srcport, dstport) */
|
||||
#define VCHIQ_MSG_BULK_RX 6 /* + (srcport, dstport), data, size */
|
||||
#define VCHIQ_MSG_BULK_TX 7 /* + (srcport, dstport), data, size */
|
||||
#define VCHIQ_MSG_BULK_RX_DONE 8 /* + (srcport, dstport), actual */
|
||||
#define VCHIQ_MSG_BULK_TX_DONE 9 /* + (srcport, dstport), actual */
|
||||
#define VCHIQ_MSG_PAUSE 10 /* - */
|
||||
#define VCHIQ_MSG_RESUME 11 /* - */
|
||||
#define VCHIQ_MSG_REMOTE_USE 12 /* - */
|
||||
#define VCHIQ_MSG_REMOTE_RELEASE 13 /* - */
|
||||
#define VCHIQ_MSG_REMOTE_USE_ACTIVE 14 /* - */
|
||||
|
||||
#define VCHIQ_PORT_MAX (VCHIQ_MAX_SERVICES - 1)
|
||||
#define VCHIQ_PORT_FREE 0x1000
|
||||
#define VCHIQ_PORT_IS_VALID(port) (port < VCHIQ_PORT_FREE)
|
||||
#define VCHIQ_MAKE_MSG(type, srcport, dstport) \
|
||||
((type<<24) | (srcport<<12) | (dstport<<0))
|
||||
#define VCHIQ_MSG_TYPE(msgid) ((unsigned int)msgid >> 24)
|
||||
#define VCHIQ_MSG_SRCPORT(msgid) \
|
||||
(unsigned short)(((unsigned int)msgid >> 12) & 0xfff)
|
||||
#define VCHIQ_MSG_DSTPORT(msgid) \
|
||||
((unsigned short)msgid & 0xfff)
|
||||
|
||||
#define VCHIQ_FOURCC_AS_4CHARS(fourcc) \
|
||||
((fourcc) >> 24) & 0xff, \
|
||||
((fourcc) >> 16) & 0xff, \
|
||||
((fourcc) >> 8) & 0xff, \
|
||||
(fourcc) & 0xff
|
||||
|
||||
/* Ensure the fields are wide enough */
|
||||
vchiq_static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX))
|
||||
== 0);
|
||||
vchiq_static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0);
|
||||
vchiq_static_assert((unsigned int)VCHIQ_PORT_MAX <
|
||||
(unsigned int)VCHIQ_PORT_FREE);
|
||||
|
||||
#define VCHIQ_MSGID_PADDING VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0)
|
||||
#define VCHIQ_MSGID_CLAIMED 0x40000000
|
||||
|
||||
#define VCHIQ_FOURCC_INVALID 0x00000000
|
||||
#define VCHIQ_FOURCC_IS_LEGAL(fourcc) (fourcc != VCHIQ_FOURCC_INVALID)
|
||||
|
||||
#define VCHIQ_BULK_ACTUAL_ABORTED -1
|
||||
|
||||
typedef uint32_t BITSET_T;
|
||||
|
||||
vchiq_static_assert((sizeof(BITSET_T) * 8) == 32);
|
||||
|
||||
#define BITSET_SIZE(b) ((b + 31) >> 5)
|
||||
#define BITSET_WORD(b) (b >> 5)
|
||||
#define BITSET_BIT(b) (1 << (b & 31))
|
||||
#define BITSET_ZERO(bs) memset(bs, 0, sizeof(bs))
|
||||
#define BITSET_IS_SET(bs, b) (bs[BITSET_WORD(b)] & BITSET_BIT(b))
|
||||
#define BITSET_SET(bs, b) (bs[BITSET_WORD(b)] |= BITSET_BIT(b))
|
||||
#define BITSET_CLR(bs, b) (bs[BITSET_WORD(b)] &= ~BITSET_BIT(b))
|
||||
|
||||
#if VCHIQ_ENABLE_STATS
|
||||
#define VCHIQ_STATS_INC(state, stat) (state->stats. stat++)
|
||||
#define VCHIQ_SERVICE_STATS_INC(service, stat) (service->stats. stat++)
|
||||
#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) \
|
||||
(service->stats. stat += addend)
|
||||
#else
|
||||
#define VCHIQ_STATS_INC(state, stat) ((void)0)
|
||||
#define VCHIQ_SERVICE_STATS_INC(service, stat) ((void)0)
|
||||
#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) ((void)0)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
DEBUG_ENTRIES,
|
||||
#if VCHIQ_ENABLE_DEBUG
|
||||
DEBUG_SLOT_HANDLER_COUNT,
|
||||
DEBUG_SLOT_HANDLER_LINE,
|
||||
DEBUG_PARSE_LINE,
|
||||
DEBUG_PARSE_HEADER,
|
||||
DEBUG_PARSE_MSGID,
|
||||
DEBUG_AWAIT_COMPLETION_LINE,
|
||||
DEBUG_DEQUEUE_MESSAGE_LINE,
|
||||
DEBUG_SERVICE_CALLBACK_LINE,
|
||||
DEBUG_MSG_QUEUE_FULL_COUNT,
|
||||
DEBUG_COMPLETION_QUEUE_FULL_COUNT,
|
||||
#endif
|
||||
DEBUG_MAX
|
||||
};
|
||||
|
||||
#if VCHIQ_ENABLE_DEBUG
|
||||
|
||||
#define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug;
|
||||
#define DEBUG_TRACE(d) \
|
||||
do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(); } while (0)
|
||||
#define DEBUG_VALUE(d, v) \
|
||||
do { debug_ptr[DEBUG_ ## d] = (v); dsb(); } while (0)
|
||||
#define DEBUG_COUNT(d) \
|
||||
do { debug_ptr[DEBUG_ ## d]++; dsb(); } while (0)
|
||||
|
||||
#else /* VCHIQ_ENABLE_DEBUG */
|
||||
|
||||
#define DEBUG_INITIALISE(local)
|
||||
#define DEBUG_TRACE(d)
|
||||
#define DEBUG_VALUE(d, v)
|
||||
#define DEBUG_COUNT(d)
|
||||
|
||||
#endif /* VCHIQ_ENABLE_DEBUG */
|
||||
|
||||
typedef enum {
|
||||
VCHIQ_CONNSTATE_DISCONNECTED,
|
||||
VCHIQ_CONNSTATE_CONNECTING,
|
||||
VCHIQ_CONNSTATE_CONNECTED,
|
||||
VCHIQ_CONNSTATE_PAUSING,
|
||||
VCHIQ_CONNSTATE_PAUSE_SENT,
|
||||
VCHIQ_CONNSTATE_PAUSED,
|
||||
VCHIQ_CONNSTATE_RESUMING,
|
||||
VCHIQ_CONNSTATE_PAUSE_TIMEOUT,
|
||||
VCHIQ_CONNSTATE_RESUME_TIMEOUT
|
||||
} VCHIQ_CONNSTATE_T;
|
||||
|
||||
enum {
|
||||
VCHIQ_SRVSTATE_FREE,
|
||||
VCHIQ_SRVSTATE_HIDDEN,
|
||||
VCHIQ_SRVSTATE_LISTENING,
|
||||
VCHIQ_SRVSTATE_OPENING,
|
||||
VCHIQ_SRVSTATE_OPEN,
|
||||
VCHIQ_SRVSTATE_OPENSYNC,
|
||||
VCHIQ_SRVSTATE_CLOSESENT,
|
||||
VCHIQ_SRVSTATE_CLOSERECVD,
|
||||
VCHIQ_SRVSTATE_CLOSEWAIT,
|
||||
VCHIQ_SRVSTATE_CLOSED
|
||||
};
|
||||
|
||||
enum {
|
||||
VCHIQ_POLL_TERMINATE,
|
||||
VCHIQ_POLL_REMOVE,
|
||||
VCHIQ_POLL_TXNOTIFY,
|
||||
VCHIQ_POLL_RXNOTIFY,
|
||||
VCHIQ_POLL_COUNT
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
VCHIQ_BULK_TRANSMIT,
|
||||
VCHIQ_BULK_RECEIVE
|
||||
} VCHIQ_BULK_DIR_T;
|
||||
|
||||
typedef void (*VCHIQ_USERDATA_TERM_T)(void *userdata);
|
||||
|
||||
typedef struct vchiq_bulk_struct {
|
||||
short mode;
|
||||
short dir;
|
||||
void *userdata;
|
||||
VCHI_MEM_HANDLE_T handle;
|
||||
void *data;
|
||||
int size;
|
||||
void *remote_data;
|
||||
int remote_size;
|
||||
int actual;
|
||||
} VCHIQ_BULK_T;
|
||||
|
||||
typedef struct vchiq_bulk_queue_struct {
|
||||
int local_insert; /* Where to insert the next local bulk */
|
||||
int remote_insert; /* Where to insert the next remote bulk (master) */
|
||||
int process; /* Bulk to transfer next */
|
||||
int remote_notify; /* Bulk to notify the remote client of next (mstr) */
|
||||
int remove; /* Bulk to notify the local client of, and remove,
|
||||
** next */
|
||||
VCHIQ_BULK_T bulks[VCHIQ_NUM_SERVICE_BULKS];
|
||||
} VCHIQ_BULK_QUEUE_T;
|
||||
|
||||
typedef struct remote_event_struct {
|
||||
int armed;
|
||||
int fired;
|
||||
struct semaphore *event;
|
||||
} REMOTE_EVENT_T;
|
||||
|
||||
typedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_T;
|
||||
|
||||
typedef struct vchiq_state_struct VCHIQ_STATE_T;
|
||||
|
||||
typedef struct vchiq_slot_struct {
|
||||
char data[VCHIQ_SLOT_SIZE];
|
||||
} VCHIQ_SLOT_T;
|
||||
|
||||
typedef struct vchiq_slot_info_struct {
|
||||
/* Use two counters rather than one to avoid the need for a mutex. */
|
||||
short use_count;
|
||||
short release_count;
|
||||
} __packed VCHIQ_SLOT_INFO_T; /* XXXGONZO: check it */
|
||||
|
||||
typedef struct vchiq_service_struct {
|
||||
VCHIQ_SERVICE_BASE_T base;
|
||||
VCHIQ_SERVICE_HANDLE_T handle;
|
||||
unsigned int ref_count;
|
||||
int srvstate;
|
||||
VCHIQ_USERDATA_TERM_T userdata_term;
|
||||
unsigned int localport;
|
||||
unsigned int remoteport;
|
||||
int public_fourcc;
|
||||
int client_id;
|
||||
char auto_close;
|
||||
char sync;
|
||||
char closing;
|
||||
atomic_t poll_flags;
|
||||
short version;
|
||||
short version_min;
|
||||
short peer_version;
|
||||
|
||||
VCHIQ_STATE_T *state;
|
||||
VCHIQ_INSTANCE_T instance;
|
||||
|
||||
int service_use_count;
|
||||
|
||||
VCHIQ_BULK_QUEUE_T bulk_tx;
|
||||
VCHIQ_BULK_QUEUE_T bulk_rx;
|
||||
|
||||
struct semaphore remove_event;
|
||||
struct semaphore bulk_remove_event;
|
||||
struct mutex bulk_mutex;
|
||||
|
||||
struct service_stats_struct {
|
||||
int quota_stalls;
|
||||
int slot_stalls;
|
||||
int bulk_stalls;
|
||||
int error_count;
|
||||
int ctrl_tx_count;
|
||||
int ctrl_rx_count;
|
||||
int bulk_tx_count;
|
||||
int bulk_rx_count;
|
||||
int bulk_aborted_count;
|
||||
uint64_t ctrl_tx_bytes;
|
||||
uint64_t ctrl_rx_bytes;
|
||||
uint64_t bulk_tx_bytes;
|
||||
uint64_t bulk_rx_bytes;
|
||||
} stats;
|
||||
} VCHIQ_SERVICE_T;
|
||||
|
||||
/* The quota information is outside VCHIQ_SERVICE_T so that it can be
|
||||
statically allocated, since for accounting reasons a service's slot
|
||||
usage is carried over between users of the same port number.
|
||||
*/
|
||||
typedef struct vchiq_service_quota_struct {
|
||||
unsigned short slot_quota;
|
||||
unsigned short slot_use_count;
|
||||
unsigned short message_quota;
|
||||
unsigned short message_use_count;
|
||||
struct semaphore quota_event;
|
||||
int previous_tx_index;
|
||||
} VCHIQ_SERVICE_QUOTA_T;
|
||||
|
||||
typedef struct vchiq_shared_state_struct {
|
||||
|
||||
/* A non-zero value here indicates that the content is valid. */
|
||||
int initialised;
|
||||
|
||||
/* The first and last (inclusive) slots allocated to the owner. */
|
||||
int slot_first;
|
||||
int slot_last;
|
||||
|
||||
/* The slot allocated to synchronous messages from the owner. */
|
||||
int slot_sync;
|
||||
|
||||
/* Signalling this event indicates that owner's slot handler thread
|
||||
** should run. */
|
||||
REMOTE_EVENT_T trigger;
|
||||
|
||||
/* Indicates the byte position within the stream where the next message
|
||||
** will be written. The least significant bits are an index into the
|
||||
** slot. The next bits are the index of the slot in slot_queue. */
|
||||
int tx_pos;
|
||||
|
||||
/* This event should be signalled when a slot is recycled. */
|
||||
REMOTE_EVENT_T recycle;
|
||||
|
||||
/* The slot_queue index where the next recycled slot will be written. */
|
||||
int slot_queue_recycle;
|
||||
|
||||
/* This event should be signalled when a synchronous message is sent. */
|
||||
REMOTE_EVENT_T sync_trigger;
|
||||
|
||||
/* This event should be signalled when a synchronous message has been
|
||||
** released. */
|
||||
REMOTE_EVENT_T sync_release;
|
||||
|
||||
/* A circular buffer of slot indexes. */
|
||||
int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE];
|
||||
|
||||
/* Debugging state */
|
||||
int debug[DEBUG_MAX];
|
||||
} __packed VCHIQ_SHARED_STATE_T;
|
||||
|
||||
typedef struct vchiq_slot_zero_struct {
|
||||
int magic;
|
||||
short version;
|
||||
short version_min;
|
||||
int slot_zero_size;
|
||||
int slot_size;
|
||||
int max_slots;
|
||||
int max_slots_per_side;
|
||||
int platform_data[2];
|
||||
VCHIQ_SHARED_STATE_T master;
|
||||
VCHIQ_SHARED_STATE_T slave;
|
||||
VCHIQ_SLOT_INFO_T slots[VCHIQ_MAX_SLOTS];
|
||||
} __packed VCHIQ_SLOT_ZERO_T;
|
||||
|
||||
struct vchiq_state_struct {
|
||||
int id;
|
||||
int initialised;
|
||||
VCHIQ_CONNSTATE_T conn_state;
|
||||
int is_master;
|
||||
|
||||
VCHIQ_SHARED_STATE_T *local;
|
||||
VCHIQ_SHARED_STATE_T *remote;
|
||||
VCHIQ_SLOT_T *slot_data;
|
||||
|
||||
unsigned short default_slot_quota;
|
||||
unsigned short default_message_quota;
|
||||
|
||||
/* Event indicating connect message received */
|
||||
struct semaphore connect;
|
||||
|
||||
/* Mutex protecting services */
|
||||
struct mutex mutex;
|
||||
VCHIQ_INSTANCE_T *instance;
|
||||
|
||||
/* Processes incoming messages */
|
||||
VCHIQ_THREAD_T slot_handler_thread;
|
||||
|
||||
/* Processes recycled slots */
|
||||
VCHIQ_THREAD_T recycle_thread;
|
||||
|
||||
/* Processes synchronous messages */
|
||||
VCHIQ_THREAD_T sync_thread;
|
||||
|
||||
/* Local implementation of the trigger remote event */
|
||||
struct semaphore trigger_event;
|
||||
|
||||
/* Local implementation of the recycle remote event */
|
||||
struct semaphore recycle_event;
|
||||
|
||||
/* Local implementation of the sync trigger remote event */
|
||||
struct semaphore sync_trigger_event;
|
||||
|
||||
/* Local implementation of the sync release remote event */
|
||||
struct semaphore sync_release_event;
|
||||
|
||||
char *tx_data;
|
||||
char *rx_data;
|
||||
VCHIQ_SLOT_INFO_T *rx_info;
|
||||
|
||||
struct mutex slot_mutex;
|
||||
|
||||
struct mutex recycle_mutex;
|
||||
|
||||
struct mutex sync_mutex;
|
||||
|
||||
struct mutex bulk_transfer_mutex;
|
||||
|
||||
/* Indicates the byte position within the stream from where the next
|
||||
** message will be read. The least significant bits are an index into
|
||||
** the slot.The next bits are the index of the slot in
|
||||
** remote->slot_queue. */
|
||||
int rx_pos;
|
||||
|
||||
/* A cached copy of local->tx_pos. Only write to local->tx_pos, and read
|
||||
from remote->tx_pos. */
|
||||
int local_tx_pos;
|
||||
|
||||
/* The slot_queue index of the slot to become available next. */
|
||||
int slot_queue_available;
|
||||
|
||||
/* A flag to indicate if any poll has been requested */
|
||||
int poll_needed;
|
||||
|
||||
/* Ths index of the previous slot used for data messages. */
|
||||
int previous_data_index;
|
||||
|
||||
/* The number of slots occupied by data messages. */
|
||||
unsigned short data_use_count;
|
||||
|
||||
/* The maximum number of slots to be occupied by data messages. */
|
||||
unsigned short data_quota;
|
||||
|
||||
/* An array of bit sets indicating which services must be polled. */
|
||||
atomic_t poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)];
|
||||
|
||||
/* The number of the first unused service */
|
||||
int unused_service;
|
||||
|
||||
/* Signalled when a free slot becomes available. */
|
||||
struct semaphore slot_available_event;
|
||||
|
||||
struct semaphore slot_remove_event;
|
||||
|
||||
/* Signalled when a free data slot becomes available. */
|
||||
struct semaphore data_quota_event;
|
||||
|
||||
/* Incremented when there are bulk transfers which cannot be processed
|
||||
* whilst paused and must be processed on resume */
|
||||
int deferred_bulks;
|
||||
|
||||
struct state_stats_struct {
|
||||
int slot_stalls;
|
||||
int data_stalls;
|
||||
int ctrl_tx_count;
|
||||
int ctrl_rx_count;
|
||||
int error_count;
|
||||
} stats;
|
||||
|
||||
VCHIQ_SERVICE_T * services[VCHIQ_MAX_SERVICES];
|
||||
VCHIQ_SERVICE_QUOTA_T service_quotas[VCHIQ_MAX_SERVICES];
|
||||
VCHIQ_SLOT_INFO_T slot_info[VCHIQ_MAX_SLOTS];
|
||||
|
||||
VCHIQ_PLATFORM_STATE_T platform_state;
|
||||
};
|
||||
|
||||
struct bulk_waiter {
|
||||
VCHIQ_BULK_T *bulk;
|
||||
struct semaphore event;
|
||||
int actual;
|
||||
};
|
||||
|
||||
extern spinlock_t bulk_waiter_spinlock;
|
||||
|
||||
extern int vchiq_core_log_level;
|
||||
extern int vchiq_core_msg_log_level;
|
||||
extern int vchiq_sync_log_level;
|
||||
|
||||
extern VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES];
|
||||
|
||||
extern const char *
|
||||
get_conn_state_name(VCHIQ_CONNSTATE_T conn_state);
|
||||
|
||||
extern VCHIQ_SLOT_ZERO_T *
|
||||
vchiq_init_slots(void *mem_base, int mem_size);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero,
|
||||
int is_master);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance);
|
||||
|
||||
extern VCHIQ_SERVICE_T *
|
||||
vchiq_add_service_internal(VCHIQ_STATE_T *state,
|
||||
const VCHIQ_SERVICE_PARAMS_T *params, int srvstate,
|
||||
VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd);
|
||||
|
||||
extern void
|
||||
vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern void
|
||||
vchiq_free_service_internal(VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_pause_internal(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_resume_internal(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
remote_event_pollall(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,
|
||||
VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata,
|
||||
VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir);
|
||||
|
||||
extern void
|
||||
vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern void
|
||||
vchiq_loud_error_header(void);
|
||||
|
||||
extern void
|
||||
vchiq_loud_error_footer(void);
|
||||
|
||||
extern void
|
||||
request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type);
|
||||
|
||||
static inline VCHIQ_SERVICE_T *
|
||||
handle_to_service(VCHIQ_SERVICE_HANDLE_T handle)
|
||||
{
|
||||
VCHIQ_STATE_T *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) &
|
||||
(VCHIQ_MAX_STATES - 1)];
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
return state->services[handle & (VCHIQ_MAX_SERVICES - 1)];
|
||||
}
|
||||
|
||||
extern VCHIQ_SERVICE_T *
|
||||
find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle);
|
||||
|
||||
extern VCHIQ_SERVICE_T *
|
||||
find_service_by_port(VCHIQ_STATE_T *state, int localport);
|
||||
|
||||
extern VCHIQ_SERVICE_T *
|
||||
find_service_for_instance(VCHIQ_INSTANCE_T instance,
|
||||
VCHIQ_SERVICE_HANDLE_T handle);
|
||||
|
||||
extern VCHIQ_SERVICE_T *
|
||||
next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance,
|
||||
int *pidx);
|
||||
|
||||
extern void
|
||||
lock_service(VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern void
|
||||
unlock_service(VCHIQ_SERVICE_T *service);
|
||||
|
||||
/* The following functions are called from vchiq_core, and external
|
||||
** implementations must be provided. */
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk,
|
||||
VCHI_MEM_HANDLE_T memhandle, void *offset, int size, int dir);
|
||||
|
||||
extern void
|
||||
vchiq_transfer_bulk(VCHIQ_BULK_T *bulk);
|
||||
|
||||
extern void
|
||||
vchiq_complete_bulk(VCHIQ_BULK_T *bulk);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_copy_from_user(void *dst, const void *src, int size);
|
||||
|
||||
extern void
|
||||
remote_event_signal(REMOTE_EVENT_T *event);
|
||||
|
||||
void
|
||||
vchiq_platform_check_suspend(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_platform_paused(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_platform_resume(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_platform_resumed(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_dump(void *dump_context, const char *str, int len);
|
||||
|
||||
extern void
|
||||
vchiq_dump_platform_state(void *dump_context);
|
||||
|
||||
extern void
|
||||
vchiq_dump_platform_instances(void *dump_context);
|
||||
|
||||
extern void
|
||||
vchiq_dump_platform_service_state(void *dump_context,
|
||||
VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_use_service_internal(VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_release_service_internal(VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern void
|
||||
vchiq_on_remote_use(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_on_remote_release(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_platform_init_state(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_check_service(VCHIQ_SERVICE_T *service);
|
||||
|
||||
extern void
|
||||
vchiq_on_remote_use_active(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_send_remote_use(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_send_remote_release(VCHIQ_STATE_T *state);
|
||||
|
||||
extern VCHIQ_STATUS_T
|
||||
vchiq_send_remote_use_active(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state,
|
||||
VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate);
|
||||
|
||||
extern void
|
||||
vchiq_platform_handle_timeout(VCHIQ_STATE_T *state);
|
||||
|
||||
extern void
|
||||
vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate);
|
||||
|
||||
|
||||
extern void
|
||||
vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem,
|
||||
size_t numBytes);
|
||||
|
||||
extern void
|
||||
vchiq_core_initialize(void);
|
||||
|
||||
#endif
|
188
sys/contrib/vchiq/interface/vchiq_arm/vchiq_if.h
Normal file
188
sys/contrib/vchiq/interface/vchiq_arm/vchiq_if.h
Normal file
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_IF_H
|
||||
#define VCHIQ_IF_H
|
||||
|
||||
#include "interface/vchi/vchi_mh.h"
|
||||
|
||||
#define VCHIQ_SERVICE_HANDLE_INVALID 0
|
||||
|
||||
#define VCHIQ_SLOT_SIZE 4096
|
||||
#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(VCHIQ_HEADER_T))
|
||||
#define VCHIQ_CHANNEL_SIZE VCHIQ_MAX_MSG_SIZE /* For backwards compatibility */
|
||||
|
||||
#define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \
|
||||
(((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3))
|
||||
#define VCHIQ_GET_SERVICE_USERDATA(service) vchiq_get_service_userdata(service)
|
||||
#define VCHIQ_GET_SERVICE_FOURCC(service) vchiq_get_service_fourcc(service)
|
||||
|
||||
typedef enum {
|
||||
VCHIQ_SERVICE_OPENED, /* service, -, - */
|
||||
VCHIQ_SERVICE_CLOSED, /* service, -, - */
|
||||
VCHIQ_MESSAGE_AVAILABLE, /* service, header, - */
|
||||
VCHIQ_BULK_TRANSMIT_DONE, /* service, -, bulk_userdata */
|
||||
VCHIQ_BULK_RECEIVE_DONE, /* service, -, bulk_userdata */
|
||||
VCHIQ_BULK_TRANSMIT_ABORTED, /* service, -, bulk_userdata */
|
||||
VCHIQ_BULK_RECEIVE_ABORTED /* service, -, bulk_userdata */
|
||||
} VCHIQ_REASON_T;
|
||||
|
||||
typedef enum {
|
||||
VCHIQ_ERROR = -1,
|
||||
VCHIQ_SUCCESS = 0,
|
||||
VCHIQ_RETRY = 1
|
||||
} VCHIQ_STATUS_T;
|
||||
|
||||
typedef enum {
|
||||
VCHIQ_BULK_MODE_CALLBACK,
|
||||
VCHIQ_BULK_MODE_BLOCKING,
|
||||
VCHIQ_BULK_MODE_NOCALLBACK,
|
||||
VCHIQ_BULK_MODE_WAITING /* Reserved for internal use */
|
||||
} VCHIQ_BULK_MODE_T;
|
||||
|
||||
typedef enum {
|
||||
VCHIQ_SERVICE_OPTION_AUTOCLOSE,
|
||||
VCHIQ_SERVICE_OPTION_SLOT_QUOTA,
|
||||
VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA,
|
||||
VCHIQ_SERVICE_OPTION_SYNCHRONOUS
|
||||
} VCHIQ_SERVICE_OPTION_T;
|
||||
|
||||
typedef struct vchiq_header_struct {
|
||||
/* The message identifier - opaque to applications. */
|
||||
int msgid;
|
||||
|
||||
/* Size of message data. */
|
||||
unsigned int size;
|
||||
|
||||
char data[0]; /* message */
|
||||
} VCHIQ_HEADER_T;
|
||||
|
||||
typedef struct {
|
||||
const void *data;
|
||||
unsigned int size;
|
||||
} VCHIQ_ELEMENT_T;
|
||||
|
||||
typedef unsigned int VCHIQ_SERVICE_HANDLE_T;
|
||||
|
||||
typedef VCHIQ_STATUS_T (*VCHIQ_CALLBACK_T)(VCHIQ_REASON_T, VCHIQ_HEADER_T *,
|
||||
VCHIQ_SERVICE_HANDLE_T, void *);
|
||||
|
||||
typedef struct vchiq_service_base_struct {
|
||||
int fourcc;
|
||||
VCHIQ_CALLBACK_T callback;
|
||||
void *userdata;
|
||||
} VCHIQ_SERVICE_BASE_T;
|
||||
|
||||
typedef struct vchiq_service_params_struct {
|
||||
int fourcc;
|
||||
VCHIQ_CALLBACK_T callback;
|
||||
void *userdata;
|
||||
short version; /* Increment for non-trivial changes */
|
||||
short version_min; /* Update for incompatible changes */
|
||||
} VCHIQ_SERVICE_PARAMS_T;
|
||||
|
||||
typedef struct vchiq_config_struct {
|
||||
unsigned int max_msg_size;
|
||||
unsigned int bulk_threshold; /* The message size above which it
|
||||
is better to use a bulk transfer
|
||||
(<= max_msg_size) */
|
||||
unsigned int max_outstanding_bulks;
|
||||
unsigned int max_services;
|
||||
short version; /* The version of VCHIQ */
|
||||
short version_min; /* The minimum compatible version of VCHIQ */
|
||||
} VCHIQ_CONFIG_T;
|
||||
|
||||
typedef struct vchiq_instance_struct *VCHIQ_INSTANCE_T;
|
||||
typedef void (*VCHIQ_REMOTE_USE_CALLBACK_T)(void *cb_arg);
|
||||
|
||||
extern VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *pinstance);
|
||||
extern VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance);
|
||||
extern VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance);
|
||||
extern VCHIQ_STATUS_T vchiq_add_service(VCHIQ_INSTANCE_T instance,
|
||||
const VCHIQ_SERVICE_PARAMS_T *params,
|
||||
VCHIQ_SERVICE_HANDLE_T *pservice);
|
||||
extern VCHIQ_STATUS_T vchiq_open_service(VCHIQ_INSTANCE_T instance,
|
||||
const VCHIQ_SERVICE_PARAMS_T *params,
|
||||
VCHIQ_SERVICE_HANDLE_T *pservice);
|
||||
extern VCHIQ_STATUS_T vchiq_close_service(VCHIQ_SERVICE_HANDLE_T service);
|
||||
extern VCHIQ_STATUS_T vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T service);
|
||||
extern VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T service);
|
||||
extern VCHIQ_STATUS_T vchiq_use_service_no_resume(
|
||||
VCHIQ_SERVICE_HANDLE_T service);
|
||||
extern VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T service);
|
||||
|
||||
extern VCHIQ_STATUS_T vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T service,
|
||||
const VCHIQ_ELEMENT_T *elements, unsigned int count);
|
||||
extern void vchiq_release_message(VCHIQ_SERVICE_HANDLE_T service,
|
||||
VCHIQ_HEADER_T *header);
|
||||
extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service,
|
||||
void *data, unsigned int size, void *userdata);
|
||||
extern VCHIQ_STATUS_T vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T service,
|
||||
void *data, unsigned int size, void *userdata);
|
||||
extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit_handle(
|
||||
VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle,
|
||||
const void *offset, unsigned int size, void *userdata);
|
||||
extern VCHIQ_STATUS_T vchiq_queue_bulk_receive_handle(
|
||||
VCHIQ_SERVICE_HANDLE_T service, VCHI_MEM_HANDLE_T handle,
|
||||
void *offset, unsigned int size, void *userdata);
|
||||
extern VCHIQ_STATUS_T vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service,
|
||||
void *data, unsigned int size, void *userdata,
|
||||
VCHIQ_BULK_MODE_T mode);
|
||||
extern VCHIQ_STATUS_T vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T service,
|
||||
void *data, unsigned int size, void *userdata,
|
||||
VCHIQ_BULK_MODE_T mode);
|
||||
extern VCHIQ_STATUS_T vchiq_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T service,
|
||||
VCHI_MEM_HANDLE_T handle, const void *offset, unsigned int size,
|
||||
void *userdata, VCHIQ_BULK_MODE_T mode);
|
||||
extern VCHIQ_STATUS_T vchiq_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T service,
|
||||
VCHI_MEM_HANDLE_T handle, void *offset, unsigned int size,
|
||||
void *userdata, VCHIQ_BULK_MODE_T mode);
|
||||
extern int vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T service);
|
||||
extern void *vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T service);
|
||||
extern int vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T service);
|
||||
extern VCHIQ_STATUS_T vchiq_get_config(VCHIQ_INSTANCE_T instance,
|
||||
int config_size, VCHIQ_CONFIG_T *pconfig);
|
||||
extern VCHIQ_STATUS_T vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T service,
|
||||
VCHIQ_SERVICE_OPTION_T option, int value);
|
||||
|
||||
extern VCHIQ_STATUS_T vchiq_remote_use(VCHIQ_INSTANCE_T instance,
|
||||
VCHIQ_REMOTE_USE_CALLBACK_T callback, void *cb_arg);
|
||||
extern VCHIQ_STATUS_T vchiq_remote_release(VCHIQ_INSTANCE_T instance);
|
||||
|
||||
extern VCHIQ_STATUS_T vchiq_dump_phys_mem(VCHIQ_SERVICE_HANDLE_T service,
|
||||
void *ptr, size_t num_bytes);
|
||||
|
||||
extern VCHIQ_STATUS_T vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle,
|
||||
short *peer_version);
|
||||
|
||||
#endif /* VCHIQ_IF_H */
|
128
sys/contrib/vchiq/interface/vchiq_arm/vchiq_ioctl.h
Normal file
128
sys/contrib/vchiq/interface/vchiq_arm/vchiq_ioctl.h
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_IOCTLS_H
|
||||
#define VCHIQ_IOCTLS_H
|
||||
|
||||
#include "vchiq_if.h"
|
||||
|
||||
#define VCHIQ_IOC_MAGIC 0xc4
|
||||
#define VCHIQ_INVALID_HANDLE (~0)
|
||||
|
||||
typedef struct {
|
||||
VCHIQ_SERVICE_PARAMS_T params;
|
||||
int is_open;
|
||||
int is_vchi;
|
||||
unsigned int handle; /* OUT */
|
||||
} VCHIQ_CREATE_SERVICE_T;
|
||||
|
||||
typedef struct {
|
||||
unsigned int handle;
|
||||
unsigned int count;
|
||||
const VCHIQ_ELEMENT_T *elements;
|
||||
} VCHIQ_QUEUE_MESSAGE_T;
|
||||
|
||||
typedef struct {
|
||||
unsigned int handle;
|
||||
void *data;
|
||||
unsigned int size;
|
||||
void *userdata;
|
||||
VCHIQ_BULK_MODE_T mode;
|
||||
} VCHIQ_QUEUE_BULK_TRANSFER_T;
|
||||
|
||||
typedef struct {
|
||||
VCHIQ_REASON_T reason;
|
||||
VCHIQ_HEADER_T *header;
|
||||
void *service_userdata;
|
||||
void *bulk_userdata;
|
||||
} VCHIQ_COMPLETION_DATA_T;
|
||||
|
||||
typedef struct {
|
||||
unsigned int count;
|
||||
VCHIQ_COMPLETION_DATA_T *buf;
|
||||
unsigned int msgbufsize;
|
||||
unsigned int msgbufcount; /* IN/OUT */
|
||||
void **msgbufs;
|
||||
} VCHIQ_AWAIT_COMPLETION_T;
|
||||
|
||||
typedef struct {
|
||||
unsigned int handle;
|
||||
int blocking;
|
||||
unsigned int bufsize;
|
||||
void *buf;
|
||||
} VCHIQ_DEQUEUE_MESSAGE_T;
|
||||
|
||||
typedef struct {
|
||||
unsigned int config_size;
|
||||
VCHIQ_CONFIG_T *pconfig;
|
||||
} VCHIQ_GET_CONFIG_T;
|
||||
|
||||
typedef struct {
|
||||
unsigned int handle;
|
||||
VCHIQ_SERVICE_OPTION_T option;
|
||||
int value;
|
||||
} VCHIQ_SET_SERVICE_OPTION_T;
|
||||
|
||||
typedef struct {
|
||||
void *virt_addr;
|
||||
size_t num_bytes;
|
||||
} VCHIQ_DUMP_MEM_T;
|
||||
|
||||
#define VCHIQ_IOC_CONNECT _IO(VCHIQ_IOC_MAGIC, 0)
|
||||
#define VCHIQ_IOC_SHUTDOWN _IO(VCHIQ_IOC_MAGIC, 1)
|
||||
#define VCHIQ_IOC_CREATE_SERVICE \
|
||||
_IOWR(VCHIQ_IOC_MAGIC, 2, VCHIQ_CREATE_SERVICE_T)
|
||||
#define VCHIQ_IOC_REMOVE_SERVICE _IO(VCHIQ_IOC_MAGIC, 3)
|
||||
#define VCHIQ_IOC_QUEUE_MESSAGE \
|
||||
_IOW(VCHIQ_IOC_MAGIC, 4, VCHIQ_QUEUE_MESSAGE_T)
|
||||
#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT \
|
||||
_IOWR(VCHIQ_IOC_MAGIC, 5, VCHIQ_QUEUE_BULK_TRANSFER_T)
|
||||
#define VCHIQ_IOC_QUEUE_BULK_RECEIVE \
|
||||
_IOWR(VCHIQ_IOC_MAGIC, 6, VCHIQ_QUEUE_BULK_TRANSFER_T)
|
||||
#define VCHIQ_IOC_AWAIT_COMPLETION \
|
||||
_IOWR(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION_T)
|
||||
#define VCHIQ_IOC_DEQUEUE_MESSAGE \
|
||||
_IOWR(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE_T)
|
||||
#define VCHIQ_IOC_GET_CLIENT_ID _IO(VCHIQ_IOC_MAGIC, 9)
|
||||
#define VCHIQ_IOC_GET_CONFIG \
|
||||
_IOWR(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG_T)
|
||||
#define VCHIQ_IOC_CLOSE_SERVICE _IO(VCHIQ_IOC_MAGIC, 11)
|
||||
#define VCHIQ_IOC_USE_SERVICE _IO(VCHIQ_IOC_MAGIC, 12)
|
||||
#define VCHIQ_IOC_RELEASE_SERVICE _IO(VCHIQ_IOC_MAGIC, 13)
|
||||
#define VCHIQ_IOC_SET_SERVICE_OPTION \
|
||||
_IOW(VCHIQ_IOC_MAGIC, 14, VCHIQ_SET_SERVICE_OPTION_T)
|
||||
#define VCHIQ_IOC_DUMP_PHYS_MEM \
|
||||
_IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM_T)
|
||||
#define VCHIQ_IOC_MAX 15
|
||||
|
||||
#endif
|
461
sys/contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c
Normal file
461
sys/contrib/vchiq/interface/vchiq_arm/vchiq_kern_lib.c
Normal file
@ -0,0 +1,461 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 Files ---------------------------------------------------- */
|
||||
|
||||
#include "vchiq_core.h"
|
||||
#include "vchiq_arm.h"
|
||||
|
||||
/* ---- Public Variables ------------------------------------------------- */
|
||||
|
||||
/* ---- Private Constants and Types -------------------------------------- */
|
||||
|
||||
struct bulk_waiter_node {
|
||||
struct bulk_waiter bulk_waiter;
|
||||
int pid;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct vchiq_instance_struct {
|
||||
VCHIQ_STATE_T *state;
|
||||
|
||||
int connected;
|
||||
|
||||
struct list_head bulk_waiter_list;
|
||||
struct mutex bulk_waiter_list_mutex;
|
||||
};
|
||||
|
||||
static VCHIQ_STATUS_T
|
||||
vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
|
||||
unsigned int size, VCHIQ_BULK_DIR_T dir);
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* vchiq_initialise
|
||||
*
|
||||
***************************************************************************/
|
||||
#define VCHIQ_INIT_RETRIES 10
|
||||
VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instanceOut)
|
||||
{
|
||||
VCHIQ_STATUS_T status = VCHIQ_ERROR;
|
||||
VCHIQ_STATE_T *state;
|
||||
VCHIQ_INSTANCE_T instance = NULL;
|
||||
int i;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level, "%s called", __func__);
|
||||
|
||||
/* VideoCore may not be ready due to boot up timing.
|
||||
It may never be ready if kernel and firmware are mismatched, so don't block forever. */
|
||||
for (i=0; i<VCHIQ_INIT_RETRIES; i++) {
|
||||
state = vchiq_get_state();
|
||||
if (state)
|
||||
break;
|
||||
udelay(500);
|
||||
}
|
||||
if (i==VCHIQ_INIT_RETRIES) {
|
||||
vchiq_log_error(vchiq_core_log_level,
|
||||
"%s: videocore not initialized\n", __func__);
|
||||
goto failed;
|
||||
} else if (i>0) {
|
||||
vchiq_log_warning(vchiq_core_log_level,
|
||||
"%s: videocore initialized after %d retries\n", __func__, i);
|
||||
}
|
||||
|
||||
instance = kzalloc(sizeof(*instance), GFP_KERNEL);
|
||||
if (!instance) {
|
||||
vchiq_log_error(vchiq_core_log_level,
|
||||
"%s: error allocating vchiq instance\n", __func__);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
instance->connected = 0;
|
||||
instance->state = state;
|
||||
lmutex_init(&instance->bulk_waiter_list_mutex);
|
||||
INIT_LIST_HEAD(&instance->bulk_waiter_list);
|
||||
|
||||
*instanceOut = instance;
|
||||
|
||||
status = VCHIQ_SUCCESS;
|
||||
|
||||
failed:
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p): returning %d", __func__, instance, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_initialise);
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* vchiq_shutdown
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance)
|
||||
{
|
||||
VCHIQ_STATUS_T status;
|
||||
VCHIQ_STATE_T *state = instance->state;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p) called", __func__, instance);
|
||||
|
||||
if (lmutex_lock_interruptible(&state->mutex) != 0)
|
||||
return VCHIQ_RETRY;
|
||||
|
||||
/* Remove all services */
|
||||
status = vchiq_shutdown_internal(state, instance);
|
||||
|
||||
lmutex_unlock(&state->mutex);
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p): returning %d", __func__, instance, status);
|
||||
|
||||
if (status == VCHIQ_SUCCESS) {
|
||||
struct list_head *pos, *next;
|
||||
list_for_each_safe(pos, next,
|
||||
&instance->bulk_waiter_list) {
|
||||
struct bulk_waiter_node *waiter;
|
||||
waiter = list_entry(pos,
|
||||
struct bulk_waiter_node,
|
||||
list);
|
||||
list_del(pos);
|
||||
vchiq_log_info(vchiq_arm_log_level,
|
||||
"bulk_waiter - cleaned up %x "
|
||||
"for pid %d",
|
||||
(unsigned int)waiter, waiter->pid);
|
||||
_sema_destroy(&waiter->bulk_waiter.event);
|
||||
|
||||
kfree(waiter);
|
||||
}
|
||||
|
||||
lmutex_destroy(&instance->bulk_waiter_list_mutex);
|
||||
|
||||
kfree(instance);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_shutdown);
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* vchiq_is_connected
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
static int vchiq_is_connected(VCHIQ_INSTANCE_T instance)
|
||||
{
|
||||
return instance->connected;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* vchiq_connect
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance)
|
||||
{
|
||||
VCHIQ_STATUS_T status;
|
||||
VCHIQ_STATE_T *state = instance->state;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p) called", __func__, instance);
|
||||
|
||||
if (lmutex_lock_interruptible(&state->mutex) != 0) {
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s: call to lmutex_lock failed", __func__);
|
||||
status = VCHIQ_RETRY;
|
||||
goto failed;
|
||||
}
|
||||
status = vchiq_connect_internal(state, instance);
|
||||
|
||||
if (status == VCHIQ_SUCCESS)
|
||||
instance->connected = 1;
|
||||
|
||||
lmutex_unlock(&state->mutex);
|
||||
|
||||
failed:
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p): returning %d", __func__, instance, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_connect);
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* vchiq_add_service
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
VCHIQ_STATUS_T vchiq_add_service(
|
||||
VCHIQ_INSTANCE_T instance,
|
||||
const VCHIQ_SERVICE_PARAMS_T *params,
|
||||
VCHIQ_SERVICE_HANDLE_T *phandle)
|
||||
{
|
||||
VCHIQ_STATUS_T status;
|
||||
VCHIQ_STATE_T *state = instance->state;
|
||||
VCHIQ_SERVICE_T *service = NULL;
|
||||
int srvstate;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p) called", __func__, instance);
|
||||
|
||||
*phandle = VCHIQ_SERVICE_HANDLE_INVALID;
|
||||
|
||||
srvstate = vchiq_is_connected(instance)
|
||||
? VCHIQ_SRVSTATE_LISTENING
|
||||
: VCHIQ_SRVSTATE_HIDDEN;
|
||||
|
||||
service = vchiq_add_service_internal(
|
||||
state,
|
||||
params,
|
||||
srvstate,
|
||||
instance,
|
||||
NULL);
|
||||
|
||||
if (service) {
|
||||
*phandle = service->handle;
|
||||
status = VCHIQ_SUCCESS;
|
||||
} else
|
||||
status = VCHIQ_ERROR;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p): returning %d", __func__, instance, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_add_service);
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* vchiq_open_service
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
VCHIQ_STATUS_T vchiq_open_service(
|
||||
VCHIQ_INSTANCE_T instance,
|
||||
const VCHIQ_SERVICE_PARAMS_T *params,
|
||||
VCHIQ_SERVICE_HANDLE_T *phandle)
|
||||
{
|
||||
VCHIQ_STATUS_T status = VCHIQ_ERROR;
|
||||
VCHIQ_STATE_T *state = instance->state;
|
||||
VCHIQ_SERVICE_T *service = NULL;
|
||||
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p) called", __func__, instance);
|
||||
|
||||
*phandle = VCHIQ_SERVICE_HANDLE_INVALID;
|
||||
|
||||
if (!vchiq_is_connected(instance))
|
||||
goto failed;
|
||||
|
||||
service = vchiq_add_service_internal(state,
|
||||
params,
|
||||
VCHIQ_SRVSTATE_OPENING,
|
||||
instance,
|
||||
NULL);
|
||||
|
||||
if (service) {
|
||||
*phandle = service->handle;
|
||||
status = vchiq_open_service_internal(service,
|
||||
(uintptr_t)current);
|
||||
if (status != VCHIQ_SUCCESS) {
|
||||
vchiq_remove_service(service->handle);
|
||||
*phandle = VCHIQ_SERVICE_HANDLE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
failed:
|
||||
vchiq_log_trace(vchiq_core_log_level,
|
||||
"%s(%p): returning %d", __func__, instance, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_open_service);
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle,
|
||||
void *data, unsigned int size, void *userdata)
|
||||
{
|
||||
return vchiq_bulk_transfer(handle,
|
||||
VCHI_MEM_HANDLE_INVALID, data, size, userdata,
|
||||
VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_TRANSMIT);
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_queue_bulk_transmit);
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_queue_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data,
|
||||
unsigned int size, void *userdata)
|
||||
{
|
||||
return vchiq_bulk_transfer(handle,
|
||||
VCHI_MEM_HANDLE_INVALID, data, size, userdata,
|
||||
VCHIQ_BULK_MODE_CALLBACK, VCHIQ_BULK_RECEIVE);
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_queue_bulk_receive);
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, void *data,
|
||||
unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode)
|
||||
{
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
switch (mode) {
|
||||
case VCHIQ_BULK_MODE_NOCALLBACK:
|
||||
case VCHIQ_BULK_MODE_CALLBACK:
|
||||
status = vchiq_bulk_transfer(handle,
|
||||
VCHI_MEM_HANDLE_INVALID, data, size, userdata,
|
||||
mode, VCHIQ_BULK_TRANSMIT);
|
||||
break;
|
||||
case VCHIQ_BULK_MODE_BLOCKING:
|
||||
status = vchiq_blocking_bulk_transfer(handle,
|
||||
data, size, VCHIQ_BULK_TRANSMIT);
|
||||
break;
|
||||
default:
|
||||
return VCHIQ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_bulk_transmit);
|
||||
|
||||
VCHIQ_STATUS_T
|
||||
vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data,
|
||||
unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode)
|
||||
{
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
switch (mode) {
|
||||
case VCHIQ_BULK_MODE_NOCALLBACK:
|
||||
case VCHIQ_BULK_MODE_CALLBACK:
|
||||
status = vchiq_bulk_transfer(handle,
|
||||
VCHI_MEM_HANDLE_INVALID, data, size, userdata,
|
||||
mode, VCHIQ_BULK_RECEIVE);
|
||||
break;
|
||||
case VCHIQ_BULK_MODE_BLOCKING:
|
||||
status = vchiq_blocking_bulk_transfer(handle,
|
||||
data, size, VCHIQ_BULK_RECEIVE);
|
||||
break;
|
||||
default:
|
||||
return VCHIQ_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(vchiq_bulk_receive);
|
||||
|
||||
static VCHIQ_STATUS_T
|
||||
vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data,
|
||||
unsigned int size, VCHIQ_BULK_DIR_T dir)
|
||||
{
|
||||
VCHIQ_INSTANCE_T instance;
|
||||
VCHIQ_SERVICE_T *service;
|
||||
VCHIQ_STATUS_T status;
|
||||
struct bulk_waiter_node *waiter = NULL;
|
||||
struct list_head *pos;
|
||||
|
||||
service = find_service_by_handle(handle);
|
||||
if (!service)
|
||||
return VCHIQ_ERROR;
|
||||
|
||||
instance = service->instance;
|
||||
|
||||
unlock_service(service);
|
||||
|
||||
lmutex_lock(&instance->bulk_waiter_list_mutex);
|
||||
list_for_each(pos, &instance->bulk_waiter_list) {
|
||||
if (list_entry(pos, struct bulk_waiter_node,
|
||||
list)->pid == current->p_pid) {
|
||||
waiter = list_entry(pos,
|
||||
struct bulk_waiter_node,
|
||||
list);
|
||||
list_del(pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
lmutex_unlock(&instance->bulk_waiter_list_mutex);
|
||||
|
||||
if (waiter) {
|
||||
VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk;
|
||||
if (bulk) {
|
||||
/* This thread has an outstanding bulk transfer. */
|
||||
if ((bulk->data != data) ||
|
||||
(bulk->size != size)) {
|
||||
/* This is not a retry of the previous one.
|
||||
** Cancel the signal when the transfer
|
||||
** completes. */
|
||||
spin_lock(&bulk_waiter_spinlock);
|
||||
bulk->userdata = NULL;
|
||||
spin_unlock(&bulk_waiter_spinlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!waiter) {
|
||||
waiter = kzalloc(sizeof(struct bulk_waiter_node), GFP_KERNEL);
|
||||
if (!waiter) {
|
||||
vchiq_log_error(vchiq_core_log_level,
|
||||
"%s - out of memory", __func__);
|
||||
return VCHIQ_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
status = vchiq_bulk_transfer(handle, VCHI_MEM_HANDLE_INVALID,
|
||||
data, size, &waiter->bulk_waiter, VCHIQ_BULK_MODE_BLOCKING,
|
||||
dir);
|
||||
if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) ||
|
||||
!waiter->bulk_waiter.bulk) {
|
||||
VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk;
|
||||
if (bulk) {
|
||||
/* Cancel the signal when the transfer
|
||||
** completes. */
|
||||
spin_lock(&bulk_waiter_spinlock);
|
||||
bulk->userdata = NULL;
|
||||
spin_unlock(&bulk_waiter_spinlock);
|
||||
}
|
||||
_sema_destroy(&waiter->bulk_waiter.event);
|
||||
|
||||
kfree(waiter);
|
||||
} else {
|
||||
waiter->pid = current->p_pid;
|
||||
lmutex_lock(&instance->bulk_waiter_list_mutex);
|
||||
list_add(&waiter->list, &instance->bulk_waiter_list);
|
||||
lmutex_unlock(&instance->bulk_waiter_list_mutex);
|
||||
vchiq_log_info(vchiq_arm_log_level,
|
||||
"saved bulk_waiter %x for pid %d",
|
||||
(unsigned int)waiter, current->p_pid);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
217
sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
Normal file
217
sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
Normal file
@ -0,0 +1,217 @@
|
||||
/*-
|
||||
* Copyright (c) 2012-2015 Oleksandr Tymoshenko <gonzo@freebsd.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/watchdog.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/intr.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 <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
|
||||
#include "vchiq_arm.h"
|
||||
#include "vchiq_2835.h"
|
||||
|
||||
#define VCHIQ_LOCK do { \
|
||||
mtx_lock(&bcm_vchiq_sc->lock); \
|
||||
} while(0)
|
||||
|
||||
#define VCHIQ_UNLOCK do { \
|
||||
mtx_unlock(&bcm_vchiq_sc->lock); \
|
||||
} while(0)
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dprintf(fmt, args...) printf(fmt, ##args)
|
||||
#else
|
||||
#define dprintf(fmt, args...)
|
||||
#endif
|
||||
|
||||
struct bcm_vchiq_softc {
|
||||
struct mtx lock;
|
||||
struct resource * mem_res;
|
||||
struct resource * irq_res;
|
||||
void* intr_hl;
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
};
|
||||
|
||||
static struct bcm_vchiq_softc *bcm_vchiq_sc = NULL;
|
||||
|
||||
#define vchiq_read_4(reg) \
|
||||
bus_space_read_4(bcm_vchiq_sc->bst, bcm_vchiq_sc->bsh, reg)
|
||||
#define vchiq_write_4(reg, val) \
|
||||
bus_space_write_4(bcm_vchiq_sc->bst, bcm_vchiq_sc->bsh, reg, val)
|
||||
|
||||
/*
|
||||
* Extern functions */
|
||||
void vchiq_exit(void);
|
||||
int vchiq_init(void);
|
||||
|
||||
extern VCHIQ_STATE_T g_state;
|
||||
|
||||
static void
|
||||
bcm_vchiq_intr(void *arg)
|
||||
{
|
||||
VCHIQ_STATE_T *state = &g_state;
|
||||
unsigned int status;
|
||||
|
||||
/* Read (and clear) the doorbell */
|
||||
status = vchiq_read_4(0x40);
|
||||
|
||||
if (status & 0x4) { /* Was the doorbell rung? */
|
||||
remote_event_pollall(state);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
remote_event_signal(REMOTE_EVENT_T *event)
|
||||
{
|
||||
event->fired = 1;
|
||||
|
||||
/* The test on the next line also ensures the write on the previous line
|
||||
has completed */
|
||||
if (event->armed) {
|
||||
/* trigger vc interrupt */
|
||||
__asm __volatile ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory");
|
||||
vchiq_write_4(0x48, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_vchiq_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (ofw_bus_is_compatible(dev, "broadcom,bcm2835-vchiq")) {
|
||||
device_set_desc(dev, "BCM2835 VCHIQ");
|
||||
return(BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_vchiq_attach(device_t dev)
|
||||
{
|
||||
struct bcm_vchiq_softc *sc = device_get_softc(dev);
|
||||
int rid = 0;
|
||||
|
||||
if (bcm_vchiq_sc != NULL)
|
||||
return (EINVAL);
|
||||
|
||||
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
|
||||
if (sc->mem_res == NULL) {
|
||||
device_printf(dev, "could not allocate memory resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->bst = rman_get_bustag(sc->mem_res);
|
||||
sc->bsh = rman_get_bushandle(sc->mem_res);
|
||||
|
||||
rid = 0;
|
||||
sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
|
||||
if (sc->irq_res == NULL) {
|
||||
device_printf(dev, "could not allocate interrupt resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
vchiq_core_initialize();
|
||||
|
||||
/* Setup and enable the timer */
|
||||
if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC,
|
||||
NULL, bcm_vchiq_intr, sc,
|
||||
&sc->intr_hl) != 0) {
|
||||
bus_release_resource(dev, SYS_RES_IRQ, rid,
|
||||
sc->irq_res);
|
||||
device_printf(dev, "Unable to setup the clock irq handler.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
mtx_init(&sc->lock, "vchiq", MTX_DEF, 0);
|
||||
bcm_vchiq_sc = sc;
|
||||
|
||||
vchiq_init();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bcm_vchiq_detach(device_t dev)
|
||||
{
|
||||
struct bcm_vchiq_softc *sc = device_get_softc(dev);
|
||||
|
||||
vchiq_exit();
|
||||
|
||||
if (sc->intr_hl)
|
||||
bus_teardown_intr(dev, sc->irq_res, sc->intr_hl);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0,
|
||||
sc->irq_res);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, 0,
|
||||
sc->mem_res);
|
||||
|
||||
mtx_destroy(&sc->lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static device_method_t bcm_vchiq_methods[] = {
|
||||
DEVMETHOD(device_probe, bcm_vchiq_probe),
|
||||
DEVMETHOD(device_attach, bcm_vchiq_attach),
|
||||
DEVMETHOD(device_detach, bcm_vchiq_detach),
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_add_child, bus_generic_add_child),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t bcm_vchiq_driver = {
|
||||
"vchiq",
|
||||
bcm_vchiq_methods,
|
||||
sizeof(struct bcm_vchiq_softc),
|
||||
};
|
||||
|
||||
static devclass_t bcm_vchiq_devclass;
|
||||
|
||||
DRIVER_MODULE(vchiq, simplebus, bcm_vchiq_driver, bcm_vchiq_devclass, 0, 0);
|
||||
MODULE_VERSION(vchiq, 1);
|
71
sys/contrib/vchiq/interface/vchiq_arm/vchiq_memdrv.h
Normal file
71
sys/contrib/vchiq/interface/vchiq_arm/vchiq_memdrv.h
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_MEMDRV_H
|
||||
#define VCHIQ_MEMDRV_H
|
||||
|
||||
/* ---- Include Files ----------------------------------------------------- */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include "vchiq_if.h"
|
||||
|
||||
/* ---- Constants and Types ---------------------------------------------- */
|
||||
|
||||
typedef struct {
|
||||
void *armSharedMemVirt;
|
||||
dma_addr_t armSharedMemPhys;
|
||||
size_t armSharedMemSize;
|
||||
|
||||
void *vcSharedMemVirt;
|
||||
dma_addr_t vcSharedMemPhys;
|
||||
size_t vcSharedMemSize;
|
||||
} VCHIQ_SHARED_MEM_INFO_T;
|
||||
|
||||
/* ---- Variable Externs ------------------------------------------------- */
|
||||
|
||||
/* ---- Function Prototypes ---------------------------------------------- */
|
||||
|
||||
void vchiq_get_shared_mem_info(VCHIQ_SHARED_MEM_INFO_T *info);
|
||||
|
||||
VCHIQ_STATUS_T vchiq_memdrv_initialise(void);
|
||||
|
||||
VCHIQ_STATUS_T vchiq_userdrv_create_instance(
|
||||
const VCHIQ_PLATFORM_DATA_T * platform_data);
|
||||
|
||||
VCHIQ_STATUS_T vchiq_userdrv_suspend(
|
||||
const VCHIQ_PLATFORM_DATA_T * platform_data);
|
||||
|
||||
VCHIQ_STATUS_T vchiq_userdrv_resume(
|
||||
const VCHIQ_PLATFORM_DATA_T * platform_data);
|
||||
|
||||
#endif
|
59
sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h
Normal file
59
sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_PAGELIST_H
|
||||
#define VCHIQ_PAGELIST_H
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 4096
|
||||
#endif
|
||||
#undef CACHE_LINE_SIZE
|
||||
#define CACHE_LINE_SIZE 32
|
||||
#define PAGELIST_WRITE 0
|
||||
#define PAGELIST_READ 1
|
||||
#define PAGELIST_READ_WITH_FRAGMENTS 2
|
||||
|
||||
typedef struct pagelist_struct {
|
||||
unsigned long length;
|
||||
unsigned short type;
|
||||
unsigned short offset;
|
||||
unsigned long addrs[1]; /* N.B. 12 LSBs hold the number of following
|
||||
pages at consecutive addresses. */
|
||||
} PAGELIST_T;
|
||||
|
||||
typedef struct fragments_struct {
|
||||
char headbuf[CACHE_LINE_SIZE];
|
||||
char tailbuf[CACHE_LINE_SIZE];
|
||||
} FRAGMENTS_T;
|
||||
|
||||
#endif /* VCHIQ_PAGELIST_H */
|
240
sys/contrib/vchiq/interface/vchiq_arm/vchiq_proc.c
Normal file
240
sys/contrib/vchiq/interface/vchiq_arm/vchiq_proc.c
Normal file
@ -0,0 +1,240 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <linux/proc_fs.h>
|
||||
#include "vchiq_core.h"
|
||||
#include "vchiq_arm.h"
|
||||
|
||||
struct vchiq_proc_info {
|
||||
/* Global 'vc' proc entry used by all instances */
|
||||
struct proc_dir_entry *vc_cfg_dir;
|
||||
|
||||
/* one entry per client process */
|
||||
struct proc_dir_entry *clients;
|
||||
|
||||
/* log categories */
|
||||
struct proc_dir_entry *log_categories;
|
||||
};
|
||||
|
||||
static struct vchiq_proc_info proc_info;
|
||||
|
||||
struct proc_dir_entry *vchiq_proc_top(void)
|
||||
{
|
||||
BUG_ON(proc_info.vc_cfg_dir == NULL);
|
||||
return proc_info.vc_cfg_dir;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* log category entries
|
||||
*
|
||||
***************************************************************************/
|
||||
#define PROC_WRITE_BUF_SIZE 256
|
||||
|
||||
#define VCHIQ_LOG_ERROR_STR "error"
|
||||
#define VCHIQ_LOG_WARNING_STR "warning"
|
||||
#define VCHIQ_LOG_INFO_STR "info"
|
||||
#define VCHIQ_LOG_TRACE_STR "trace"
|
||||
|
||||
static int log_cfg_read(char *buffer,
|
||||
char **start,
|
||||
off_t off,
|
||||
int count,
|
||||
int *eof,
|
||||
void *data)
|
||||
{
|
||||
int len = 0;
|
||||
char *log_value = NULL;
|
||||
|
||||
switch (*((int *)data)) {
|
||||
case VCHIQ_LOG_ERROR:
|
||||
log_value = VCHIQ_LOG_ERROR_STR;
|
||||
break;
|
||||
case VCHIQ_LOG_WARNING:
|
||||
log_value = VCHIQ_LOG_WARNING_STR;
|
||||
break;
|
||||
case VCHIQ_LOG_INFO:
|
||||
log_value = VCHIQ_LOG_INFO_STR;
|
||||
break;
|
||||
case VCHIQ_LOG_TRACE:
|
||||
log_value = VCHIQ_LOG_TRACE_STR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
len += snprintf(buffer + len, count - len,
|
||||
"%s\n",
|
||||
log_value ? log_value : "(null)");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int log_cfg_write(struct file *file,
|
||||
const char __user *buffer,
|
||||
unsigned long count,
|
||||
void *data)
|
||||
{
|
||||
int *log_module = data;
|
||||
char kbuf[PROC_WRITE_BUF_SIZE + 1];
|
||||
|
||||
(void)file;
|
||||
|
||||
memset(kbuf, 0, PROC_WRITE_BUF_SIZE + 1);
|
||||
if (count >= PROC_WRITE_BUF_SIZE)
|
||||
count = PROC_WRITE_BUF_SIZE;
|
||||
|
||||
if (copy_from_user(kbuf,
|
||||
buffer,
|
||||
count) != 0)
|
||||
return -EFAULT;
|
||||
kbuf[count - 1] = 0;
|
||||
|
||||
if (strncmp("error", kbuf, strlen("error")) == 0)
|
||||
*log_module = VCHIQ_LOG_ERROR;
|
||||
else if (strncmp("warning", kbuf, strlen("warning")) == 0)
|
||||
*log_module = VCHIQ_LOG_WARNING;
|
||||
else if (strncmp("info", kbuf, strlen("info")) == 0)
|
||||
*log_module = VCHIQ_LOG_INFO;
|
||||
else if (strncmp("trace", kbuf, strlen("trace")) == 0)
|
||||
*log_module = VCHIQ_LOG_TRACE;
|
||||
else
|
||||
*log_module = VCHIQ_LOG_DEFAULT;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Log category proc entries */
|
||||
struct vchiq_proc_log_entry {
|
||||
const char *name;
|
||||
int *plevel;
|
||||
struct proc_dir_entry *dir;
|
||||
};
|
||||
|
||||
static struct vchiq_proc_log_entry vchiq_proc_log_entries[] = {
|
||||
{ "core", &vchiq_core_log_level },
|
||||
{ "msg", &vchiq_core_msg_log_level },
|
||||
{ "sync", &vchiq_sync_log_level },
|
||||
{ "susp", &vchiq_susp_log_level },
|
||||
{ "arm", &vchiq_arm_log_level },
|
||||
};
|
||||
static int n_log_entries =
|
||||
sizeof(vchiq_proc_log_entries)/sizeof(vchiq_proc_log_entries[0]);
|
||||
|
||||
/* create an entry under /proc/vc/log for each log category */
|
||||
static int vchiq_proc_create_log_entries(struct proc_dir_entry *top)
|
||||
{
|
||||
struct proc_dir_entry *dir;
|
||||
size_t i;
|
||||
int ret = 0;
|
||||
|
||||
dir = proc_mkdir("log", proc_info.vc_cfg_dir);
|
||||
if (!dir)
|
||||
return -ENOMEM;
|
||||
proc_info.log_categories = dir;
|
||||
|
||||
for (i = 0; i < n_log_entries; i++) {
|
||||
dir = create_proc_entry(vchiq_proc_log_entries[i].name,
|
||||
0644,
|
||||
proc_info.log_categories);
|
||||
if (!dir) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
dir->read_proc = &log_cfg_read;
|
||||
dir->write_proc = &log_cfg_write;
|
||||
dir->data = (void *)vchiq_proc_log_entries[i].plevel;
|
||||
|
||||
vchiq_proc_log_entries[i].dir = dir;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int vchiq_proc_init(void)
|
||||
{
|
||||
BUG_ON(proc_info.vc_cfg_dir != NULL);
|
||||
|
||||
proc_info.vc_cfg_dir = proc_mkdir("vc", NULL);
|
||||
if (proc_info.vc_cfg_dir == NULL)
|
||||
goto fail;
|
||||
|
||||
proc_info.clients = proc_mkdir("clients",
|
||||
proc_info.vc_cfg_dir);
|
||||
if (!proc_info.clients)
|
||||
goto fail;
|
||||
|
||||
if (vchiq_proc_create_log_entries(proc_info.vc_cfg_dir) != 0)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
vchiq_proc_deinit();
|
||||
vchiq_log_error(vchiq_arm_log_level,
|
||||
"%s: failed to create proc directory",
|
||||
__func__);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* remove all the proc entries */
|
||||
void vchiq_proc_deinit(void)
|
||||
{
|
||||
/* log category entries */
|
||||
if (proc_info.log_categories) {
|
||||
size_t i;
|
||||
for (i = 0; i < n_log_entries; i++)
|
||||
if (vchiq_proc_log_entries[i].dir)
|
||||
remove_proc_entry(
|
||||
vchiq_proc_log_entries[i].name,
|
||||
proc_info.log_categories);
|
||||
|
||||
remove_proc_entry(proc_info.log_categories->name,
|
||||
proc_info.vc_cfg_dir);
|
||||
}
|
||||
if (proc_info.clients)
|
||||
remove_proc_entry(proc_info.clients->name,
|
||||
proc_info.vc_cfg_dir);
|
||||
if (proc_info.vc_cfg_dir)
|
||||
remove_proc_entry(proc_info.vc_cfg_dir->name, NULL);
|
||||
}
|
||||
|
||||
struct proc_dir_entry *vchiq_clients_top(void)
|
||||
{
|
||||
return proc_info.clients;
|
||||
}
|
||||
|
830
sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c
Normal file
830
sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c
Normal file
@ -0,0 +1,830 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <interface/compat/vchi_bsd.h>
|
||||
|
||||
#include "interface/vchi/vchi.h"
|
||||
#include "vchiq.h"
|
||||
#include "vchiq_core.h"
|
||||
|
||||
#include "vchiq_util.h"
|
||||
|
||||
#define vchiq_status_to_vchi(status) ((int32_t)status)
|
||||
|
||||
typedef struct {
|
||||
VCHIQ_SERVICE_HANDLE_T handle;
|
||||
|
||||
VCHIU_QUEUE_T queue;
|
||||
|
||||
VCHI_CALLBACK_T callback;
|
||||
void *callback_param;
|
||||
} SHIM_SERVICE_T;
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* return pointer to the mphi message driver function table
|
||||
* -------------------------------------------------------------------- */
|
||||
const VCHI_MESSAGE_DRIVER_T *
|
||||
vchi_mphi_message_driver_func_table(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* return a pointer to the 'single' connection driver fops
|
||||
* -------------------------------------------------------------------- */
|
||||
const VCHI_CONNECTION_API_T *
|
||||
single_get_func_table(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VCHI_CONNECTION_T *vchi_create_connection(
|
||||
const VCHI_CONNECTION_API_T *function_table,
|
||||
const VCHI_MESSAGE_DRIVER_T *low_level)
|
||||
{
|
||||
(void)function_table;
|
||||
(void)low_level;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_msg_peek
|
||||
*
|
||||
* Arguments: const VCHI_SERVICE_HANDLE_T handle,
|
||||
* void **data,
|
||||
* uint32_t *msg_size,
|
||||
|
||||
|
||||
* VCHI_FLAGS_T flags
|
||||
*
|
||||
* Description: Routine to return a pointer to the current message (to allow in
|
||||
* place processing). The message can be removed using
|
||||
* vchi_msg_remove when you're finished
|
||||
*
|
||||
* Returns: int32_t - success == 0
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle,
|
||||
void **data,
|
||||
uint32_t *msg_size,
|
||||
VCHI_FLAGS_T flags)
|
||||
{
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
VCHIQ_HEADER_T *header;
|
||||
|
||||
WARN_ON((flags != VCHI_FLAGS_NONE) &&
|
||||
(flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
|
||||
|
||||
if (flags == VCHI_FLAGS_NONE)
|
||||
if (vchiu_queue_is_empty(&service->queue))
|
||||
return -1;
|
||||
|
||||
header = vchiu_queue_peek(&service->queue);
|
||||
|
||||
*data = header->data;
|
||||
*msg_size = header->size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_msg_peek);
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_msg_remove
|
||||
*
|
||||
* Arguments: const VCHI_SERVICE_HANDLE_T handle,
|
||||
*
|
||||
* Description: Routine to remove a message (after it has been read with
|
||||
* vchi_msg_peek)
|
||||
*
|
||||
* Returns: int32_t - success == 0
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle)
|
||||
{
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
VCHIQ_HEADER_T *header;
|
||||
|
||||
header = vchiu_queue_pop(&service->queue);
|
||||
|
||||
vchiq_release_message(service->handle, header);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_msg_remove);
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_msg_queue
|
||||
*
|
||||
* Arguments: VCHI_SERVICE_HANDLE_T handle,
|
||||
* const void *data,
|
||||
* uint32_t data_size,
|
||||
* VCHI_FLAGS_T flags,
|
||||
* void *msg_handle,
|
||||
*
|
||||
* Description: Thin wrapper to queue a message onto a connection
|
||||
*
|
||||
* Returns: int32_t - success == 0
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle,
|
||||
const void *data,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *msg_handle)
|
||||
{
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
VCHIQ_ELEMENT_T element = {data, data_size};
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
(void)msg_handle;
|
||||
|
||||
WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
|
||||
|
||||
status = vchiq_queue_message(service->handle, &element, 1);
|
||||
|
||||
/* vchiq_queue_message() may return VCHIQ_RETRY, so we need to
|
||||
** implement a retry mechanism since this function is supposed
|
||||
** to block until queued
|
||||
*/
|
||||
while (status == VCHIQ_RETRY) {
|
||||
msleep(1);
|
||||
status = vchiq_queue_message(service->handle, &element, 1);
|
||||
}
|
||||
|
||||
return vchiq_status_to_vchi(status);
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_msg_queue);
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_bulk_queue_receive
|
||||
*
|
||||
* Arguments: VCHI_BULK_HANDLE_T handle,
|
||||
* void *data_dst,
|
||||
* const uint32_t data_size,
|
||||
* VCHI_FLAGS_T flags
|
||||
* void *bulk_handle
|
||||
*
|
||||
* Description: Routine to setup a rcv buffer
|
||||
*
|
||||
* Returns: int32_t - success == 0
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle,
|
||||
void *data_dst,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *bulk_handle)
|
||||
{
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
VCHIQ_BULK_MODE_T mode;
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
switch ((int)flags) {
|
||||
case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
|
||||
| VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
|
||||
WARN_ON(!service->callback);
|
||||
mode = VCHIQ_BULK_MODE_CALLBACK;
|
||||
break;
|
||||
case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
|
||||
mode = VCHIQ_BULK_MODE_BLOCKING;
|
||||
break;
|
||||
case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
|
||||
case VCHI_FLAGS_NONE:
|
||||
mode = VCHIQ_BULK_MODE_NOCALLBACK;
|
||||
break;
|
||||
default:
|
||||
WARN(1, "unsupported message\n");
|
||||
return vchiq_status_to_vchi(VCHIQ_ERROR);
|
||||
}
|
||||
|
||||
status = vchiq_bulk_receive(service->handle, data_dst, data_size,
|
||||
bulk_handle, mode);
|
||||
|
||||
/* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to
|
||||
** implement a retry mechanism since this function is supposed
|
||||
** to block until queued
|
||||
*/
|
||||
while (status == VCHIQ_RETRY) {
|
||||
msleep(1);
|
||||
status = vchiq_bulk_receive(service->handle, data_dst,
|
||||
data_size, bulk_handle, mode);
|
||||
}
|
||||
|
||||
return vchiq_status_to_vchi(status);
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_bulk_queue_receive);
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_bulk_queue_transmit
|
||||
*
|
||||
* Arguments: VCHI_BULK_HANDLE_T handle,
|
||||
* void *data_src,
|
||||
* uint32_t data_size,
|
||||
* VCHI_FLAGS_T flags,
|
||||
* void *bulk_handle
|
||||
*
|
||||
* Description: Routine to transmit some data
|
||||
*
|
||||
* Returns: int32_t - success == 0
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle,
|
||||
void *data_src,
|
||||
uint32_t data_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *bulk_handle)
|
||||
{
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
VCHIQ_BULK_MODE_T mode;
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
switch ((int)flags) {
|
||||
case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE
|
||||
| VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
|
||||
WARN_ON(!service->callback);
|
||||
mode = VCHIQ_BULK_MODE_CALLBACK;
|
||||
break;
|
||||
case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ:
|
||||
case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE:
|
||||
mode = VCHIQ_BULK_MODE_BLOCKING;
|
||||
break;
|
||||
case VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
|
||||
case VCHI_FLAGS_NONE:
|
||||
mode = VCHIQ_BULK_MODE_NOCALLBACK;
|
||||
break;
|
||||
default:
|
||||
WARN(1, "unsupported message\n");
|
||||
return vchiq_status_to_vchi(VCHIQ_ERROR);
|
||||
}
|
||||
|
||||
status = vchiq_bulk_transmit(service->handle, data_src, data_size,
|
||||
bulk_handle, mode);
|
||||
|
||||
/* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to
|
||||
** implement a retry mechanism since this function is supposed
|
||||
** to block until queued
|
||||
*/
|
||||
while (status == VCHIQ_RETRY) {
|
||||
msleep(1);
|
||||
status = vchiq_bulk_transmit(service->handle, data_src,
|
||||
data_size, bulk_handle, mode);
|
||||
}
|
||||
|
||||
return vchiq_status_to_vchi(status);
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_bulk_queue_transmit);
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_msg_dequeue
|
||||
*
|
||||
* Arguments: VCHI_SERVICE_HANDLE_T handle,
|
||||
* void *data,
|
||||
* uint32_t max_data_size_to_read,
|
||||
* uint32_t *actual_msg_size
|
||||
* VCHI_FLAGS_T flags
|
||||
*
|
||||
* Description: Routine to dequeue a message into the supplied buffer
|
||||
*
|
||||
* Returns: int32_t - success == 0
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle,
|
||||
void *data,
|
||||
uint32_t max_data_size_to_read,
|
||||
uint32_t *actual_msg_size,
|
||||
VCHI_FLAGS_T flags)
|
||||
{
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
VCHIQ_HEADER_T *header;
|
||||
|
||||
WARN_ON((flags != VCHI_FLAGS_NONE) &&
|
||||
(flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
|
||||
|
||||
if (flags == VCHI_FLAGS_NONE)
|
||||
if (vchiu_queue_is_empty(&service->queue))
|
||||
return -1;
|
||||
|
||||
header = vchiu_queue_pop(&service->queue);
|
||||
|
||||
memcpy(data, header->data, header->size < max_data_size_to_read ?
|
||||
header->size : max_data_size_to_read);
|
||||
|
||||
*actual_msg_size = header->size;
|
||||
|
||||
vchiq_release_message(service->handle, header);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_msg_dequeue);
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_msg_queuev
|
||||
*
|
||||
* Arguments: VCHI_SERVICE_HANDLE_T handle,
|
||||
* VCHI_MSG_VECTOR_T *vector,
|
||||
* uint32_t count,
|
||||
* VCHI_FLAGS_T flags,
|
||||
* void *msg_handle
|
||||
*
|
||||
* Description: Thin wrapper to queue a message onto a connection
|
||||
*
|
||||
* Returns: int32_t - success == 0
|
||||
*
|
||||
***********************************************************/
|
||||
|
||||
vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T));
|
||||
vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) ==
|
||||
offsetof(VCHIQ_ELEMENT_T, data));
|
||||
vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) ==
|
||||
offsetof(VCHIQ_ELEMENT_T, size));
|
||||
|
||||
int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle,
|
||||
VCHI_MSG_VECTOR_T *vector,
|
||||
uint32_t count,
|
||||
VCHI_FLAGS_T flags,
|
||||
void *msg_handle)
|
||||
{
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
|
||||
(void)msg_handle;
|
||||
|
||||
WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
|
||||
|
||||
return vchiq_status_to_vchi(vchiq_queue_message(service->handle,
|
||||
(const VCHIQ_ELEMENT_T *)vector, count));
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_msg_queuev);
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_held_msg_release
|
||||
*
|
||||
* Arguments: VCHI_HELD_MSG_T *message
|
||||
*
|
||||
* Description: Routine to release a held message (after it has been read with
|
||||
* vchi_msg_hold)
|
||||
*
|
||||
* Returns: int32_t - success == 0
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message)
|
||||
{
|
||||
vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service,
|
||||
(VCHIQ_HEADER_T *)message->message);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_msg_hold
|
||||
*
|
||||
* Arguments: VCHI_SERVICE_HANDLE_T handle,
|
||||
* void **data,
|
||||
* uint32_t *msg_size,
|
||||
* VCHI_FLAGS_T flags,
|
||||
* VCHI_HELD_MSG_T *message_handle
|
||||
*
|
||||
* Description: Routine to return a pointer to the current message (to allow
|
||||
* in place processing). The message is dequeued - don't forget
|
||||
* to release the message using vchi_held_msg_release when you're
|
||||
* finished.
|
||||
*
|
||||
* Returns: int32_t - success == 0
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle,
|
||||
void **data,
|
||||
uint32_t *msg_size,
|
||||
VCHI_FLAGS_T flags,
|
||||
VCHI_HELD_MSG_T *message_handle)
|
||||
{
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
VCHIQ_HEADER_T *header;
|
||||
|
||||
WARN_ON((flags != VCHI_FLAGS_NONE) &&
|
||||
(flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE));
|
||||
|
||||
if (flags == VCHI_FLAGS_NONE)
|
||||
if (vchiu_queue_is_empty(&service->queue))
|
||||
return -1;
|
||||
|
||||
header = vchiu_queue_pop(&service->queue);
|
||||
|
||||
*data = header->data;
|
||||
*msg_size = header->size;
|
||||
|
||||
message_handle->service =
|
||||
(struct opaque_vchi_service_t *)service->handle;
|
||||
message_handle->message = header;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_initialise
|
||||
*
|
||||
* Arguments: VCHI_INSTANCE_T *instance_handle
|
||||
* VCHI_CONNECTION_T **connections
|
||||
* const uint32_t num_connections
|
||||
*
|
||||
* Description: Initialises the hardware but does not transmit anything
|
||||
* When run as a Host App this will be called twice hence the need
|
||||
* to malloc the state information
|
||||
*
|
||||
* Returns: 0 if successful, failure otherwise
|
||||
*
|
||||
***********************************************************/
|
||||
|
||||
int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle)
|
||||
{
|
||||
VCHIQ_INSTANCE_T instance;
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
status = vchiq_initialise(&instance);
|
||||
|
||||
*instance_handle = (VCHI_INSTANCE_T)instance;
|
||||
|
||||
return vchiq_status_to_vchi(status);
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_initialise);
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_connect
|
||||
*
|
||||
* Arguments: VCHI_CONNECTION_T **connections
|
||||
* const uint32_t num_connections
|
||||
* VCHI_INSTANCE_T instance_handle)
|
||||
*
|
||||
* Description: Starts the command service on each connection,
|
||||
* causing INIT messages to be pinged back and forth
|
||||
*
|
||||
* Returns: 0 if successful, failure otherwise
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_connect(VCHI_CONNECTION_T **connections,
|
||||
const uint32_t num_connections,
|
||||
VCHI_INSTANCE_T instance_handle)
|
||||
{
|
||||
VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
|
||||
|
||||
(void)connections;
|
||||
(void)num_connections;
|
||||
|
||||
return vchiq_connect(instance);
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_connect);
|
||||
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_disconnect
|
||||
*
|
||||
* Arguments: VCHI_INSTANCE_T instance_handle
|
||||
*
|
||||
* Description: Stops the command service on each connection,
|
||||
* causing DE-INIT messages to be pinged back and forth
|
||||
*
|
||||
* Returns: 0 if successful, failure otherwise
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle)
|
||||
{
|
||||
VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
|
||||
return vchiq_status_to_vchi(vchiq_shutdown(instance));
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_disconnect);
|
||||
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_service_open
|
||||
* Name: vchi_service_create
|
||||
*
|
||||
* Arguments: VCHI_INSTANCE_T *instance_handle
|
||||
* SERVICE_CREATION_T *setup,
|
||||
* VCHI_SERVICE_HANDLE_T *handle
|
||||
*
|
||||
* Description: Routine to open a service
|
||||
*
|
||||
* Returns: int32_t - success == 0
|
||||
*
|
||||
***********************************************************/
|
||||
|
||||
static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason,
|
||||
VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user)
|
||||
{
|
||||
SHIM_SERVICE_T *service =
|
||||
(SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle);
|
||||
|
||||
if (!service->callback)
|
||||
goto release;
|
||||
|
||||
switch (reason) {
|
||||
case VCHIQ_MESSAGE_AVAILABLE:
|
||||
vchiu_queue_push(&service->queue, header);
|
||||
|
||||
service->callback(service->callback_param,
|
||||
VCHI_CALLBACK_MSG_AVAILABLE, NULL);
|
||||
|
||||
goto done;
|
||||
break;
|
||||
|
||||
case VCHIQ_BULK_TRANSMIT_DONE:
|
||||
service->callback(service->callback_param,
|
||||
VCHI_CALLBACK_BULK_SENT, bulk_user);
|
||||
break;
|
||||
|
||||
case VCHIQ_BULK_RECEIVE_DONE:
|
||||
service->callback(service->callback_param,
|
||||
VCHI_CALLBACK_BULK_RECEIVED, bulk_user);
|
||||
break;
|
||||
|
||||
case VCHIQ_SERVICE_CLOSED:
|
||||
service->callback(service->callback_param,
|
||||
VCHI_CALLBACK_SERVICE_CLOSED, NULL);
|
||||
break;
|
||||
|
||||
case VCHIQ_SERVICE_OPENED:
|
||||
/* No equivalent VCHI reason */
|
||||
break;
|
||||
|
||||
case VCHIQ_BULK_TRANSMIT_ABORTED:
|
||||
service->callback(service->callback_param,
|
||||
VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,
|
||||
bulk_user);
|
||||
break;
|
||||
|
||||
case VCHIQ_BULK_RECEIVE_ABORTED:
|
||||
service->callback(service->callback_param,
|
||||
VCHI_CALLBACK_BULK_RECEIVE_ABORTED,
|
||||
bulk_user);
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN(1, "not supported\n");
|
||||
break;
|
||||
}
|
||||
|
||||
release:
|
||||
vchiq_release_message(service->handle, header);
|
||||
done:
|
||||
return VCHIQ_SUCCESS;
|
||||
}
|
||||
|
||||
static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance,
|
||||
SERVICE_CREATION_T *setup)
|
||||
{
|
||||
SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL);
|
||||
|
||||
(void)instance;
|
||||
|
||||
if (service) {
|
||||
if (vchiu_queue_init(&service->queue, 64)) {
|
||||
service->callback = setup->callback;
|
||||
service->callback_param = setup->callback_param;
|
||||
} else {
|
||||
kfree(service);
|
||||
service = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
static void service_free(SHIM_SERVICE_T *service)
|
||||
{
|
||||
if (service) {
|
||||
vchiu_queue_delete(&service->queue);
|
||||
kfree(service);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle,
|
||||
SERVICE_CREATION_T *setup,
|
||||
VCHI_SERVICE_HANDLE_T *handle)
|
||||
{
|
||||
VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
|
||||
SHIM_SERVICE_T *service = service_alloc(instance, setup);
|
||||
|
||||
*handle = (VCHI_SERVICE_HANDLE_T)service;
|
||||
|
||||
if (service) {
|
||||
VCHIQ_SERVICE_PARAMS_T params;
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.fourcc = setup->service_id;
|
||||
params.callback = shim_callback;
|
||||
params.userdata = service;
|
||||
params.version = setup->version.version;
|
||||
params.version_min = setup->version.version_min;
|
||||
|
||||
status = vchiq_open_service(instance, ¶ms,
|
||||
&service->handle);
|
||||
if (status != VCHIQ_SUCCESS) {
|
||||
service_free(service);
|
||||
service = NULL;
|
||||
*handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (service != NULL) ? 0 : -1;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_open);
|
||||
|
||||
int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle,
|
||||
SERVICE_CREATION_T *setup,
|
||||
VCHI_SERVICE_HANDLE_T *handle)
|
||||
{
|
||||
VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle;
|
||||
SHIM_SERVICE_T *service = service_alloc(instance, setup);
|
||||
|
||||
*handle = (VCHI_SERVICE_HANDLE_T)service;
|
||||
|
||||
if (service) {
|
||||
VCHIQ_SERVICE_PARAMS_T params;
|
||||
VCHIQ_STATUS_T status;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.fourcc = setup->service_id;
|
||||
params.callback = shim_callback;
|
||||
params.userdata = service;
|
||||
params.version = setup->version.version;
|
||||
params.version_min = setup->version.version_min;
|
||||
status = vchiq_add_service(instance, ¶ms, &service->handle);
|
||||
|
||||
if (status != VCHIQ_SUCCESS) {
|
||||
service_free(service);
|
||||
service = NULL;
|
||||
*handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (service != NULL) ? 0 : -1;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_create);
|
||||
|
||||
int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
if (service) {
|
||||
VCHIQ_STATUS_T status = vchiq_close_service(service->handle);
|
||||
if (status == VCHIQ_SUCCESS) {
|
||||
service_free(service);
|
||||
service = NULL;
|
||||
}
|
||||
|
||||
ret = vchiq_status_to_vchi(status);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_close);
|
||||
|
||||
int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
if (service) {
|
||||
VCHIQ_STATUS_T status = vchiq_remove_service(service->handle);
|
||||
if (status == VCHIQ_SUCCESS) {
|
||||
service_free(service);
|
||||
service = NULL;
|
||||
}
|
||||
|
||||
ret = vchiq_status_to_vchi(status);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_destroy);
|
||||
|
||||
int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version )
|
||||
{
|
||||
int32_t ret = -1;
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
if(service)
|
||||
{
|
||||
VCHIQ_STATUS_T status = vchiq_get_peer_version(service->handle, peer_version);
|
||||
ret = vchiq_status_to_vchi( status );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_get_peer_version);
|
||||
|
||||
#ifdef notyet
|
||||
/* ----------------------------------------------------------------------
|
||||
* read a uint32_t from buffer.
|
||||
* network format is defined to be little endian
|
||||
* -------------------------------------------------------------------- */
|
||||
uint32_t
|
||||
vchi_readbuf_uint32(const void *_ptr)
|
||||
{
|
||||
const unsigned char *ptr = _ptr;
|
||||
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* write a uint32_t to buffer.
|
||||
* network format is defined to be little endian
|
||||
* -------------------------------------------------------------------- */
|
||||
void
|
||||
vchi_writebuf_uint32(void *_ptr, uint32_t value)
|
||||
{
|
||||
unsigned char *ptr = _ptr;
|
||||
ptr[0] = (unsigned char)((value >> 0) & 0xFF);
|
||||
ptr[1] = (unsigned char)((value >> 8) & 0xFF);
|
||||
ptr[2] = (unsigned char)((value >> 16) & 0xFF);
|
||||
ptr[3] = (unsigned char)((value >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* read a uint16_t from buffer.
|
||||
* network format is defined to be little endian
|
||||
* -------------------------------------------------------------------- */
|
||||
uint16_t
|
||||
vchi_readbuf_uint16(const void *_ptr)
|
||||
{
|
||||
const unsigned char *ptr = _ptr;
|
||||
return ptr[0] | (ptr[1] << 8);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* write a uint16_t into the buffer.
|
||||
* network format is defined to be little endian
|
||||
* -------------------------------------------------------------------- */
|
||||
void
|
||||
vchi_writebuf_uint16(void *_ptr, uint16_t value)
|
||||
{
|
||||
unsigned char *ptr = _ptr;
|
||||
ptr[0] = (value >> 0) & 0xFF;
|
||||
ptr[1] = (value >> 8) & 0xFF;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_service_use
|
||||
*
|
||||
* Arguments: const VCHI_SERVICE_HANDLE_T handle
|
||||
*
|
||||
* Description: Routine to increment refcount on a service
|
||||
*
|
||||
* Returns: void
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
if (service)
|
||||
ret = vchiq_status_to_vchi(vchiq_use_service(service->handle));
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_use);
|
||||
|
||||
/***********************************************************
|
||||
* Name: vchi_service_release
|
||||
*
|
||||
* Arguments: const VCHI_SERVICE_HANDLE_T handle
|
||||
*
|
||||
* Description: Routine to decrement refcount on a service
|
||||
*
|
||||
* Returns: void
|
||||
*
|
||||
***********************************************************/
|
||||
int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
|
||||
if (service)
|
||||
ret = vchiq_status_to_vchi(
|
||||
vchiq_release_service(service->handle));
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(vchi_service_release);
|
151
sys/contrib/vchiq/interface/vchiq_arm/vchiq_util.c
Normal file
151
sys/contrib/vchiq/interface/vchiq_arm/vchiq_util.c
Normal file
@ -0,0 +1,151 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 "vchiq_util.h"
|
||||
|
||||
static inline int is_pow2(int i)
|
||||
{
|
||||
return i && !(i & (i - 1));
|
||||
}
|
||||
|
||||
int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size)
|
||||
{
|
||||
WARN_ON(!is_pow2(size));
|
||||
|
||||
queue->size = size;
|
||||
queue->read = 0;
|
||||
queue->write = 0;
|
||||
|
||||
_sema_init(&queue->pop, 0);
|
||||
_sema_init(&queue->push, 0);
|
||||
|
||||
queue->storage = kzalloc(size * sizeof(VCHIQ_HEADER_T *), GFP_KERNEL);
|
||||
if (queue->storage == NULL) {
|
||||
vchiu_queue_delete(queue);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void vchiu_queue_delete(VCHIU_QUEUE_T *queue)
|
||||
{
|
||||
if (queue->storage != NULL)
|
||||
kfree(queue->storage);
|
||||
}
|
||||
|
||||
int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue)
|
||||
{
|
||||
return queue->read == queue->write;
|
||||
}
|
||||
|
||||
int vchiu_queue_is_full(VCHIU_QUEUE_T *queue)
|
||||
{
|
||||
return queue->write == queue->read + queue->size;
|
||||
}
|
||||
|
||||
void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)
|
||||
{
|
||||
while (queue->write == queue->read + queue->size) {
|
||||
if (down_interruptible(&queue->pop) != 0) {
|
||||
flush_signals(current);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to queue->storage must be visible after read from
|
||||
* queue->read
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
queue->storage[queue->write & (queue->size - 1)] = header;
|
||||
|
||||
/*
|
||||
* Write to queue->storage must be visible before write to
|
||||
* queue->write
|
||||
*/
|
||||
smp_wmb();
|
||||
|
||||
queue->write++;
|
||||
|
||||
up(&queue->push);
|
||||
}
|
||||
|
||||
VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue)
|
||||
{
|
||||
while (queue->write == queue->read) {
|
||||
if (down_interruptible(&queue->push) != 0) {
|
||||
flush_signals(current);
|
||||
}
|
||||
}
|
||||
|
||||
up(&queue->push); // We haven't removed anything from the queue.
|
||||
|
||||
/*
|
||||
* Read from queue->storage must be visible after read from
|
||||
* queue->write
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
return queue->storage[queue->read & (queue->size - 1)];
|
||||
}
|
||||
|
||||
VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue)
|
||||
{
|
||||
VCHIQ_HEADER_T *header;
|
||||
|
||||
while (queue->write == queue->read) {
|
||||
if (down_interruptible(&queue->push) != 0) {
|
||||
flush_signals(current);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from queue->storage must be visible after read from
|
||||
* queue->write
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
header = queue->storage[queue->read & (queue->size - 1)];
|
||||
|
||||
/*
|
||||
* Read from queue->storage must be visible before write to
|
||||
* queue->read
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
queue->read++;
|
||||
|
||||
up(&queue->pop);
|
||||
|
||||
return header;
|
||||
}
|
66
sys/contrib/vchiq/interface/vchiq_arm/vchiq_util.h
Normal file
66
sys/contrib/vchiq/interface/vchiq_arm/vchiq_util.h
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef VCHIQ_UTIL_H
|
||||
#define VCHIQ_UTIL_H
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <interface/compat/vchi_bsd.h>
|
||||
#endif
|
||||
|
||||
#include "vchiq_if.h"
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
int read;
|
||||
int write;
|
||||
|
||||
struct semaphore pop;
|
||||
struct semaphore push;
|
||||
|
||||
VCHIQ_HEADER_T **storage;
|
||||
} VCHIU_QUEUE_T;
|
||||
|
||||
extern int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size);
|
||||
extern void vchiu_queue_delete(VCHIU_QUEUE_T *queue);
|
||||
|
||||
extern int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue);
|
||||
extern int vchiu_queue_is_full(VCHIU_QUEUE_T *queue);
|
||||
|
||||
extern void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header);
|
||||
|
||||
extern VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue);
|
||||
extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue);
|
||||
|
||||
#endif
|
||||
|
59
sys/contrib/vchiq/interface/vchiq_arm/vchiq_version.c
Normal file
59
sys/contrib/vchiq/interface/vchiq_arm/vchiq_version.c
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2012 Broadcom. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the above-listed copyright holders may not be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2, as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 "vchiq_build_info.h"
|
||||
#include <linux/broadcom/vc_debug_sym.h>
|
||||
|
||||
VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_hostname, "dc4-arm-01" );
|
||||
VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_version, "9245b4c35b99b3870e1f7dc598c5692b3c66a6f0 (tainted)" );
|
||||
VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_time, __TIME__ );
|
||||
VC_DEBUG_DECLARE_STRING_VAR( vchiq_build_date, __DATE__ );
|
||||
|
||||
const char *vchiq_get_build_hostname( void )
|
||||
{
|
||||
return vchiq_build_hostname;
|
||||
}
|
||||
|
||||
const char *vchiq_get_build_version( void )
|
||||
{
|
||||
return vchiq_build_version;
|
||||
}
|
||||
|
||||
const char *vchiq_get_build_date( void )
|
||||
{
|
||||
return vchiq_build_date;
|
||||
}
|
||||
|
||||
const char *vchiq_get_build_time( void )
|
||||
{
|
||||
return vchiq_build_time;
|
||||
}
|
@ -129,6 +129,7 @@ struct t4_virt_res { /* virtualized HW resources */
|
||||
enum {
|
||||
ULD_TOM = 1,
|
||||
ULD_IWARP = 2,
|
||||
ULD_ISCSI = 3,
|
||||
};
|
||||
|
||||
struct adapter;
|
||||
|
@ -113,6 +113,7 @@ struct icl_conn {
|
||||
bool ic_disconnecting;
|
||||
bool ic_iser;
|
||||
const char *ic_name;
|
||||
const char *ic_offload;
|
||||
|
||||
void (*ic_receive)(struct icl_pdu *);
|
||||
void (*ic_error)(struct icl_conn *);
|
||||
|
@ -1185,6 +1185,7 @@ icl_soft_new_conn(const char *name, struct mtx *lock)
|
||||
#endif
|
||||
ic->ic_max_data_segment_length = ICL_MAX_DATA_SEGMENT_LENGTH;
|
||||
ic->ic_name = name;
|
||||
ic->ic_offload = "none";
|
||||
|
||||
return (ic);
|
||||
}
|
||||
|
@ -421,6 +421,7 @@ iscsi_maintenance_thread_terminate(struct iscsi_session *is)
|
||||
sx_xunlock(&sc->sc_lock);
|
||||
|
||||
icl_conn_close(is->is_conn);
|
||||
callout_drain(&is->is_callout);
|
||||
|
||||
ISCSI_SESSION_LOCK(is);
|
||||
|
||||
@ -434,8 +435,6 @@ iscsi_maintenance_thread_terminate(struct iscsi_session *is)
|
||||
cv_signal(&is->is_login_cv);
|
||||
#endif
|
||||
|
||||
callout_drain(&is->is_callout);
|
||||
|
||||
iscsi_session_cleanup(is, true);
|
||||
|
||||
KASSERT(TAILQ_EMPTY(&is->is_outstanding),
|
||||
@ -511,6 +510,7 @@ iscsi_session_reconnect(struct iscsi_session *is)
|
||||
static void
|
||||
iscsi_session_terminate(struct iscsi_session *is)
|
||||
{
|
||||
|
||||
if (is->is_terminating)
|
||||
return;
|
||||
|
||||
@ -532,12 +532,14 @@ iscsi_callout(void *context)
|
||||
|
||||
is = context;
|
||||
|
||||
if (is->is_terminating)
|
||||
ISCSI_SESSION_LOCK(is);
|
||||
if (is->is_terminating) {
|
||||
ISCSI_SESSION_UNLOCK(is);
|
||||
return;
|
||||
}
|
||||
|
||||
callout_schedule(&is->is_callout, 1 * hz);
|
||||
|
||||
ISCSI_SESSION_LOCK(is);
|
||||
is->is_timeout++;
|
||||
|
||||
if (is->is_waiting_for_iscsid) {
|
||||
@ -1306,6 +1308,16 @@ iscsi_ioctl_daemon_wait(struct iscsi_softc *sc,
|
||||
request->idr_tsih = 0; /* New or reinstated session. */
|
||||
memcpy(&request->idr_conf, &is->is_conf,
|
||||
sizeof(request->idr_conf));
|
||||
|
||||
error = icl_limits(is->is_conf.isc_offload,
|
||||
&request->idr_limits.isl_max_data_segment_length);
|
||||
if (error != 0) {
|
||||
ISCSI_SESSION_WARN(is, "icl_limits for offload \"%s\" "
|
||||
"failed with error %d", is->is_conf.isc_offload,
|
||||
error);
|
||||
sx_sunlock(&sc->sc_lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
sx_sunlock(&sc->sc_lock);
|
||||
return (0);
|
||||
@ -1731,7 +1743,13 @@ iscsi_ioctl_session_add(struct iscsi_softc *sc, struct iscsi_session_add *isa)
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
is->is_conn = icl_new_conn(NULL, "iscsi", &is->is_lock);
|
||||
is->is_conn = icl_new_conn(is->is_conf.isc_offload,
|
||||
"iscsi", &is->is_lock);
|
||||
if (is->is_conn == NULL) {
|
||||
sx_xunlock(&sc->sc_lock);
|
||||
free(is, M_ISCSI);
|
||||
return (EINVAL);
|
||||
}
|
||||
is->is_conn->ic_receive = iscsi_receive_callback;
|
||||
is->is_conn->ic_error = iscsi_error_callback;
|
||||
is->is_conn->ic_prv0 = is;
|
||||
@ -1750,15 +1768,17 @@ iscsi_ioctl_session_add(struct iscsi_softc *sc, struct iscsi_session_add *isa)
|
||||
arc4rand(&is->is_isid[1], 5, 0);
|
||||
is->is_tsih = 0;
|
||||
callout_init(&is->is_callout, 1);
|
||||
callout_reset(&is->is_callout, 1 * hz, iscsi_callout, is);
|
||||
TAILQ_INSERT_TAIL(&sc->sc_sessions, is, is_next);
|
||||
|
||||
error = kthread_add(iscsi_maintenance_thread, is, NULL, NULL, 0, 0, "iscsimt");
|
||||
if (error != 0) {
|
||||
ISCSI_SESSION_WARN(is, "kthread_add(9) failed with error %d", error);
|
||||
sx_xunlock(&sc->sc_lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
callout_reset(&is->is_callout, 1 * hz, iscsi_callout, is);
|
||||
TAILQ_INSERT_TAIL(&sc->sc_sessions, is, is_next);
|
||||
|
||||
/*
|
||||
* Trigger immediate reconnection.
|
||||
*/
|
||||
@ -1836,6 +1856,7 @@ iscsi_ioctl_session_list(struct iscsi_softc *sc, struct iscsi_session_list *isl)
|
||||
iss.iss_id = is->is_id;
|
||||
strlcpy(iss.iss_target_alias, is->is_target_alias, sizeof(iss.iss_target_alias));
|
||||
strlcpy(iss.iss_reason, is->is_reason, sizeof(iss.iss_reason));
|
||||
strlcpy(iss.iss_offload, is->is_conn->ic_offload, sizeof(iss.iss_offload));
|
||||
|
||||
if (is->is_conn->ic_header_crc32c)
|
||||
iss.iss_header_digest = ISCSI_DIGEST_CRC32C;
|
||||
|
@ -43,6 +43,7 @@
|
||||
#define ISCSI_ADDR_LEN 47 /* INET6_ADDRSTRLEN + '\0' */
|
||||
#define ISCSI_ALIAS_LEN 256 /* XXX: Where did it come from? */
|
||||
#define ISCSI_SECRET_LEN 17 /* 16 + '\0' */
|
||||
#define ISCSI_OFFLOAD_LEN 8
|
||||
#define ISCSI_REASON_LEN 64
|
||||
|
||||
#define ISCSI_DIGEST_NONE 0
|
||||
@ -65,7 +66,16 @@ struct iscsi_session_conf {
|
||||
int isc_header_digest;
|
||||
int isc_data_digest;
|
||||
int isc_iser;
|
||||
int isc_spare[4];
|
||||
char isc_offload[ISCSI_OFFLOAD_LEN];
|
||||
int isc_spare[2];
|
||||
};
|
||||
|
||||
/*
|
||||
* Additional constraints imposed by chosen ICL offload module;
|
||||
* iscsid(8) must obey those when negotiating operational parameters.
|
||||
*/
|
||||
struct iscsi_session_limits {
|
||||
size_t isl_max_data_segment_length;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -81,20 +91,21 @@ struct iscsi_session_state {
|
||||
int iss_immediate_data;
|
||||
int iss_connected;
|
||||
char iss_reason[ISCSI_REASON_LEN];
|
||||
int iss_spare[4];
|
||||
char iss_offload[ISCSI_OFFLOAD_LEN];
|
||||
int iss_spare[2];
|
||||
};
|
||||
|
||||
/*
|
||||
* For use with iscsid(8).
|
||||
* The following ioctls are used by iscsid(8).
|
||||
*/
|
||||
|
||||
struct iscsi_daemon_request {
|
||||
unsigned int idr_session_id;
|
||||
struct iscsi_session_conf idr_conf;
|
||||
uint8_t idr_isid[6];
|
||||
uint16_t idr_tsih;
|
||||
uint16_t idr_spare_cid;
|
||||
int idr_spare[4];
|
||||
struct iscsi_session_limits idr_limits;
|
||||
int idr_spare[2];
|
||||
};
|
||||
|
||||
struct iscsi_daemon_handoff {
|
||||
@ -182,9 +193,8 @@ struct iscsi_daemon_receive {
|
||||
#endif /* ICL_KERNEL_PROXY */
|
||||
|
||||
/*
|
||||
* For use with iscsictl(8).
|
||||
* The following ioctls are used by iscsictl(8).
|
||||
*/
|
||||
|
||||
struct iscsi_session_add {
|
||||
struct iscsi_session_conf isa_conf;
|
||||
int isa_spare[4];
|
||||
|
@ -51,7 +51,11 @@ extern "C" {
|
||||
#include <machine/endian.h>
|
||||
|
||||
#define EFSYS_HAS_UINT64 1
|
||||
#if defined(__x86_64__)
|
||||
#define EFSYS_USE_UINT64 1
|
||||
#else
|
||||
#define EFSYS_USE_UINT64 0
|
||||
#endif
|
||||
#if _BYTE_ORDER == _BIG_ENDIAN
|
||||
#define EFSYS_IS_BIG_ENDIAN 1
|
||||
#define EFSYS_IS_LITTLE_ENDIAN 0
|
||||
@ -398,6 +402,26 @@ typedef struct efsys_mem_s {
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define EFSYS_MEM_READQ(_esmp, _offset, _eqp) \
|
||||
do { \
|
||||
uint64_t *addr; \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
||||
("not power of 2 aligned")); \
|
||||
\
|
||||
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
||||
\
|
||||
(_eqp)->eq_u64[0] = *addr; \
|
||||
\
|
||||
EFSYS_PROBE3(mem_readq, unsigned int, (_offset), \
|
||||
uint32_t, (_eqp)->eq_u32[1], \
|
||||
uint32_t, (_eqp)->eq_u32[0]); \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#else
|
||||
#define EFSYS_MEM_READQ(_esmp, _offset, _eqp) \
|
||||
do { \
|
||||
uint32_t *addr; \
|
||||
@ -417,7 +441,31 @@ typedef struct efsys_mem_s {
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define EFSYS_MEM_READO(_esmp, _offset, _eop) \
|
||||
do { \
|
||||
uint64_t *addr; \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
||||
("not power of 2 aligned")); \
|
||||
\
|
||||
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
||||
\
|
||||
(_eop)->eo_u64[0] = *addr++; \
|
||||
(_eop)->eo_u64[1] = *addr; \
|
||||
\
|
||||
EFSYS_PROBE5(mem_reado, unsigned int, (_offset), \
|
||||
uint32_t, (_eop)->eo_u32[3], \
|
||||
uint32_t, (_eop)->eo_u32[2], \
|
||||
uint32_t, (_eop)->eo_u32[1], \
|
||||
uint32_t, (_eop)->eo_u32[0]); \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#else
|
||||
#define EFSYS_MEM_READO(_esmp, _offset, _eop) \
|
||||
do { \
|
||||
uint32_t *addr; \
|
||||
@ -441,6 +489,7 @@ typedef struct efsys_mem_s {
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#endif
|
||||
|
||||
#define EFSYS_MEM_WRITED(_esmp, _offset, _edp) \
|
||||
do { \
|
||||
@ -460,6 +509,27 @@ typedef struct efsys_mem_s {
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp) \
|
||||
do { \
|
||||
uint64_t *addr; \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
||||
("not power of 2 aligned")); \
|
||||
\
|
||||
EFSYS_PROBE3(mem_writeq, unsigned int, (_offset), \
|
||||
uint32_t, (_eqp)->eq_u32[1], \
|
||||
uint32_t, (_eqp)->eq_u32[0]); \
|
||||
\
|
||||
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
||||
\
|
||||
*addr = (_eqp)->eq_u64[0]; \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
|
||||
#else
|
||||
#define EFSYS_MEM_WRITEQ(_esmp, _offset, _eqp) \
|
||||
do { \
|
||||
uint32_t *addr; \
|
||||
@ -479,7 +549,31 @@ typedef struct efsys_mem_s {
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define EFSYS_MEM_WRITEO(_esmp, _offset, _eop) \
|
||||
do { \
|
||||
uint64_t *addr; \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
||||
("not power of 2 aligned")); \
|
||||
\
|
||||
EFSYS_PROBE5(mem_writeo, unsigned int, (_offset), \
|
||||
uint32_t, (_eop)->eo_u32[3], \
|
||||
uint32_t, (_eop)->eo_u32[2], \
|
||||
uint32_t, (_eop)->eo_u32[1], \
|
||||
uint32_t, (_eop)->eo_u32[0]); \
|
||||
\
|
||||
addr = (void *)((_esmp)->esm_base + (_offset)); \
|
||||
\
|
||||
*addr++ = (_eop)->eo_u64[0]; \
|
||||
*addr = (_eop)->eo_u64[1]; \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#else
|
||||
#define EFSYS_MEM_WRITEO(_esmp, _offset, _eop) \
|
||||
do { \
|
||||
uint32_t *addr; \
|
||||
@ -503,22 +597,33 @@ typedef struct efsys_mem_s {
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#endif
|
||||
|
||||
#define EFSYS_MEM_ADDR(_esmp) \
|
||||
((_esmp)->esm_addr)
|
||||
|
||||
/* BAR */
|
||||
|
||||
#define SFXGE_LOCK_NAME_MAX 16
|
||||
|
||||
typedef struct efsys_bar_s {
|
||||
struct mtx esb_lock;
|
||||
char esb_lock_name[SFXGE_LOCK_NAME_MAX];
|
||||
bus_space_tag_t esb_tag;
|
||||
bus_space_handle_t esb_handle;
|
||||
int esb_rid;
|
||||
struct resource *esb_res;
|
||||
} efsys_bar_t;
|
||||
|
||||
#define SFXGE_BAR_LOCK_INIT(_esbp, _name) \
|
||||
mtx_init(&(_esbp)->esb_lock, (_name), NULL, MTX_DEF)
|
||||
#define SFXGE_BAR_LOCK_INIT(_esbp, _ifname) \
|
||||
do { \
|
||||
snprintf((_esbp)->esb_lock_name, \
|
||||
sizeof((_esbp)->esb_lock_name), \
|
||||
"%s:bar", (_ifname)); \
|
||||
mtx_init(&(_esbp)->esb_lock, (_esbp)->esb_lock_name, \
|
||||
NULL, MTX_DEF); \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#define SFXGE_BAR_LOCK_DESTROY(_esbp) \
|
||||
mtx_destroy(&(_esbp)->esb_lock)
|
||||
#define SFXGE_BAR_LOCK(_esbp) \
|
||||
@ -548,6 +653,7 @@ typedef struct efsys_bar_s {
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define EFSYS_BAR_READQ(_esbp, _offset, _eqp) \
|
||||
do { \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
@ -556,6 +662,53 @@ typedef struct efsys_bar_s {
|
||||
\
|
||||
SFXGE_BAR_LOCK(_esbp); \
|
||||
\
|
||||
(_eqp)->eq_u64[0] = bus_space_read_8((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset)); \
|
||||
\
|
||||
EFSYS_PROBE3(bar_readq, unsigned int, (_offset), \
|
||||
uint32_t, (_eqp)->eq_u32[1], \
|
||||
uint32_t, (_eqp)->eq_u32[0]); \
|
||||
\
|
||||
mtx_unlock(&((_esbp)->esb_lock)); \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
|
||||
#define EFSYS_BAR_READO(_esbp, _offset, _eop, _lock) \
|
||||
do { \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
||||
("not power of 2 aligned")); \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
if (_lock) \
|
||||
mtx_lock(&((_esbp)->esb_lock)); \
|
||||
\
|
||||
(_eop)->eo_u64[0] = bus_space_read_8((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset)); \
|
||||
(_eop)->eo_u64[1] = bus_space_read_8((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset+8)); \
|
||||
\
|
||||
EFSYS_PROBE5(bar_reado, unsigned int, (_offset), \
|
||||
uint32_t, (_eop)->eo_u32[3], \
|
||||
uint32_t, (_eop)->eo_u32[2], \
|
||||
uint32_t, (_eop)->eo_u32[1], \
|
||||
uint32_t, (_eop)->eo_u32[0]); \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
if (_lock) \
|
||||
mtx_unlock(&((_esbp)->esb_lock)); \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
|
||||
#else
|
||||
#define EFSYS_BAR_READQ(_esbp, _offset, _eqp) \
|
||||
do { \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
||||
("not power of 2 aligned")); \
|
||||
\
|
||||
mtx_lock(&((_esbp)->esb_lock)); \
|
||||
\
|
||||
(_eqp)->eq_u32[0] = bus_space_read_4((_esbp)->esb_tag, \
|
||||
(_esbp)->esb_handle, (_offset)); \
|
||||
(_eqp)->eq_u32[1] = bus_space_read_4((_esbp)->esb_tag, \
|
||||
@ -599,6 +752,7 @@ typedef struct efsys_bar_s {
|
||||
SFXGE_BAR_UNLOCK(_esbp); \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#endif
|
||||
|
||||
#define EFSYS_BAR_WRITED(_esbp, _offset, _edp, _lock) \
|
||||
do { \
|
||||
@ -622,6 +776,7 @@ typedef struct efsys_bar_s {
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp) \
|
||||
do { \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
@ -634,6 +789,25 @@ typedef struct efsys_bar_s {
|
||||
uint32_t, (_eqp)->eq_u32[1], \
|
||||
uint32_t, (_eqp)->eq_u32[0]); \
|
||||
\
|
||||
bus_space_write_8((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
(_offset), (_eqp)->eq_u64[0]); \
|
||||
\
|
||||
mtx_unlock(&((_esbp)->esb_lock)); \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#else
|
||||
#define EFSYS_BAR_WRITEQ(_esbp, _offset, _eqp) \
|
||||
do { \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_qword_t)), \
|
||||
("not power of 2 aligned")); \
|
||||
\
|
||||
mtx_lock(&((_esbp)->esb_lock)); \
|
||||
\
|
||||
EFSYS_PROBE3(bar_writeq, unsigned int, (_offset), \
|
||||
uint32_t, (_eqp)->eq_u32[1], \
|
||||
uint32_t, (_eqp)->eq_u32[0]); \
|
||||
\
|
||||
bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
(_offset), (_eqp)->eq_u32[0]); \
|
||||
bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
@ -642,7 +816,9 @@ typedef struct efsys_bar_s {
|
||||
SFXGE_BAR_UNLOCK(_esbp); \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock) \
|
||||
do { \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
@ -659,6 +835,34 @@ typedef struct efsys_bar_s {
|
||||
uint32_t, (_eop)->eo_u32[1], \
|
||||
uint32_t, (_eop)->eo_u32[0]); \
|
||||
\
|
||||
bus_space_write_8((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
(_offset), (_eop)->eo_u64[0]); \
|
||||
bus_space_write_8((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
(_offset+8), (_eop)->eo_u64[1]); \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
if (_lock) \
|
||||
mtx_unlock(&((_esbp)->esb_lock)); \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
|
||||
#else
|
||||
#define EFSYS_BAR_WRITEO(_esbp, _offset, _eop, _lock) \
|
||||
do { \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
KASSERT(IS_P2ALIGNED(_offset, sizeof (efx_oword_t)), \
|
||||
("not power of 2 aligned")); \
|
||||
\
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
if (_lock) \
|
||||
mtx_lock(&((_esbp)->esb_lock)); \
|
||||
\
|
||||
EFSYS_PROBE5(bar_writeo, unsigned int, (_offset), \
|
||||
uint32_t, (_eop)->eo_u32[3], \
|
||||
uint32_t, (_eop)->eo_u32[2], \
|
||||
uint32_t, (_eop)->eo_u32[1], \
|
||||
uint32_t, (_eop)->eo_u32[0]); \
|
||||
\
|
||||
bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
(_offset), (_eop)->eo_u32[0]); \
|
||||
bus_space_write_4((_esbp)->esb_tag, (_esbp)->esb_handle,\
|
||||
@ -673,6 +877,7 @@ typedef struct efsys_bar_s {
|
||||
SFXGE_BAR_UNLOCK(_esbp); \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
#endif
|
||||
|
||||
/* SPIN */
|
||||
|
||||
@ -721,13 +926,35 @@ typedef clock_t efsys_timestamp_t;
|
||||
|
||||
/* LOCK */
|
||||
|
||||
typedef struct mtx efsys_lock_t;
|
||||
typedef struct efsys_lock_s {
|
||||
struct mtx lock;
|
||||
char lock_name[SFXGE_LOCK_NAME_MAX];
|
||||
} efsys_lock_t;
|
||||
|
||||
#define SFXGE_EFSYS_LOCK_INIT(_eslp, _ifname, _label) \
|
||||
do { \
|
||||
efsys_lock_t *__eslp = (_eslp); \
|
||||
\
|
||||
snprintf((__eslp)->lock_name, \
|
||||
sizeof((__eslp)->lock_name), \
|
||||
"%s:%s", (_ifname), (_label)); \
|
||||
mtx_init(&(__eslp)->lock, (__eslp)->lock_name, \
|
||||
NULL, MTX_DEF); \
|
||||
} while (B_FALSE)
|
||||
#define SFXGE_EFSYS_LOCK_DESTROY(_eslp) \
|
||||
mtx_destroy(&(_eslp)->lock)
|
||||
#define SFXGE_EFSYS_LOCK(_eslp) \
|
||||
mtx_lock(&(_eslp)->lock)
|
||||
#define SFXGE_EFSYS_UNLOCK(_eslp) \
|
||||
mtx_unlock(&(_eslp)->lock)
|
||||
#define SFXGE_EFSYS_LOCK_ASSERT_OWNED(_eslp) \
|
||||
mtx_assert(&(_eslp)->lock, MA_OWNED)
|
||||
|
||||
#define EFSYS_LOCK_MAGIC 0x000010c4
|
||||
|
||||
#define EFSYS_LOCK(_lockp, _state) \
|
||||
do { \
|
||||
mtx_lock(_lockp); \
|
||||
SFXGE_EFSYS_LOCK(_lockp); \
|
||||
(_state) = EFSYS_LOCK_MAGIC; \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
@ -736,7 +963,7 @@ typedef struct mtx efsys_lock_t;
|
||||
do { \
|
||||
if ((_state) != EFSYS_LOCK_MAGIC) \
|
||||
KASSERT(B_FALSE, ("not locked")); \
|
||||
mtx_unlock(_lockp); \
|
||||
SFXGE_EFSYS_UNLOCK(_lockp); \
|
||||
_NOTE(CONSTANTCONDITION) \
|
||||
} while (B_FALSE)
|
||||
|
||||
|
@ -338,7 +338,9 @@ sfxge_ifnet_init(struct ifnet *ifp, struct sfxge_softc *sc)
|
||||
ifp->if_snd.ifq_drv_maxlen = sc->txq_entries - 1;
|
||||
IFQ_SET_READY(&ifp->if_snd);
|
||||
|
||||
mtx_init(&sc->tx_lock, "txq", NULL, MTX_DEF);
|
||||
snprintf(sc->tx_lock_name, sizeof(sc->tx_lock_name),
|
||||
"%s:tx", device_get_nameunit(sc->dev));
|
||||
mtx_init(&sc->tx_lock, sc->tx_lock_name, NULL, MTX_DEF);
|
||||
#endif
|
||||
|
||||
if ((rc = sfxge_port_ifmedia_init(sc)) != 0)
|
||||
@ -376,7 +378,8 @@ sfxge_bar_init(struct sfxge_softc *sc)
|
||||
}
|
||||
esbp->esb_tag = rman_get_bustag(esbp->esb_res);
|
||||
esbp->esb_handle = rman_get_bushandle(esbp->esb_res);
|
||||
SFXGE_BAR_LOCK_INIT(esbp, "sfxge_efsys_bar");
|
||||
|
||||
SFXGE_BAR_LOCK_INIT(esbp, device_get_nameunit(sc->dev));
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -401,7 +404,7 @@ sfxge_create(struct sfxge_softc *sc)
|
||||
|
||||
dev = sc->dev;
|
||||
|
||||
SFXGE_ADAPTER_LOCK_INIT(sc, "sfxge_softc");
|
||||
SFXGE_ADAPTER_LOCK_INIT(sc, device_get_nameunit(sc->dev));
|
||||
|
||||
sc->max_rss_channels = 0;
|
||||
snprintf(rss_param_name, sizeof(rss_param_name),
|
||||
@ -435,7 +438,8 @@ sfxge_create(struct sfxge_softc *sc)
|
||||
KASSERT(error == 0, ("Family should be filtered by sfxge_probe()"));
|
||||
|
||||
/* Create the common code nic object. */
|
||||
mtx_init(&sc->enp_lock, "sfxge_nic", NULL, MTX_DEF);
|
||||
SFXGE_EFSYS_LOCK_INIT(&sc->enp_lock,
|
||||
device_get_nameunit(sc->dev), "nic");
|
||||
if ((error = efx_nic_create(sc->family, (efsys_identifier_t *)sc,
|
||||
&sc->bar, &sc->enp_lock, &enp)) != 0)
|
||||
goto fail3;
|
||||
@ -537,7 +541,7 @@ sfxge_create(struct sfxge_softc *sc)
|
||||
fail_rx_ring_entries:
|
||||
sc->enp = NULL;
|
||||
efx_nic_destroy(enp);
|
||||
mtx_destroy(&sc->enp_lock);
|
||||
SFXGE_EFSYS_LOCK_DESTROY(&sc->enp_lock);
|
||||
|
||||
fail3:
|
||||
sfxge_bar_fini(sc);
|
||||
|
@ -122,6 +122,7 @@ struct sfxge_evq {
|
||||
/* Structure members not used on event processing path */
|
||||
unsigned int buf_base_id;
|
||||
unsigned int entries;
|
||||
char lock_name[SFXGE_LOCK_NAME_MAX];
|
||||
} __aligned(CACHE_LINE_SIZE);
|
||||
|
||||
#define SFXGE_NDESCS 1024
|
||||
@ -162,6 +163,9 @@ struct sfxge_mcdi {
|
||||
struct cv cv;
|
||||
enum sfxge_mcdi_state state;
|
||||
efx_mcdi_transport_t transport;
|
||||
|
||||
/* Only used in debugging output */
|
||||
char lock_name[SFXGE_LOCK_NAME_MAX];
|
||||
};
|
||||
|
||||
struct sfxge_hw_stats {
|
||||
@ -186,6 +190,9 @@ struct sfxge_port {
|
||||
struct sfxge_hw_stats phy_stats;
|
||||
struct sfxge_hw_stats mac_stats;
|
||||
efx_link_mode_t link_mode;
|
||||
|
||||
/* Only used in debugging output */
|
||||
char lock_name[SFXGE_LOCK_NAME_MAX];
|
||||
};
|
||||
|
||||
enum sfxge_softc_state {
|
||||
@ -198,6 +205,7 @@ enum sfxge_softc_state {
|
||||
struct sfxge_softc {
|
||||
device_t dev;
|
||||
struct sx softc_lock;
|
||||
char softc_lock_name[SFXGE_LOCK_NAME_MAX];
|
||||
enum sfxge_softc_state init_state;
|
||||
struct ifnet *ifnet;
|
||||
unsigned int if_flags;
|
||||
@ -210,7 +218,7 @@ struct sfxge_softc {
|
||||
caddr_t vpd_data;
|
||||
size_t vpd_size;
|
||||
efx_nic_t *enp;
|
||||
struct mtx enp_lock;
|
||||
efsys_lock_t enp_lock;
|
||||
|
||||
unsigned int rxq_entries;
|
||||
unsigned int txq_entries;
|
||||
@ -249,6 +257,7 @@ struct sfxge_softc {
|
||||
|
||||
#ifndef SFXGE_HAVE_MQ
|
||||
struct mtx tx_lock __aligned(CACHE_LINE_SIZE);
|
||||
char tx_lock_name[SFXGE_LOCK_NAME_MAX];
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -314,8 +323,15 @@ extern int sfxge_port_ifmedia_init(struct sfxge_softc *sc);
|
||||
|
||||
#define SFXGE_MAX_MTU (9 * 1024)
|
||||
|
||||
#define SFXGE_ADAPTER_LOCK_INIT(_sc, _name) \
|
||||
sx_init(&(_sc)->softc_lock, (_name))
|
||||
#define SFXGE_ADAPTER_LOCK_INIT(_sc, _ifname) \
|
||||
do { \
|
||||
struct sfxge_softc *__sc = (_sc); \
|
||||
\
|
||||
snprintf((__sc)->softc_lock_name, \
|
||||
sizeof((__sc)->softc_lock_name), \
|
||||
"%s:softc", (_ifname)); \
|
||||
sx_init(&(__sc)->softc_lock, (__sc)->softc_lock_name); \
|
||||
} while (B_FALSE)
|
||||
#define SFXGE_ADAPTER_LOCK_DESTROY(_sc) \
|
||||
sx_destroy(&(_sc)->softc_lock)
|
||||
#define SFXGE_ADAPTER_LOCK(_sc) \
|
||||
@ -325,8 +341,16 @@ extern int sfxge_port_ifmedia_init(struct sfxge_softc *sc);
|
||||
#define SFXGE_ADAPTER_LOCK_ASSERT_OWNED(_sc) \
|
||||
sx_assert(&(_sc)->softc_lock, LA_XLOCKED)
|
||||
|
||||
#define SFXGE_PORT_LOCK_INIT(_port, _name) \
|
||||
mtx_init(&(_port)->lock, (_name), NULL, MTX_DEF)
|
||||
#define SFXGE_PORT_LOCK_INIT(_port, _ifname) \
|
||||
do { \
|
||||
struct sfxge_port *__port = (_port); \
|
||||
\
|
||||
snprintf((__port)->lock_name, \
|
||||
sizeof((__port)->lock_name), \
|
||||
"%s:port", (_ifname)); \
|
||||
mtx_init(&(__port)->lock, (__port)->lock_name, \
|
||||
NULL, MTX_DEF); \
|
||||
} while (B_FALSE)
|
||||
#define SFXGE_PORT_LOCK_DESTROY(_port) \
|
||||
mtx_destroy(&(_port)->lock)
|
||||
#define SFXGE_PORT_LOCK(_port) \
|
||||
@ -336,8 +360,16 @@ extern int sfxge_port_ifmedia_init(struct sfxge_softc *sc);
|
||||
#define SFXGE_PORT_LOCK_ASSERT_OWNED(_port) \
|
||||
mtx_assert(&(_port)->lock, MA_OWNED)
|
||||
|
||||
#define SFXGE_MCDI_LOCK_INIT(_mcdi, _name) \
|
||||
mtx_init(&(_mcdi)->lock, (_name), NULL, MTX_DEF)
|
||||
#define SFXGE_MCDI_LOCK_INIT(_mcdi, _ifname) \
|
||||
do { \
|
||||
struct sfxge_mcdi *__mcdi = (_mcdi); \
|
||||
\
|
||||
snprintf((__mcdi)->lock_name, \
|
||||
sizeof((__mcdi)->lock_name), \
|
||||
"%s:mcdi", (_ifname)); \
|
||||
mtx_init(&(__mcdi)->lock, (__mcdi)->lock_name, \
|
||||
NULL, MTX_DEF); \
|
||||
} while (B_FALSE)
|
||||
#define SFXGE_MCDI_LOCK_DESTROY(_mcdi) \
|
||||
mtx_destroy(&(_mcdi)->lock)
|
||||
#define SFXGE_MCDI_LOCK(_mcdi) \
|
||||
@ -347,8 +379,16 @@ extern int sfxge_port_ifmedia_init(struct sfxge_softc *sc);
|
||||
#define SFXGE_MCDI_LOCK_ASSERT_OWNED(_mcdi) \
|
||||
mtx_assert(&(_mcdi)->lock, MA_OWNED)
|
||||
|
||||
#define SFXGE_EVQ_LOCK_INIT(_evq, _name) \
|
||||
mtx_init(&(_evq)->lock, (_name), NULL, MTX_DEF)
|
||||
#define SFXGE_EVQ_LOCK_INIT(_evq, _ifname, _evq_index) \
|
||||
do { \
|
||||
struct sfxge_evq *__evq = (_evq); \
|
||||
\
|
||||
snprintf((__evq)->lock_name, \
|
||||
sizeof((__evq)->lock_name), \
|
||||
"%s:evq%u", (_ifname), (_evq_index)); \
|
||||
mtx_init(&(__evq)->lock, (__evq)->lock_name, \
|
||||
NULL, MTX_DEF); \
|
||||
} while (B_FALSE)
|
||||
#define SFXGE_EVQ_LOCK_DESTROY(_evq) \
|
||||
mtx_destroy(&(_evq)->lock)
|
||||
#define SFXGE_EVQ_LOCK(_evq) \
|
||||
|
@ -832,7 +832,7 @@ sfxge_ev_qinit(struct sfxge_softc *sc, unsigned int index)
|
||||
sfxge_sram_buf_tbl_alloc(sc, EFX_EVQ_NBUFS(evq->entries),
|
||||
&evq->buf_base_id);
|
||||
|
||||
SFXGE_EVQ_LOCK_INIT(evq, "evq");
|
||||
SFXGE_EVQ_LOCK_INIT(evq, device_get_nameunit(sc->dev), index);
|
||||
|
||||
evq->init_state = SFXGE_EVQ_INITIALIZED;
|
||||
|
||||
|
@ -201,7 +201,7 @@ sfxge_mcdi_init(struct sfxge_softc *sc)
|
||||
KASSERT(mcdi->state == SFXGE_MCDI_UNINITIALIZED,
|
||||
("MCDI already initialized"));
|
||||
|
||||
SFXGE_MCDI_LOCK_INIT(mcdi, "sfxge_mcdi");
|
||||
SFXGE_MCDI_LOCK_INIT(mcdi, device_get_nameunit(sc->dev));
|
||||
|
||||
mcdi->state = SFXGE_MCDI_INITIALIZED;
|
||||
|
||||
|
@ -48,7 +48,7 @@ sfxge_mac_stat_update(struct sfxge_softc *sc)
|
||||
unsigned int count;
|
||||
int rc;
|
||||
|
||||
SFXGE_PORT_LOCK(port);
|
||||
SFXGE_PORT_LOCK_ASSERT_OWNED(port);
|
||||
|
||||
if (port->init_state != SFXGE_PORT_STARTED) {
|
||||
rc = 0;
|
||||
@ -82,7 +82,6 @@ sfxge_mac_stat_update(struct sfxge_softc *sc)
|
||||
|
||||
rc = ETIMEDOUT;
|
||||
out:
|
||||
SFXGE_PORT_UNLOCK(port);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
@ -93,12 +92,16 @@ sfxge_mac_stat_handler(SYSCTL_HANDLER_ARGS)
|
||||
unsigned int id = arg2;
|
||||
int rc;
|
||||
|
||||
SFXGE_PORT_LOCK(&sc->port);
|
||||
if ((rc = sfxge_mac_stat_update(sc)) != 0)
|
||||
return (rc);
|
||||
goto out;
|
||||
|
||||
return (SYSCTL_OUT(req,
|
||||
(uint64_t *)sc->port.mac_stats.decode_buf + id,
|
||||
sizeof(uint64_t)));
|
||||
rc = SYSCTL_OUT(req,
|
||||
(uint64_t *)sc->port.mac_stats.decode_buf + id,
|
||||
sizeof(uint64_t));
|
||||
out:
|
||||
SFXGE_PORT_UNLOCK(&sc->port);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -453,7 +456,7 @@ sfxge_phy_stat_update(struct sfxge_softc *sc)
|
||||
unsigned int count;
|
||||
int rc;
|
||||
|
||||
SFXGE_PORT_LOCK(port);
|
||||
SFXGE_PORT_LOCK_ASSERT_OWNED(port);
|
||||
|
||||
if (port->init_state != SFXGE_PORT_STARTED) {
|
||||
rc = 0;
|
||||
@ -487,7 +490,6 @@ sfxge_phy_stat_update(struct sfxge_softc *sc)
|
||||
|
||||
rc = ETIMEDOUT;
|
||||
out:
|
||||
SFXGE_PORT_UNLOCK(port);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
@ -498,12 +500,16 @@ sfxge_phy_stat_handler(SYSCTL_HANDLER_ARGS)
|
||||
unsigned int id = arg2;
|
||||
int rc;
|
||||
|
||||
SFXGE_PORT_LOCK(&sc->port);
|
||||
if ((rc = sfxge_phy_stat_update(sc)) != 0)
|
||||
return (rc);
|
||||
goto out;
|
||||
|
||||
return (SYSCTL_OUT(req,
|
||||
(uint32_t *)sc->port.phy_stats.decode_buf + id,
|
||||
sizeof(uint32_t)));
|
||||
rc = SYSCTL_OUT(req,
|
||||
(uint32_t *)sc->port.phy_stats.decode_buf + id,
|
||||
sizeof(uint32_t));
|
||||
out:
|
||||
SFXGE_PORT_UNLOCK(&sc->port);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -577,7 +583,7 @@ sfxge_port_init(struct sfxge_softc *sc)
|
||||
|
||||
port->sc = sc;
|
||||
|
||||
SFXGE_PORT_LOCK_INIT(port, "sfxge_port");
|
||||
SFXGE_PORT_LOCK_INIT(port, device_get_nameunit(sc->dev));
|
||||
|
||||
port->phy_stats.decode_buf = malloc(EFX_PHY_NSTATS * sizeof(uint32_t),
|
||||
M_SFXGE, M_WAITOK | M_ZERO);
|
||||
|
@ -1094,12 +1094,16 @@ sfxge_tx_queue_tso(struct sfxge_txq *txq, struct mbuf *mbuf,
|
||||
* roll back the work we have done.
|
||||
*/
|
||||
if (txq->n_pend_desc >
|
||||
SFXGE_TSO_MAX_DESC - (1 + SFXGE_TX_MAPPING_MAX_SEG))
|
||||
SFXGE_TSO_MAX_DESC - (1 + SFXGE_TX_MAPPING_MAX_SEG)) {
|
||||
txq->tso_pdrop_too_many++;
|
||||
break;
|
||||
}
|
||||
next_id = (id + 1) & txq->ptr_mask;
|
||||
if (__predict_false(tso_start_new_packet(txq, &tso,
|
||||
next_id)))
|
||||
next_id))) {
|
||||
txq->tso_pdrop_no_rsrc++;
|
||||
break;
|
||||
}
|
||||
id = next_id;
|
||||
}
|
||||
}
|
||||
@ -1467,7 +1471,7 @@ sfxge_tx_qinit(struct sfxge_softc *sc, unsigned int txq_index,
|
||||
stdp->std_get_non_tcp_max = sfxge_tx_dpl_get_non_tcp_max;
|
||||
stdp->std_getp = &stdp->std_get;
|
||||
|
||||
SFXGE_TXQ_LOCK_INIT(txq, "txq");
|
||||
SFXGE_TXQ_LOCK_INIT(txq, device_get_nameunit(sc->dev), txq_index);
|
||||
|
||||
SYSCTL_ADD_UINT(device_get_sysctl_ctx(sc->dev),
|
||||
SYSCTL_CHILDREN(txq_node), OID_AUTO,
|
||||
@ -1516,6 +1520,8 @@ static const struct {
|
||||
SFXGE_TX_STAT(tso_bursts, tso_bursts),
|
||||
SFXGE_TX_STAT(tso_packets, tso_packets),
|
||||
SFXGE_TX_STAT(tso_long_headers, tso_long_headers),
|
||||
SFXGE_TX_STAT(tso_pdrop_too_many, tso_pdrop_too_many),
|
||||
SFXGE_TX_STAT(tso_pdrop_no_rsrc, tso_pdrop_no_rsrc),
|
||||
SFXGE_TX_STAT(tx_collapses, collapses),
|
||||
SFXGE_TX_STAT(tx_drops, drops),
|
||||
SFXGE_TX_STAT(tx_get_overflow, get_overflow),
|
||||
|
@ -130,8 +130,16 @@ enum sfxge_txq_type {
|
||||
#define SFXGE_TX_SCALE(sc) 1
|
||||
#endif
|
||||
|
||||
#define SFXGE_TXQ_LOCK_INIT(_txq, _name) \
|
||||
mtx_init(&(_txq)->lock, (_name), NULL, MTX_DEF)
|
||||
#define SFXGE_TXQ_LOCK_INIT(_txq, _ifname, _txq_index) \
|
||||
do { \
|
||||
struct sfxge_txq *__txq = (_txq); \
|
||||
\
|
||||
snprintf((__txq)->lock_name, \
|
||||
sizeof((__txq)->lock_name), \
|
||||
"%s:txq%u", (_ifname), (_txq_index)); \
|
||||
mtx_init(&(__txq)->lock, (__txq)->lock_name, \
|
||||
NULL, MTX_DEF); \
|
||||
} while (B_FALSE)
|
||||
#define SFXGE_TXQ_LOCK_DESTROY(_txq) \
|
||||
mtx_destroy(&(_txq)->lock)
|
||||
#define SFXGE_TXQ_LOCK(_txq) \
|
||||
@ -164,6 +172,8 @@ struct sfxge_txq {
|
||||
|
||||
efsys_mem_t *tsoh_buffer;
|
||||
|
||||
char lock_name[SFXGE_LOCK_NAME_MAX];
|
||||
|
||||
/* This field changes more often and is read regularly on both
|
||||
* the initiation and completion paths
|
||||
*/
|
||||
@ -191,6 +201,8 @@ struct sfxge_txq {
|
||||
unsigned long get_non_tcp_overflow;
|
||||
unsigned long put_overflow;
|
||||
unsigned long netdown_drops;
|
||||
unsigned long tso_pdrop_too_many;
|
||||
unsigned long tso_pdrop_no_rsrc;
|
||||
|
||||
/* The following fields change more often, and are used mostly
|
||||
* on the completion path
|
||||
|
@ -121,6 +121,7 @@ static const struct pci_id pci_ns8250_ids[] = {
|
||||
{ 0x8086, 0x1c3d, 0xffff, 0, "Intel AMT - KT Controller", 0x10 },
|
||||
{ 0x8086, 0x1d3d, 0xffff, 0, "Intel C600/X79 Series Chipset KT Controller", 0x10 },
|
||||
{ 0x8086, 0x2a07, 0xffff, 0, "Intel AMT - PM965/GM965 KT Controller", 0x10 },
|
||||
{ 0x8086, 0x2a47, 0xffff, 0, "Mobile 4 Series Chipset KT Controller", 0x10 },
|
||||
{ 0x8086, 0x2e17, 0xffff, 0, "4 Series Chipset Serial KT Controller", 0x10 },
|
||||
{ 0x8086, 0x3b67, 0xffff, 0, "5 Series/3400 Series Chipset KT Controller",
|
||||
0x10 },
|
||||
|
@ -1263,7 +1263,8 @@ static int
|
||||
vtvga_probe(device_t dev)
|
||||
{
|
||||
|
||||
device_set_desc(dev, "vt_vga driver");
|
||||
device_set_desc(dev, "VT VGA driver");
|
||||
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_init_path.h"
|
||||
#include "opt_verbose_sysinit.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -410,6 +410,11 @@ initclocks(dummy)
|
||||
#ifdef SW_WATCHDOG
|
||||
EVENTHANDLER_REGISTER(watchdog_list, watchdog_config, NULL, 0);
|
||||
#endif
|
||||
/*
|
||||
* Arrange for ticks to wrap 10 minutes after boot to help catch
|
||||
* sign problems sooner.
|
||||
*/
|
||||
ticks = INT_MAX - (hz * 10 * 60);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3653,7 +3653,7 @@ bus_generic_suspend_child(device_t dev, device_t child)
|
||||
error = DEVICE_SUSPEND(child);
|
||||
|
||||
if (error == 0)
|
||||
dev->flags |= DF_SUSPENDED;
|
||||
child->flags |= DF_SUSPENDED;
|
||||
|
||||
return (error);
|
||||
}
|
||||
@ -3668,7 +3668,7 @@ bus_generic_resume_child(device_t dev, device_t child)
|
||||
{
|
||||
|
||||
DEVICE_RESUME(child);
|
||||
dev->flags &= ~DF_SUSPENDED;
|
||||
child->flags &= ~DF_SUSPENDED;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -1333,6 +1333,7 @@ in6_purgeaddr(struct ifaddr *ifa)
|
||||
static void
|
||||
in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
|
||||
{
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
|
||||
IF_ADDR_WLOCK(ifp);
|
||||
TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
|
||||
@ -1356,7 +1357,7 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
|
||||
if (ia->ia6_ndpr == NULL) {
|
||||
nd6log((LOG_NOTICE,
|
||||
"in6_unlink_ifa: autoconf'ed address "
|
||||
"%p has no prefix\n", ia));
|
||||
"%s has no prefix\n", ip6_sprintf(ip6buf, IA6_IN6(ia))));
|
||||
} else {
|
||||
ia->ia6_ndpr->ndpr_refcnt--;
|
||||
ia->ia6_ndpr = NULL;
|
||||
|
@ -24,7 +24,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: projects/ipfw/sys/netpfil/ipfw/ip_fw_iface.c 267384 2014-06-12 09:59:11Z melifaro $");
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* Kernel interface tracking API.
|
||||
@ -397,20 +397,20 @@ ipfw_iface_del_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic)
|
||||
|
||||
/*
|
||||
* Unreference interface specified by @ic.
|
||||
* Must be called without holding any locks.
|
||||
* Must be called while holding UH lock.
|
||||
*/
|
||||
void
|
||||
ipfw_iface_unref(struct ip_fw_chain *ch, struct ipfw_ifc *ic)
|
||||
{
|
||||
struct ipfw_iface *iif;
|
||||
|
||||
IPFW_UH_WLOCK_ASSERT(ch);
|
||||
|
||||
iif = ic->iface;
|
||||
ic->iface = NULL;
|
||||
|
||||
IPFW_UH_WLOCK(ch);
|
||||
iif->no.refcnt--;
|
||||
/* TODO: check for references & delete */
|
||||
IPFW_UH_WUNLOCK(ch);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -691,7 +691,7 @@ nat44_get_cfg(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
export_nat_cfg(ptr, ucfg);
|
||||
|
||||
/* Estimate memory amount */
|
||||
sz = sizeof(struct nat44_cfg_nat);
|
||||
sz = sizeof(ipfw_obj_header) + sizeof(struct nat44_cfg_nat);
|
||||
LIST_FOREACH(r, &ptr->redir_chain, _next) {
|
||||
sz += sizeof(struct nat44_cfg_redir);
|
||||
LIST_FOREACH(s, &r->spool_chain, _next)
|
||||
@ -699,7 +699,7 @@ nat44_get_cfg(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
}
|
||||
|
||||
ucfg->size = sz;
|
||||
if (sd->valsize < sz + sizeof(*oh)) {
|
||||
if (sd->valsize < sz) {
|
||||
|
||||
/*
|
||||
* Submitted buffer size is not enough.
|
||||
|
@ -429,6 +429,7 @@ struct ipfw_ifc {
|
||||
|
||||
#define IPFW_UH_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_RLOCKED)
|
||||
#define IPFW_UH_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_WLOCKED)
|
||||
#define IPFW_UH_UNLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_UNLOCKED)
|
||||
|
||||
#define IPFW_UH_RLOCK(p) rw_rlock(&(p)->uh_lock)
|
||||
#define IPFW_UH_RUNLOCK(p) rw_runlock(&(p)->uh_lock)
|
||||
|
@ -1198,7 +1198,7 @@ flush_table(struct ip_fw_chain *ch, struct tid_info *ti)
|
||||
void *astate_old, *astate_new;
|
||||
char algostate[64], *pstate;
|
||||
struct tableop_state ts;
|
||||
int error;
|
||||
int error, need_gc;
|
||||
uint16_t kidx;
|
||||
uint8_t tflags;
|
||||
|
||||
@ -1212,6 +1212,9 @@ flush_table(struct ip_fw_chain *ch, struct tid_info *ti)
|
||||
IPFW_UH_WUNLOCK(ch);
|
||||
return (ESRCH);
|
||||
}
|
||||
need_gc = 0;
|
||||
astate_new = NULL;
|
||||
memset(&ti_new, 0, sizeof(ti_new));
|
||||
restart:
|
||||
/* Set up swap handler */
|
||||
memset(&ts, 0, sizeof(ts));
|
||||
@ -1236,6 +1239,14 @@ flush_table(struct ip_fw_chain *ch, struct tid_info *ti)
|
||||
add_toperation_state(ch, &ts);
|
||||
IPFW_UH_WUNLOCK(ch);
|
||||
|
||||
/*
|
||||
* Stage 1.5: if this is not the first attempt, destroy previous state
|
||||
*/
|
||||
if (need_gc != 0) {
|
||||
ta->destroy(astate_new, &ti_new);
|
||||
need_gc = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stage 2: allocate new table instance using same algo.
|
||||
*/
|
||||
@ -1262,7 +1273,8 @@ flush_table(struct ip_fw_chain *ch, struct tid_info *ti)
|
||||
* complex checks.
|
||||
*/
|
||||
if (ts.modified != 0) {
|
||||
ta->destroy(astate_new, &ti_new);
|
||||
/* Delay destroying data since we're holding UH lock */
|
||||
need_gc = 1;
|
||||
goto restart;
|
||||
}
|
||||
|
||||
@ -3042,6 +3054,7 @@ free_table_config(struct namedobj_instance *ni, struct table_config *tc)
|
||||
{
|
||||
|
||||
KASSERT(tc->linked == 0, ("free() on linked config"));
|
||||
/* UH lock MUST NOT be held */
|
||||
|
||||
/*
|
||||
* We're using ta without any locking/referencing.
|
||||
|
@ -97,7 +97,7 @@ __FBSDID("$FreeBSD$");
|
||||
*
|
||||
* -destroy: request to destroy table instance.
|
||||
* typedef void (ta_destroy)(void *ta_state, struct table_info *ti);
|
||||
* MANDATORY, may be locked (UH+WLOCK). (M_NOWAIT).
|
||||
* MANDATORY, unlocked. (M_WAITOK).
|
||||
*
|
||||
* Frees all table entries and all tables structures allocated by -init.
|
||||
*
|
||||
@ -2134,6 +2134,7 @@ destroy_ifidx_locked(struct namedobj_instance *ii, struct named_object *no,
|
||||
ife = (struct ifentry *)no;
|
||||
|
||||
ipfw_iface_del_notify(ch, &ife->ic);
|
||||
ipfw_iface_unref(ch, &ife->ic);
|
||||
free(ife, M_IPFW_TBL);
|
||||
}
|
||||
|
||||
@ -2153,7 +2154,9 @@ ta_destroy_ifidx(void *ta_state, struct table_info *ti)
|
||||
if (icfg->main_ptr != NULL)
|
||||
free(icfg->main_ptr, M_IPFW);
|
||||
|
||||
IPFW_UH_WLOCK(ch);
|
||||
ipfw_objhash_foreach(icfg->ii, destroy_ifidx_locked, ch);
|
||||
IPFW_UH_WUNLOCK(ch);
|
||||
|
||||
ipfw_objhash_destroy(icfg->ii);
|
||||
|
||||
@ -2333,8 +2336,9 @@ ta_del_ifidx(void *ta_state, struct table_info *ti, struct tentry_info *tei,
|
||||
|
||||
/* Unlink from local list */
|
||||
ipfw_objhash_del(icfg->ii, &ife->no);
|
||||
/* Unlink notifier */
|
||||
/* Unlink notifier and deref */
|
||||
ipfw_iface_del_notify(icfg->ch, &ife->ic);
|
||||
ipfw_iface_unref(icfg->ch, &ife->ic);
|
||||
|
||||
icfg->count--;
|
||||
tei->value = ife->value;
|
||||
@ -2357,11 +2361,8 @@ ta_flush_ifidx_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
|
||||
|
||||
tb = (struct ta_buf_ifidx *)ta_buf;
|
||||
|
||||
if (tb->ife != NULL) {
|
||||
/* Unlink first */
|
||||
ipfw_iface_unref(ch, &tb->ife->ic);
|
||||
if (tb->ife != NULL)
|
||||
free(tb->ife, M_IPFW_TBL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -357,7 +357,6 @@ static __inline intrmask_t splhigh(void) { return 0; }
|
||||
static __inline intrmask_t splimp(void) { return 0; }
|
||||
static __inline intrmask_t splnet(void) { return 0; }
|
||||
static __inline intrmask_t spltty(void) { return 0; }
|
||||
static __inline intrmask_t splvm(void) { return 0; }
|
||||
static __inline void splx(intrmask_t ipl __unused) { return; }
|
||||
|
||||
/*
|
||||
|
@ -1393,7 +1393,7 @@ softdep_flush(addr)
|
||||
VFSTOUFS(mp)->softdep_jblocks->jb_suspended))
|
||||
kthread_suspend_check();
|
||||
ACQUIRE_LOCK(ump);
|
||||
while ((ump->softdep_flags & (FLUSH_CLEANUP | FLUSH_EXIT)) == 0)
|
||||
if ((ump->softdep_flags & (FLUSH_CLEANUP | FLUSH_EXIT)) == 0)
|
||||
msleep(&ump->softdep_flushtd, LOCK_PTR(ump), PVM,
|
||||
"sdflush", hz / 2);
|
||||
ump->softdep_flags &= ~FLUSH_CLEANUP;
|
||||
@ -1423,10 +1423,9 @@ worklist_speedup(mp)
|
||||
|
||||
ump = VFSTOUFS(mp);
|
||||
LOCK_OWNED(ump);
|
||||
if ((ump->softdep_flags & (FLUSH_CLEANUP | FLUSH_EXIT)) == 0) {
|
||||
if ((ump->softdep_flags & (FLUSH_CLEANUP | FLUSH_EXIT)) == 0)
|
||||
ump->softdep_flags |= FLUSH_CLEANUP;
|
||||
wakeup(&ump->softdep_flushtd);
|
||||
}
|
||||
wakeup(&ump->softdep_flushtd);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1471,11 +1470,10 @@ softdep_speedup(ump)
|
||||
TAILQ_INSERT_TAIL(&softdepmounts, sdp, sd_next);
|
||||
FREE_GBLLOCK(&lk);
|
||||
if ((altump->softdep_flags &
|
||||
(FLUSH_CLEANUP | FLUSH_EXIT)) == 0) {
|
||||
(FLUSH_CLEANUP | FLUSH_EXIT)) == 0)
|
||||
altump->softdep_flags |= FLUSH_CLEANUP;
|
||||
altump->um_softdep->sd_cleanups++;
|
||||
wakeup(&altump->softdep_flushtd);
|
||||
}
|
||||
altump->um_softdep->sd_cleanups++;
|
||||
wakeup(&altump->softdep_flushtd);
|
||||
FREE_LOCK(altump);
|
||||
}
|
||||
}
|
||||
|
11
tools/tools/qrndtest/Makefile
Normal file
11
tools/tools/qrndtest/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
PROG = qrndtest
|
||||
|
||||
SRCS = r.c
|
||||
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
4
tools/tools/qrndtest/README
Normal file
4
tools/tools/qrndtest/README
Normal file
@ -0,0 +1,4 @@
|
||||
This is a really quick random testing that I wrote for adrian.
|
||||
|
||||
If you want a real randomness tester, look at dieharder that has a much
|
||||
larger battery of tests and will tell you if your PRNG is good or not.
|
81
tools/tools/qrndtest/r.c
Normal file
81
tools/tools/qrndtest/r.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*-
|
||||
* Copyright 2015 John-Mark Gurney.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
|
||||
typedef uint32_t (*rndfun_t)();
|
||||
|
||||
uint32_t
|
||||
randomwrap()
|
||||
{
|
||||
return random();
|
||||
}
|
||||
|
||||
struct {
|
||||
const char *name;
|
||||
rndfun_t rndfun;
|
||||
} rndfuns[] = {
|
||||
{ "random", randomwrap },
|
||||
{ "arc4random", arc4random },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
uint64_t vals[4] = {};
|
||||
uint64_t avg;
|
||||
unsigned int i;
|
||||
rndfun_t f;
|
||||
|
||||
if (argc == 1)
|
||||
f = rndfuns[0].rndfun;
|
||||
else {
|
||||
for (i = 0; rndfuns[i].name != NULL; i++) {
|
||||
if (strcasecmp(rndfuns[i].name, argv[1]) == 0)
|
||||
break;
|
||||
}
|
||||
if (rndfuns[i].name == NULL)
|
||||
return 1;
|
||||
f = rndfuns[i].rndfun;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
vals[f() % 4]++;
|
||||
if (((i++) % (4*1024*1024)) == 0) {
|
||||
avg = vals[0] + vals[1] + vals[2] + vals[3];
|
||||
avg /= 4;
|
||||
printf("%d: %ld %ld %ld %ld\n", i, vals[0] - avg, vals[1] - avg, vals[2] - avg, vals[3] - avg);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 17, 2013
|
||||
.Dd February 4, 2015
|
||||
.Dt ISCSI.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -110,6 +110,8 @@ flag of
|
||||
The following are not specified in the
|
||||
.Sy RFC 3720
|
||||
.Bl -tag -width sockbufsize
|
||||
.It Cm offload
|
||||
Name of selected iSCSI hardware offload driver.
|
||||
.It Cm port
|
||||
The iSCSI port used by the iSCSI protocol, defaults to 3260.
|
||||
.It Cm tags
|
||||
|
@ -327,6 +327,9 @@ conf_from_target(struct iscsi_session_conf *conf,
|
||||
conf->isc_discovery = 1;
|
||||
if (targ->t_protocol == PROTOCOL_ISER)
|
||||
conf->isc_iser = 1;
|
||||
if (targ->t_offload != NULL)
|
||||
strlcpy(conf->isc_offload, targ->t_offload,
|
||||
sizeof(conf->isc_offload));
|
||||
if (targ->t_header_digest == DIGEST_CRC32C)
|
||||
conf->isc_header_digest = ISCSI_DIGEST_CRC32C;
|
||||
else
|
||||
@ -517,6 +520,7 @@ kernel_list(int iscsi_fd, const struct target *targ __unused,
|
||||
state->iss_immediate_data ? "Yes" : "No");
|
||||
printf("iSER (RDMA): %s\n",
|
||||
conf->isc_iser ? "Yes" : "No");
|
||||
printf("Offload driver: %s\n", state->iss_offload);
|
||||
printf("Device nodes: ");
|
||||
print_periphs(state->iss_id);
|
||||
printf("\n\n");
|
||||
|
@ -72,6 +72,7 @@ struct target {
|
||||
int t_auth_method;
|
||||
int t_session_type;
|
||||
int t_protocol;
|
||||
char *t_offload;
|
||||
char *t_user;
|
||||
char *t_secret;
|
||||
char *t_mutual_user;
|
||||
|
@ -57,8 +57,8 @@ extern void yyrestart(FILE *);
|
||||
|
||||
%token AUTH_METHOD HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS
|
||||
%token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET
|
||||
%token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL IGNORED
|
||||
%token EQUALS OPENING_BRACKET CLOSING_BRACKET
|
||||
%token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD
|
||||
%token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET
|
||||
|
||||
%union
|
||||
{
|
||||
@ -117,6 +117,8 @@ target_entry:
|
||||
|
|
||||
session_type
|
||||
|
|
||||
offload
|
||||
|
|
||||
protocol
|
||||
|
|
||||
ignored
|
||||
@ -250,6 +252,14 @@ session_type: SESSION_TYPE EQUALS STR
|
||||
}
|
||||
;
|
||||
|
||||
offload: OFFLOAD EQUALS STR
|
||||
{
|
||||
if (target->t_offload != NULL)
|
||||
errx(1, "duplicated offload at line %d", lineno);
|
||||
target->t_offload = $3;
|
||||
}
|
||||
;
|
||||
|
||||
protocol: PROTOCOL EQUALS STR
|
||||
{
|
||||
if (target->t_protocol != PROTOCOL_UNSPECIFIED)
|
||||
|
@ -63,6 +63,7 @@ tgtChapSecret { return MUTUAL_SECRET; }
|
||||
AuthMethod { return AUTH_METHOD; }
|
||||
SessionType { return SESSION_TYPE; }
|
||||
protocol { return PROTOCOL; }
|
||||
offload { return OFFLOAD; }
|
||||
port { return IGNORED; }
|
||||
MaxConnections { return IGNORED; }
|
||||
TargetAlias { return IGNORED; }
|
||||
|
@ -151,8 +151,7 @@ resolve_addr(const struct connection *conn, const char *address,
|
||||
}
|
||||
|
||||
static struct connection *
|
||||
connection_new(unsigned int session_id, const uint8_t isid[8], uint16_t tsih,
|
||||
const struct iscsi_session_conf *conf, int iscsi_fd)
|
||||
connection_new(int iscsi_fd, const struct iscsi_daemon_request *request)
|
||||
{
|
||||
struct connection *conn;
|
||||
struct addrinfo *from_ai, *to_ai;
|
||||
@ -176,16 +175,13 @@ connection_new(unsigned int session_id, const uint8_t isid[8], uint16_t tsih,
|
||||
conn->conn_max_data_segment_length = 8192;
|
||||
conn->conn_max_burst_length = 262144;
|
||||
conn->conn_first_burst_length = 65536;
|
||||
|
||||
conn->conn_session_id = session_id;
|
||||
memcpy(&conn->conn_isid, isid, sizeof(conn->conn_isid));
|
||||
conn->conn_tsih = tsih;
|
||||
conn->conn_iscsi_fd = iscsi_fd;
|
||||
|
||||
/*
|
||||
* XXX: Should we sanitize this somehow?
|
||||
*/
|
||||
memcpy(&conn->conn_conf, conf, sizeof(conn->conn_conf));
|
||||
conn->conn_session_id = request->idr_session_id;
|
||||
memcpy(&conn->conn_conf, &request->idr_conf, sizeof(conn->conn_conf));
|
||||
memcpy(&conn->conn_isid, &request->idr_isid, sizeof(conn->conn_isid));
|
||||
conn->conn_tsih = request->idr_tsih;
|
||||
memcpy(&conn->conn_limits, &request->idr_limits, sizeof(conn->conn_limits));
|
||||
|
||||
from_addr = conn->conn_conf.isc_initiator_addr;
|
||||
to_addr = conn->conn_conf.isc_target_addr;
|
||||
@ -442,8 +438,7 @@ handle_request(int iscsi_fd, const struct iscsi_daemon_request *request, int tim
|
||||
setproctitle("%s", request->idr_conf.isc_target_addr);
|
||||
}
|
||||
|
||||
conn = connection_new(request->idr_session_id, request->idr_isid,
|
||||
request->idr_tsih, &request->idr_conf, iscsi_fd);
|
||||
conn = connection_new(iscsi_fd, request);
|
||||
set_timeout(timeout);
|
||||
capsicate(conn);
|
||||
login(conn);
|
||||
|
@ -51,6 +51,7 @@ struct connection {
|
||||
int conn_socket;
|
||||
unsigned int conn_session_id;
|
||||
struct iscsi_session_conf conn_conf;
|
||||
struct iscsi_session_limits conn_limits;
|
||||
char conn_target_alias[ISCSI_ADDR_LEN];
|
||||
uint8_t conn_isid[6];
|
||||
uint16_t conn_tsih;
|
||||
|
@ -441,6 +441,10 @@ login_negotiate(struct connection *conn)
|
||||
request = login_new_request(conn, BHSLR_STAGE_OPERATIONAL_NEGOTIATION);
|
||||
request_keys = keys_new();
|
||||
|
||||
log_debugx("offload \"%s\" limits MaxRecvDataSegmentLength to %zd",
|
||||
conn->conn_conf.isc_offload,
|
||||
conn->conn_limits.isl_max_data_segment_length);
|
||||
|
||||
/*
|
||||
* The following keys are irrelevant for discovery sessions.
|
||||
*/
|
||||
@ -456,9 +460,9 @@ login_negotiate(struct connection *conn)
|
||||
|
||||
keys_add(request_keys, "ImmediateData", "Yes");
|
||||
keys_add_int(request_keys, "MaxBurstLength",
|
||||
2 * ISCSI_MAX_DATA_SEGMENT_LENGTH);
|
||||
2 * conn->conn_limits.isl_max_data_segment_length);
|
||||
keys_add_int(request_keys, "FirstBurstLength",
|
||||
ISCSI_MAX_DATA_SEGMENT_LENGTH);
|
||||
conn->conn_limits.isl_max_data_segment_length);
|
||||
keys_add(request_keys, "InitialR2T", "Yes");
|
||||
keys_add(request_keys, "MaxOutstandingR2T", "1");
|
||||
} else {
|
||||
@ -467,7 +471,7 @@ login_negotiate(struct connection *conn)
|
||||
}
|
||||
|
||||
keys_add_int(request_keys, "MaxRecvDataSegmentLength",
|
||||
ISCSI_MAX_DATA_SEGMENT_LENGTH);
|
||||
conn->conn_limits.isl_max_data_segment_length);
|
||||
keys_add(request_keys, "DefaultTime2Wait", "0");
|
||||
keys_add(request_keys, "DefaultTime2Retain", "0");
|
||||
keys_add(request_keys, "ErrorRecoveryLevel", "0");
|
||||
|
@ -1020,7 +1020,7 @@ logmsg(int pri, const char *msg, const char *from, int flags)
|
||||
*/
|
||||
if (no_compress - (f->f_type != F_PIPE) < 1 &&
|
||||
(flags & MARK) == 0 && msglen == f->f_prevlen &&
|
||||
f->f_prevline && !strcmp(msg, f->f_prevline) &&
|
||||
!strcmp(msg, f->f_prevline) &&
|
||||
!strcasecmp(from, f->f_prevhost)) {
|
||||
(void)strlcpy(f->f_lasttime, timestamp,
|
||||
sizeof(f->f_lasttime));
|
||||
@ -1175,11 +1175,9 @@ fprintlog(struct filed *f, int flags, const char *msg)
|
||||
v->iov_base = repbuf;
|
||||
v->iov_len = snprintf(repbuf, sizeof repbuf,
|
||||
"last message repeated %d times", f->f_prevcount);
|
||||
} else if (f->f_prevline) {
|
||||
} else {
|
||||
v->iov_base = f->f_prevline;
|
||||
v->iov_len = f->f_prevlen;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
v++;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user