Index: head/include/ifaddrs.h =================================================================== --- head/include/ifaddrs.h (revision 326822) +++ head/include/ifaddrs.h (revision 326823) @@ -1,65 +1,67 @@ /* $FreeBSD$ */ -/* +/*- + * SPDX-License-Identifier: BSD-1-Clause + * * Copyright (c) 1995, 1999 * Berkeley Software Design, Inc. 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. * * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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. * * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp */ #ifndef _IFADDRS_H_ #define _IFADDRS_H_ struct ifaddrs { struct ifaddrs *ifa_next; char *ifa_name; unsigned int ifa_flags; struct sockaddr *ifa_addr; struct sockaddr *ifa_netmask; struct sockaddr *ifa_dstaddr; void *ifa_data; }; /* * This may have been defined in . Note that if is * to be included it must be included before this header file. */ #ifndef ifa_broadaddr #define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ #endif struct ifmaddrs { struct ifmaddrs *ifma_next; struct sockaddr *ifma_name; struct sockaddr *ifma_addr; struct sockaddr *ifma_lladdr; }; #include __BEGIN_DECLS extern int getifaddrs(struct ifaddrs **); extern void freeifaddrs(struct ifaddrs *); extern int getifmaddrs(struct ifmaddrs **); extern void freeifmaddrs(struct ifmaddrs *); __END_DECLS #endif Index: head/lib/libc/net/getifaddrs.c =================================================================== --- head/lib/libc/net/getifaddrs.c (revision 326822) +++ head/lib/libc/net/getifaddrs.c (revision 326823) @@ -1,344 +1,346 @@ /* $KAME: getifaddrs.c,v 1.9 2001/08/20 02:31:20 itojun Exp $ */ -/* +/*- + * SPDX-License-Identifier: BSD-1-Clause + * * Copyright (c) 1995, 1999 * Berkeley Software Design, Inc. 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. * * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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. * * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp */ /* * NOTE: SIOCGIFCONF case is not LP64 friendly. it also does not perform * try-and-error for region size. */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #ifdef NET_RT_IFLIST #include #include #include #include #endif #include #include #include #include #include "un-namespace.h" #if !defined(AF_LINK) #define SA_LEN(sa) sizeof(struct sockaddr) #endif #if !defined(SA_LEN) #define SA_LEN(sa) (sa)->sa_len #endif #define SALIGN (sizeof(long) - 1) #define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1)) #ifndef ALIGNBYTES /* * On systems with a routing socket, ALIGNBYTES should match the value * that the kernel uses when building the messages. */ #define ALIGNBYTES XXX #endif #ifndef ALIGN #define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES) #endif #define MAX_SYSCTL_TRY 5 int getifaddrs(struct ifaddrs **pif) { int icnt = 1; int dcnt = 0; int ncnt = 0; int ntry = 0; int mib[6]; size_t needed; char *buf; char *next; struct ifaddrs *cif; char *p, *p0; struct rt_msghdr *rtm; struct if_msghdrl *ifm; struct ifa_msghdrl *ifam; struct sockaddr_dl *dl; struct sockaddr *sa; struct ifaddrs *ifa, *ift; struct if_data *if_data; u_short idx = 0; int i; size_t len, alen; char *data; char *names; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; /* protocol */ mib[3] = 0; /* wildcard address family */ mib[4] = NET_RT_IFLISTL;/* extra fields for extensible msghdr structs */ mib[5] = 0; /* no flags */ do { /* * We'll try to get addresses several times in case that * the number of addresses is unexpectedly increased during * the two sysctl calls. This should rarely happen, but we'll * try to do our best for applications that assume success of * this library (which should usually be the case). * Portability note: since FreeBSD does not add margin of * memory at the first sysctl, the possibility of failure on * the second sysctl call is a bit higher. */ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) return (-1); if ((buf = malloc(needed)) == NULL) return (-1); if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { free(buf); return (-1); } free(buf); buf = NULL; } } while (buf == NULL); for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)(void *)next; if (rtm->rtm_version != RTM_VERSION) continue; switch (rtm->rtm_type) { case RTM_IFINFO: ifm = (struct if_msghdrl *)(void *)rtm; if (ifm->ifm_addrs & RTA_IFP) { idx = ifm->ifm_index; ++icnt; if_data = IF_MSGHDRL_IFM_DATA(ifm); dcnt += if_data->ifi_datalen; dl = (struct sockaddr_dl *)IF_MSGHDRL_RTA(ifm); dcnt += SA_RLEN((struct sockaddr *)(void*)dl) + ALIGNBYTES; ncnt += dl->sdl_nlen + 1; } else idx = 0; break; case RTM_NEWADDR: ifam = (struct ifa_msghdrl *)(void *)rtm; if (idx && ifam->ifam_index != idx) abort(); /* this cannot happen */ #define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD) if (idx == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0) break; p = (char *)IFA_MSGHDRL_RTA(ifam); ++icnt; if_data = IFA_MSGHDRL_IFAM_DATA(ifam); dcnt += if_data->ifi_datalen + ALIGNBYTES; /* Scan to look for length of address */ alen = 0; for (p0 = p, i = 0; i < RTAX_MAX; i++) { if ((RTA_MASKS & ifam->ifam_addrs & (1 << i)) == 0) continue; sa = (struct sockaddr *)(void *)p; len = SA_RLEN(sa); if (i == RTAX_IFA) { alen = len; break; } p += len; } for (p = p0, i = 0; i < RTAX_MAX; i++) { if ((RTA_MASKS & ifam->ifam_addrs & (1 << i)) == 0) continue; sa = (struct sockaddr *)(void *)p; len = SA_RLEN(sa); if (i == RTAX_NETMASK && SA_LEN(sa) == 0) dcnt += alen; else dcnt += len; p += len; } break; } } if (icnt + dcnt + ncnt == 1) { *pif = NULL; free(buf); return (0); } data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt); if (data == NULL) { free(buf); return(-1); } ifa = (struct ifaddrs *)(void *)data; data += sizeof(struct ifaddrs) * icnt; names = data + dcnt; memset(ifa, 0, sizeof(struct ifaddrs) * icnt); ift = ifa; idx = 0; cif = NULL; for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)(void *)next; if (rtm->rtm_version != RTM_VERSION) continue; switch (rtm->rtm_type) { case RTM_IFINFO: ifm = (struct if_msghdrl *)(void *)rtm; if ((ifm->ifm_addrs & RTA_IFP) == 0) { idx = 0; break; } idx = ifm->ifm_index; dl = (struct sockaddr_dl *)IF_MSGHDRL_RTA(ifm); cif = ift; ift->ifa_name = names; ift->ifa_flags = (int)ifm->ifm_flags; memcpy(names, dl->sdl_data, (size_t)dl->sdl_nlen); names[dl->sdl_nlen] = 0; names += dl->sdl_nlen + 1; ift->ifa_addr = (struct sockaddr *)(void *)data; memcpy(data, dl, (size_t)SA_LEN((struct sockaddr *) (void *)dl)); data += SA_RLEN((struct sockaddr *)(void *)dl); if_data = IF_MSGHDRL_IFM_DATA(ifm); /* ifm_data needs to be aligned */ ift->ifa_data = data = (void *)ALIGN(data); memcpy(data, if_data, if_data->ifi_datalen); data += if_data->ifi_datalen; ift = (ift->ifa_next = ift + 1); break; case RTM_NEWADDR: ifam = (struct ifa_msghdrl *)(void *)rtm; if (idx && ifam->ifam_index != idx) abort(); /* this cannot happen */ if (idx == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0) break; ift->ifa_name = cif->ifa_name; ift->ifa_flags = cif->ifa_flags; ift->ifa_data = NULL; p = (char *)IFA_MSGHDRL_RTA(ifam); /* Scan to look for length of address */ alen = 0; for (p0 = p, i = 0; i < RTAX_MAX; i++) { if ((RTA_MASKS & ifam->ifam_addrs & (1 << i)) == 0) continue; sa = (struct sockaddr *)(void *)p; len = SA_RLEN(sa); if (i == RTAX_IFA) { alen = len; break; } p += len; } for (p = p0, i = 0; i < RTAX_MAX; i++) { if ((RTA_MASKS & ifam->ifam_addrs & (1 << i)) == 0) continue; sa = (struct sockaddr *)(void *)p; len = SA_RLEN(sa); switch (i) { case RTAX_IFA: ift->ifa_addr = (struct sockaddr *)(void *)data; memcpy(data, p, len); data += len; break; case RTAX_NETMASK: ift->ifa_netmask = (struct sockaddr *)(void *)data; if (SA_LEN(sa) == 0) { memset(data, 0, alen); data += alen; break; } memcpy(data, p, len); data += len; break; case RTAX_BRD: ift->ifa_broadaddr = (struct sockaddr *)(void *)data; memcpy(data, p, len); data += len; break; } p += len; } if_data = IFA_MSGHDRL_IFAM_DATA(ifam); /* ifam_data needs to be aligned */ ift->ifa_data = data = (void *)ALIGN(data); memcpy(data, if_data, if_data->ifi_datalen); data += if_data->ifi_datalen; ift = (ift->ifa_next = ift + 1); break; } } free(buf); if (--ift >= ifa) { ift->ifa_next = NULL; *pif = ifa; } else { *pif = NULL; free(ifa); } return (0); } void freeifaddrs(struct ifaddrs *ifp) { free(ifp); } Index: head/lib/libc/net/if_indextoname.c =================================================================== --- head/lib/libc/net/if_indextoname.c (revision 326822) +++ head/lib/libc/net/if_indextoname.c (revision 326823) @@ -1,88 +1,90 @@ /* $KAME: if_indextoname.c,v 1.7 2000/11/08 03:09:30 itojun Exp $ */ /*- + * SPDX-License-Identifier: BSD-1-Clause + * * Copyright (c) 1997, 2000 * Berkeley Software Design, Inc. 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. * * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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. * * BSDI Id: if_indextoname.c,v 2.3 2000/04/17 22:38:05 dab Exp */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include /* * From RFC 2533: * * The second function maps an interface index into its corresponding * name. * * #include * * char *if_indextoname(unsigned int ifindex, char *ifname); * * The ifname argument must point to a buffer of at least IF_NAMESIZE * bytes into which the interface name corresponding to the specified * index is returned. (IF_NAMESIZE is also defined in and * its value includes a terminating null byte at the end of the * interface name.) This pointer is also the return value of the * function. If there is no interface corresponding to the specified * index, NULL is returned, and errno is set to ENXIO, if there was a * system error (such as running out of memory), if_indextoname returns * NULL and errno would be set to the proper value (e.g., ENOMEM). */ char * if_indextoname(unsigned int ifindex, char *ifname) { struct ifaddrs *ifaddrs, *ifa; int error = 0; if (getifaddrs(&ifaddrs) < 0) return(NULL); /* getifaddrs properly set errno */ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK && ifindex == LLINDEX((struct sockaddr_dl*)ifa->ifa_addr)) break; } if (ifa == NULL) { error = ENXIO; ifname = NULL; } else strncpy(ifname, ifa->ifa_name, IFNAMSIZ); freeifaddrs(ifaddrs); errno = error; return(ifname); } Index: head/lib/libc/net/if_nameindex.c =================================================================== --- head/lib/libc/net/if_nameindex.c (revision 326822) +++ head/lib/libc/net/if_nameindex.c (revision 326823) @@ -1,147 +1,149 @@ /* $KAME: if_nameindex.c,v 1.8 2000/11/24 08:20:01 itojun Exp $ */ /*- + * SPDX-License-Identifier: BSD-1-Clause + * * Copyright (c) 1997, 2000 * Berkeley Software Design, Inc. 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. * * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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. * * BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include /* * From RFC 2553: * * 4.3 Return All Interface Names and Indexes * * The if_nameindex structure holds the information about a single * interface and is defined as a result of including the * header. * * struct if_nameindex { * unsigned int if_index; * char *if_name; * }; * * The final function returns an array of if_nameindex structures, one * structure per interface. * * struct if_nameindex *if_nameindex(void); * * The end of the array of structures is indicated by a structure with * an if_index of 0 and an if_name of NULL. The function returns a NULL * pointer upon an error, and would set errno to the appropriate value. * * The memory used for this array of structures along with the interface * names pointed to by the if_name members is obtained dynamically. * This memory is freed by the next function. * * 4.4. Free Memory * * The following function frees the dynamic memory that was allocated by * if_nameindex(). * * #include * * void if_freenameindex(struct if_nameindex *ptr); * * The argument to this function must be a pointer that was returned by * if_nameindex(). */ struct if_nameindex * if_nameindex(void) { struct ifaddrs *ifaddrs, *ifa; unsigned int ni; int nbytes; struct if_nameindex *ifni, *ifni2; char *cp; if (getifaddrs(&ifaddrs) < 0) return(NULL); /* * First, find out how many interfaces there are, and how * much space we need for the string names. */ ni = 0; nbytes = 0; for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK) { nbytes += strlen(ifa->ifa_name) + 1; ni++; } } /* * Next, allocate a chunk of memory, use the first part * for the array of structures, and the last part for * the strings. */ cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes); ifni = (struct if_nameindex *)cp; if (ifni == NULL) goto out; cp += (ni + 1) * sizeof(struct if_nameindex); /* * Now just loop through the list of interfaces again, * filling in the if_nameindex array and making copies * of all the strings. */ ifni2 = ifni; for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK) { ifni2->if_index = LLINDEX((struct sockaddr_dl*)ifa->ifa_addr); ifni2->if_name = cp; strcpy(cp, ifa->ifa_name); ifni2++; cp += strlen(cp) + 1; } } /* * Finally, don't forget to terminate the array. */ ifni2->if_index = 0; ifni2->if_name = NULL; out: freeifaddrs(ifaddrs); return(ifni); } void if_freenameindex(struct if_nameindex *ptr) { free(ptr); } Index: head/lib/libc/net/if_nametoindex.c =================================================================== --- head/lib/libc/net/if_nametoindex.c (revision 326822) +++ head/lib/libc/net/if_nametoindex.c (revision 326823) @@ -1,100 +1,102 @@ /* $KAME: if_nametoindex.c,v 1.6 2000/11/24 08:18:54 itojun Exp $ */ /*- + * SPDX-License-Identifier: BSD-1-Clause + * * Copyright (c) 1997, 2000 * Berkeley Software Design, Inc. 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. * * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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. * * BSDI Id: if_nametoindex.c,v 2.3 2000/04/17 22:38:05 dab Exp */ #include __FBSDID("$FreeBSD$"); #include "namespace.h" #include #include #include #include #include #include #include #include #include #include #include "un-namespace.h" /* * From RFC 2553: * * 4.1 Name-to-Index * * * The first function maps an interface name into its corresponding * index. * * #include * * unsigned int if_nametoindex(const char *ifname); * * If the specified interface name does not exist, the return value is * 0, and errno is set to ENXIO. If there was a system error (such as * running out of memory), the return value is 0 and errno is set to the * proper value (e.g., ENOMEM). */ unsigned int if_nametoindex(const char *ifname) { int s; struct ifreq ifr; struct ifaddrs *ifaddrs, *ifa; unsigned int ni; s = _socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (s != -1) { memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (_ioctl(s, SIOCGIFINDEX, &ifr) != -1) { _close(s); return (ifr.ifr_index); } _close(s); } if (getifaddrs(&ifaddrs) < 0) return(0); ni = 0; for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_LINK && strcmp(ifa->ifa_name, ifname) == 0) { ni = LLINDEX((struct sockaddr_dl*)ifa->ifa_addr); break; } } freeifaddrs(ifaddrs); if (!ni) errno = ENXIO; return(ni); } Index: head/sys/dev/usb/net/if_mos.c =================================================================== --- head/sys/dev/usb/net/if_mos.c (revision 326822) +++ head/sys/dev/usb/net/if_mos.c (revision 326823) @@ -1,1032 +1,1032 @@ /*- - * SPDX-License-Identifier: 0BSD AND BSD-4-Clause + * SPDX-License-Identifier: (BSD-1-Clause AND BSD-4-Clause) * * Copyright (c) 2011 Rick van der Zwet * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /*- * Copyright (c) 2008 Johann Christian Rode * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /*- * Copyright (c) 2005, 2006, 2007 Jonathan Gray * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /*- * Copyright (c) 1997, 1998, 1999, 2000-2003 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD * 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 __FBSDID("$FreeBSD$"); /* * Moschip MCS7730/MCS7830/MCS7832 USB to Ethernet controller * The datasheet is available at the following URL: * http://www.moschip.com/data/products/MCS7830/Data%20Sheet_7830.pdf */ /* * The FreeBSD if_mos.c driver is based on various different sources: * The vendor provided driver at the following URL: * http://www.moschip.com/data/products/MCS7830/Driver_FreeBSD_7830.tar.gz * * Mixed together with the OpenBSD if_mos.c driver for validation and checking * and the FreeBSD if_reu.c as reference for the USB Ethernet framework. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "usbdevs.h" #define USB_DEBUG_VAR mos_debug #include #include #include //#include #include "if_mosreg.h" #ifdef USB_DEBUG static int mos_debug = 0; static SYSCTL_NODE(_hw_usb, OID_AUTO, mos, CTLFLAG_RW, 0, "USB mos"); SYSCTL_INT(_hw_usb_mos, OID_AUTO, debug, CTLFLAG_RWTUN, &mos_debug, 0, "Debug level"); #endif #define MOS_DPRINTFN(fmt,...) \ DPRINTF("mos: %s: " fmt "\n",__FUNCTION__,## __VA_ARGS__) #define USB_PRODUCT_MOSCHIP_MCS7730 0x7730 #define USB_PRODUCT_SITECOMEU_LN030 0x0021 /* Various supported device vendors/products. */ static const STRUCT_USB_HOST_ID mos_devs[] = { {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7730, MCS7730)}, {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7830, MCS7830)}, {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7832, MCS7832)}, {USB_VPI(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN030, MCS7830)}, }; static int mos_probe(device_t dev); static int mos_attach(device_t dev); static void mos_attach_post(struct usb_ether *ue); static int mos_detach(device_t dev); static void mos_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error); static void mos_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error); static void mos_intr_callback(struct usb_xfer *xfer, usb_error_t error); static void mos_tick(struct usb_ether *); static void mos_start(struct usb_ether *); static void mos_init(struct usb_ether *); static void mos_chip_init(struct mos_softc *); static void mos_stop(struct usb_ether *); static int mos_miibus_readreg(device_t, int, int); static int mos_miibus_writereg(device_t, int, int, int); static void mos_miibus_statchg(device_t); static int mos_ifmedia_upd(struct ifnet *); static void mos_ifmedia_sts(struct ifnet *, struct ifmediareq *); static void mos_reset(struct mos_softc *sc); static int mos_reg_read_1(struct mos_softc *, int); static int mos_reg_read_2(struct mos_softc *, int); static int mos_reg_write_1(struct mos_softc *, int, int); static int mos_reg_write_2(struct mos_softc *, int, int); static int mos_readmac(struct mos_softc *, uint8_t *); static int mos_writemac(struct mos_softc *, uint8_t *); static int mos_write_mcast(struct mos_softc *, u_char *); static void mos_setmulti(struct usb_ether *); static void mos_setpromisc(struct usb_ether *); static const struct usb_config mos_config[MOS_ENDPT_MAX] = { [MOS_ENDPT_TX] = { .type = UE_BULK, .endpoint = UE_ADDR_ANY, .direction = UE_DIR_OUT, .bufsize = (MCLBYTES + 2), .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, .callback = mos_bulk_write_callback, .timeout = 10000, }, [MOS_ENDPT_RX] = { .type = UE_BULK, .endpoint = UE_ADDR_ANY, .direction = UE_DIR_IN, .bufsize = (MCLBYTES + 4 + ETHER_CRC_LEN), .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, .callback = mos_bulk_read_callback, }, [MOS_ENDPT_INTR] = { .type = UE_INTERRUPT, .endpoint = UE_ADDR_ANY, .direction = UE_DIR_IN, .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, .bufsize = 0, .callback = mos_intr_callback, }, }; static device_method_t mos_methods[] = { /* Device interface */ DEVMETHOD(device_probe, mos_probe), DEVMETHOD(device_attach, mos_attach), DEVMETHOD(device_detach, mos_detach), /* MII interface */ DEVMETHOD(miibus_readreg, mos_miibus_readreg), DEVMETHOD(miibus_writereg, mos_miibus_writereg), DEVMETHOD(miibus_statchg, mos_miibus_statchg), DEVMETHOD_END }; static driver_t mos_driver = { .name = "mos", .methods = mos_methods, .size = sizeof(struct mos_softc) }; static devclass_t mos_devclass; DRIVER_MODULE(mos, uhub, mos_driver, mos_devclass, NULL, 0); DRIVER_MODULE(miibus, mos, miibus_driver, miibus_devclass, 0, 0); MODULE_DEPEND(mos, uether, 1, 1, 1); MODULE_DEPEND(mos, usb, 1, 1, 1); MODULE_DEPEND(mos, ether, 1, 1, 1); MODULE_DEPEND(mos, miibus, 1, 1, 1); USB_PNP_HOST_INFO(mos_devs); static const struct usb_ether_methods mos_ue_methods = { .ue_attach_post = mos_attach_post, .ue_start = mos_start, .ue_init = mos_init, .ue_stop = mos_stop, .ue_tick = mos_tick, .ue_setmulti = mos_setmulti, .ue_setpromisc = mos_setpromisc, .ue_mii_upd = mos_ifmedia_upd, .ue_mii_sts = mos_ifmedia_sts, }; static int mos_reg_read_1(struct mos_softc *sc, int reg) { struct usb_device_request req; usb_error_t err; uByte val = 0; req.bmRequestType = UT_READ_VENDOR_DEVICE; req.bRequest = MOS_UR_READREG; USETW(req.wValue, 0); USETW(req.wIndex, reg); USETW(req.wLength, 1); err = uether_do_request(&sc->sc_ue, &req, &val, 1000); if (err) { MOS_DPRINTFN("mos_reg_read_1 error, reg: %d\n", reg); return (-1); } return (val); } static int mos_reg_read_2(struct mos_softc *sc, int reg) { struct usb_device_request req; usb_error_t err; uWord val; USETW(val, 0); req.bmRequestType = UT_READ_VENDOR_DEVICE; req.bRequest = MOS_UR_READREG; USETW(req.wValue, 0); USETW(req.wIndex, reg); USETW(req.wLength, 2); err = uether_do_request(&sc->sc_ue, &req, &val, 1000); if (err) { MOS_DPRINTFN("mos_reg_read_2 error, reg: %d", reg); return (-1); } return (UGETW(val)); } static int mos_reg_write_1(struct mos_softc *sc, int reg, int aval) { struct usb_device_request req; usb_error_t err; uByte val; val = aval; req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = MOS_UR_WRITEREG; USETW(req.wValue, 0); USETW(req.wIndex, reg); USETW(req.wLength, 1); err = uether_do_request(&sc->sc_ue, &req, &val, 1000); if (err) { MOS_DPRINTFN("mos_reg_write_1 error, reg: %d", reg); return (-1); } return (0); } static int mos_reg_write_2(struct mos_softc *sc, int reg, int aval) { struct usb_device_request req; usb_error_t err; uWord val; USETW(val, aval); req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = MOS_UR_WRITEREG; USETW(req.wValue, 0); USETW(req.wIndex, reg); USETW(req.wLength, 2); err = uether_do_request(&sc->sc_ue, &req, &val, 1000); if (err) { MOS_DPRINTFN("mos_reg_write_2 error, reg: %d", reg); return (-1); } return (0); } static int mos_readmac(struct mos_softc *sc, u_char *mac) { struct usb_device_request req; usb_error_t err; req.bmRequestType = UT_READ_VENDOR_DEVICE; req.bRequest = MOS_UR_READREG; USETW(req.wValue, 0); USETW(req.wIndex, MOS_MAC); USETW(req.wLength, ETHER_ADDR_LEN); err = uether_do_request(&sc->sc_ue, &req, mac, 1000); if (err) { return (-1); } return (0); } static int mos_writemac(struct mos_softc *sc, uint8_t *mac) { struct usb_device_request req; usb_error_t err; req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = MOS_UR_WRITEREG; USETW(req.wValue, 0); USETW(req.wIndex, MOS_MAC); USETW(req.wLength, ETHER_ADDR_LEN); err = uether_do_request(&sc->sc_ue, &req, mac, 1000); if (err) { MOS_DPRINTFN("mos_writemac error"); return (-1); } return (0); } static int mos_write_mcast(struct mos_softc *sc, u_char *hashtbl) { struct usb_device_request req; usb_error_t err; req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = MOS_UR_WRITEREG; USETW(req.wValue, 0); USETW(req.wIndex, MOS_MCAST_TABLE); USETW(req.wLength, 8); err = uether_do_request(&sc->sc_ue, &req, hashtbl, 1000); if (err) { MOS_DPRINTFN("mos_reg_mcast error"); return (-1); } return (0); } static int mos_miibus_readreg(device_t dev, int phy, int reg) { struct mos_softc *sc = device_get_softc(dev); uWord val; int i, res, locked; USETW(val, 0); locked = mtx_owned(&sc->sc_mtx); if (!locked) MOS_LOCK(sc); mos_reg_write_2(sc, MOS_PHY_DATA, 0); mos_reg_write_1(sc, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) | MOS_PHYCTL_READ); mos_reg_write_1(sc, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) | MOS_PHYSTS_PENDING); for (i = 0; i < MOS_TIMEOUT; i++) { if (mos_reg_read_1(sc, MOS_PHY_STS) & MOS_PHYSTS_READY) break; } if (i == MOS_TIMEOUT) { MOS_DPRINTFN("MII read timeout"); } res = mos_reg_read_2(sc, MOS_PHY_DATA); if (!locked) MOS_UNLOCK(sc); return (res); } static int mos_miibus_writereg(device_t dev, int phy, int reg, int val) { struct mos_softc *sc = device_get_softc(dev); int i, locked; locked = mtx_owned(&sc->sc_mtx); if (!locked) MOS_LOCK(sc); mos_reg_write_2(sc, MOS_PHY_DATA, val); mos_reg_write_1(sc, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) | MOS_PHYCTL_WRITE); mos_reg_write_1(sc, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) | MOS_PHYSTS_PENDING); for (i = 0; i < MOS_TIMEOUT; i++) { if (mos_reg_read_1(sc, MOS_PHY_STS) & MOS_PHYSTS_READY) break; } if (i == MOS_TIMEOUT) MOS_DPRINTFN("MII write timeout"); if (!locked) MOS_UNLOCK(sc); return 0; } static void mos_miibus_statchg(device_t dev) { struct mos_softc *sc = device_get_softc(dev); struct mii_data *mii = GET_MII(sc); int val, err, locked; locked = mtx_owned(&sc->sc_mtx); if (!locked) MOS_LOCK(sc); /* disable RX, TX prior to changing FDX, SPEEDSEL */ val = mos_reg_read_1(sc, MOS_CTL); val &= ~(MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); mos_reg_write_1(sc, MOS_CTL, val); /* reset register which counts dropped frames */ mos_reg_write_1(sc, MOS_FRAME_DROP_CNT, 0); if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) val |= MOS_CTL_FDX_ENB; else val &= ~(MOS_CTL_FDX_ENB); switch (IFM_SUBTYPE(mii->mii_media_active)) { case IFM_100_TX: val |= MOS_CTL_SPEEDSEL; break; case IFM_10_T: val &= ~(MOS_CTL_SPEEDSEL); break; } /* re-enable TX, RX */ val |= (MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); err = mos_reg_write_1(sc, MOS_CTL, val); if (err) MOS_DPRINTFN("media change failed"); if (!locked) MOS_UNLOCK(sc); } /* * Set media options. */ static int mos_ifmedia_upd(struct ifnet *ifp) { struct mos_softc *sc = ifp->if_softc; struct mii_data *mii = GET_MII(sc); struct mii_softc *miisc; int error; MOS_LOCK_ASSERT(sc, MA_OWNED); sc->mos_link = 0; LIST_FOREACH(miisc, &mii->mii_phys, mii_list) PHY_RESET(miisc); error = mii_mediachg(mii); return (error); } /* * Report current media status. */ static void mos_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) { struct mos_softc *sc = ifp->if_softc; struct mii_data *mii = GET_MII(sc); MOS_LOCK(sc); mii_pollstat(mii); ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; MOS_UNLOCK(sc); } static void mos_setpromisc(struct usb_ether *ue) { struct mos_softc *sc = uether_getsc(ue); struct ifnet *ifp = uether_getifp(ue); uint8_t rxmode; MOS_LOCK_ASSERT(sc, MA_OWNED); rxmode = mos_reg_read_1(sc, MOS_CTL); /* If we want promiscuous mode, set the allframes bit. */ if (ifp->if_flags & IFF_PROMISC) { rxmode |= MOS_CTL_RX_PROMISC; } else { rxmode &= ~MOS_CTL_RX_PROMISC; } mos_reg_write_1(sc, MOS_CTL, rxmode); } static void mos_setmulti(struct usb_ether *ue) { struct mos_softc *sc = uether_getsc(ue); struct ifnet *ifp = uether_getifp(ue); struct ifmultiaddr *ifma; uint32_t h = 0; uint8_t rxmode; uint8_t hashtbl[8] = {0, 0, 0, 0, 0, 0, 0, 0}; int allmulti = 0; MOS_LOCK_ASSERT(sc, MA_OWNED); rxmode = mos_reg_read_1(sc, MOS_CTL); if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) allmulti = 1; /* get all new ones */ if_maddr_rlock(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) { allmulti = 1; continue; } h = ether_crc32_be(LLADDR((struct sockaddr_dl *) ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; hashtbl[h / 8] |= 1 << (h % 8); } if_maddr_runlock(ifp); /* now program new ones */ if (allmulti == 1) { rxmode |= MOS_CTL_ALLMULTI; mos_reg_write_1(sc, MOS_CTL, rxmode); } else { rxmode &= ~MOS_CTL_ALLMULTI; mos_write_mcast(sc, (void *)&hashtbl); mos_reg_write_1(sc, MOS_CTL, rxmode); } } static void mos_reset(struct mos_softc *sc) { uint8_t ctl; ctl = mos_reg_read_1(sc, MOS_CTL); ctl &= ~(MOS_CTL_RX_PROMISC | MOS_CTL_ALLMULTI | MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); /* Disable RX, TX, promiscuous and allmulticast mode */ mos_reg_write_1(sc, MOS_CTL, ctl); /* Reset frame drop counter register to zero */ mos_reg_write_1(sc, MOS_FRAME_DROP_CNT, 0); /* Wait a little while for the chip to get its brains in order. */ usb_pause_mtx(&sc->sc_mtx, hz / 128); return; } static void mos_chip_init(struct mos_softc *sc) { int i; /* * Rev.C devices have a pause threshold register which needs to be set * at startup. */ if (mos_reg_read_1(sc, MOS_PAUSE_TRHD) != -1) { for (i = 0; i < MOS_PAUSE_REWRITES; i++) mos_reg_write_1(sc, MOS_PAUSE_TRHD, 0); } sc->mos_phyaddrs[0] = 1; sc->mos_phyaddrs[1] = 0xFF; } /* * Probe for a MCS7x30 chip. */ static int mos_probe(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); int retval; if (uaa->usb_mode != USB_MODE_HOST) return (ENXIO); if (uaa->info.bConfigIndex != MOS_CONFIG_IDX) return (ENXIO); if (uaa->info.bIfaceIndex != MOS_IFACE_IDX) return (ENXIO); retval = usbd_lookup_id_by_uaa(mos_devs, sizeof(mos_devs), uaa); return (retval); } /* * Attach the interface. Allocate softc structures, do ifmedia * setup and ethernet/BPF attach. */ static int mos_attach(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); struct mos_softc *sc = device_get_softc(dev); struct usb_ether *ue = &sc->sc_ue; uint8_t iface_index; int error; sc->mos_flags = USB_GET_DRIVER_INFO(uaa); device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); iface_index = MOS_IFACE_IDX; error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, mos_config, MOS_ENDPT_MAX, sc, &sc->sc_mtx); if (error) { device_printf(dev, "allocating USB transfers failed\n"); goto detach; } ue->ue_sc = sc; ue->ue_dev = dev; ue->ue_udev = uaa->device; ue->ue_mtx = &sc->sc_mtx; ue->ue_methods = &mos_ue_methods; if (sc->mos_flags & MCS7730) { MOS_DPRINTFN("model: MCS7730"); } else if (sc->mos_flags & MCS7830) { MOS_DPRINTFN("model: MCS7830"); } else if (sc->mos_flags & MCS7832) { MOS_DPRINTFN("model: MCS7832"); } error = uether_ifattach(ue); if (error) { device_printf(dev, "could not attach interface\n"); goto detach; } return (0); detach: mos_detach(dev); return (ENXIO); } static void mos_attach_post(struct usb_ether *ue) { struct mos_softc *sc = uether_getsc(ue); int err; /* Read MAC address, inform the world. */ err = mos_readmac(sc, ue->ue_eaddr); if (err) MOS_DPRINTFN("couldn't get MAC address"); MOS_DPRINTFN("address: %s", ether_sprintf(ue->ue_eaddr)); mos_chip_init(sc); } static int mos_detach(device_t dev) { struct mos_softc *sc = device_get_softc(dev); struct usb_ether *ue = &sc->sc_ue; usbd_transfer_unsetup(sc->sc_xfer, MOS_ENDPT_MAX); uether_ifdetach(ue); mtx_destroy(&sc->sc_mtx); return (0); } /* * A frame has been uploaded: pass the resulting mbuf chain up to * the higher level protocols. */ static void mos_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) { struct mos_softc *sc = usbd_xfer_softc(xfer); struct usb_ether *ue = &sc->sc_ue; struct ifnet *ifp = uether_getifp(ue); uint8_t rxstat = 0; uint32_t actlen; uint16_t pktlen = 0; struct usb_page_cache *pc; usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); pc = usbd_xfer_get_frame(xfer, 0); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: MOS_DPRINTFN("actlen : %d", actlen); if (actlen <= 1) { if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); goto tr_setup; } /* evaluate status byte at the end */ usbd_copy_out(pc, actlen - sizeof(rxstat), &rxstat, sizeof(rxstat)); if (rxstat != MOS_RXSTS_VALID) { MOS_DPRINTFN("erroneous frame received"); if (rxstat & MOS_RXSTS_SHORT_FRAME) MOS_DPRINTFN("frame size less than 64 bytes"); if (rxstat & MOS_RXSTS_LARGE_FRAME) { MOS_DPRINTFN("frame size larger than " "1532 bytes"); } if (rxstat & MOS_RXSTS_CRC_ERROR) MOS_DPRINTFN("CRC error"); if (rxstat & MOS_RXSTS_ALIGN_ERROR) MOS_DPRINTFN("alignment error"); if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); goto tr_setup; } /* Remember the last byte was used for the status fields */ pktlen = actlen - 1; if (pktlen < sizeof(struct ether_header)) { MOS_DPRINTFN("error: pktlen %d is smaller " "than ether_header %zd", pktlen, sizeof(struct ether_header)); if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); goto tr_setup; } uether_rxbuf(ue, pc, 0, actlen); /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); usbd_transfer_submit(xfer); uether_rxflush(ue); return; default: MOS_DPRINTFN("bulk read error, %s", usbd_errstr(error)); if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); goto tr_setup; } MOS_DPRINTFN("start rx %i", usbd_xfer_max_len(xfer)); return; } } /* * A frame was downloaded to the chip. It's safe for us to clean up * the list buffers. */ static void mos_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) { struct mos_softc *sc = usbd_xfer_softc(xfer); struct ifnet *ifp = uether_getifp(&sc->sc_ue); struct usb_page_cache *pc; struct mbuf *m; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: MOS_DPRINTFN("transfer of complete"); if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: /* * XXX: don't send anything if there is no link? */ IFQ_DRV_DEQUEUE(&ifp->if_snd, m); if (m == NULL) return; pc = usbd_xfer_get_frame(xfer, 0); usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len); usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len); /* * if there's a BPF listener, bounce a copy * of this frame to him: */ BPF_MTAP(ifp, m); m_freem(m); usbd_transfer_submit(xfer); if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); return; default: MOS_DPRINTFN("usb error on tx: %s\n", usbd_errstr(error)); if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); goto tr_setup; } return; } } static void mos_tick(struct usb_ether *ue) { struct mos_softc *sc = uether_getsc(ue); struct mii_data *mii = GET_MII(sc); MOS_LOCK_ASSERT(sc, MA_OWNED); mii_tick(mii); if (!sc->mos_link && mii->mii_media_status & IFM_ACTIVE && IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { MOS_DPRINTFN("got link"); sc->mos_link++; mos_start(ue); } } static void mos_start(struct usb_ether *ue) { struct mos_softc *sc = uether_getsc(ue); /* * start the USB transfers, if not already started: */ usbd_transfer_start(sc->sc_xfer[MOS_ENDPT_TX]); usbd_transfer_start(sc->sc_xfer[MOS_ENDPT_RX]); usbd_transfer_start(sc->sc_xfer[MOS_ENDPT_INTR]); } static void mos_init(struct usb_ether *ue) { struct mos_softc *sc = uether_getsc(ue); struct ifnet *ifp = uether_getifp(ue); uint8_t rxmode; MOS_LOCK_ASSERT(sc, MA_OWNED); /* Cancel pending I/O and free all RX/TX buffers. */ mos_reset(sc); /* Write MAC address */ mos_writemac(sc, IF_LLADDR(ifp)); /* Read and set transmitter IPG values */ sc->mos_ipgs[0] = mos_reg_read_1(sc, MOS_IPG0); sc->mos_ipgs[1] = mos_reg_read_1(sc, MOS_IPG1); mos_reg_write_1(sc, MOS_IPG0, sc->mos_ipgs[0]); mos_reg_write_1(sc, MOS_IPG1, sc->mos_ipgs[1]); /* * Enable receiver and transmitter, bridge controls speed/duplex * mode */ rxmode = mos_reg_read_1(sc, MOS_CTL); rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB; rxmode &= ~(MOS_CTL_SLEEP); mos_setpromisc(ue); /* XXX: broadcast mode? */ mos_reg_write_1(sc, MOS_CTL, rxmode); /* Load the multicast filter. */ mos_setmulti(ue); ifp->if_drv_flags |= IFF_DRV_RUNNING; mos_start(ue); } static void mos_intr_callback(struct usb_xfer *xfer, usb_error_t error) { struct mos_softc *sc = usbd_xfer_softc(xfer); struct ifnet *ifp = uether_getifp(&sc->sc_ue); struct usb_page_cache *pc; uint32_t pkt; int actlen; if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); MOS_DPRINTFN("actlen %i", actlen); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: pc = usbd_xfer_get_frame(xfer, 0); usbd_copy_out(pc, 0, &pkt, sizeof(pkt)); /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: return; default: if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); goto tr_setup; } return; } } /* * Stop the adapter and free any mbufs allocated to the * RX and TX lists. */ static void mos_stop(struct usb_ether *ue) { struct mos_softc *sc = uether_getsc(ue); struct ifnet *ifp = uether_getifp(ue); mos_reset(sc); MOS_LOCK_ASSERT(sc, MA_OWNED); ifp->if_drv_flags &= ~IFF_DRV_RUNNING; /* stop all the transfers, if not already stopped */ usbd_transfer_stop(sc->sc_xfer[MOS_ENDPT_TX]); usbd_transfer_stop(sc->sc_xfer[MOS_ENDPT_RX]); usbd_transfer_stop(sc->sc_xfer[MOS_ENDPT_INTR]); sc->mos_link = 0; } Index: head/sys/dev/usb/wlan/if_uath.c =================================================================== --- head/sys/dev/usb/wlan/if_uath.c (revision 326822) +++ head/sys/dev/usb/wlan/if_uath.c (revision 326823) @@ -1,2876 +1,2876 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND 0BSD + * SPDX-License-Identifier: (BSD-2-Clause-FreeBSD AND BSD-1-Clause) * * Copyright (c) 2006 Sam Leffler, Errno Consulting * Copyright (c) 2008-2009 Weongyo Jeong * 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 at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * 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 NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. */ /* * This driver is distantly derived from a driver of the same name * by Damien Bergamini. The original copyright is included below: * * Copyright (c) 2006 * Damien Bergamini * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include __FBSDID("$FreeBSD$"); /*- * Driver for Atheros AR5523 USB parts. * * The driver requires firmware to be loaded into the device. This * is done on device discovery from a user application (uathload) * that is launched by devd when a device with suitable product ID * is recognized. Once firmware has been loaded the device will * reset the USB port and re-attach with the original product ID+1 * and this driver will be attached. The firmware is licensed for * general use (royalty free) and may be incorporated in products. * Note that the firmware normally packaged with the NDIS drivers * for these devices does not work in this way and so does not work * with this driver. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef INET #include #include #include #include #include #endif #include #include #include #include #include #include #include "usbdevs.h" #include #include static SYSCTL_NODE(_hw_usb, OID_AUTO, uath, CTLFLAG_RW, 0, "USB Atheros"); static int uath_countrycode = CTRY_DEFAULT; /* country code */ SYSCTL_INT(_hw_usb_uath, OID_AUTO, countrycode, CTLFLAG_RWTUN, &uath_countrycode, 0, "country code"); static int uath_regdomain = 0; /* regulatory domain */ SYSCTL_INT(_hw_usb_uath, OID_AUTO, regdomain, CTLFLAG_RD, &uath_regdomain, 0, "regulatory domain"); #ifdef UATH_DEBUG int uath_debug = 0; SYSCTL_INT(_hw_usb_uath, OID_AUTO, debug, CTLFLAG_RWTUN, &uath_debug, 0, "uath debug level"); enum { UATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ UATH_DEBUG_XMIT_DUMP = 0x00000002, /* xmit dump */ UATH_DEBUG_RECV = 0x00000004, /* basic recv operation */ UATH_DEBUG_TX_PROC = 0x00000008, /* tx ISR proc */ UATH_DEBUG_RX_PROC = 0x00000010, /* rx ISR proc */ UATH_DEBUG_RECV_ALL = 0x00000020, /* trace all frames (beacons) */ UATH_DEBUG_INIT = 0x00000040, /* initialization of dev */ UATH_DEBUG_DEVCAP = 0x00000080, /* dev caps */ UATH_DEBUG_CMDS = 0x00000100, /* commands */ UATH_DEBUG_CMDS_DUMP = 0x00000200, /* command buffer dump */ UATH_DEBUG_RESET = 0x00000400, /* reset processing */ UATH_DEBUG_STATE = 0x00000800, /* 802.11 state transitions */ UATH_DEBUG_MULTICAST = 0x00001000, /* multicast */ UATH_DEBUG_WME = 0x00002000, /* WME */ UATH_DEBUG_CHANNEL = 0x00004000, /* channel */ UATH_DEBUG_RATES = 0x00008000, /* rates */ UATH_DEBUG_CRYPTO = 0x00010000, /* crypto */ UATH_DEBUG_LED = 0x00020000, /* LED */ UATH_DEBUG_ANY = 0xffffffff }; #define DPRINTF(sc, m, fmt, ...) do { \ if (sc->sc_debug & (m)) \ printf(fmt, __VA_ARGS__); \ } while (0) #else #define DPRINTF(sc, m, fmt, ...) do { \ (void) sc; \ } while (0) #endif /* recognized device vendors/products */ static const STRUCT_USB_HOST_ID uath_devs[] = { #define UATH_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } UATH_DEV(ACCTON, SMCWUSBTG2), UATH_DEV(ATHEROS, AR5523), UATH_DEV(ATHEROS2, AR5523_1), UATH_DEV(ATHEROS2, AR5523_2), UATH_DEV(ATHEROS2, AR5523_3), UATH_DEV(CONCEPTRONIC, AR5523_1), UATH_DEV(CONCEPTRONIC, AR5523_2), UATH_DEV(DLINK, DWLAG122), UATH_DEV(DLINK, DWLAG132), UATH_DEV(DLINK, DWLG132), UATH_DEV(DLINK2, DWA120), UATH_DEV(GIGASET, AR5523), UATH_DEV(GIGASET, SMCWUSBTG), UATH_DEV(GLOBALSUN, AR5523_1), UATH_DEV(GLOBALSUN, AR5523_2), UATH_DEV(NETGEAR, WG111U), UATH_DEV(NETGEAR3, WG111T), UATH_DEV(NETGEAR3, WPN111), UATH_DEV(NETGEAR3, WPN111_2), UATH_DEV(UMEDIA, TEW444UBEU), UATH_DEV(UMEDIA, AR5523_2), UATH_DEV(WISTRONNEWEB, AR5523_1), UATH_DEV(WISTRONNEWEB, AR5523_2), UATH_DEV(ZCOM, AR5523) #undef UATH_DEV }; static usb_callback_t uath_intr_rx_callback; static usb_callback_t uath_intr_tx_callback; static usb_callback_t uath_bulk_rx_callback; static usb_callback_t uath_bulk_tx_callback; static const struct usb_config uath_usbconfig[UATH_N_XFERS] = { [UATH_INTR_RX] = { .type = UE_BULK, .endpoint = 0x1, .direction = UE_DIR_IN, .bufsize = UATH_MAX_CMDSZ, .flags = { .pipe_bof = 1, .short_xfer_ok = 1 }, .callback = uath_intr_rx_callback }, [UATH_INTR_TX] = { .type = UE_BULK, .endpoint = 0x1, .direction = UE_DIR_OUT, .bufsize = UATH_MAX_CMDSZ * UATH_CMD_LIST_COUNT, .flags = { .force_short_xfer = 1, .pipe_bof = 1, }, .callback = uath_intr_tx_callback, .timeout = UATH_CMD_TIMEOUT }, [UATH_BULK_RX] = { .type = UE_BULK, .endpoint = 0x2, .direction = UE_DIR_IN, .bufsize = MCLBYTES, .flags = { .ext_buffer = 1, .pipe_bof = 1, .short_xfer_ok = 1 }, .callback = uath_bulk_rx_callback }, [UATH_BULK_TX] = { .type = UE_BULK, .endpoint = 0x2, .direction = UE_DIR_OUT, .bufsize = UATH_MAX_TXBUFSZ * UATH_TX_DATA_LIST_COUNT, .flags = { .force_short_xfer = 1, .pipe_bof = 1 }, .callback = uath_bulk_tx_callback, .timeout = UATH_DATA_TIMEOUT } }; static struct ieee80211vap *uath_vap_create(struct ieee80211com *, const char [IFNAMSIZ], int, enum ieee80211_opmode, int, const uint8_t [IEEE80211_ADDR_LEN], const uint8_t [IEEE80211_ADDR_LEN]); static void uath_vap_delete(struct ieee80211vap *); static int uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd []); static void uath_free_cmd_list(struct uath_softc *, struct uath_cmd []); static int uath_host_available(struct uath_softc *); static int uath_get_capability(struct uath_softc *, uint32_t, uint32_t *); static int uath_get_devcap(struct uath_softc *); static struct uath_cmd * uath_get_cmdbuf(struct uath_softc *); static int uath_cmd_read(struct uath_softc *, uint32_t, const void *, int, void *, int, int); static int uath_cmd_write(struct uath_softc *, uint32_t, const void *, int, int); static void uath_stat(void *); #ifdef UATH_DEBUG static void uath_dump_cmd(const uint8_t *, int, char); static const char * uath_codename(int); #endif static int uath_get_devstatus(struct uath_softc *, uint8_t macaddr[IEEE80211_ADDR_LEN]); static int uath_get_status(struct uath_softc *, uint32_t, void *, int); static int uath_alloc_rx_data_list(struct uath_softc *); static int uath_alloc_tx_data_list(struct uath_softc *); static void uath_free_rx_data_list(struct uath_softc *); static void uath_free_tx_data_list(struct uath_softc *); static int uath_init(struct uath_softc *); static void uath_stop(struct uath_softc *); static void uath_parent(struct ieee80211com *); static int uath_transmit(struct ieee80211com *, struct mbuf *); static void uath_start(struct uath_softc *); static int uath_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); static void uath_scan_start(struct ieee80211com *); static void uath_scan_end(struct ieee80211com *); static void uath_set_channel(struct ieee80211com *); static void uath_update_mcast(struct ieee80211com *); static void uath_update_promisc(struct ieee80211com *); static int uath_config(struct uath_softc *, uint32_t, uint32_t); static int uath_config_multi(struct uath_softc *, uint32_t, const void *, int); static int uath_switch_channel(struct uath_softc *, struct ieee80211_channel *); static int uath_set_rxfilter(struct uath_softc *, uint32_t, uint32_t); static void uath_watchdog(void *); static void uath_abort_xfers(struct uath_softc *); static int uath_dataflush(struct uath_softc *); static int uath_cmdflush(struct uath_softc *); static int uath_flush(struct uath_softc *); static int uath_set_ledstate(struct uath_softc *, int); static int uath_set_chan(struct uath_softc *, struct ieee80211_channel *); static int uath_reset_tx_queues(struct uath_softc *); static int uath_wme_init(struct uath_softc *); static struct uath_data * uath_getbuf(struct uath_softc *); static int uath_newstate(struct ieee80211vap *, enum ieee80211_state, int); static int uath_set_key(struct uath_softc *, const struct ieee80211_key *, int); static int uath_set_keys(struct uath_softc *, struct ieee80211vap *); static void uath_sysctl_node(struct uath_softc *); static int uath_match(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); if (uaa->usb_mode != USB_MODE_HOST) return (ENXIO); if (uaa->info.bConfigIndex != UATH_CONFIG_INDEX) return (ENXIO); if (uaa->info.bIfaceIndex != UATH_IFACE_INDEX) return (ENXIO); return (usbd_lookup_id_by_uaa(uath_devs, sizeof(uath_devs), uaa)); } static int uath_attach(device_t dev) { struct uath_softc *sc = device_get_softc(dev); struct usb_attach_arg *uaa = device_get_ivars(dev); struct ieee80211com *ic = &sc->sc_ic; uint8_t bands[IEEE80211_MODE_BYTES]; uint8_t iface_index = UATH_IFACE_INDEX; /* XXX */ usb_error_t error; sc->sc_dev = dev; sc->sc_udev = uaa->device; #ifdef UATH_DEBUG sc->sc_debug = uath_debug; #endif device_set_usb_desc(dev); /* * Only post-firmware devices here. */ mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, MTX_DEF); callout_init(&sc->stat_ch, 0); callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0); mbufq_init(&sc->sc_snd, ifqmaxlen); error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx); if (error) { device_printf(dev, "could not allocate USB transfers, " "err=%s\n", usbd_errstr(error)); goto fail; } sc->sc_cmd_dma_buf = usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_INTR_TX], 0); sc->sc_tx_dma_buf = usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_BULK_TX], 0); /* * Setup buffers for firmware commands. */ error = uath_alloc_cmd_list(sc, sc->sc_cmd); if (error != 0) { device_printf(sc->sc_dev, "could not allocate Tx command list\n"); goto fail1; } /* * We're now ready to send+receive firmware commands. */ UATH_LOCK(sc); error = uath_host_available(sc); if (error != 0) { device_printf(sc->sc_dev, "could not initialize adapter\n"); goto fail2; } error = uath_get_devcap(sc); if (error != 0) { device_printf(sc->sc_dev, "could not get device capabilities\n"); goto fail2; } UATH_UNLOCK(sc); /* Create device sysctl node. */ uath_sysctl_node(sc); UATH_LOCK(sc); error = uath_get_devstatus(sc, ic->ic_macaddr); if (error != 0) { device_printf(sc->sc_dev, "could not get device status\n"); goto fail2; } /* * Allocate xfers for Rx/Tx data pipes. */ error = uath_alloc_rx_data_list(sc); if (error != 0) { device_printf(sc->sc_dev, "could not allocate Rx data list\n"); goto fail2; } error = uath_alloc_tx_data_list(sc); if (error != 0) { device_printf(sc->sc_dev, "could not allocate Tx data list\n"); goto fail2; } UATH_UNLOCK(sc); ic->ic_softc = sc; ic->ic_name = device_get_nameunit(dev); ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ /* set device capabilities */ ic->ic_caps = IEEE80211_C_STA | /* station mode */ IEEE80211_C_MONITOR | /* monitor mode supported */ IEEE80211_C_TXPMGT | /* tx power management */ IEEE80211_C_SHPREAMBLE | /* short preamble supported */ IEEE80211_C_SHSLOT | /* short slot time supported */ IEEE80211_C_WPA | /* 802.11i */ IEEE80211_C_BGSCAN | /* capable of bg scanning */ IEEE80211_C_TXFRAG; /* handle tx frags */ /* put a regulatory domain to reveal informations. */ uath_regdomain = sc->sc_devcap.regDomain; memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); if ((sc->sc_devcap.analog5GhzRevision & 0xf0) == 0x30) setbit(bands, IEEE80211_MODE_11A); /* XXX turbo */ ieee80211_init_channels(ic, NULL, bands); ieee80211_ifattach(ic); ic->ic_raw_xmit = uath_raw_xmit; ic->ic_scan_start = uath_scan_start; ic->ic_scan_end = uath_scan_end; ic->ic_set_channel = uath_set_channel; ic->ic_vap_create = uath_vap_create; ic->ic_vap_delete = uath_vap_delete; ic->ic_update_mcast = uath_update_mcast; ic->ic_update_promisc = uath_update_promisc; ic->ic_transmit = uath_transmit; ic->ic_parent = uath_parent; ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), UATH_TX_RADIOTAP_PRESENT, &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), UATH_RX_RADIOTAP_PRESENT); if (bootverbose) ieee80211_announce(ic); return (0); fail2: UATH_UNLOCK(sc); uath_free_cmd_list(sc, sc->sc_cmd); fail1: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS); fail: return (error); } static int uath_detach(device_t dev) { struct uath_softc *sc = device_get_softc(dev); struct ieee80211com *ic = &sc->sc_ic; unsigned int x; /* * Prevent further allocations from RX/TX/CMD * data lists and ioctls */ UATH_LOCK(sc); sc->sc_flags |= UATH_FLAG_INVALID; STAILQ_INIT(&sc->sc_rx_active); STAILQ_INIT(&sc->sc_rx_inactive); STAILQ_INIT(&sc->sc_tx_active); STAILQ_INIT(&sc->sc_tx_inactive); STAILQ_INIT(&sc->sc_tx_pending); STAILQ_INIT(&sc->sc_cmd_active); STAILQ_INIT(&sc->sc_cmd_pending); STAILQ_INIT(&sc->sc_cmd_waiting); STAILQ_INIT(&sc->sc_cmd_inactive); uath_stop(sc); UATH_UNLOCK(sc); callout_drain(&sc->stat_ch); callout_drain(&sc->watchdog_ch); /* drain USB transfers */ for (x = 0; x != UATH_N_XFERS; x++) usbd_transfer_drain(sc->sc_xfer[x]); /* free data buffers */ UATH_LOCK(sc); uath_free_rx_data_list(sc); uath_free_tx_data_list(sc); uath_free_cmd_list(sc, sc->sc_cmd); UATH_UNLOCK(sc); /* free USB transfers and some data buffers */ usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS); ieee80211_ifdetach(ic); mbufq_drain(&sc->sc_snd); mtx_destroy(&sc->sc_mtx); return (0); } static void uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[]) { int i; for (i = 0; i != UATH_CMD_LIST_COUNT; i++) cmds[i].buf = NULL; } static int uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[]) { int i; STAILQ_INIT(&sc->sc_cmd_active); STAILQ_INIT(&sc->sc_cmd_pending); STAILQ_INIT(&sc->sc_cmd_waiting); STAILQ_INIT(&sc->sc_cmd_inactive); for (i = 0; i != UATH_CMD_LIST_COUNT; i++) { struct uath_cmd *cmd = &cmds[i]; cmd->sc = sc; /* backpointer for callbacks */ cmd->msgid = i; cmd->buf = ((uint8_t *)sc->sc_cmd_dma_buf) + (i * UATH_MAX_CMDSZ); STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next); UATH_STAT_INC(sc, st_cmd_inactive); } return (0); } static int uath_host_available(struct uath_softc *sc) { struct uath_cmd_host_available setup; UATH_ASSERT_LOCKED(sc); /* inform target the host is available */ setup.sw_ver_major = htobe32(ATH_SW_VER_MAJOR); setup.sw_ver_minor = htobe32(ATH_SW_VER_MINOR); setup.sw_ver_patch = htobe32(ATH_SW_VER_PATCH); setup.sw_ver_build = htobe32(ATH_SW_VER_BUILD); return uath_cmd_read(sc, WDCMSG_HOST_AVAILABLE, &setup, sizeof setup, NULL, 0, 0); } #ifdef UATH_DEBUG static void uath_dump_cmd(const uint8_t *buf, int len, char prefix) { const char *sep = ""; int i; for (i = 0; i < len; i++) { if ((i % 16) == 0) { printf("%s%c ", sep, prefix); sep = "\n"; } else if ((i % 4) == 0) printf(" "); printf("%02x", buf[i]); } printf("\n"); } static const char * uath_codename(int code) { static const char *names[] = { "0x00", "HOST_AVAILABLE", "BIND", "TARGET_RESET", "TARGET_GET_CAPABILITY", "TARGET_SET_CONFIG", "TARGET_GET_STATUS", "TARGET_GET_STATS", "TARGET_START", "TARGET_STOP", "TARGET_ENABLE", "TARGET_DISABLE", "CREATE_CONNECTION", "UPDATE_CONNECT_ATTR", "DELETE_CONNECT", "SEND", "FLUSH", "STATS_UPDATE", "BMISS", "DEVICE_AVAIL", "SEND_COMPLETE", "DATA_AVAIL", "SET_PWR_MODE", "BMISS_ACK", "SET_LED_STEADY", "SET_LED_BLINK", "SETUP_BEACON_DESC", "BEACON_INIT", "RESET_KEY_CACHE", "RESET_KEY_CACHE_ENTRY", "SET_KEY_CACHE_ENTRY", "SET_DECOMP_MASK", "SET_REGULATORY_DOMAIN", "SET_LED_STATE", "WRITE_ASSOCID", "SET_STA_BEACON_TIMERS", "GET_TSF", "RESET_TSF", "SET_ADHOC_MODE", "SET_BASIC_RATE", "MIB_CONTROL", "GET_CHANNEL_DATA", "GET_CUR_RSSI", "SET_ANTENNA_SWITCH", "0x2c", "0x2d", "0x2e", "USE_SHORT_SLOT_TIME", "SET_POWER_MODE", "SETUP_PSPOLL_DESC", "SET_RX_MULTICAST_FILTER", "RX_FILTER", "PER_CALIBRATION", "RESET", "DISABLE", "PHY_DISABLE", "SET_TX_POWER_LIMIT", "SET_TX_QUEUE_PARAMS", "SETUP_TX_QUEUE", "RELEASE_TX_QUEUE", }; static char buf[8]; if (code < nitems(names)) return names[code]; if (code == WDCMSG_SET_DEFAULT_KEY) return "SET_DEFAULT_KEY"; snprintf(buf, sizeof(buf), "0x%02x", code); return buf; } #endif /* * Low-level function to send read or write commands to the firmware. */ static int uath_cmdsend(struct uath_softc *sc, uint32_t code, const void *idata, int ilen, void *odata, int olen, int flags) { struct uath_cmd_hdr *hdr; struct uath_cmd *cmd; int error; UATH_ASSERT_LOCKED(sc); /* grab a xfer */ cmd = uath_get_cmdbuf(sc); if (cmd == NULL) { device_printf(sc->sc_dev, "%s: empty inactive queue\n", __func__); return (ENOBUFS); } cmd->flags = flags; /* always bulk-out a multiple of 4 bytes */ cmd->buflen = roundup2(sizeof(struct uath_cmd_hdr) + ilen, 4); hdr = (struct uath_cmd_hdr *)cmd->buf; memset(hdr, 0, sizeof(struct uath_cmd_hdr)); hdr->len = htobe32(cmd->buflen); hdr->code = htobe32(code); hdr->msgid = cmd->msgid; /* don't care about endianness */ hdr->magic = htobe32((cmd->flags & UATH_CMD_FLAG_MAGIC) ? 1 << 24 : 0); memcpy((uint8_t *)(hdr + 1), idata, ilen); #ifdef UATH_DEBUG if (sc->sc_debug & UATH_DEBUG_CMDS) { printf("%s: send %s [flags 0x%x] olen %d\n", __func__, uath_codename(code), cmd->flags, olen); if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP) uath_dump_cmd(cmd->buf, cmd->buflen, '+'); } #endif cmd->odata = odata; KASSERT(odata == NULL || olen < UATH_MAX_CMDSZ - sizeof(*hdr) + sizeof(uint32_t), ("odata %p olen %u", odata, olen)); cmd->olen = olen; STAILQ_INSERT_TAIL(&sc->sc_cmd_pending, cmd, next); UATH_STAT_INC(sc, st_cmd_pending); usbd_transfer_start(sc->sc_xfer[UATH_INTR_TX]); if (cmd->flags & UATH_CMD_FLAG_READ) { usbd_transfer_start(sc->sc_xfer[UATH_INTR_RX]); /* wait at most two seconds for command reply */ error = mtx_sleep(cmd, &sc->sc_mtx, 0, "uathcmd", 2 * hz); cmd->odata = NULL; /* in case reply comes too late */ if (error != 0) { device_printf(sc->sc_dev, "timeout waiting for reply " "to cmd 0x%x (%u)\n", code, code); } else if (cmd->olen != olen) { device_printf(sc->sc_dev, "unexpected reply data count " "to cmd 0x%x (%u), got %u, expected %u\n", code, code, cmd->olen, olen); error = EINVAL; } return (error); } return (0); } static int uath_cmd_read(struct uath_softc *sc, uint32_t code, const void *idata, int ilen, void *odata, int olen, int flags) { flags |= UATH_CMD_FLAG_READ; return uath_cmdsend(sc, code, idata, ilen, odata, olen, flags); } static int uath_cmd_write(struct uath_softc *sc, uint32_t code, const void *data, int len, int flags) { flags &= ~UATH_CMD_FLAG_READ; return uath_cmdsend(sc, code, data, len, NULL, 0, flags); } static struct uath_cmd * uath_get_cmdbuf(struct uath_softc *sc) { struct uath_cmd *uc; UATH_ASSERT_LOCKED(sc); uc = STAILQ_FIRST(&sc->sc_cmd_inactive); if (uc != NULL) { STAILQ_REMOVE_HEAD(&sc->sc_cmd_inactive, next); UATH_STAT_DEC(sc, st_cmd_inactive); } else uc = NULL; if (uc == NULL) DPRINTF(sc, UATH_DEBUG_XMIT, "%s: %s\n", __func__, "out of command xmit buffers"); return (uc); } /* * This function is called periodically (every second) when associated to * query device statistics. */ static void uath_stat(void *arg) { struct uath_softc *sc = arg; int error; UATH_LOCK(sc); /* * Send request for statistics asynchronously. The timer will be * restarted when we'll get the stats notification. */ error = uath_cmd_write(sc, WDCMSG_TARGET_GET_STATS, NULL, 0, UATH_CMD_FLAG_ASYNC); if (error != 0) { device_printf(sc->sc_dev, "could not query stats, error %d\n", error); } UATH_UNLOCK(sc); } static int uath_get_capability(struct uath_softc *sc, uint32_t cap, uint32_t *val) { int error; cap = htobe32(cap); error = uath_cmd_read(sc, WDCMSG_TARGET_GET_CAPABILITY, &cap, sizeof cap, val, sizeof(uint32_t), UATH_CMD_FLAG_MAGIC); if (error != 0) { device_printf(sc->sc_dev, "could not read capability %u\n", be32toh(cap)); return (error); } *val = be32toh(*val); return (error); } static int uath_get_devcap(struct uath_softc *sc) { #define GETCAP(x, v) do { \ error = uath_get_capability(sc, x, &v); \ if (error != 0) \ return (error); \ DPRINTF(sc, UATH_DEBUG_DEVCAP, \ "%s: %s=0x%08x\n", __func__, #x, v); \ } while (0) struct uath_devcap *cap = &sc->sc_devcap; int error; /* collect device capabilities */ GETCAP(CAP_TARGET_VERSION, cap->targetVersion); GETCAP(CAP_TARGET_REVISION, cap->targetRevision); GETCAP(CAP_MAC_VERSION, cap->macVersion); GETCAP(CAP_MAC_REVISION, cap->macRevision); GETCAP(CAP_PHY_REVISION, cap->phyRevision); GETCAP(CAP_ANALOG_5GHz_REVISION, cap->analog5GhzRevision); GETCAP(CAP_ANALOG_2GHz_REVISION, cap->analog2GhzRevision); GETCAP(CAP_REG_DOMAIN, cap->regDomain); GETCAP(CAP_REG_CAP_BITS, cap->regCapBits); #if 0 /* NB: not supported in rev 1.5 */ GETCAP(CAP_COUNTRY_CODE, cap->countryCode); #endif GETCAP(CAP_WIRELESS_MODES, cap->wirelessModes); GETCAP(CAP_CHAN_SPREAD_SUPPORT, cap->chanSpreadSupport); GETCAP(CAP_COMPRESS_SUPPORT, cap->compressSupport); GETCAP(CAP_BURST_SUPPORT, cap->burstSupport); GETCAP(CAP_FAST_FRAMES_SUPPORT, cap->fastFramesSupport); GETCAP(CAP_CHAP_TUNING_SUPPORT, cap->chapTuningSupport); GETCAP(CAP_TURBOG_SUPPORT, cap->turboGSupport); GETCAP(CAP_TURBO_PRIME_SUPPORT, cap->turboPrimeSupport); GETCAP(CAP_DEVICE_TYPE, cap->deviceType); GETCAP(CAP_WME_SUPPORT, cap->wmeSupport); GETCAP(CAP_TOTAL_QUEUES, cap->numTxQueues); GETCAP(CAP_CONNECTION_ID_MAX, cap->connectionIdMax); GETCAP(CAP_LOW_5GHZ_CHAN, cap->low5GhzChan); GETCAP(CAP_HIGH_5GHZ_CHAN, cap->high5GhzChan); GETCAP(CAP_LOW_2GHZ_CHAN, cap->low2GhzChan); GETCAP(CAP_HIGH_2GHZ_CHAN, cap->high2GhzChan); GETCAP(CAP_TWICE_ANTENNAGAIN_5G, cap->twiceAntennaGain5G); GETCAP(CAP_TWICE_ANTENNAGAIN_2G, cap->twiceAntennaGain2G); GETCAP(CAP_CIPHER_AES_CCM, cap->supportCipherAES_CCM); GETCAP(CAP_CIPHER_TKIP, cap->supportCipherTKIP); GETCAP(CAP_MIC_TKIP, cap->supportMicTKIP); cap->supportCipherWEP = 1; /* NB: always available */ return (0); } static int uath_get_devstatus(struct uath_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN]) { int error; /* retrieve MAC address */ error = uath_get_status(sc, ST_MAC_ADDR, macaddr, IEEE80211_ADDR_LEN); if (error != 0) { device_printf(sc->sc_dev, "could not read MAC address\n"); return (error); } error = uath_get_status(sc, ST_SERIAL_NUMBER, &sc->sc_serial[0], sizeof(sc->sc_serial)); if (error != 0) { device_printf(sc->sc_dev, "could not read device serial number\n"); return (error); } return (0); } static int uath_get_status(struct uath_softc *sc, uint32_t which, void *odata, int olen) { int error; which = htobe32(which); error = uath_cmd_read(sc, WDCMSG_TARGET_GET_STATUS, &which, sizeof(which), odata, olen, UATH_CMD_FLAG_MAGIC); if (error != 0) device_printf(sc->sc_dev, "could not read EEPROM offset 0x%02x\n", be32toh(which)); return (error); } static void uath_free_data_list(struct uath_softc *sc, struct uath_data data[], int ndata, int fillmbuf) { int i; for (i = 0; i < ndata; i++) { struct uath_data *dp = &data[i]; if (fillmbuf == 1) { if (dp->m != NULL) { m_freem(dp->m); dp->m = NULL; dp->buf = NULL; } } else { dp->buf = NULL; } if (dp->ni != NULL) { ieee80211_free_node(dp->ni); dp->ni = NULL; } } } static int uath_alloc_data_list(struct uath_softc *sc, struct uath_data data[], int ndata, int maxsz, void *dma_buf) { int i, error; for (i = 0; i < ndata; i++) { struct uath_data *dp = &data[i]; dp->sc = sc; if (dma_buf == NULL) { /* XXX check maxsz */ dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (dp->m == NULL) { device_printf(sc->sc_dev, "could not allocate rx mbuf\n"); error = ENOMEM; goto fail; } dp->buf = mtod(dp->m, uint8_t *); } else { dp->m = NULL; dp->buf = ((uint8_t *)dma_buf) + (i * maxsz); } dp->ni = NULL; } return (0); fail: uath_free_data_list(sc, data, ndata, 1 /* free mbufs */); return (error); } static int uath_alloc_rx_data_list(struct uath_softc *sc) { int error, i; /* XXX is it enough to store the RX packet with MCLBYTES bytes? */ error = uath_alloc_data_list(sc, sc->sc_rx, UATH_RX_DATA_LIST_COUNT, MCLBYTES, NULL /* setup mbufs */); if (error != 0) return (error); STAILQ_INIT(&sc->sc_rx_active); STAILQ_INIT(&sc->sc_rx_inactive); for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) { STAILQ_INSERT_HEAD(&sc->sc_rx_inactive, &sc->sc_rx[i], next); UATH_STAT_INC(sc, st_rx_inactive); } return (0); } static int uath_alloc_tx_data_list(struct uath_softc *sc) { int error, i; error = uath_alloc_data_list(sc, sc->sc_tx, UATH_TX_DATA_LIST_COUNT, UATH_MAX_TXBUFSZ, sc->sc_tx_dma_buf); if (error != 0) return (error); STAILQ_INIT(&sc->sc_tx_active); STAILQ_INIT(&sc->sc_tx_inactive); STAILQ_INIT(&sc->sc_tx_pending); for (i = 0; i < UATH_TX_DATA_LIST_COUNT; i++) { STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, &sc->sc_tx[i], next); UATH_STAT_INC(sc, st_tx_inactive); } return (0); } static void uath_free_rx_data_list(struct uath_softc *sc) { uath_free_data_list(sc, sc->sc_rx, UATH_RX_DATA_LIST_COUNT, 1 /* free mbufs */); } static void uath_free_tx_data_list(struct uath_softc *sc) { uath_free_data_list(sc, sc->sc_tx, UATH_TX_DATA_LIST_COUNT, 0 /* no mbufs */); } static struct ieee80211vap * uath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode, int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { struct uath_vap *uvp; struct ieee80211vap *vap; if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return (NULL); uvp = malloc(sizeof(struct uath_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &uvp->vap; /* enable s/w bmiss handling for sta mode */ if (ieee80211_vap_setup(ic, vap, name, unit, opmode, flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) { /* out of memory */ free(uvp, M_80211_VAP); return (NULL); } /* override state transition machine */ uvp->newstate = vap->iv_newstate; vap->iv_newstate = uath_newstate; /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status, mac); ic->ic_opmode = opmode; return (vap); } static void uath_vap_delete(struct ieee80211vap *vap) { struct uath_vap *uvp = UATH_VAP(vap); ieee80211_vap_detach(vap); free(uvp, M_80211_VAP); } static int uath_init(struct uath_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t val; int error; UATH_ASSERT_LOCKED(sc); if (sc->sc_flags & UATH_FLAG_INITDONE) uath_stop(sc); /* reset variables */ sc->sc_intrx_nextnum = sc->sc_msgid = 0; val = htobe32(0); uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof val, 0); /* set MAC address */ uath_config_multi(sc, CFG_MAC_ADDR, vap ? vap->iv_myaddr : ic->ic_macaddr, IEEE80211_ADDR_LEN); /* XXX honor net80211 state */ uath_config(sc, CFG_RATE_CONTROL_ENABLE, 0x00000001); uath_config(sc, CFG_DIVERSITY_CTL, 0x00000001); uath_config(sc, CFG_ABOLT, 0x0000003f); uath_config(sc, CFG_WME_ENABLED, 0x00000001); uath_config(sc, CFG_SERVICE_TYPE, 1); uath_config(sc, CFG_TP_SCALE, 0x00000000); uath_config(sc, CFG_TPC_HALF_DBM5, 0x0000003c); uath_config(sc, CFG_TPC_HALF_DBM2, 0x0000003c); uath_config(sc, CFG_OVERRD_TX_POWER, 0x00000000); uath_config(sc, CFG_GMODE_PROTECTION, 0x00000000); uath_config(sc, CFG_GMODE_PROTECT_RATE_INDEX, 0x00000003); uath_config(sc, CFG_PROTECTION_TYPE, 0x00000000); uath_config(sc, CFG_MODE_CTS, 0x00000002); error = uath_cmd_read(sc, WDCMSG_TARGET_START, NULL, 0, &val, sizeof(val), UATH_CMD_FLAG_MAGIC); if (error) { device_printf(sc->sc_dev, "could not start target, error %d\n", error); goto fail; } DPRINTF(sc, UATH_DEBUG_INIT, "%s returns handle: 0x%x\n", uath_codename(WDCMSG_TARGET_START), be32toh(val)); /* set default channel */ error = uath_switch_channel(sc, ic->ic_curchan); if (error) { device_printf(sc->sc_dev, "could not switch channel, error %d\n", error); goto fail; } val = htobe32(TARGET_DEVICE_AWAKE); uath_cmd_write(sc, WDCMSG_SET_PWR_MODE, &val, sizeof val, 0); /* XXX? check */ uath_cmd_write(sc, WDCMSG_RESET_KEY_CACHE, NULL, 0, 0); usbd_transfer_start(sc->sc_xfer[UATH_BULK_RX]); /* enable Rx */ uath_set_rxfilter(sc, 0x0, UATH_FILTER_OP_INIT); uath_set_rxfilter(sc, UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST | UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON, UATH_FILTER_OP_SET); sc->sc_flags |= UATH_FLAG_INITDONE; callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc); return (0); fail: uath_stop(sc); return (error); } static void uath_stop(struct uath_softc *sc) { UATH_ASSERT_LOCKED(sc); sc->sc_flags &= ~UATH_FLAG_INITDONE; callout_stop(&sc->stat_ch); callout_stop(&sc->watchdog_ch); sc->sc_tx_timer = 0; /* abort pending transmits */ uath_abort_xfers(sc); /* flush data & control requests into the target */ (void)uath_flush(sc); /* set a LED status to the disconnected. */ uath_set_ledstate(sc, 0); /* stop the target */ uath_cmd_write(sc, WDCMSG_TARGET_STOP, NULL, 0, 0); } static int uath_config(struct uath_softc *sc, uint32_t reg, uint32_t val) { struct uath_write_mac write; int error; write.reg = htobe32(reg); write.len = htobe32(0); /* 0 = single write */ *(uint32_t *)write.data = htobe32(val); error = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write, 3 * sizeof (uint32_t), 0); if (error != 0) { device_printf(sc->sc_dev, "could not write register 0x%02x\n", reg); } return (error); } static int uath_config_multi(struct uath_softc *sc, uint32_t reg, const void *data, int len) { struct uath_write_mac write; int error; write.reg = htobe32(reg); write.len = htobe32(len); bcopy(data, write.data, len); /* properly handle the case where len is zero (reset) */ error = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write, (len == 0) ? sizeof (uint32_t) : 2 * sizeof (uint32_t) + len, 0); if (error != 0) { device_printf(sc->sc_dev, "could not write %d bytes to register 0x%02x\n", len, reg); } return (error); } static int uath_switch_channel(struct uath_softc *sc, struct ieee80211_channel *c) { int error; UATH_ASSERT_LOCKED(sc); /* set radio frequency */ error = uath_set_chan(sc, c); if (error) { device_printf(sc->sc_dev, "could not set channel, error %d\n", error); goto failed; } /* reset Tx rings */ error = uath_reset_tx_queues(sc); if (error) { device_printf(sc->sc_dev, "could not reset Tx queues, error %d\n", error); goto failed; } /* set Tx rings WME properties */ error = uath_wme_init(sc); if (error) { device_printf(sc->sc_dev, "could not init Tx queues, error %d\n", error); goto failed; } error = uath_set_ledstate(sc, 0); if (error) { device_printf(sc->sc_dev, "could not set led state, error %d\n", error); goto failed; } error = uath_flush(sc); if (error) { device_printf(sc->sc_dev, "could not flush pipes, error %d\n", error); goto failed; } failed: return (error); } static int uath_set_rxfilter(struct uath_softc *sc, uint32_t bits, uint32_t op) { struct uath_cmd_rx_filter rxfilter; rxfilter.bits = htobe32(bits); rxfilter.op = htobe32(op); DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, "setting Rx filter=0x%x flags=0x%x\n", bits, op); return uath_cmd_write(sc, WDCMSG_RX_FILTER, &rxfilter, sizeof rxfilter, 0); } static void uath_watchdog(void *arg) { struct uath_softc *sc = arg; struct ieee80211com *ic = &sc->sc_ic; if (sc->sc_tx_timer > 0) { if (--sc->sc_tx_timer == 0) { device_printf(sc->sc_dev, "device timeout\n"); /*uath_init(sc); XXX needs a process context! */ counter_u64_add(ic->ic_oerrors, 1); return; } callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc); } } static void uath_abort_xfers(struct uath_softc *sc) { int i; UATH_ASSERT_LOCKED(sc); /* abort any pending transfers */ for (i = 0; i < UATH_N_XFERS; i++) usbd_transfer_stop(sc->sc_xfer[i]); } static int uath_flush(struct uath_softc *sc) { int error; error = uath_dataflush(sc); if (error != 0) goto failed; error = uath_cmdflush(sc); if (error != 0) goto failed; failed: return (error); } static int uath_cmdflush(struct uath_softc *sc) { return uath_cmd_write(sc, WDCMSG_FLUSH, NULL, 0, 0); } static int uath_dataflush(struct uath_softc *sc) { struct uath_data *data; struct uath_chunk *chunk; struct uath_tx_desc *desc; UATH_ASSERT_LOCKED(sc); data = uath_getbuf(sc); if (data == NULL) return (ENOBUFS); data->buflen = sizeof(struct uath_chunk) + sizeof(struct uath_tx_desc); data->m = NULL; data->ni = NULL; chunk = (struct uath_chunk *)data->buf; desc = (struct uath_tx_desc *)(chunk + 1); /* one chunk only */ chunk->seqnum = 0; chunk->flags = UATH_CFLAGS_FINAL; chunk->length = htobe16(sizeof (struct uath_tx_desc)); memset(desc, 0, sizeof(struct uath_tx_desc)); desc->msglen = htobe32(sizeof(struct uath_tx_desc)); desc->msgid = (sc->sc_msgid++) + 1; /* don't care about endianness */ desc->type = htobe32(WDCMSG_FLUSH); desc->txqid = htobe32(0); desc->connid = htobe32(0); desc->flags = htobe32(0); #ifdef UATH_DEBUG if (sc->sc_debug & UATH_DEBUG_CMDS) { DPRINTF(sc, UATH_DEBUG_RESET, "send flush ix %d\n", desc->msgid); if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP) uath_dump_cmd(data->buf, data->buflen, '+'); } #endif STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next); UATH_STAT_INC(sc, st_tx_pending); sc->sc_tx_timer = 5; usbd_transfer_start(sc->sc_xfer[UATH_BULK_TX]); return (0); } static struct uath_data * _uath_getbuf(struct uath_softc *sc) { struct uath_data *bf; bf = STAILQ_FIRST(&sc->sc_tx_inactive); if (bf != NULL) { STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next); UATH_STAT_DEC(sc, st_tx_inactive); } else bf = NULL; if (bf == NULL) DPRINTF(sc, UATH_DEBUG_XMIT, "%s: %s\n", __func__, "out of xmit buffers"); return (bf); } static struct uath_data * uath_getbuf(struct uath_softc *sc) { struct uath_data *bf; UATH_ASSERT_LOCKED(sc); bf = _uath_getbuf(sc); if (bf == NULL) DPRINTF(sc, UATH_DEBUG_XMIT, "%s: stop queue\n", __func__); return (bf); } static int uath_set_ledstate(struct uath_softc *sc, int connected) { DPRINTF(sc, UATH_DEBUG_LED, "set led state %sconnected\n", connected ? "" : "!"); connected = htobe32(connected); return uath_cmd_write(sc, WDCMSG_SET_LED_STATE, &connected, sizeof connected, 0); } static int uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c) { #ifdef UATH_DEBUG struct ieee80211com *ic = &sc->sc_ic; #endif struct uath_cmd_reset reset; memset(&reset, 0, sizeof(reset)); if (IEEE80211_IS_CHAN_2GHZ(c)) reset.flags |= htobe32(UATH_CHAN_2GHZ); if (IEEE80211_IS_CHAN_5GHZ(c)) reset.flags |= htobe32(UATH_CHAN_5GHZ); /* NB: 11g =>'s 11b so don't specify both OFDM and CCK */ if (IEEE80211_IS_CHAN_OFDM(c)) reset.flags |= htobe32(UATH_CHAN_OFDM); else if (IEEE80211_IS_CHAN_CCK(c)) reset.flags |= htobe32(UATH_CHAN_CCK); /* turbo can be used in either 2GHz or 5GHz */ if (c->ic_flags & IEEE80211_CHAN_TURBO) reset.flags |= htobe32(UATH_CHAN_TURBO); reset.freq = htobe32(c->ic_freq); reset.maxrdpower = htobe32(50); /* XXX */ reset.channelchange = htobe32(1); reset.keeprccontent = htobe32(0); DPRINTF(sc, UATH_DEBUG_CHANNEL, "set channel %d, flags 0x%x freq %u\n", ieee80211_chan2ieee(ic, c), be32toh(reset.flags), be32toh(reset.freq)); return uath_cmd_write(sc, WDCMSG_RESET, &reset, sizeof reset, 0); } static int uath_reset_tx_queues(struct uath_softc *sc) { int ac, error; DPRINTF(sc, UATH_DEBUG_RESET, "%s: reset Tx queues\n", __func__); for (ac = 0; ac < 4; ac++) { const uint32_t qid = htobe32(ac); error = uath_cmd_write(sc, WDCMSG_RELEASE_TX_QUEUE, &qid, sizeof qid, 0); if (error != 0) break; } return (error); } static int uath_wme_init(struct uath_softc *sc) { /* XXX get from net80211 */ static const struct uath_wme_settings uath_wme_11g[4] = { { 7, 4, 10, 0, 0 }, /* Background */ { 3, 4, 10, 0, 0 }, /* Best-Effort */ { 3, 3, 4, 26, 0 }, /* Video */ { 2, 2, 3, 47, 0 } /* Voice */ }; struct uath_cmd_txq_setup qinfo; int ac, error; DPRINTF(sc, UATH_DEBUG_WME, "%s: setup Tx queues\n", __func__); for (ac = 0; ac < 4; ac++) { qinfo.qid = htobe32(ac); qinfo.len = htobe32(sizeof(qinfo.attr)); qinfo.attr.priority = htobe32(ac); /* XXX */ qinfo.attr.aifs = htobe32(uath_wme_11g[ac].aifsn); qinfo.attr.logcwmin = htobe32(uath_wme_11g[ac].logcwmin); qinfo.attr.logcwmax = htobe32(uath_wme_11g[ac].logcwmax); qinfo.attr.bursttime = htobe32(IEEE80211_TXOP_TO_US( uath_wme_11g[ac].txop)); qinfo.attr.mode = htobe32(uath_wme_11g[ac].acm);/*XXX? */ qinfo.attr.qflags = htobe32(1); /* XXX? */ error = uath_cmd_write(sc, WDCMSG_SETUP_TX_QUEUE, &qinfo, sizeof qinfo, 0); if (error != 0) break; } return (error); } static void uath_parent(struct ieee80211com *ic) { struct uath_softc *sc = ic->ic_softc; int startall = 0; UATH_LOCK(sc); if (sc->sc_flags & UATH_FLAG_INVALID) { UATH_UNLOCK(sc); return; } if (ic->ic_nrunning > 0) { if (!(sc->sc_flags & UATH_FLAG_INITDONE)) { uath_init(sc); startall = 1; } } else if (sc->sc_flags & UATH_FLAG_INITDONE) uath_stop(sc); UATH_UNLOCK(sc); if (startall) ieee80211_start_all(ic); } static int uath_tx_start(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, struct uath_data *data) { struct ieee80211vap *vap = ni->ni_vap; struct uath_chunk *chunk; struct uath_tx_desc *desc; const struct ieee80211_frame *wh; struct ieee80211_key *k; int framelen, msglen; UATH_ASSERT_LOCKED(sc); data->ni = ni; data->m = m0; chunk = (struct uath_chunk *)data->buf; desc = (struct uath_tx_desc *)(chunk + 1); if (ieee80211_radiotap_active_vap(vap)) { struct uath_tx_radiotap_header *tap = &sc->sc_txtap; tap->wt_flags = 0; if (m0->m_flags & M_FRAG) tap->wt_flags |= IEEE80211_RADIOTAP_F_FRAG; ieee80211_radiotap_tx(vap, m0); } wh = mtod(m0, struct ieee80211_frame *); if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { m_freem(m0); return (ENOBUFS); } /* packet header may have moved, reset our local pointer */ wh = mtod(m0, struct ieee80211_frame *); } m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(desc + 1)); framelen = m0->m_pkthdr.len + IEEE80211_CRC_LEN; msglen = framelen + sizeof (struct uath_tx_desc); data->buflen = msglen + sizeof (struct uath_chunk); /* one chunk only for now */ chunk->seqnum = sc->sc_seqnum++; chunk->flags = (m0->m_flags & M_FRAG) ? 0 : UATH_CFLAGS_FINAL; if (m0->m_flags & M_LASTFRAG) chunk->flags |= UATH_CFLAGS_FINAL; chunk->flags = UATH_CFLAGS_FINAL; chunk->length = htobe16(msglen); /* fill Tx descriptor */ desc->msglen = htobe32(msglen); /* NB: to get UATH_TX_NOTIFY reply, `msgid' must be larger than 0 */ desc->msgid = (sc->sc_msgid++) + 1; /* don't care about endianness */ desc->type = htobe32(WDCMSG_SEND); switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { case IEEE80211_FC0_TYPE_CTL: case IEEE80211_FC0_TYPE_MGT: /* NB: force all management frames to highest queue */ if (ni->ni_flags & IEEE80211_NODE_QOS) { /* NB: force all management frames to highest queue */ desc->txqid = htobe32(WME_AC_VO | UATH_TXQID_MINRATE); } else desc->txqid = htobe32(WME_AC_BE | UATH_TXQID_MINRATE); break; case IEEE80211_FC0_TYPE_DATA: /* XXX multicast frames should honor mcastrate */ desc->txqid = htobe32(M_WME_GETAC(m0)); break; default: device_printf(sc->sc_dev, "bogus frame type 0x%x (%s)\n", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); m_freem(m0); return (EIO); } if (vap->iv_state == IEEE80211_S_AUTH || vap->iv_state == IEEE80211_S_ASSOC || vap->iv_state == IEEE80211_S_RUN) desc->connid = htobe32(UATH_ID_BSS); else desc->connid = htobe32(UATH_ID_INVALID); desc->flags = htobe32(0 /* no UATH_TX_NOTIFY */); desc->buflen = htobe32(m0->m_pkthdr.len); #ifdef UATH_DEBUG DPRINTF(sc, UATH_DEBUG_XMIT, "send frame ix %u framelen %d msglen %d connid 0x%x txqid 0x%x\n", desc->msgid, framelen, msglen, be32toh(desc->connid), be32toh(desc->txqid)); if (sc->sc_debug & UATH_DEBUG_XMIT_DUMP) uath_dump_cmd(data->buf, data->buflen, '+'); #endif STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next); UATH_STAT_INC(sc, st_tx_pending); usbd_transfer_start(sc->sc_xfer[UATH_BULK_TX]); return (0); } /* * Cleanup driver resources when we run out of buffers while processing * fragments; return the tx buffers allocated and drop node references. */ static void uath_txfrag_cleanup(struct uath_softc *sc, uath_datahead *frags, struct ieee80211_node *ni) { struct uath_data *bf, *next; UATH_ASSERT_LOCKED(sc); STAILQ_FOREACH_SAFE(bf, frags, next, next) { /* NB: bf assumed clean */ STAILQ_REMOVE_HEAD(frags, next); STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); UATH_STAT_INC(sc, st_tx_inactive); ieee80211_node_decref(ni); } } /* * Setup xmit of a fragmented frame. Allocate a buffer for each frag and bump * the node reference count to reflect the held reference to be setup by * uath_tx_start. */ static int uath_txfrag_setup(struct uath_softc *sc, uath_datahead *frags, struct mbuf *m0, struct ieee80211_node *ni) { struct mbuf *m; struct uath_data *bf; UATH_ASSERT_LOCKED(sc); for (m = m0->m_nextpkt; m != NULL; m = m->m_nextpkt) { bf = uath_getbuf(sc); if (bf == NULL) { /* out of buffers, cleanup */ uath_txfrag_cleanup(sc, frags, ni); break; } ieee80211_node_incref(ni); STAILQ_INSERT_TAIL(frags, bf, next); } return !STAILQ_EMPTY(frags); } static int uath_transmit(struct ieee80211com *ic, struct mbuf *m) { struct uath_softc *sc = ic->ic_softc; int error; UATH_LOCK(sc); if ((sc->sc_flags & UATH_FLAG_INITDONE) == 0) { UATH_UNLOCK(sc); return (ENXIO); } error = mbufq_enqueue(&sc->sc_snd, m); if (error) { UATH_UNLOCK(sc); return (error); } uath_start(sc); UATH_UNLOCK(sc); return (0); } static void uath_start(struct uath_softc *sc) { struct uath_data *bf; struct ieee80211_node *ni; struct mbuf *m, *next; uath_datahead frags; UATH_ASSERT_LOCKED(sc); if ((sc->sc_flags & UATH_FLAG_INITDONE) == 0 || (sc->sc_flags & UATH_FLAG_INVALID)) return; while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { bf = uath_getbuf(sc); if (bf == NULL) { mbufq_prepend(&sc->sc_snd, m); break; } ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; m->m_pkthdr.rcvif = NULL; /* * Check for fragmentation. If this frame has been broken up * verify we have enough buffers to send all the fragments * so all go out or none... */ STAILQ_INIT(&frags); if ((m->m_flags & M_FRAG) && !uath_txfrag_setup(sc, &frags, m, ni)) { DPRINTF(sc, UATH_DEBUG_XMIT, "%s: out of txfrag buffers\n", __func__); ieee80211_free_mbuf(m); goto bad; } sc->sc_seqnum = 0; nextfrag: /* * Pass the frame to the h/w for transmission. * Fragmented frames have each frag chained together * with m_nextpkt. We know there are sufficient uath_data's * to send all the frags because of work done by * uath_txfrag_setup. */ next = m->m_nextpkt; if (uath_tx_start(sc, m, ni, bf) != 0) { bad: if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); reclaim: STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); UATH_STAT_INC(sc, st_tx_inactive); uath_txfrag_cleanup(sc, &frags, ni); ieee80211_free_node(ni); continue; } if (next != NULL) { /* * Beware of state changing between frags. XXX check sta power-save state? */ if (ni->ni_vap->iv_state != IEEE80211_S_RUN) { DPRINTF(sc, UATH_DEBUG_XMIT, "%s: flush fragmented packet, state %s\n", __func__, ieee80211_state_name[ni->ni_vap->iv_state]); ieee80211_free_mbuf(next); goto reclaim; } m = next; bf = STAILQ_FIRST(&frags); KASSERT(bf != NULL, ("no buf for txfrag")); STAILQ_REMOVE_HEAD(&frags, next); goto nextfrag; } sc->sc_tx_timer = 5; } } static int uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; struct uath_data *bf; struct uath_softc *sc = ic->ic_softc; UATH_LOCK(sc); /* prevent management frames from being sent if we're not ready */ if ((sc->sc_flags & UATH_FLAG_INVALID) || !(sc->sc_flags & UATH_FLAG_INITDONE)) { m_freem(m); UATH_UNLOCK(sc); return (ENETDOWN); } /* grab a TX buffer */ bf = uath_getbuf(sc); if (bf == NULL) { m_freem(m); UATH_UNLOCK(sc); return (ENOBUFS); } sc->sc_seqnum = 0; if (uath_tx_start(sc, m, ni, bf) != 0) { STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); UATH_STAT_INC(sc, st_tx_inactive); UATH_UNLOCK(sc); return (EIO); } UATH_UNLOCK(sc); sc->sc_tx_timer = 5; return (0); } static void uath_scan_start(struct ieee80211com *ic) { /* do nothing */ } static void uath_scan_end(struct ieee80211com *ic) { /* do nothing */ } static void uath_set_channel(struct ieee80211com *ic) { struct uath_softc *sc = ic->ic_softc; UATH_LOCK(sc); if ((sc->sc_flags & UATH_FLAG_INVALID) || (sc->sc_flags & UATH_FLAG_INITDONE) == 0) { UATH_UNLOCK(sc); return; } (void)uath_switch_channel(sc, ic->ic_curchan); UATH_UNLOCK(sc); } static int uath_set_rxmulti_filter(struct uath_softc *sc) { /* XXX broken */ return (0); } static void uath_update_mcast(struct ieee80211com *ic) { struct uath_softc *sc = ic->ic_softc; UATH_LOCK(sc); if ((sc->sc_flags & UATH_FLAG_INVALID) || (sc->sc_flags & UATH_FLAG_INITDONE) == 0) { UATH_UNLOCK(sc); return; } /* * this is for avoiding the race condition when we're try to * connect to the AP with WPA. */ if (sc->sc_flags & UATH_FLAG_INITDONE) (void)uath_set_rxmulti_filter(sc); UATH_UNLOCK(sc); } static void uath_update_promisc(struct ieee80211com *ic) { struct uath_softc *sc = ic->ic_softc; UATH_LOCK(sc); if ((sc->sc_flags & UATH_FLAG_INVALID) || (sc->sc_flags & UATH_FLAG_INITDONE) == 0) { UATH_UNLOCK(sc); return; } if (sc->sc_flags & UATH_FLAG_INITDONE) { uath_set_rxfilter(sc, UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST | UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON | UATH_FILTER_RX_PROM, UATH_FILTER_OP_SET); } UATH_UNLOCK(sc); } static int uath_create_connection(struct uath_softc *sc, uint32_t connid) { const struct ieee80211_rateset *rs; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct ieee80211_node *ni; struct uath_cmd_create_connection create; ni = ieee80211_ref_node(vap->iv_bss); memset(&create, 0, sizeof(create)); create.connid = htobe32(connid); create.bssid = htobe32(0); /* XXX packed or not? */ create.size = htobe32(sizeof(struct uath_cmd_rateset)); rs = &ni->ni_rates; create.connattr.rateset.length = rs->rs_nrates; bcopy(rs->rs_rates, &create.connattr.rateset.set[0], rs->rs_nrates); /* XXX turbo */ if (IEEE80211_IS_CHAN_A(ni->ni_chan)) create.connattr.wlanmode = htobe32(WLAN_MODE_11a); else if (IEEE80211_IS_CHAN_ANYG(ni->ni_chan)) create.connattr.wlanmode = htobe32(WLAN_MODE_11g); else create.connattr.wlanmode = htobe32(WLAN_MODE_11b); ieee80211_free_node(ni); return uath_cmd_write(sc, WDCMSG_CREATE_CONNECTION, &create, sizeof create, 0); } static int uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs) { struct uath_cmd_rates rates; memset(&rates, 0, sizeof(rates)); rates.connid = htobe32(UATH_ID_BSS); /* XXX */ rates.size = htobe32(sizeof(struct uath_cmd_rateset)); /* XXX bounds check rs->rs_nrates */ rates.rateset.length = rs->rs_nrates; bcopy(rs->rs_rates, &rates.rateset.set[0], rs->rs_nrates); DPRINTF(sc, UATH_DEBUG_RATES, "setting supported rates nrates=%d\n", rs->rs_nrates); return uath_cmd_write(sc, WDCMSG_SET_BASIC_RATE, &rates, sizeof rates, 0); } static int uath_write_associd(struct uath_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct ieee80211_node *ni; struct uath_cmd_set_associd associd; ni = ieee80211_ref_node(vap->iv_bss); memset(&associd, 0, sizeof(associd)); associd.defaultrateix = htobe32(1); /* XXX */ associd.associd = htobe32(ni->ni_associd); associd.timoffset = htobe32(0x3b); /* XXX */ IEEE80211_ADDR_COPY(associd.bssid, ni->ni_bssid); ieee80211_free_node(ni); return uath_cmd_write(sc, WDCMSG_WRITE_ASSOCID, &associd, sizeof associd, 0); } static int uath_set_ledsteady(struct uath_softc *sc, int lednum, int ledmode) { struct uath_cmd_ledsteady led; led.lednum = htobe32(lednum); led.ledmode = htobe32(ledmode); DPRINTF(sc, UATH_DEBUG_LED, "set %s led %s (steady)\n", (lednum == UATH_LED_LINK) ? "link" : "activity", ledmode ? "on" : "off"); return uath_cmd_write(sc, WDCMSG_SET_LED_STEADY, &led, sizeof led, 0); } static int uath_set_ledblink(struct uath_softc *sc, int lednum, int ledmode, int blinkrate, int slowmode) { struct uath_cmd_ledblink led; led.lednum = htobe32(lednum); led.ledmode = htobe32(ledmode); led.blinkrate = htobe32(blinkrate); led.slowmode = htobe32(slowmode); DPRINTF(sc, UATH_DEBUG_LED, "set %s led %s (blink)\n", (lednum == UATH_LED_LINK) ? "link" : "activity", ledmode ? "on" : "off"); return uath_cmd_write(sc, WDCMSG_SET_LED_BLINK, &led, sizeof led, 0); } static int uath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { enum ieee80211_state ostate = vap->iv_state; int error; struct ieee80211_node *ni; struct ieee80211com *ic = vap->iv_ic; struct uath_softc *sc = ic->ic_softc; struct uath_vap *uvp = UATH_VAP(vap); DPRINTF(sc, UATH_DEBUG_STATE, "%s: %s -> %s\n", __func__, ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]); IEEE80211_UNLOCK(ic); UATH_LOCK(sc); callout_stop(&sc->stat_ch); callout_stop(&sc->watchdog_ch); ni = ieee80211_ref_node(vap->iv_bss); switch (nstate) { case IEEE80211_S_INIT: if (ostate == IEEE80211_S_RUN) { /* turn link and activity LEDs off */ uath_set_ledstate(sc, 0); } break; case IEEE80211_S_SCAN: break; case IEEE80211_S_AUTH: /* XXX good place? set RTS threshold */ uath_config(sc, CFG_USER_RTS_THRESHOLD, vap->iv_rtsthreshold); /* XXX bad place */ error = uath_set_keys(sc, vap); if (error != 0) { device_printf(sc->sc_dev, "could not set crypto keys, error %d\n", error); break; } if (uath_switch_channel(sc, ni->ni_chan) != 0) { device_printf(sc->sc_dev, "could not switch channel\n"); break; } if (uath_create_connection(sc, UATH_ID_BSS) != 0) { device_printf(sc->sc_dev, "could not create connection\n"); break; } break; case IEEE80211_S_ASSOC: if (uath_set_rates(sc, &ni->ni_rates) != 0) { device_printf(sc->sc_dev, "could not set negotiated rate set\n"); break; } break; case IEEE80211_S_RUN: /* XXX monitor mode doesn't be tested */ if (ic->ic_opmode == IEEE80211_M_MONITOR) { uath_set_ledstate(sc, 1); break; } /* * Tx rate is controlled by firmware, report the maximum * negotiated rate in ifconfig output. */ ni->ni_txrate = ni->ni_rates.rs_rates[ni->ni_rates.rs_nrates-1]; if (uath_write_associd(sc) != 0) { device_printf(sc->sc_dev, "could not write association id\n"); break; } /* turn link LED on */ uath_set_ledsteady(sc, UATH_LED_LINK, UATH_LED_ON); /* make activity LED blink */ uath_set_ledblink(sc, UATH_LED_ACTIVITY, UATH_LED_ON, 1, 2); /* set state to associated */ uath_set_ledstate(sc, 1); /* start statistics timer */ callout_reset(&sc->stat_ch, hz, uath_stat, sc); break; default: break; } ieee80211_free_node(ni); UATH_UNLOCK(sc); IEEE80211_LOCK(ic); return (uvp->newstate(vap, nstate, arg)); } static int uath_set_key(struct uath_softc *sc, const struct ieee80211_key *wk, int index) { #if 0 struct uath_cmd_crypto crypto; int i; memset(&crypto, 0, sizeof(crypto)); crypto.keyidx = htobe32(index); crypto.magic1 = htobe32(1); crypto.size = htobe32(368); crypto.mask = htobe32(0xffff); crypto.flags = htobe32(0x80000068); if (index != UATH_DEFAULT_KEY) crypto.flags |= htobe32(index << 16); memset(crypto.magic2, 0xff, sizeof(crypto.magic2)); /* * Each byte of the key must be XOR'ed with 10101010 before being * transmitted to the firmware. */ for (i = 0; i < wk->wk_keylen; i++) crypto.key[i] = wk->wk_key[i] ^ 0xaa; DPRINTF(sc, UATH_DEBUG_CRYPTO, "setting crypto key index=%d len=%d\n", index, wk->wk_keylen); return uath_cmd_write(sc, WDCMSG_SET_KEY_CACHE_ENTRY, &crypto, sizeof crypto, 0); #else /* XXX support H/W cryto */ return (0); #endif } static int uath_set_keys(struct uath_softc *sc, struct ieee80211vap *vap) { int i, error; error = 0; for (i = 0; i < IEEE80211_WEP_NKID; i++) { const struct ieee80211_key *wk = &vap->iv_nw_keys[i]; if (wk->wk_flags & (IEEE80211_KEY_XMIT|IEEE80211_KEY_RECV)) { error = uath_set_key(sc, wk, i); if (error) return (error); } } if (vap->iv_def_txkey != IEEE80211_KEYIX_NONE) { error = uath_set_key(sc, &vap->iv_nw_keys[vap->iv_def_txkey], UATH_DEFAULT_KEY); } return (error); } #define UATH_SYSCTL_STAT_ADD32(c, h, n, p, d) \ SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d) static void uath_sysctl_node(struct uath_softc *sc) { struct sysctl_ctx_list *ctx; struct sysctl_oid_list *child; struct sysctl_oid *tree; struct uath_stat *stats; stats = &sc->sc_stat; ctx = device_get_sysctl_ctx(sc->sc_dev); child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)); tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD, NULL, "UATH statistics"); child = SYSCTL_CHILDREN(tree); UATH_SYSCTL_STAT_ADD32(ctx, child, "badchunkseqnum", &stats->st_badchunkseqnum, "Bad chunk sequence numbers"); UATH_SYSCTL_STAT_ADD32(ctx, child, "invalidlen", &stats->st_invalidlen, "Invalid length"); UATH_SYSCTL_STAT_ADD32(ctx, child, "multichunk", &stats->st_multichunk, "Multi chunks"); UATH_SYSCTL_STAT_ADD32(ctx, child, "toobigrxpkt", &stats->st_toobigrxpkt, "Too big rx packets"); UATH_SYSCTL_STAT_ADD32(ctx, child, "stopinprogress", &stats->st_stopinprogress, "Stop in progress"); UATH_SYSCTL_STAT_ADD32(ctx, child, "crcerrs", &stats->st_crcerr, "CRC errors"); UATH_SYSCTL_STAT_ADD32(ctx, child, "phyerr", &stats->st_phyerr, "PHY errors"); UATH_SYSCTL_STAT_ADD32(ctx, child, "decrypt_crcerr", &stats->st_decrypt_crcerr, "Decryption CRC errors"); UATH_SYSCTL_STAT_ADD32(ctx, child, "decrypt_micerr", &stats->st_decrypt_micerr, "Decryption Misc errors"); UATH_SYSCTL_STAT_ADD32(ctx, child, "decomperr", &stats->st_decomperr, "Decomp errors"); UATH_SYSCTL_STAT_ADD32(ctx, child, "keyerr", &stats->st_keyerr, "Key errors"); UATH_SYSCTL_STAT_ADD32(ctx, child, "err", &stats->st_err, "Unknown errors"); UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_active", &stats->st_cmd_active, "Active numbers in Command queue"); UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_inactive", &stats->st_cmd_inactive, "Inactive numbers in Command queue"); UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_pending", &stats->st_cmd_pending, "Pending numbers in Command queue"); UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_waiting", &stats->st_cmd_waiting, "Waiting numbers in Command queue"); UATH_SYSCTL_STAT_ADD32(ctx, child, "rx_active", &stats->st_rx_active, "Active numbers in RX queue"); UATH_SYSCTL_STAT_ADD32(ctx, child, "rx_inactive", &stats->st_rx_inactive, "Inactive numbers in RX queue"); UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_active", &stats->st_tx_active, "Active numbers in TX queue"); UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_inactive", &stats->st_tx_inactive, "Inactive numbers in TX queue"); UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_pending", &stats->st_tx_pending, "Pending numbers in TX queue"); } #undef UATH_SYSCTL_STAT_ADD32 CTASSERT(sizeof(u_int) >= sizeof(uint32_t)); static void uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) { struct uath_cmd_hdr *hdr; uint32_t dlen; hdr = (struct uath_cmd_hdr *)cmd->buf; /* NB: msgid is passed thru w/o byte swapping */ #ifdef UATH_DEBUG if (sc->sc_debug & UATH_DEBUG_CMDS) { uint32_t len = be32toh(hdr->len); printf("%s: %s [ix %u] len %u status %u\n", __func__, uath_codename(be32toh(hdr->code)), hdr->msgid, len, be32toh(hdr->magic)); if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP) uath_dump_cmd(cmd->buf, len > UATH_MAX_CMDSZ ? sizeof(*hdr) : len, '-'); } #endif hdr->code = be32toh(hdr->code); hdr->len = be32toh(hdr->len); hdr->magic = be32toh(hdr->magic); /* target status on return */ switch (hdr->code & 0xff) { /* reply to a read command */ default: DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL, "%s: code %d hdr len %u\n", __func__, hdr->code & 0xff, hdr->len); /* * The first response from the target after the * HOST_AVAILABLE has an invalid msgid so we must * treat it specially. */ if (hdr->msgid < UATH_CMD_LIST_COUNT) { uint32_t *rp = (uint32_t *)(hdr+1); u_int olen; if (sizeof(*hdr) > hdr->len || hdr->len >= UATH_MAX_CMDSZ) { device_printf(sc->sc_dev, "%s: invalid WDC msg length %u; " "msg ignored\n", __func__, hdr->len); return; } /* * Calculate return/receive payload size; the * first word, if present, always gives the * number of bytes--unless it's 0 in which * case a single 32-bit word should be present. */ dlen = hdr->len - sizeof(*hdr); if (dlen >= sizeof(uint32_t)) { olen = be32toh(rp[0]); dlen -= sizeof(uint32_t); if (olen == 0) { /* convention is 0 =>'s one word */ olen = sizeof(uint32_t); /* XXX KASSERT(olen == dlen ) */ } } else olen = 0; if (cmd->odata != NULL) { /* NB: cmd->olen validated in uath_cmd */ if (olen > (u_int)cmd->olen) { /* XXX complain? */ device_printf(sc->sc_dev, "%s: cmd 0x%x olen %u cmd olen %u\n", __func__, hdr->code, olen, cmd->olen); olen = cmd->olen; } if (olen > dlen) { /* XXX complain, shouldn't happen */ device_printf(sc->sc_dev, "%s: cmd 0x%x olen %u dlen %u\n", __func__, hdr->code, olen, dlen); olen = dlen; } /* XXX have submitter do this */ /* copy answer into caller's supplied buffer */ bcopy(&rp[1], cmd->odata, olen); cmd->olen = olen; } } wakeup_one(cmd); /* wake up caller */ break; case WDCMSG_TARGET_START: if (hdr->msgid >= UATH_CMD_LIST_COUNT) { /* XXX */ return; } dlen = hdr->len - sizeof(*hdr); if (dlen != sizeof(uint32_t)) { device_printf(sc->sc_dev, "%s: dlen (%u) != %zu!\n", __func__, dlen, sizeof(uint32_t)); return; } /* XXX have submitter do this */ /* copy answer into caller's supplied buffer */ bcopy(hdr+1, cmd->odata, sizeof(uint32_t)); cmd->olen = sizeof(uint32_t); wakeup_one(cmd); /* wake up caller */ break; case WDCMSG_SEND_COMPLETE: /* this notification is sent when UATH_TX_NOTIFY is set */ DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL, "%s: received Tx notification\n", __func__); break; case WDCMSG_TARGET_GET_STATS: DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL, "%s: received device statistics\n", __func__); callout_reset(&sc->stat_ch, hz, uath_stat, sc); break; } } static void uath_intr_rx_callback(struct usb_xfer *xfer, usb_error_t error) { struct uath_softc *sc = usbd_xfer_softc(xfer); struct uath_cmd *cmd; struct uath_cmd_hdr *hdr; struct usb_page_cache *pc; int actlen; usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); UATH_ASSERT_LOCKED(sc); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: cmd = STAILQ_FIRST(&sc->sc_cmd_waiting); if (cmd == NULL) goto setup; STAILQ_REMOVE_HEAD(&sc->sc_cmd_waiting, next); UATH_STAT_DEC(sc, st_cmd_waiting); STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next); UATH_STAT_INC(sc, st_cmd_inactive); if (actlen < sizeof(struct uath_cmd_hdr)) { device_printf(sc->sc_dev, "%s: short xfer error (actlen %d)\n", __func__, actlen); goto setup; } pc = usbd_xfer_get_frame(xfer, 0); usbd_copy_out(pc, 0, cmd->buf, actlen); hdr = (struct uath_cmd_hdr *)cmd->buf; hdr->len = be32toh(hdr->len); if (hdr->len > (uint32_t)actlen) { device_printf(sc->sc_dev, "%s: truncated xfer (len %u, actlen %d)\n", __func__, hdr->len, actlen); goto setup; } uath_cmdeof(sc, cmd); case USB_ST_SETUP: setup: usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); usbd_transfer_submit(xfer); break; default: if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); goto setup; } break; } } static void uath_intr_tx_callback(struct usb_xfer *xfer, usb_error_t error) { struct uath_softc *sc = usbd_xfer_softc(xfer); struct uath_cmd *cmd; UATH_ASSERT_LOCKED(sc); cmd = STAILQ_FIRST(&sc->sc_cmd_active); if (cmd != NULL && USB_GET_STATE(xfer) != USB_ST_SETUP) { STAILQ_REMOVE_HEAD(&sc->sc_cmd_active, next); UATH_STAT_DEC(sc, st_cmd_active); STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_READ) ? &sc->sc_cmd_waiting : &sc->sc_cmd_inactive, cmd, next); if (cmd->flags & UATH_CMD_FLAG_READ) UATH_STAT_INC(sc, st_cmd_waiting); else UATH_STAT_INC(sc, st_cmd_inactive); } switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: case USB_ST_SETUP: setup: cmd = STAILQ_FIRST(&sc->sc_cmd_pending); if (cmd == NULL) { DPRINTF(sc, UATH_DEBUG_XMIT, "%s: empty pending queue\n", __func__); return; } STAILQ_REMOVE_HEAD(&sc->sc_cmd_pending, next); UATH_STAT_DEC(sc, st_cmd_pending); STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_ASYNC) ? &sc->sc_cmd_inactive : &sc->sc_cmd_active, cmd, next); if (cmd->flags & UATH_CMD_FLAG_ASYNC) UATH_STAT_INC(sc, st_cmd_inactive); else UATH_STAT_INC(sc, st_cmd_active); usbd_xfer_set_frame_data(xfer, 0, cmd->buf, cmd->buflen); usbd_transfer_submit(xfer); break; default: if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); goto setup; } break; } } static void uath_update_rxstat(struct uath_softc *sc, uint32_t status) { switch (status) { case UATH_STATUS_STOP_IN_PROGRESS: UATH_STAT_INC(sc, st_stopinprogress); break; case UATH_STATUS_CRC_ERR: UATH_STAT_INC(sc, st_crcerr); break; case UATH_STATUS_PHY_ERR: UATH_STAT_INC(sc, st_phyerr); break; case UATH_STATUS_DECRYPT_CRC_ERR: UATH_STAT_INC(sc, st_decrypt_crcerr); break; case UATH_STATUS_DECRYPT_MIC_ERR: UATH_STAT_INC(sc, st_decrypt_micerr); break; case UATH_STATUS_DECOMP_ERR: UATH_STAT_INC(sc, st_decomperr); break; case UATH_STATUS_KEY_ERR: UATH_STAT_INC(sc, st_keyerr); break; case UATH_STATUS_ERR: UATH_STAT_INC(sc, st_err); break; default: break; } } CTASSERT(UATH_MIN_RXBUFSZ >= sizeof(struct uath_chunk)); static struct mbuf * uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, struct uath_rx_desc **pdesc) { struct uath_softc *sc = usbd_xfer_softc(xfer); struct ieee80211com *ic = &sc->sc_ic; struct uath_chunk *chunk; struct uath_rx_desc *desc; struct mbuf *m = data->m, *mnew, *mp; uint16_t chunklen; int actlen; usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); if (actlen < (int)UATH_MIN_RXBUFSZ) { DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, "%s: wrong xfer size (len=%d)\n", __func__, actlen); counter_u64_add(ic->ic_ierrors, 1); return (NULL); } chunk = (struct uath_chunk *)data->buf; chunklen = be16toh(chunk->length); if (chunk->seqnum == 0 && chunk->flags == 0 && chunklen == 0) { device_printf(sc->sc_dev, "%s: strange response\n", __func__); counter_u64_add(ic->ic_ierrors, 1); UATH_RESET_INTRX(sc); return (NULL); } if (chunklen > actlen) { device_printf(sc->sc_dev, "%s: invalid chunk length (len %u > actlen %d)\n", __func__, chunklen, actlen); counter_u64_add(ic->ic_ierrors, 1); /* XXX cleanup? */ UATH_RESET_INTRX(sc); return (NULL); } if (chunk->seqnum != sc->sc_intrx_nextnum) { DPRINTF(sc, UATH_DEBUG_XMIT, "invalid seqnum %d, expected %d\n", chunk->seqnum, sc->sc_intrx_nextnum); UATH_STAT_INC(sc, st_badchunkseqnum); if (sc->sc_intrx_head != NULL) m_freem(sc->sc_intrx_head); UATH_RESET_INTRX(sc); return (NULL); } /* check multi-chunk frames */ if ((chunk->seqnum == 0 && !(chunk->flags & UATH_CFLAGS_FINAL)) || (chunk->seqnum != 0 && (chunk->flags & UATH_CFLAGS_FINAL)) || chunk->flags & UATH_CFLAGS_RXMSG) UATH_STAT_INC(sc, st_multichunk); if (chunk->flags & UATH_CFLAGS_FINAL) { if (chunklen < sizeof(struct uath_rx_desc)) { device_printf(sc->sc_dev, "%s: invalid chunk length %d\n", __func__, chunklen); counter_u64_add(ic->ic_ierrors, 1); if (sc->sc_intrx_head != NULL) m_freem(sc->sc_intrx_head); UATH_RESET_INTRX(sc); return (NULL); } chunklen -= sizeof(struct uath_rx_desc); } if (chunklen > 0 && (!(chunk->flags & UATH_CFLAGS_FINAL) || !(chunk->seqnum == 0))) { /* we should use intermediate RX buffer */ if (chunk->seqnum == 0) UATH_RESET_INTRX(sc); if ((sc->sc_intrx_len + sizeof(struct uath_rx_desc) + chunklen) > UATH_MAX_INTRX_SIZE) { UATH_STAT_INC(sc, st_invalidlen); counter_u64_add(ic->ic_ierrors, 1); if (sc->sc_intrx_head != NULL) m_freem(sc->sc_intrx_head); UATH_RESET_INTRX(sc); return (NULL); } m->m_len = chunklen; m->m_data += sizeof(struct uath_chunk); if (sc->sc_intrx_head == NULL) { sc->sc_intrx_head = m; sc->sc_intrx_tail = m; } else { m->m_flags &= ~M_PKTHDR; sc->sc_intrx_tail->m_next = m; sc->sc_intrx_tail = m; } } sc->sc_intrx_len += chunklen; mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (mnew == NULL) { DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, "%s: can't get new mbuf, drop frame\n", __func__); counter_u64_add(ic->ic_ierrors, 1); if (sc->sc_intrx_head != NULL) m_freem(sc->sc_intrx_head); UATH_RESET_INTRX(sc); return (NULL); } data->m = mnew; data->buf = mtod(mnew, uint8_t *); /* if the frame is not final continue the transfer */ if (!(chunk->flags & UATH_CFLAGS_FINAL)) { sc->sc_intrx_nextnum++; UATH_RESET_INTRX(sc); return (NULL); } /* * if the frame is not set UATH_CFLAGS_RXMSG, then rx descriptor is * located at the end, 32-bit aligned */ desc = (chunk->flags & UATH_CFLAGS_RXMSG) ? (struct uath_rx_desc *)(chunk + 1) : (struct uath_rx_desc *)(((uint8_t *)chunk) + sizeof(struct uath_chunk) + be16toh(chunk->length) - sizeof(struct uath_rx_desc)); if ((uint8_t *)chunk + actlen - sizeof(struct uath_rx_desc) < (uint8_t *)desc) { device_printf(sc->sc_dev, "%s: wrong Rx descriptor pointer " "(desc %p chunk %p actlen %d)\n", __func__, desc, chunk, actlen); counter_u64_add(ic->ic_ierrors, 1); if (sc->sc_intrx_head != NULL) m_freem(sc->sc_intrx_head); UATH_RESET_INTRX(sc); return (NULL); } *pdesc = desc; DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, "%s: frame len %u code %u status %u rate %u antenna %u " "rssi %d channel %u phyerror %u connix %u decrypterror %u " "keycachemiss %u\n", __func__, be32toh(desc->framelen) , be32toh(desc->code), be32toh(desc->status), be32toh(desc->rate) , be32toh(desc->antenna), be32toh(desc->rssi), be32toh(desc->channel) , be32toh(desc->phyerror), be32toh(desc->connix) , be32toh(desc->decrypterror), be32toh(desc->keycachemiss)); if (be32toh(desc->len) > MCLBYTES) { DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, "%s: bad descriptor (len=%d)\n", __func__, be32toh(desc->len)); counter_u64_add(ic->ic_ierrors, 1); UATH_STAT_INC(sc, st_toobigrxpkt); if (sc->sc_intrx_head != NULL) m_freem(sc->sc_intrx_head); UATH_RESET_INTRX(sc); return (NULL); } uath_update_rxstat(sc, be32toh(desc->status)); /* finalize mbuf */ if (sc->sc_intrx_head == NULL) { uint32_t framelen; if (be32toh(desc->framelen) < UATH_RX_DUMMYSIZE) { device_printf(sc->sc_dev, "%s: framelen too small (%u)\n", __func__, be32toh(desc->framelen)); counter_u64_add(ic->ic_ierrors, 1); if (sc->sc_intrx_head != NULL) m_freem(sc->sc_intrx_head); UATH_RESET_INTRX(sc); return (NULL); } framelen = be32toh(desc->framelen) - UATH_RX_DUMMYSIZE; if (framelen > actlen - sizeof(struct uath_chunk) || framelen < sizeof(struct ieee80211_frame_ack)) { device_printf(sc->sc_dev, "%s: wrong frame length (%u, actlen %d)!\n", __func__, framelen, actlen); counter_u64_add(ic->ic_ierrors, 1); if (sc->sc_intrx_head != NULL) m_freem(sc->sc_intrx_head); UATH_RESET_INTRX(sc); return (NULL); } m->m_pkthdr.len = m->m_len = framelen; m->m_data += sizeof(struct uath_chunk); } else { mp = sc->sc_intrx_head; mp->m_flags |= M_PKTHDR; mp->m_pkthdr.len = sc->sc_intrx_len; m = mp; } /* there are a lot more fields in the RX descriptor */ if ((sc->sc_flags & UATH_FLAG_INVALID) == 0 && ieee80211_radiotap_active(ic)) { struct uath_rx_radiotap_header *tap = &sc->sc_rxtap; uint32_t tsf_hi = be32toh(desc->tstamp_high); uint32_t tsf_lo = be32toh(desc->tstamp_low); /* XXX only get low order 24bits of tsf from h/w */ tap->wr_tsf = htole64(((uint64_t)tsf_hi << 32) | tsf_lo); tap->wr_flags = 0; if (be32toh(desc->status) == UATH_STATUS_CRC_ERR) tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; /* XXX map other status to BADFCS? */ /* XXX ath h/w rate code, need to map */ tap->wr_rate = be32toh(desc->rate); tap->wr_antenna = be32toh(desc->antenna); tap->wr_antsignal = -95 + be32toh(desc->rssi); tap->wr_antnoise = -95; } UATH_RESET_INTRX(sc); return (m); } static void uath_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) { struct uath_softc *sc = usbd_xfer_softc(xfer); struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_frame *wh; struct ieee80211_node *ni; struct mbuf *m = NULL; struct uath_data *data; struct uath_rx_desc *desc = NULL; int8_t nf; UATH_ASSERT_LOCKED(sc); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: data = STAILQ_FIRST(&sc->sc_rx_active); if (data == NULL) goto setup; STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next); UATH_STAT_DEC(sc, st_rx_active); m = uath_data_rxeof(xfer, data, &desc); STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); UATH_STAT_INC(sc, st_rx_inactive); /* FALLTHROUGH */ case USB_ST_SETUP: setup: data = STAILQ_FIRST(&sc->sc_rx_inactive); if (data == NULL) return; STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next); UATH_STAT_DEC(sc, st_rx_inactive); STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next); UATH_STAT_INC(sc, st_rx_active); usbd_xfer_set_frame_data(xfer, 0, data->buf, MCLBYTES); usbd_transfer_submit(xfer); /* * To avoid LOR we should unlock our private mutex here to call * ieee80211_input() because here is at the end of a USB * callback and safe to unlock. */ if (sc->sc_flags & UATH_FLAG_INVALID) { if (m != NULL) m_freem(m); return; } UATH_UNLOCK(sc); if (m != NULL && desc != NULL) { wh = mtod(m, struct ieee80211_frame *); ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); nf = -95; /* XXX */ if (ni != NULL) { (void) ieee80211_input(ni, m, (int)be32toh(desc->rssi), nf); /* node is no longer needed */ ieee80211_free_node(ni); } else (void) ieee80211_input_all(ic, m, (int)be32toh(desc->rssi), nf); m = NULL; desc = NULL; } UATH_LOCK(sc); uath_start(sc); break; default: /* needs it to the inactive queue due to a error. */ data = STAILQ_FIRST(&sc->sc_rx_active); if (data != NULL) { STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next); UATH_STAT_DEC(sc, st_rx_active); STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); UATH_STAT_INC(sc, st_rx_inactive); } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); counter_u64_add(ic->ic_ierrors, 1); goto setup; } break; } } static void uath_data_txeof(struct usb_xfer *xfer, struct uath_data *data) { struct uath_softc *sc = usbd_xfer_softc(xfer); UATH_ASSERT_LOCKED(sc); if (data->m) { /* XXX status? */ ieee80211_tx_complete(data->ni, data->m, 0); data->m = NULL; data->ni = NULL; } sc->sc_tx_timer = 0; } static void uath_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) { struct uath_softc *sc = usbd_xfer_softc(xfer); struct uath_data *data; UATH_ASSERT_LOCKED(sc); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: data = STAILQ_FIRST(&sc->sc_tx_active); if (data == NULL) goto setup; STAILQ_REMOVE_HEAD(&sc->sc_tx_active, next); UATH_STAT_DEC(sc, st_tx_active); uath_data_txeof(xfer, data); STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next); UATH_STAT_INC(sc, st_tx_inactive); /* FALLTHROUGH */ case USB_ST_SETUP: setup: data = STAILQ_FIRST(&sc->sc_tx_pending); if (data == NULL) { DPRINTF(sc, UATH_DEBUG_XMIT, "%s: empty pending queue\n", __func__); return; } STAILQ_REMOVE_HEAD(&sc->sc_tx_pending, next); UATH_STAT_DEC(sc, st_tx_pending); STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next); UATH_STAT_INC(sc, st_tx_active); usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen); usbd_transfer_submit(xfer); uath_start(sc); break; default: data = STAILQ_FIRST(&sc->sc_tx_active); if (data == NULL) goto setup; if (data->ni != NULL) { if_inc_counter(data->ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); if ((sc->sc_flags & UATH_FLAG_INVALID) == 0) ieee80211_free_node(data->ni); data->ni = NULL; } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); goto setup; } break; } } static device_method_t uath_methods[] = { DEVMETHOD(device_probe, uath_match), DEVMETHOD(device_attach, uath_attach), DEVMETHOD(device_detach, uath_detach), DEVMETHOD_END }; static driver_t uath_driver = { .name = "uath", .methods = uath_methods, .size = sizeof(struct uath_softc) }; static devclass_t uath_devclass; DRIVER_MODULE(uath, uhub, uath_driver, uath_devclass, NULL, 0); MODULE_DEPEND(uath, wlan, 1, 1, 1); MODULE_DEPEND(uath, usb, 1, 1, 1); MODULE_VERSION(uath, 1); USB_PNP_HOST_INFO(uath_devs); Index: head/sys/sys/_ucontext.h =================================================================== --- head/sys/sys/_ucontext.h (revision 326822) +++ head/sys/sys/_ucontext.h (revision 326823) @@ -1,52 +1,54 @@ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1999 Marcel Moolenaar * 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 * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS__UCONTEXT_H_ #define _SYS__UCONTEXT_H_ typedef struct __ucontext { /* * Keep the order of the first two fields. Also, * keep them the first two fields in the structure. * This way we can have a union with struct * sigcontext and ucontext_t. This allows us to * support them both at the same time. * note: the union is not defined, though. */ __sigset_t uc_sigmask; mcontext_t uc_mcontext; struct __ucontext *uc_link; struct __stack_t uc_stack; int uc_flags; int __spare__[4]; } ucontext_t; #endif /* _SYS__UCONTEXT_H */ Index: head/sys/sys/_vm_domain.h =================================================================== --- head/sys/sys/_vm_domain.h (revision 326822) +++ head/sys/sys/_vm_domain.h (revision 326823) @@ -1,61 +1,63 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2015 Adrian Chadd . * 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 at minimum a disclaimer * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any * redistribution must be conditioned upon including a substantially * similar Disclaimer requirement for further binary redistribution. * * NO WARRANTY * 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 NONINFRINGEMENT, MERCHANTIBILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. * * $FreeBSD$ */ #ifndef __SYS_VM_DOMAIN_H__ #define __SYS_VM_DOMAIN_H__ #include typedef enum { VM_POLICY_NONE, VM_POLICY_ROUND_ROBIN, VM_POLICY_FIXED_DOMAIN, VM_POLICY_FIXED_DOMAIN_ROUND_ROBIN, VM_POLICY_FIRST_TOUCH, VM_POLICY_FIRST_TOUCH_ROUND_ROBIN, VM_POLICY_MAX } vm_domain_policy_type_t; struct vm_domain_policy_entry { vm_domain_policy_type_t policy; int domain; }; struct vm_domain_policy { seq_t seq; struct vm_domain_policy_entry p; }; #define VM_DOMAIN_POLICY_STATIC_INITIALISER(vt, vd) \ { .seq = 0, \ .p.policy = vt, \ .p.domain = vd } #endif /* __SYS_VM_DOMAIN_H__ */ Index: head/sys/sys/auxv.h =================================================================== --- head/sys/sys/auxv.h (revision 326822) +++ head/sys/sys/auxv.h (revision 326823) @@ -1,39 +1,41 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2017 Michal Meloun * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_AUXV_H_ #define _SYS_AUXV_H_ #include #include __BEGIN_DECLS int elf_aux_info(int aux, void *buf, int buflen); __END_DECLS #endif /* !_SYS_AUXV_H_ */ Index: head/sys/sys/bus_dma.h =================================================================== --- head/sys/sys/bus_dma.h (revision 326822) +++ head/sys/sys/bus_dma.h (revision 326823) @@ -1,298 +1,298 @@ /* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */ /*- - * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * SPDX-License-Identifier: (BSD-2-Clause-NetBSD AND BSD-4-Clause) * * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, * NASA Ames Research Center. * * 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. */ /*- * Copyright (c) 1996 Charles M. Hannum. All rights reserved. * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christopher G. Demetriou * for the NetBSD Project. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* $FreeBSD$ */ #ifndef _BUS_DMA_H_ #define _BUS_DMA_H_ #include /* * Machine independent interface for mapping physical addresses to peripheral * bus 'physical' addresses, and assisting with DMA operations. * * XXX This file is always included from and should not * (yet) be included directly. */ /* * Flags used in various bus DMA methods. */ #define BUS_DMA_WAITOK 0x00 /* safe to sleep (pseudo-flag) */ #define BUS_DMA_NOWAIT 0x01 /* not safe to sleep */ #define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */ #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ #define BUS_DMA_ZERO 0x08 /* allocate zero'ed memory */ #define BUS_DMA_BUS1 0x10 /* placeholders for bus functions... */ #define BUS_DMA_BUS2 0x20 #define BUS_DMA_BUS3 0x40 #define BUS_DMA_BUS4 0x80 /* * The following two flags are non-standard or specific to only certain * architectures */ #define BUS_DMA_NOWRITE 0x100 #define BUS_DMA_NOCACHE 0x200 /* * The following flag is a DMA tag hint that the page offset of the * loaded kernel virtual address must be preserved in the first * physical segment address, when the KVA is loaded into DMA. */ #define BUS_DMA_KEEP_PG_OFFSET 0x400 #define BUS_DMA_LOAD_MBUF 0x800 /* Forwards needed by prototypes below. */ union ccb; struct bio; struct mbuf; struct memdesc; struct pmap; struct uio; /* * Operations performed by bus_dmamap_sync(). */ #define BUS_DMASYNC_PREREAD 1 #define BUS_DMASYNC_POSTREAD 2 #define BUS_DMASYNC_PREWRITE 4 #define BUS_DMASYNC_POSTWRITE 8 /* * bus_dma_segment_t * * Describes a single contiguous DMA transaction. Values * are suitable for programming into DMA registers. */ typedef struct bus_dma_segment { bus_addr_t ds_addr; /* DMA address */ bus_size_t ds_len; /* length of transfer */ } bus_dma_segment_t; /* * A function that returns 1 if the address cannot be accessed by * a device and 0 if it can be. */ typedef int bus_dma_filter_t(void *, bus_addr_t); /* * Generic helper function for manipulating mutexes. */ void busdma_lock_mutex(void *arg, bus_dma_lock_op_t op); /* * Allocate a device specific dma_tag encapsulating the constraints of * the parent tag in addition to other restrictions specified: * * alignment: Alignment for segments. * boundary: Boundary that segments cannot cross. * lowaddr: Low restricted address that cannot appear in a mapping. * highaddr: High restricted address that cannot appear in a mapping. * filtfunc: An optional function to further test if an address * within the range of lowaddr and highaddr cannot appear * in a mapping. * filtfuncarg: An argument that will be passed to filtfunc in addition * to the address to test. * maxsize: Maximum mapping size supported by this tag. * nsegments: Number of discontinuities allowed in maps. * maxsegsz: Maximum size of a segment in the map. * flags: Bus DMA flags. * lockfunc: An optional function to handle driver-defined lock * operations. * lockfuncarg: An argument that will be passed to lockfunc in addition * to the lock operation. * dmat: A pointer to set to a valid dma tag should the return * value of this function indicate success. */ /* XXX Should probably allow specification of alignment */ int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, bus_addr_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, bus_dma_filter_t *filtfunc, void *filtfuncarg, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, void *lockfuncarg, bus_dma_tag_t *dmat); int bus_dma_tag_destroy(bus_dma_tag_t dmat); /* * A function that processes a successfully loaded dma map or an error * from a delayed load map. */ typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); /* * Like bus_dmamap_callback but includes map size in bytes. This is * defined as a separate interface to maintain compatibility for users * of bus_dmamap_callback_t--at some point these interfaces should be merged. */ typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, bus_size_t, int); /* * Map the buffer buf into bus space using the dmamap map. */ int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, int flags); /* * Like bus_dmamap_load but for mbufs. Note the use of the * bus_dmamap_callback2_t interface. */ int bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *mbuf, bus_dmamap_callback2_t *callback, void *callback_arg, int flags); int bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *mbuf, bus_dma_segment_t *segs, int *nsegs, int flags); /* * Like bus_dmamap_load but for uios. Note the use of the * bus_dmamap_callback2_t interface. */ int bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *ui, bus_dmamap_callback2_t *callback, void *callback_arg, int flags); /* * Like bus_dmamap_load but for cam control blocks. */ int bus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb, bus_dmamap_callback_t *callback, void *callback_arg, int flags); /* * Like bus_dmamap_load but for bios. */ int bus_dmamap_load_bio(bus_dma_tag_t dmat, bus_dmamap_t map, struct bio *bio, bus_dmamap_callback_t *callback, void *callback_arg, int flags); /* * Loads any memory descriptor. */ int bus_dmamap_load_mem(bus_dma_tag_t dmat, bus_dmamap_t map, struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg, int flags); /* * Placeholder for use by busdma implementations which do not benefit * from optimized procedure to load an array of vm_page_t. Falls back * to do _bus_dmamap_load_phys() in loop. */ int bus_dmamap_load_ma_triv(bus_dma_tag_t dmat, bus_dmamap_t map, struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags, bus_dma_segment_t *segs, int *segp); #ifdef WANT_INLINE_DMAMAP #define BUS_DMAMAP_OP static inline #else #define BUS_DMAMAP_OP #endif /* * Allocate a handle for mapping from kva/uva/physical * address space into bus device space. */ BUS_DMAMAP_OP int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp); /* * Destroy a handle for mapping from kva/uva/physical * address space into bus device space. */ BUS_DMAMAP_OP int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map); /* * Allocate a piece of memory that can be efficiently mapped into * bus device space based on the constraints listed in the dma tag. * A dmamap to for use with dmamap_load is also allocated. */ BUS_DMAMAP_OP int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, bus_dmamap_t *mapp); /* * Free a piece of memory and its allocated dmamap, that was allocated * via bus_dmamem_alloc. */ BUS_DMAMAP_OP void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); /* * Perform a synchronization operation on the given map. If the map * is NULL we have a fully IO-coherent system. */ BUS_DMAMAP_OP void bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t dmamap, bus_dmasync_op_t op); /* * Release the mapping held by map. */ BUS_DMAMAP_OP void bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t dmamap); #undef BUS_DMAMAP_OP #endif /* _BUS_DMA_H_ */ Index: head/sys/sys/bus_dma_internal.h =================================================================== --- head/sys/sys/bus_dma_internal.h (revision 326822) +++ head/sys/sys/bus_dma_internal.h (revision 326823) @@ -1,59 +1,61 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2017 Jason A. Harmening. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _BUS_DMA_INTERNAL_H_ #define _BUS_DMA_INTERNAL_H_ /* * The following functions define the interface between the MD and MI * busdma layers. These are not intended for consumption by driver * software. */ bus_dma_segment_t *_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dma_segment_t *segs, int nsegs, int error); int _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, struct pmap *pmap, int flags, bus_dma_segment_t *segs, int *segp); int _bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map, struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags, bus_dma_segment_t *segs, int *segp); int _bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t paddr, bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp); void _bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map, struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg); #endif /* !_BUS_DMA_INTERNAL_H_ */ Index: head/sys/sys/capsicum.h =================================================================== --- head/sys/sys/capsicum.h (revision 326822) +++ head/sys/sys/capsicum.h (revision 326823) @@ -1,428 +1,430 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2008-2010, 2015 Robert N. M. Watson * Copyright (c) 2012 FreeBSD Foundation * All rights reserved. * * This software was developed at the University of Cambridge Computer * Laboratory with support from a grant from Google, Inc. * * Portions of this software were developed by Pawel Jakub Dawidek under * sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE 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$ */ /* * Definitions for FreeBSD capabilities facility. */ #ifndef _SYS_CAPSICUM_H_ #define _SYS_CAPSICUM_H_ #include #include #include #include #include #ifndef _KERNEL #include #endif #define CAPRIGHT(idx, bit) ((1ULL << (57 + (idx))) | (bit)) /* * Possible rights on capabilities. * * Notes: * Some system calls don't require a capability in order to perform an * operation on an fd. These include: close, dup, dup2. * * sendfile is authorized using CAP_READ on the file and CAP_WRITE on the * socket. * * mmap() and aio*() system calls will need special attention as they may * involve reads or writes depending a great deal on context. */ /* INDEX 0 */ /* * General file I/O. */ /* Allows for openat(O_RDONLY), read(2), readv(2). */ #define CAP_READ CAPRIGHT(0, 0x0000000000000001ULL) /* Allows for openat(O_WRONLY | O_APPEND), write(2), writev(2). */ #define CAP_WRITE CAPRIGHT(0, 0x0000000000000002ULL) /* Allows for lseek(fd, 0, SEEK_CUR). */ #define CAP_SEEK_TELL CAPRIGHT(0, 0x0000000000000004ULL) /* Allows for lseek(2). */ #define CAP_SEEK (CAP_SEEK_TELL | 0x0000000000000008ULL) /* Allows for aio_read(2), pread(2), preadv(2). */ #define CAP_PREAD (CAP_SEEK | CAP_READ) /* * Allows for aio_write(2), openat(O_WRONLY) (without O_APPEND), pwrite(2), * pwritev(2). */ #define CAP_PWRITE (CAP_SEEK | CAP_WRITE) /* Allows for mmap(PROT_NONE). */ #define CAP_MMAP CAPRIGHT(0, 0x0000000000000010ULL) /* Allows for mmap(PROT_READ). */ #define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ) /* Allows for mmap(PROT_WRITE). */ #define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE) /* Allows for mmap(PROT_EXEC). */ #define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000020ULL) /* Allows for mmap(PROT_READ | PROT_WRITE). */ #define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W) /* Allows for mmap(PROT_READ | PROT_EXEC). */ #define CAP_MMAP_RX (CAP_MMAP_R | CAP_MMAP_X) /* Allows for mmap(PROT_WRITE | PROT_EXEC). */ #define CAP_MMAP_WX (CAP_MMAP_W | CAP_MMAP_X) /* Allows for mmap(PROT_READ | PROT_WRITE | PROT_EXEC). */ #define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X) /* Allows for openat(O_CREAT). */ #define CAP_CREATE CAPRIGHT(0, 0x0000000000000040ULL) /* Allows for openat(O_EXEC) and fexecve(2) in turn. */ #define CAP_FEXECVE CAPRIGHT(0, 0x0000000000000080ULL) /* Allows for openat(O_SYNC), openat(O_FSYNC), fsync(2), aio_fsync(2). */ #define CAP_FSYNC CAPRIGHT(0, 0x0000000000000100ULL) /* Allows for openat(O_TRUNC), ftruncate(2). */ #define CAP_FTRUNCATE CAPRIGHT(0, 0x0000000000000200ULL) /* Lookups - used to constrain *at() calls. */ #define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL) /* VFS methods. */ /* Allows for fchdir(2). */ #define CAP_FCHDIR CAPRIGHT(0, 0x0000000000000800ULL) /* Allows for fchflags(2). */ #define CAP_FCHFLAGS CAPRIGHT(0, 0x0000000000001000ULL) /* Allows for fchflags(2) and chflagsat(2). */ #define CAP_CHFLAGSAT (CAP_FCHFLAGS | CAP_LOOKUP) /* Allows for fchmod(2). */ #define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL) /* Allows for fchmod(2) and fchmodat(2). */ #define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP) /* Allows for fchown(2). */ #define CAP_FCHOWN CAPRIGHT(0, 0x0000000000004000ULL) /* Allows for fchown(2) and fchownat(2). */ #define CAP_FCHOWNAT (CAP_FCHOWN | CAP_LOOKUP) /* Allows for fcntl(2). */ #define CAP_FCNTL CAPRIGHT(0, 0x0000000000008000ULL) /* * Allows for flock(2), openat(O_SHLOCK), openat(O_EXLOCK), * fcntl(F_SETLK_REMOTE), fcntl(F_SETLKW), fcntl(F_SETLK), fcntl(F_GETLK). */ #define CAP_FLOCK CAPRIGHT(0, 0x0000000000010000ULL) /* Allows for fpathconf(2). */ #define CAP_FPATHCONF CAPRIGHT(0, 0x0000000000020000ULL) /* Allows for UFS background-fsck operations. */ #define CAP_FSCK CAPRIGHT(0, 0x0000000000040000ULL) /* Allows for fstat(2). */ #define CAP_FSTAT CAPRIGHT(0, 0x0000000000080000ULL) /* Allows for fstat(2), fstatat(2) and faccessat(2). */ #define CAP_FSTATAT (CAP_FSTAT | CAP_LOOKUP) /* Allows for fstatfs(2). */ #define CAP_FSTATFS CAPRIGHT(0, 0x0000000000100000ULL) /* Allows for futimens(2) and futimes(2). */ #define CAP_FUTIMES CAPRIGHT(0, 0x0000000000200000ULL) /* Allows for futimens(2), futimes(2), futimesat(2) and utimensat(2). */ #define CAP_FUTIMESAT (CAP_FUTIMES | CAP_LOOKUP) /* Allows for linkat(2) (target directory descriptor). */ #define CAP_LINKAT_TARGET (CAP_LOOKUP | 0x0000000000400000ULL) /* Allows for mkdirat(2). */ #define CAP_MKDIRAT (CAP_LOOKUP | 0x0000000000800000ULL) /* Allows for mkfifoat(2). */ #define CAP_MKFIFOAT (CAP_LOOKUP | 0x0000000001000000ULL) /* Allows for mknodat(2). */ #define CAP_MKNODAT (CAP_LOOKUP | 0x0000000002000000ULL) /* Allows for renameat(2) (source directory descriptor). */ #define CAP_RENAMEAT_SOURCE (CAP_LOOKUP | 0x0000000004000000ULL) /* Allows for symlinkat(2). */ #define CAP_SYMLINKAT (CAP_LOOKUP | 0x0000000008000000ULL) /* * Allows for unlinkat(2) and renameat(2) if destination object exists and * will be removed. */ #define CAP_UNLINKAT (CAP_LOOKUP | 0x0000000010000000ULL) /* Socket operations. */ /* Allows for accept(2) and accept4(2). */ #define CAP_ACCEPT CAPRIGHT(0, 0x0000000020000000ULL) /* Allows for bind(2). */ #define CAP_BIND CAPRIGHT(0, 0x0000000040000000ULL) /* Allows for connect(2). */ #define CAP_CONNECT CAPRIGHT(0, 0x0000000080000000ULL) /* Allows for getpeername(2). */ #define CAP_GETPEERNAME CAPRIGHT(0, 0x0000000100000000ULL) /* Allows for getsockname(2). */ #define CAP_GETSOCKNAME CAPRIGHT(0, 0x0000000200000000ULL) /* Allows for getsockopt(2). */ #define CAP_GETSOCKOPT CAPRIGHT(0, 0x0000000400000000ULL) /* Allows for listen(2). */ #define CAP_LISTEN CAPRIGHT(0, 0x0000000800000000ULL) /* Allows for sctp_peeloff(2). */ #define CAP_PEELOFF CAPRIGHT(0, 0x0000001000000000ULL) #define CAP_RECV CAP_READ #define CAP_SEND CAP_WRITE /* Allows for setsockopt(2). */ #define CAP_SETSOCKOPT CAPRIGHT(0, 0x0000002000000000ULL) /* Allows for shutdown(2). */ #define CAP_SHUTDOWN CAPRIGHT(0, 0x0000004000000000ULL) /* Allows for bindat(2) on a directory descriptor. */ #define CAP_BINDAT (CAP_LOOKUP | 0x0000008000000000ULL) /* Allows for connectat(2) on a directory descriptor. */ #define CAP_CONNECTAT (CAP_LOOKUP | 0x0000010000000000ULL) /* Allows for linkat(2) (source directory descriptor). */ #define CAP_LINKAT_SOURCE (CAP_LOOKUP | 0x0000020000000000ULL) /* Allows for renameat(2) (target directory descriptor). */ #define CAP_RENAMEAT_TARGET (CAP_LOOKUP | 0x0000040000000000ULL) #define CAP_SOCK_CLIENT \ (CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \ CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN) #define CAP_SOCK_SERVER \ (CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \ CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \ CAP_SETSOCKOPT | CAP_SHUTDOWN) /* All used bits for index 0. */ #define CAP_ALL0 CAPRIGHT(0, 0x000007FFFFFFFFFFULL) /* Available bits for index 0. */ #define CAP_UNUSED0_44 CAPRIGHT(0, 0x0000080000000000ULL) /* ... */ #define CAP_UNUSED0_57 CAPRIGHT(0, 0x0100000000000000ULL) /* INDEX 1 */ /* Mandatory Access Control. */ /* Allows for mac_get_fd(3). */ #define CAP_MAC_GET CAPRIGHT(1, 0x0000000000000001ULL) /* Allows for mac_set_fd(3). */ #define CAP_MAC_SET CAPRIGHT(1, 0x0000000000000002ULL) /* Methods on semaphores. */ #define CAP_SEM_GETVALUE CAPRIGHT(1, 0x0000000000000004ULL) #define CAP_SEM_POST CAPRIGHT(1, 0x0000000000000008ULL) #define CAP_SEM_WAIT CAPRIGHT(1, 0x0000000000000010ULL) /* Allows select(2) and poll(2) on descriptor. */ #define CAP_EVENT CAPRIGHT(1, 0x0000000000000020ULL) /* Allows for kevent(2) on kqueue descriptor with eventlist != NULL. */ #define CAP_KQUEUE_EVENT CAPRIGHT(1, 0x0000000000000040ULL) /* Strange and powerful rights that should not be given lightly. */ /* Allows for ioctl(2). */ #define CAP_IOCTL CAPRIGHT(1, 0x0000000000000080ULL) #define CAP_TTYHOOK CAPRIGHT(1, 0x0000000000000100ULL) /* Process management via process descriptors. */ /* Allows for pdgetpid(2). */ #define CAP_PDGETPID CAPRIGHT(1, 0x0000000000000200ULL) /* Allows for pdwait4(2). */ #define CAP_PDWAIT CAPRIGHT(1, 0x0000000000000400ULL) /* Allows for pdkill(2). */ #define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL) /* Extended attributes. */ /* Allows for extattr_delete_fd(2). */ #define CAP_EXTATTR_DELETE CAPRIGHT(1, 0x0000000000001000ULL) /* Allows for extattr_get_fd(2). */ #define CAP_EXTATTR_GET CAPRIGHT(1, 0x0000000000002000ULL) /* Allows for extattr_list_fd(2). */ #define CAP_EXTATTR_LIST CAPRIGHT(1, 0x0000000000004000ULL) /* Allows for extattr_set_fd(2). */ #define CAP_EXTATTR_SET CAPRIGHT(1, 0x0000000000008000ULL) /* Access Control Lists. */ /* Allows for acl_valid_fd_np(3). */ #define CAP_ACL_CHECK CAPRIGHT(1, 0x0000000000010000ULL) /* Allows for acl_delete_fd_np(3). */ #define CAP_ACL_DELETE CAPRIGHT(1, 0x0000000000020000ULL) /* Allows for acl_get_fd(3) and acl_get_fd_np(3). */ #define CAP_ACL_GET CAPRIGHT(1, 0x0000000000040000ULL) /* Allows for acl_set_fd(3) and acl_set_fd_np(3). */ #define CAP_ACL_SET CAPRIGHT(1, 0x0000000000080000ULL) /* Allows for kevent(2) on kqueue descriptor with changelist != NULL. */ #define CAP_KQUEUE_CHANGE CAPRIGHT(1, 0x0000000000100000ULL) #define CAP_KQUEUE (CAP_KQUEUE_EVENT | CAP_KQUEUE_CHANGE) /* All used bits for index 1. */ #define CAP_ALL1 CAPRIGHT(1, 0x00000000001FFFFFULL) /* Available bits for index 1. */ #define CAP_UNUSED1_22 CAPRIGHT(1, 0x0000000000200000ULL) /* ... */ #define CAP_UNUSED1_57 CAPRIGHT(1, 0x0100000000000000ULL) /* Backward compatibility. */ #define CAP_POLL_EVENT CAP_EVENT #define CAP_ALL(rights) do { \ (rights)->cr_rights[0] = \ ((uint64_t)CAP_RIGHTS_VERSION << 62) | CAP_ALL0; \ (rights)->cr_rights[1] = CAP_ALL1; \ } while (0) #define CAP_NONE(rights) do { \ (rights)->cr_rights[0] = \ ((uint64_t)CAP_RIGHTS_VERSION << 62) | CAPRIGHT(0, 0ULL); \ (rights)->cr_rights[1] = CAPRIGHT(1, 0ULL); \ } while (0) #define CAPRVER(right) ((int)((right) >> 62)) #define CAPVER(rights) CAPRVER((rights)->cr_rights[0]) #define CAPARSIZE(rights) (CAPVER(rights) + 2) #define CAPIDXBIT(right) ((int)(((right) >> 57) & 0x1F)) /* * Allowed fcntl(2) commands. */ #define CAP_FCNTL_GETFL (1 << F_GETFL) #define CAP_FCNTL_SETFL (1 << F_SETFL) #define CAP_FCNTL_GETOWN (1 << F_GETOWN) #define CAP_FCNTL_SETOWN (1 << F_SETOWN) #define CAP_FCNTL_ALL (CAP_FCNTL_GETFL | CAP_FCNTL_SETFL | \ CAP_FCNTL_GETOWN | CAP_FCNTL_SETOWN) #define CAP_IOCTLS_ALL SSIZE_MAX __BEGIN_DECLS #define cap_rights_init(...) \ __cap_rights_init(CAP_RIGHTS_VERSION, __VA_ARGS__, 0ULL) cap_rights_t *__cap_rights_init(int version, cap_rights_t *rights, ...); #define cap_rights_set(...) \ __cap_rights_set(__VA_ARGS__, 0ULL) cap_rights_t *__cap_rights_set(cap_rights_t *rights, ...); #define cap_rights_clear(...) \ __cap_rights_clear(__VA_ARGS__, 0ULL) cap_rights_t *__cap_rights_clear(cap_rights_t *rights, ...); #define cap_rights_is_set(...) \ __cap_rights_is_set(__VA_ARGS__, 0ULL) bool __cap_rights_is_set(const cap_rights_t *rights, ...); bool cap_rights_is_valid(const cap_rights_t *rights); cap_rights_t *cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src); cap_rights_t *cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src); bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little); __END_DECLS #ifdef _KERNEL #include #define IN_CAPABILITY_MODE(td) (((td)->td_ucred->cr_flags & CRED_FLAG_CAPMODE) != 0) struct filedesc; struct filedescent; /* * Test whether a capability grants the requested rights. */ int cap_check(const cap_rights_t *havep, const cap_rights_t *needp); /* * Convert capability rights into VM access flags. */ u_char cap_rights_to_vmprot(cap_rights_t *havep); /* * For the purposes of procstat(1) and similar tools, allow kern_descrip.c to * extract the rights from a capability. */ cap_rights_t *cap_rights_fde(struct filedescent *fde); cap_rights_t *cap_rights(struct filedesc *fdp, int fd); int cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd); int cap_fcntl_check_fde(struct filedescent *fde, int cmd); int cap_fcntl_check(struct filedesc *fdp, int fd, int cmd); extern int trap_enotcap; #else /* !_KERNEL */ __BEGIN_DECLS /* * cap_enter(): Cause the process to enter capability mode, which will * prevent it from directly accessing global namespaces. System calls will * be limited to process-local, process-inherited, or file descriptor * operations. If already in capability mode, a no-op. */ int cap_enter(void); /* * Are we sandboxed (in capability mode)? * This is a libc wrapper around the cap_getmode(2) system call. */ bool cap_sandboxed(void); /* * cap_getmode(): Are we in capability mode? */ int cap_getmode(u_int *modep); /* * Limits capability rights for the given descriptor (CAP_*). */ int cap_rights_limit(int fd, const cap_rights_t *rights); /* * Returns capability rights for the given descriptor. */ #define cap_rights_get(fd, rights) \ __cap_rights_get(CAP_RIGHTS_VERSION, (fd), (rights)) int __cap_rights_get(int version, int fd, cap_rights_t *rights); /* * Limits allowed ioctls for the given descriptor. */ int cap_ioctls_limit(int fd, const cap_ioctl_t *cmds, size_t ncmds); /* * Returns array of allowed ioctls for the given descriptor. * If all ioctls are allowed, the cmds array is not populated and * the function returns CAP_IOCTLS_ALL. */ ssize_t cap_ioctls_get(int fd, cap_ioctl_t *cmds, size_t maxcmds); /* * Limits allowed fcntls for the given descriptor (CAP_FCNTL_*). */ int cap_fcntls_limit(int fd, uint32_t fcntlrights); /* * Returns bitmask of allowed fcntls for the given descriptor. */ int cap_fcntls_get(int fd, uint32_t *fcntlrightsp); __END_DECLS #endif /* !_KERNEL */ #endif /* !_SYS_CAPSICUM_H_ */ Index: head/sys/sys/cnv.h =================================================================== --- head/sys/sys/cnv.h (revision 326822) +++ head/sys/sys/cnv.h (revision 326823) @@ -1,118 +1,120 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2016 Adam Starak * 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 AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _CNV_H_ #define _CNV_H_ #include #ifndef _KERNEL #include #include #include #include #endif #ifndef _NVLIST_T_DECLARED #define _NVLIST_T_DECLARED struct nvlist; typedef struct nvlist nvlist_t; #endif __BEGIN_DECLS /* * Functions which returns information about the given cookie. */ const char *cnvlist_name(void *cookiep); int cnvlist_type(void *cookiep); /* * The cnvlist_get functions returns value associated with the given cookie. * If it returns a pointer, the pointer represents internal buffer and should * not be freed by the caller. */ bool cnvlist_get_bool(void *cookiep); uint64_t cnvlist_get_number(void *cookiep); const char *cnvlist_get_string(void *cookiep); const nvlist_t *cnvlist_get_nvlist(void *cookiep); const void *cnvlist_get_binary(void *cookiep, size_t *sizep); const bool *cnvlist_get_bool_array(void *cookiep, size_t *nitemsp); const uint64_t *cnvlist_get_number_array(void *cookiep, size_t *nitemsp); const char * const *cnvlist_get_string_array(void *cookiep, size_t *nitemsp); const nvlist_t * const *cnvlist_get_nvlist_array(void *cookiep, size_t *nitemsp); #ifndef _KERNEL int cnvlist_get_descriptor(void *cookiep); const int *cnvlist_get_descriptor_array(void *cookiep, size_t *nitemsp); #endif /* * The cnvlist_take functions returns value associated with the given cookie and * remove the given entry from the nvlist. * The caller is responsible for freeing received data. */ bool cnvlist_take_bool(nvlist_t *nvl, void *cookiep); uint64_t cnvlist_take_number(nvlist_t *nvl, void *cookiep); char *cnvlist_take_string(nvlist_t *nvl, void *cookiep); nvlist_t *cnvlist_take_nvlist(nvlist_t *nvl, void *cookiep); void *cnvlist_take_binary(nvlist_t *nvl, void *cookiep, size_t *sizep); bool *cnvlist_take_bool_array(nvlist_t *nvl, void *cookiep, size_t *nitemsp); uint64_t *cnvlist_take_number_array(nvlist_t *nvl, void *cookiep, size_t *nitemsp); char **cnvlist_take_string_array(nvlist_t *nvl, void *cookiep, size_t *nitemsp); nvlist_t **cnvlist_take_nvlist_array(nvlist_t *nvl, void *cookiep, size_t *nitemsp); #ifndef _KERNEL int cnvlist_take_descriptor(nvlist_t *nvl, void *cookiep); int *cnvlist_take_descriptor_array(nvlist_t *nvl, void *cookiep, size_t *nitemsp); #endif /* * The cnvlist_free functions removes the given name/value pair from the nvlist based on cookie * and frees memory associated with it. */ void cnvlist_free_bool(nvlist_t *nvl, void *cookiep); void cnvlist_free_number(nvlist_t *nvl, void *cookiep); void cnvlist_free_string(nvlist_t *nvl, void *cookiep); void cnvlist_free_nvlist(nvlist_t *nvl, void *cookiep); void cnvlist_free_binary(nvlist_t *nvl, void *cookiep); void cnvlist_free_bool_array(nvlist_t *nvl, void *cookiep); void cnvlist_free_number_array(nvlist_t *nvl, void *cookiep); void cnvlist_free_string_array(nvlist_t *nvl, void *cookiep); void cnvlist_free_nvlist_array(nvlist_t *nvl, void *cookiep); #ifndef _KERNEL void cnvlist_free_descriptor(nvlist_t *nvl, void *cookiep); void cnvlist_free_descriptor_array(nvlist_t *nvl, void *cookiep); #endif __END_DECLS #endif /* !_CNV_H_ */ Index: head/sys/sys/devmap.h =================================================================== --- head/sys/sys/devmap.h (revision 326822) +++ head/sys/sys/devmap.h (revision 326823) @@ -1,95 +1,97 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2013 Ian Lepore * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_DEVMAP_H_ #define _SYS_DEVMAP_H_ #ifndef _KERNEL #error "no user-serviceable parts inside" #endif /* * This structure is used by MD code to describe static mappings of devices * which are established as part of bringing up the MMU early in the boot. */ struct devmap_entry { vm_offset_t pd_va; /* virtual address */ vm_paddr_t pd_pa; /* physical address */ vm_size_t pd_size; /* size of region */ }; /* * Return the lowest KVA address used in any entry in the registered devmap * table. This works with whatever table is registered, including the internal * table used by devmap_add_entry() if that routine was used. Platforms can * implement platform_lastaddr() by calling this if static device mappings are * their only use of high KVA space. */ vm_offset_t devmap_lastaddr(void); /* * Automatically allocate KVA (from the top of the address space downwards) and * make static device mapping entries in an internal table. The internal table * is automatically registered on the first call to this. */ void devmap_add_entry(vm_paddr_t pa, vm_size_t sz); /* * Register a platform-local table to be bootstrapped by the generic * initarm() in arm/machdep.c. This is used by newer code that allocates and * fills in its own local table but does not have its own initarm() routine. */ void devmap_register_table(const struct devmap_entry * _table); /* * Establish mappings for all the entries in the table. This is called * automatically from the common initarm() in arm/machdep.c, and also from the * custom initarm() routines in older code. If the table pointer is NULL, this * will use the table installed previously by devmap_register_table(). */ void devmap_bootstrap(vm_offset_t _l1pt, const struct devmap_entry *_table); /* * Translate between virtual and physical addresses within a region that is * static-mapped by the devmap code. If the given address range isn't * static-mapped, then ptov returns NULL and vtop returns DEVMAP_PADDR_NOTFOUND. * The latter implies that you can't vtop just the last byte of physical address * space. This is not as limiting as it might sound, because even if a device * occupies the end of the physical address space, you're only prevented from * doing vtop for that single byte. If you vtop a size bigger than 1 it works. */ #define DEVMAP_PADDR_NOTFOUND ((vm_paddr_t)(-1)) void * devmap_ptov(vm_paddr_t _pa, vm_size_t _sz); vm_paddr_t devmap_vtop(void * _va, vm_size_t _sz); /* Print the static mapping table; used for bootverbose output. */ void devmap_print_table(void); #endif /* !_SYS_DEVMAP_H_ */ Index: head/sys/sys/disk_zone.h =================================================================== --- head/sys/sys/disk_zone.h (revision 326822) +++ head/sys/sys/disk_zone.h (revision 326823) @@ -1,184 +1,186 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2015 Spectra Logic Corporation * 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 at minimum a disclaimer * substantially similar to the "NO WARRANTY" disclaimer below * ("Disclaimer") and any redistribution must be conditioned upon * including a substantially similar Disclaimer requirement for further * binary redistribution. * * NO WARRANTY * 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 MERCHANTIBILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. * * Authors: Ken Merry (Spectra Logic Corporation) * * $FreeBSD$ */ #ifndef _SYS_DISK_ZONE_H_ #define _SYS_DISK_ZONE_H_ /* * Interface for Zone-based disks. This allows managing devices that * conform to the SCSI Zoned Block Commands (ZBC) and ATA Zoned ATA Command * Set (ZAC) specifications. Devices using these command sets are * currently (October 2015) hard drives using Shingled Magnetic Recording * (SMR). */ /* * There are currently three types of zoned devices: * * Drive Managed: * Drive Managed drives look and act just like a standard random access * block device, but underneath, the drive reads and writes the bulk of * its capacity using SMR zones. Sequential writes will yield better * performance, but writing sequentially is not required. * * Host Aware: * Host Aware drives expose the underlying zone layout via SCSI or ATA * commands and allow the host to manage the zone conditions. The host * is not required to manage the zones on the drive, though. Sequential * writes will yield better performance in Sequential Write Preferred * zones, but the host can write randomly in those zones. * * Host Managed: * Host Managed drives expose the underlying zone layout via SCSI or ATA * commands. The host is required to access the zones according to the * rules described by the zone layout. Any commands that violate the * rules will be returned with an error. */ struct disk_zone_disk_params { uint32_t zone_mode; #define DISK_ZONE_MODE_NONE 0x00 #define DISK_ZONE_MODE_HOST_AWARE 0x01 #define DISK_ZONE_MODE_DRIVE_MANAGED 0x02 #define DISK_ZONE_MODE_HOST_MANAGED 0x04 uint64_t flags; #define DISK_ZONE_DISK_URSWRZ 0x001 #define DISK_ZONE_OPT_SEQ_SET 0x002 #define DISK_ZONE_OPT_NONSEQ_SET 0x004 #define DISK_ZONE_MAX_SEQ_SET 0x008 #define DISK_ZONE_RZ_SUP 0x010 #define DISK_ZONE_OPEN_SUP 0x020 #define DISK_ZONE_CLOSE_SUP 0x040 #define DISK_ZONE_FINISH_SUP 0x080 #define DISK_ZONE_RWP_SUP 0x100 #define DISK_ZONE_CMD_SUP_MASK 0x1f0 uint64_t optimal_seq_zones; uint64_t optimal_nonseq_zones; uint64_t max_seq_zones; }; /* * Used for reset write pointer, open, close and finish. */ struct disk_zone_rwp { uint64_t id; uint8_t flags; #define DISK_ZONE_RWP_FLAG_NONE 0x00 #define DISK_ZONE_RWP_FLAG_ALL 0x01 }; /* * Report Zones header. All of these values are passed out. */ struct disk_zone_rep_header { uint8_t same; #define DISK_ZONE_SAME_ALL_DIFFERENT 0x0 /* Lengths and types vary */ #define DISK_ZONE_SAME_ALL_SAME 0x1 /* Lengths and types the same */ #define DISK_ZONE_SAME_LAST_DIFFERENT 0x2 /* Types same, last len varies */ #define DISK_ZONE_SAME_TYPES_DIFFERENT 0x3 /* Types vary, length the same */ uint64_t maximum_lba; /* * XXX KDM padding space may not be a good idea inside the bio. */ uint8_t reserved[64]; }; /* * Report Zones entry. Note that the zone types, conditions, and flags * are mapped directly from the SCSI/ATA flag values. Any additional * SCSI/ATA zone types or conditions or flags that are defined in the * future could result in additional values that are not yet defined here. */ struct disk_zone_rep_entry { uint8_t zone_type; #define DISK_ZONE_TYPE_CONVENTIONAL 0x01 #define DISK_ZONE_TYPE_SEQ_REQUIRED 0x02 /* Host Managed */ #define DISK_ZONE_TYPE_SEQ_PREFERRED 0x03 /* Host Aware */ uint8_t zone_condition; #define DISK_ZONE_COND_NOT_WP 0x00 #define DISK_ZONE_COND_EMPTY 0x01 #define DISK_ZONE_COND_IMPLICIT_OPEN 0x02 #define DISK_ZONE_COND_EXPLICIT_OPEN 0x03 #define DISK_ZONE_COND_CLOSED 0x04 #define DISK_ZONE_COND_READONLY 0x0D #define DISK_ZONE_COND_FULL 0x0E #define DISK_ZONE_COND_OFFLINE 0x0F uint8_t zone_flags; #define DISK_ZONE_FLAG_RESET 0x01 /* Zone needs RWP */ #define DISK_ZONE_FLAG_NON_SEQ 0x02 /* Zone accssessed nonseq */ uint64_t zone_length; uint64_t zone_start_lba; uint64_t write_pointer_lba; /* XXX KDM padding space may not be a good idea inside the bio */ uint8_t reserved[32]; }; struct disk_zone_report { uint64_t starting_id; /* Passed In */ uint8_t rep_options; /* Passed In */ #define DISK_ZONE_REP_ALL 0x00 #define DISK_ZONE_REP_EMPTY 0x01 #define DISK_ZONE_REP_IMP_OPEN 0x02 #define DISK_ZONE_REP_EXP_OPEN 0x03 #define DISK_ZONE_REP_CLOSED 0x04 #define DISK_ZONE_REP_FULL 0x05 #define DISK_ZONE_REP_READONLY 0x06 #define DISK_ZONE_REP_OFFLINE 0x07 #define DISK_ZONE_REP_RWP 0x10 #define DISK_ZONE_REP_NON_SEQ 0x11 #define DISK_ZONE_REP_NON_WP 0x3F struct disk_zone_rep_header header; uint32_t entries_allocated; /* Passed In */ uint32_t entries_filled; /* Passed Out */ uint32_t entries_available; /* Passed Out */ struct disk_zone_rep_entry *entries; }; union disk_zone_params { struct disk_zone_disk_params disk_params; struct disk_zone_rwp rwp; struct disk_zone_report report; }; struct disk_zone_args { uint8_t zone_cmd; #define DISK_ZONE_OPEN 0x00 #define DISK_ZONE_CLOSE 0x01 #define DISK_ZONE_FINISH 0x02 #define DISK_ZONE_REPORT_ZONES 0x03 #define DISK_ZONE_RWP 0x04 #define DISK_ZONE_GET_PARAMS 0x05 union disk_zone_params zone_params; }; #endif /* _SYS_DISK_ZONE_H_ */ Index: head/sys/sys/dnv.h =================================================================== --- head/sys/sys/dnv.h (revision 326822) +++ head/sys/sys/dnv.h (revision 326823) @@ -1,85 +1,87 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2013 The FreeBSD Foundation * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _DNV_H_ #define _DNV_H_ #include #ifndef _KERNEL #include #include #include #include #endif #ifndef _NVLIST_T_DECLARED #define _NVLIST_T_DECLARED struct nvlist; typedef struct nvlist nvlist_t; #endif __BEGIN_DECLS /* * The dnvlist_get functions returns value associated with the given name. * If it returns a pointer, the pointer represents internal buffer and should * not be freed by the caller. * If no element of the given name and type exists, the function will return * provided default value. */ bool dnvlist_get_bool(const nvlist_t *nvl, const char *name, bool defval); uint64_t dnvlist_get_number(const nvlist_t *nvl, const char *name, uint64_t defval); const char *dnvlist_get_string(const nvlist_t *nvl, const char *name, const char *defval); const nvlist_t *dnvlist_get_nvlist(const nvlist_t *nvl, const char *name, const nvlist_t *defval); int dnvlist_get_descriptor(const nvlist_t *nvl, const char *name, int defval); const void *dnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep, const void *defval, size_t defsize); /* * The dnvlist_take functions returns value associated with the given name and * remove corresponding nvpair. * If it returns a pointer, the caller has to free it. * If no element of the given name and type exists, the function will return * provided default value. */ bool dnvlist_take_bool(nvlist_t *nvl, const char *name, bool defval); uint64_t dnvlist_take_number(nvlist_t *nvl, const char *name, uint64_t defval); char *dnvlist_take_string(nvlist_t *nvl, const char *name, char *defval); nvlist_t *dnvlist_take_nvlist(nvlist_t *nvl, const char *name, nvlist_t *defval); int dnvlist_take_descriptor(nvlist_t *nvl, const char *name, int defval); void *dnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep, void *defval, size_t defsize); __END_DECLS #endif /* !_DNV_H_ */ Index: head/sys/sys/gtaskqueue.h =================================================================== --- head/sys/sys/gtaskqueue.h (revision 326822) +++ head/sys/sys/gtaskqueue.h (revision 326823) @@ -1,108 +1,110 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2014 Jeffrey Roberson * Copyright (c) 2016 Matthew Macy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_GTASKQUEUE_H_ #define _SYS_GTASKQUEUE_H_ #include #ifndef _KERNEL #error "no user-serviceable parts inside" #endif struct gtaskqueue; typedef void (*gtaskqueue_enqueue_fn)(void *context); /* * Taskqueue groups. Manages dynamic thread groups and irq binding for * device and other tasks. */ void gtaskqueue_block(struct gtaskqueue *queue); void gtaskqueue_unblock(struct gtaskqueue *queue); int gtaskqueue_cancel(struct gtaskqueue *queue, struct gtask *gtask); void gtaskqueue_drain(struct gtaskqueue *queue, struct gtask *task); void gtaskqueue_drain_all(struct gtaskqueue *queue); int grouptaskqueue_enqueue(struct gtaskqueue *queue, struct gtask *task); void taskqgroup_attach(struct taskqgroup *qgroup, struct grouptask *grptask, void *uniq, int irq, char *name); int taskqgroup_attach_cpu(struct taskqgroup *qgroup, struct grouptask *grptask, void *uniq, int cpu, int irq, char *name); void taskqgroup_detach(struct taskqgroup *qgroup, struct grouptask *gtask); struct taskqgroup *taskqgroup_create(char *name); void taskqgroup_destroy(struct taskqgroup *qgroup); int taskqgroup_adjust(struct taskqgroup *qgroup, int cnt, int stride); #define TASK_ENQUEUED 0x1 #define TASK_SKIP_WAKEUP 0x2 #define GTASK_INIT(task, flags, priority, func, context) do { \ (task)->ta_flags = flags; \ (task)->ta_priority = (priority); \ (task)->ta_func = (func); \ (task)->ta_context = (context); \ } while (0) #define GROUPTASK_INIT(gtask, priority, func, context) \ GTASK_INIT(&(gtask)->gt_task, TASK_SKIP_WAKEUP, priority, func, context) #define GROUPTASK_ENQUEUE(gtask) \ grouptaskqueue_enqueue((gtask)->gt_taskqueue, &(gtask)->gt_task) #define TASKQGROUP_DECLARE(name) \ extern struct taskqgroup *qgroup_##name #define TASKQGROUP_DEFINE(name, cnt, stride) \ \ struct taskqgroup *qgroup_##name; \ \ static void \ taskqgroup_define_##name(void *arg) \ { \ qgroup_##name = taskqgroup_create(#name); \ } \ \ SYSINIT(taskqgroup_##name, SI_SUB_TASKQ, SI_ORDER_FIRST, \ taskqgroup_define_##name, NULL); \ \ static void \ taskqgroup_adjust_##name(void *arg) \ { \ taskqgroup_adjust(qgroup_##name, (cnt), (stride)); \ } \ \ SYSINIT(taskqgroup_adj_##name, SI_SUB_SMP, SI_ORDER_ANY, \ taskqgroup_adjust_##name, NULL) TASKQGROUP_DECLARE(net); TASKQGROUP_DECLARE(softirq); #endif /* !_SYS_GTASKQUEUE_H_ */ Index: head/sys/sys/gzio.h =================================================================== --- head/sys/sys/gzio.h (revision 326822) +++ head/sys/sys/gzio.h (revision 326823) @@ -1,50 +1,52 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2014 Mark Johnston * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS__GZIO_H_ #define _SYS__GZIO_H_ #ifdef _KERNEL enum gzio_mode { GZIO_DEFLATE, }; typedef int (*gzio_cb)(void *, size_t, off_t, void *); struct gzio_stream; struct gzio_stream *gzio_init(gzio_cb cb, enum gzio_mode, size_t, int, void *); void gzio_reset(struct gzio_stream *); int gzio_write(struct gzio_stream *, void *, u_int); int gzio_flush(struct gzio_stream *); void gzio_fini(struct gzio_stream *); #endif /* _KERNEL */ #endif /* _SYS__GZIO_H_ */ Index: head/sys/sys/imgact_binmisc.h =================================================================== --- head/sys/sys/imgact_binmisc.h (revision 326822) +++ head/sys/sys/imgact_binmisc.h (revision 326823) @@ -1,172 +1,174 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2013 Stacey D. Son * * 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _IMGACT_BINMISC_H_ #define _IMGACT_BINMISC_H_ /** * Miscellaneous binary interpreter image activator. */ #include /* for MAXPATHLEN */ /* * Imgact bin misc parameters. */ #define IBE_VERSION 1 /* struct ximgact_binmisc_entry version. */ #define IBE_NAME_MAX 32 /* Max size for entry name. */ #define IBE_MAGIC_MAX 256 /* Max size for header magic and mask. */ #define IBE_ARG_LEN_MAX 256 /* Max space for optional interpreter command- line arguments separated by white space */ #define IBE_INTERP_LEN_MAX (MAXPATHLEN + IBE_ARG_LEN_MAX) #define IBE_MAX_ENTRIES 64 /* Max number of interpreter entries. */ /* * Imgact bin misc interpreter entry flags. */ #define IBF_ENABLED 0x0001 /* Entry is active. */ #define IBF_USE_MASK 0x0002 /* Use mask on header magic field. */ /* * Used with sysctlbyname() to pass imgact bin misc entries in and out of the * kernel. */ typedef struct ximgact_binmisc_entry { uint32_t xbe_version; /* Struct version(IBE_VERSION) */ uint32_t xbe_flags; /* Entry flags (IBF_*) */ uint32_t xbe_moffset; /* Magic offset in header */ uint32_t xbe_msize; /* Magic size */ uint32_t spare[3]; /* Spare fields for future use */ char xbe_name[IBE_NAME_MAX]; /* Unique interpreter name */ char xbe_interpreter[IBE_INTERP_LEN_MAX]; /* Interpreter path + args */ uint8_t xbe_magic[IBE_MAGIC_MAX]; /* Header Magic */ uint8_t xbe_mask[IBE_MAGIC_MAX]; /* Magic Mask */ } ximgact_binmisc_entry_t; /* * sysctl() command names. */ #define IBE_SYSCTL_NAME "kern.binmisc" #define IBE_SYSCTL_NAME_ADD IBE_SYSCTL_NAME ".add" #define IBE_SYSCTL_NAME_REMOVE IBE_SYSCTL_NAME ".remove" #define IBE_SYSCTL_NAME_DISABLE IBE_SYSCTL_NAME ".disable" #define IBE_SYSCTL_NAME_ENABLE IBE_SYSCTL_NAME ".enable" #define IBE_SYSCTL_NAME_LOOKUP IBE_SYSCTL_NAME ".lookup" #define IBE_SYSCTL_NAME_LIST IBE_SYSCTL_NAME ".list" #define KMOD_NAME "imgact_binmisc" /* * Examples of manipulating the interpreter table using sysctlbyname(3): * * #include * * #define LLVM_MAGIC "BC\xc0\xde" * * #define MIPS64_ELF_MAGIC "\x7f\x45\x4c\x46\x02\x02\x01\x00\x00\x00" \ * "\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08" * #define MIPS64_ELF_MASK "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff" \ * "\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff" * * ximgact_binmisc_entry_t xbe, *xbep, out_xbe; * size_t size = 0, osize; * int error, i; * * // Add image activator for LLVM byte code * bzero(&xbe, sizeof(xbe)); * xbe.xbe_version = IBE_VERSION; * xbe.xbe_flags = IBF_ENABLED; * strlcpy(xbe.xbe_name, "llvm_bc", IBE_NAME_MAX); * strlcpy(xbe.xbe_interpreter, "/usr/bin/lli --fake-arg0=#a", * IBE_INTERP_LEN_MAX); * xbe.xbe_moffset = 0; * xbe.xbe_msize = 4; * memcpy(xbe.xbe_magic, LLVM_MAGIC, xbe.xbe_msize); * error = sysctlbyname(IBE_SYSCTL_NAME_ADD, NULL, NULL, &xbe, sizeof(xbe)); * * // Add image activator for mips64 ELF binaries to use qemu user mode * bzero(&xbe, sizeof(xbe)); * xbe.xbe_version = IBE_VERSION; * xbe.xbe_flags = IBF_ENABLED | IBF_USE_MASK; * strlcpy(xbe.xbe_name, "mips64elf", IBE_NAME_MAX); * strlcpy(xbe.xbe_interpreter, "/usr/local/bin/qemu-mips64", * IBE_INTERP_LEN_MAX); * xbe.xbe_moffset = 0; * xbe.xbe_msize = 20; * memcpy(xbe.xbe_magic, MIPS64_ELF_MAGIC, xbe.xbe_msize); * memcpy(xbe.xbe_mask, MIPS64_ELF_MASK, xbe.xbe_msize); * sysctlbyname(IBE_SYSCTL_NAME_ADD, NULL, NULL, &xbe, sizeof(xbe)); * * // Disable (OR Enable OR Remove) image activator for LLVM byte code * bzero(&xbe, sizeof(xbe)); * xbe.xbe_version = IBE_VERSION; * strlcpy(xbe.xbe_name, "llvm_bc", IBE_NAME_MAX); * error = sysctlbyname(IBE_SYSCTL_NAME_DISABLE, NULL, NULL, &xbe, sizeof(xbe)); * // OR sysctlbyname(IBE_SYSCTL_NAME_ENABLE, NULL, NULL, &xbe, sizeof(xbe)); * // OR sysctlbyname(IBE_SYSCTL_NAME_REMOVE, NULL, NULL, &xbe, sizeof(xbe)); * * // Lookup image activator "llvm_bc" * bzero(&xbe, sizeof(xbe)); * xbe.xbe_version = IBE_VERSION; * strlcpy(xbe.xbe_name, "llvm_bc", IBE_NAME_MAX); * size = sizeof(out_xbe); * error = sysctlbyname(IBE_SYSCTL_NAME_LOOKUP, &out_xbe, &size, &xbe, * sizeof(xbe)); * * // Get all the currently configured image activators and report * error = sysctlbyname(IBE_SYSCTL_NAME_LIST, NULL, &size, NULL, 0); * if (0 == error && size > 0) { * xbep = malloc(size); * while(1) { * osize = size; * error = sysctlbyname("kern.binmisc.list", xbep, &size, NULL, 0); * if (-1 == error && ENOMEM == errno && size == osize) { * // The buffer too small and needs to grow * size += sizeof(xbe); * xbep = realloc(xbep, size); * } else * break; * } * } * for(i = 0; i < (size / sizeof(xbe)); i++, xbep++) * printf("name: %s interpreter: %s flags: %s %s\n", xbep->xbe_name, * xbep->xbe_interpreter, (xbep->xbe_flags & IBF_ENABLED) ? * "ENABLED" : "", (xbep->xbe_flags & IBF_ENABLED) ? "USE_MASK" : ""); * * The sysctlbyname() calls above may return the following errors in addition * to the standard ones: * * [EINVAL] Invalid argument in the input ximgact_binmisc_entry_t structure. * [EEXIST] Interpreter entry for given name already exist in kernel list. * [ENOMEM] Allocating memory in the kernel failed or, in the case of * kern.binmisc.list, the user buffer is too small. * [ENOENT] Interpreter entry for given name is not found. * [ENOSPC] Attempted to exceed maximum number of entries (IBE_MAX_ENTRIES). */ #endif /* !_IMGACT_BINMISC_H_ */ Index: head/sys/sys/intr.h =================================================================== --- head/sys/sys/intr.h (revision 326822) +++ head/sys/sys/intr.h (revision 326823) @@ -1,162 +1,164 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2015-2016 Svatopluk Kraus * Copyright (c) 2015-2016 Michal Meloun * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_INTR_H_ #define _SYS_INTR_H_ #ifndef INTRNG #error Need INTRNG for this file #endif #include #define INTR_IRQ_INVALID 0xFFFFFFFF enum intr_map_data_type { INTR_MAP_DATA_ACPI = 0, INTR_MAP_DATA_FDT, INTR_MAP_DATA_GPIO, INTR_MAP_DATA_MSI, /* Placeholders for platform specific types */ INTR_MAP_DATA_PLAT_1 = 1000, INTR_MAP_DATA_PLAT_2, INTR_MAP_DATA_PLAT_3, INTR_MAP_DATA_PLAT_4, INTR_MAP_DATA_PLAT_5, }; struct intr_map_data { size_t len; enum intr_map_data_type type; }; struct intr_map_data_msi { struct intr_map_data hdr; struct intr_irqsrc *isrc; }; #ifdef notyet #define INTR_SOLO INTR_MD1 typedef int intr_irq_filter_t(void *arg, struct trapframe *tf); #else typedef int intr_irq_filter_t(void *arg); #endif typedef int intr_child_irq_filter_t(void *arg, uintptr_t irq); #define INTR_ISRC_NAMELEN (MAXCOMLEN + 1) #define INTR_ISRCF_IPI 0x01 /* IPI interrupt */ #define INTR_ISRCF_PPI 0x02 /* PPI interrupt */ #define INTR_ISRCF_BOUND 0x04 /* bound to a CPU */ struct intr_pic; /* Interrupt source definition. */ struct intr_irqsrc { device_t isrc_dev; /* where isrc is mapped */ u_int isrc_irq; /* unique identificator */ u_int isrc_flags; char isrc_name[INTR_ISRC_NAMELEN]; cpuset_t isrc_cpu; /* on which CPUs is enabled */ u_int isrc_index; u_long * isrc_count; u_int isrc_handlers; struct intr_event * isrc_event; #ifdef INTR_SOLO intr_irq_filter_t * isrc_filter; void * isrc_arg; #endif }; /* Intr interface for PIC. */ int intr_isrc_deregister(struct intr_irqsrc *); int intr_isrc_register(struct intr_irqsrc *, device_t, u_int, const char *, ...) __printflike(4, 5); #ifdef SMP bool intr_isrc_init_on_cpu(struct intr_irqsrc *isrc, u_int cpu); #endif int intr_isrc_dispatch(struct intr_irqsrc *, struct trapframe *); u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask); struct intr_pic *intr_pic_register(device_t, intptr_t); int intr_pic_deregister(device_t, intptr_t); int intr_pic_claim_root(device_t, intptr_t, intr_irq_filter_t *, void *, u_int); struct intr_pic *intr_pic_add_handler(device_t, struct intr_pic *, intr_child_irq_filter_t *, void *, uintptr_t, uintptr_t); extern device_t intr_irq_root_dev; /* Intr interface for BUS. */ int intr_activate_irq(device_t, struct resource *); int intr_deactivate_irq(device_t, struct resource *); int intr_setup_irq(device_t, struct resource *, driver_filter_t, driver_intr_t, void *, int, void **); int intr_teardown_irq(device_t, struct resource *, void *); int intr_describe_irq(device_t, struct resource *, void *, const char *); int intr_child_irq_handler(struct intr_pic *, uintptr_t); /* Intr resources mapping. */ struct intr_map_data *intr_alloc_map_data(enum intr_map_data_type, size_t, int); void intr_free_intr_map_data(struct intr_map_data *); u_int intr_map_irq(device_t, intptr_t, struct intr_map_data *); void intr_unmap_irq(u_int ); u_int intr_map_clone_irq(u_int ); /* MSI/MSI-X handling */ int intr_msi_register(device_t, intptr_t); int intr_alloc_msi(device_t, device_t, intptr_t, int, int, int *); int intr_release_msi(device_t, device_t, intptr_t, int, int *); int intr_map_msi(device_t, device_t, intptr_t, int, uint64_t *, uint32_t *); int intr_alloc_msix(device_t, device_t, intptr_t, int *); int intr_release_msix(device_t, device_t, intptr_t, int); #ifdef SMP int intr_bind_irq(device_t, struct resource *, int); void intr_pic_init_secondary(void); /* Virtualization for interrupt source IPI counter increment. */ static inline void intr_ipi_increment_count(u_long *counter, u_int cpu) { KASSERT(cpu < MAXCPU, ("%s: too big cpu %u", __func__, cpu)); counter[cpu]++; } /* Virtualization for interrupt source IPI counters setup. */ u_long * intr_ipi_setup_counters(const char *name); #endif #endif /* _SYS_INTR_H */ Index: head/sys/sys/iov.h =================================================================== --- head/sys/sys/iov.h (revision 326822) +++ head/sys/sys/iov.h (revision 326823) @@ -1,257 +1,259 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2013-2015 Sandvine Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_IOV_H_ #define _SYS_IOV_H_ #include #define PF_CONFIG_NAME "PF" #define VF_SCHEMA_NAME "VF" #define VF_PREFIX "VF-" #define VF_PREFIX_LEN 3 #define VF_NUM_LEN 5 /* The maximum VF num is 65535. */ #define VF_MAX_NAME (VF_PREFIX_LEN + VF_NUM_LEN + 1) #define DRIVER_CONFIG_NAME "DRIVER" #define IOV_CONFIG_NAME "IOV" #define TYPE_SCHEMA_NAME "TYPE" #define DEFAULT_SCHEMA_NAME "DEFAULT" #define REQUIRED_SCHEMA_NAME "REQUIRED" /* * Because each PF device is expected to expose a unique set of possible * configurations, the SR-IOV infrastructure dynamically queries the PF * driver for its capabilities. These capabilities are exposed to userland * with a configuration schema. The schema is exported from the kernel as a * packed nvlist. See nv(3) for the details of the nvlist API. The expected * format of the nvlist is: * * BASIC RULES * 1) All keys are case-insensitive. * 2) No keys that are not specified below may exist at any level of the * schema. * 3) All keys are mandatory unless explicitly documented as optional. If a * key is mandatory then the associated value is also mandatory. * 4) Order of keys is irrelevant. * * TOP LEVEL * 1) There must be a top-level key with the name PF_CONFIG_NAME. The value * associated with this key is a nvlist that follows the device schema * node format. The parameters in this node specify the configuration * parameters that may be applied to a PF. * 2) There must be a top-level key with the name VF_SCHEMA_NAME. The value * associated with this key is a nvlist that follows the device schema * node format. The parameters in this node specify the configuration * parameters that may be applied to a VF. * * DEVICE SCHEMA NODE * 1) There must be a key with the name DRIVER_CONFIG_NAME. The value * associated with this key is a nvlist that follows the device/subsystem * schema node format. The parameters in this node specify the * configuration parameters that are specific to a particular device * driver. * 2) There must be a key with the name IOV_CONFIG_NAME. The value associated * with this key is an nvlist that follows the device/subsystem schema node * format. The parameters in this node specify the configuration * parameters that are applied by the SR-IOV infrastructure. * * DEVICE/SUBSYSTEM SCHEMA NODE * 1) All keys in the device/subsystem schema node are optional. * 2) Each key specifies the name of a valid configuration parameter that may * be applied to the device/subsystem combination specified by this node. * The value associated with the key specifies the format of valid * configuration values, and must be a nvlist in parameter schema node * format. * * PARAMETER SCHEMA NODE * 1) The parameter schema node must contain a key with the name * TYPE_SCHEMA_NAME. The value associated with this key must be a string. * This string specifies the type of value that the parameter specified by * this node must take. The string must have one of the following values: * - "bool" - The configuration value must be a boolean. * - "mac-addr" - The configuration value must be a binary value. In * addition, the value must be exactly 6 bytes long and * the value must not be a multicast or broadcast mac. * - "uint8_t" - The configuration value must be a integer value in * the range [0, UINT8_MAX]. * - "uint16_t" - The configuration value must be a integer value in * the range [0, UINT16_MAX]. * - "uint32_t" - The configuration value must be a integer value in * the range [0, UINT32_MAX]. * - "uint64_t" - The configuration value must be a integer value in * the range [0, UINT64_MAX]. * 2) The parameter schema may contain a key with the name * REQUIRED_SCHEMA_NAME. This key is optional. If this key is present, the * value associated with it must have a boolean type. If the value is true, * then the parameter specified by this schema is a required parameter. All * valid configurations must include all required parameters. * 3) The parameter schema may contain a key with the name DEFAULT_SCHEMA_NAME. * This key is optional. This key must not be present if the parameter * specified by this schema is required. If this key is present, the value * associated with the parent key must follow all restrictions specified by * the type specified by this schema. If a configuration does not supply a * value for the parameter specified by this schema, then the kernel will * apply the value associated with this key in its place. * * The following is an example of a valid schema, as printed by nvlist_dump. * Keys are printed followed by the type of the value in parantheses. The * value is displayed following a colon. The indentation level reflects the * level of nesting of nvlists. String values are displayed between [] * brackets. Binary values are shown with the length of the binary value (in * bytes) followed by the actual binary values. * * PF (NVLIST): * IOV (NVLIST): * num_vfs (NVLIST): * type (STRING): [uint16_t] * required (BOOL): TRUE * device (NVLIST): * type (STRING): [string] * required (BOOL): TRUE * DRIVER (NVLIST): * VF (NVLIST): * IOV (NVLIST): * passthrough (NVLIST): * type (STRING): [bool] * default (BOOL): FALSE * DRIVER (NVLIST): * mac-addr (NVLIST): * type (STRING): [mac-addr] * default (BINARY): 6 000000000000 * vlan (NVLIST): * type (STRING): [uint16_t] * spoof-check (NVLIST): * type (STRING): [bool] * default (BOOL): TRUE * allow-set-mac (NVLIST): * type (STRING): [bool] * default (BOOL): FALSE */ struct pci_iov_schema { void *schema; size_t len; int error; }; /* * SR-IOV configuration is passed to the kernel as a packed nvlist. See nv(3) * for the details of the nvlist API. The expected format of the nvlist is: * * BASIC RULES * 1) All keys are case-insensitive. * 2) No keys that are not specified below may exist at any level of the * config nvlist. * 3) Unless otherwise specified, all keys are optional. It should go without * saying a key being mandatory is transitive: that is, if a key is * specified to contain a sub-nodes that contains a mandatory key, then * the outer key is implicitly mandatory. If a key is mandatory then the * associated value is also mandatory. * 4) Order of keys is irrelevant. * * TOP LEVEL OF CONFIG NVLIST * 1) All keys specified in this section are mandatory. * 2) There must be a top-level key with the name PF_CONFIG_NAME. The value * associated is an nvlist that follows the "device node" format. The * parameters in this node specify parameters that apply to the PF. * 3) For every VF being configured (this is set via the "num_vfs" parameter * in the PF section), there must be a top-level key whose name is VF_PREFIX * immediately followed by the index of the VF as a decimal integer. For * example, this would be VF-0 for the first VF. VFs are numbered starting * from 0. The value associated with this key follows the "device node" * format. The parameters in this node specify configuration that applies * to the VF specified in the key. Leading zeros are not permitted in VF * index. Configuration for the second VF must be specified in a node with * the key VF-1. VF-01 is not a valid key. * * DEVICE NODES * 1) All keys specified in this section are mandatory. * 2) The device node must contain a key with the name DRIVER_CONFIG_NAME. The * value associated with this key is an nvlist following the subsystem node * format. The parameters in this key specify configuration that is specific * to a particular device driver. * 3) The device node must contain a key with the name IOV_CONFIG_NAME. The * value associated with this key is an nvlist following the subsystem node * format. The parameters in this key specify configuration that is consumed * by the SR-IOV infrastructure. * * SUBSYSTEM NODES * 1) A subsystem node specifies configuration parameters that apply to a * particular subsystem (driver or infrastructure) of a particular device * (PF or individual VF). * Note: We will refer to the section of the configuration schema that * specifies the parameters for this subsystem and device * configuration as the device/subystem schema. * 2) The subsystem node must contain only keys that correspond to parameters * that are specified in the device/subsystem schema. * 3) Every parameter specified as required in the device/subsystem schema is * a mandatory key in the subsystem node. * Note: All parameters that are not required in device/subsystem schema are * optional keys. In particular, any parameter specified to have a * default value in the device/subsystem schema is optional. The * kernel is responsible for applying default values. * 4) The value of every parameter in the device node must conform to the * restrictions of the type specified for that parameter in the device/ * subsystem schema. * * The following is an example of a valid configuration, when validated against * the schema example given above. * * PF (NVLIST): * driver (NVLIST): * iov (NVLIST): * num_vfs (NUMBER): 3 (3) (0x3) * device (STRING): [ix0] * VF-0 (NVLIST): * driver (NVLIST): * vlan (NUMBER): 1000 (1000) (0x3e8) * iov (NVLIST): * passthrough (BOOL): TRUE * VF-1 (NVLIST): * driver (NVLIST): * iov (NVLIST): * VF-2 (NVLIST): * driver (NVLIST): * mac-addr (BINARY): 6 020102030405 * iov (NVLIST): */ struct pci_iov_arg { void *config; size_t len; }; #define IOV_CONFIG _IOW('p', 10, struct pci_iov_arg) #define IOV_DELETE _IO('p', 11) #define IOV_GET_SCHEMA _IOWR('p', 12, struct pci_iov_schema) #endif Index: head/sys/sys/iov_schema.h =================================================================== --- head/sys/sys/iov_schema.h (revision 326822) +++ head/sys/sys/iov_schema.h (revision 326823) @@ -1,52 +1,54 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * * Copyright (c) 2014-2015 Sandvine Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_IOV_SCHEMA_H_ #define _SYS_IOV_SCHEMA_H_ #define IOV_SCHEMA_HASDEFAULT (1 << 0) #define IOV_SCHEMA_REQUIRED (1 << 1) nvlist_t *pci_iov_schema_alloc_node(void); void pci_iov_schema_add_bool(nvlist_t *schema, const char *name, uint32_t flags, int defaultVal); void pci_iov_schema_add_string(nvlist_t *schema, const char *name, uint32_t flags, const char *defaultVal); void pci_iov_schema_add_uint8(nvlist_t *schema, const char *name, uint32_t flags, uint8_t defaultVal); void pci_iov_schema_add_uint16(nvlist_t *schema, const char *name, uint32_t flags, uint16_t defaultVal); void pci_iov_schema_add_uint32(nvlist_t *schema, const char *name, uint32_t flags, uint32_t defaultVal); void pci_iov_schema_add_uint64(nvlist_t *schema, const char *name, uint32_t flags, uint64_t defaultVal); void pci_iov_schema_add_unicast_mac(nvlist_t *schema, const char *name, uint32_t flags, const uint8_t * defaultVal); #endif Index: head/sys/sys/mouse.h =================================================================== --- head/sys/sys/mouse.h (revision 326822) +++ head/sys/sys/mouse.h (revision 326823) @@ -1,395 +1,397 @@ /*- + * SPDX-License-Identifier: BSD-1-Clause + * * Copyright (c) 1992, 1993 Erik Forsberg. * Copyright (c) 1996, 1997 Kazutaka YOKOTA * 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. * * THIS SOFTWARE IS PROVIDED BY ``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 I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_MOUSE_H_ #define _SYS_MOUSE_H_ #include #include /* ioctls */ #define MOUSE_GETSTATUS _IOR('M', 0, mousestatus_t) #define MOUSE_GETHWINFO _IOR('M', 1, mousehw_t) #define MOUSE_GETMODE _IOR('M', 2, mousemode_t) #define MOUSE_SETMODE _IOW('M', 3, mousemode_t) #define MOUSE_GETLEVEL _IOR('M', 4, int) #define MOUSE_SETLEVEL _IOW('M', 5, int) #define MOUSE_GETVARS _IOR('M', 6, mousevar_t) #define MOUSE_SETVARS _IOW('M', 7, mousevar_t) #define MOUSE_READSTATE _IOWR('M', 8, mousedata_t) #define MOUSE_READDATA _IOWR('M', 9, mousedata_t) #ifdef notyet #define MOUSE_SETRESOLUTION _IOW('M', 10, int) #define MOUSE_SETSCALING _IOW('M', 11, int) #define MOUSE_SETRATE _IOW('M', 12, int) #define MOUSE_GETHWID _IOR('M', 13, int) #endif #define MOUSE_SYN_GETHWINFO _IOR('M', 100, synapticshw_t) /* mouse status block */ typedef struct mousestatus { int flags; /* state change flags */ int button; /* button status */ int obutton; /* previous button status */ int dx; /* x movement */ int dy; /* y movement */ int dz; /* z movement */ } mousestatus_t; /* button */ #define MOUSE_BUTTON1DOWN 0x0001 /* left */ #define MOUSE_BUTTON2DOWN 0x0002 /* middle */ #define MOUSE_BUTTON3DOWN 0x0004 /* right */ #define MOUSE_BUTTON4DOWN 0x0008 #define MOUSE_BUTTON5DOWN 0x0010 #define MOUSE_BUTTON6DOWN 0x0020 #define MOUSE_BUTTON7DOWN 0x0040 #define MOUSE_BUTTON8DOWN 0x0080 #define MOUSE_MAXBUTTON 31 #define MOUSE_STDBUTTONS 0x0007 /* buttons 1-3 */ #define MOUSE_EXTBUTTONS 0x7ffffff8 /* the others (28 of them!) */ #define MOUSE_BUTTONS (MOUSE_STDBUTTONS | MOUSE_EXTBUTTONS) /* flags */ #define MOUSE_STDBUTTONSCHANGED MOUSE_STDBUTTONS #define MOUSE_EXTBUTTONSCHANGED MOUSE_EXTBUTTONS #define MOUSE_BUTTONSCHANGED MOUSE_BUTTONS #define MOUSE_POSCHANGED 0x80000000 typedef struct mousehw { int buttons; /* -1 if unknown */ int iftype; /* MOUSE_IF_XXX */ int type; /* mouse/track ball/pad... */ int model; /* I/F dependent model ID: MOUSE_MODEL_XXX */ int hwid; /* I/F dependent hardware ID * for the PS/2 mouse, it will be PSM_XXX_ID */ } mousehw_t; typedef struct synapticshw { int infoMajor; int infoMinor; int infoRot180; int infoPortrait; int infoSensor; int infoHardware; int infoNewAbs; int capPen; int infoSimplC; int infoGeometry; int capExtended; int capSleep; int capFourButtons; int capMultiFinger; int capPalmDetect; int capPassthrough; int capMiddle; int capLowPower; int capMultiFingerReport; int capBallistics; int nExtendedButtons; int nExtendedQueries; int capClickPad; int capDeluxeLEDs; int noAbsoluteFilter; int capReportsV; int capUniformClickPad; int capReportsMin; int capInterTouch; int capReportsMax; int capClearPad; int capAdvancedGestures; int multiFingerMode; int capCoveredPad; int verticalScroll; int horizontalScroll; int verticalWheel; int capEWmode; int minimumXCoord; int minimumYCoord; int maximumXCoord; int maximumYCoord; int infoXupmm; int infoYupmm; } synapticshw_t; /* iftype */ #define MOUSE_IF_UNKNOWN (-1) #define MOUSE_IF_SERIAL 0 #define MOUSE_IF_BUS 1 #define MOUSE_IF_INPORT 2 #define MOUSE_IF_PS2 3 #define MOUSE_IF_SYSMOUSE 4 #define MOUSE_IF_USB 5 /* type */ #define MOUSE_UNKNOWN (-1) /* should be treated as a mouse */ #define MOUSE_MOUSE 0 #define MOUSE_TRACKBALL 1 #define MOUSE_STICK 2 #define MOUSE_PAD 3 /* model */ #define MOUSE_MODEL_UNKNOWN (-1) #define MOUSE_MODEL_GENERIC 0 #define MOUSE_MODEL_GLIDEPOINT 1 #define MOUSE_MODEL_NETSCROLL 2 #define MOUSE_MODEL_NET 3 #define MOUSE_MODEL_INTELLI 4 #define MOUSE_MODEL_THINK 5 #define MOUSE_MODEL_EASYSCROLL 6 #define MOUSE_MODEL_MOUSEMANPLUS 7 #define MOUSE_MODEL_KIDSPAD 8 #define MOUSE_MODEL_VERSAPAD 9 #define MOUSE_MODEL_EXPLORER 10 #define MOUSE_MODEL_4D 11 #define MOUSE_MODEL_4DPLUS 12 #define MOUSE_MODEL_SYNAPTICS 13 #define MOUSE_MODEL_TRACKPOINT 14 #define MOUSE_MODEL_ELANTECH 15 typedef struct mousemode { int protocol; /* MOUSE_PROTO_XXX */ int rate; /* report rate (per sec), -1 if unknown */ int resolution; /* MOUSE_RES_XXX, -1 if unknown */ int accelfactor; /* accelation factor (must be 1 or greater) */ int level; /* driver operation level */ int packetsize; /* the length of the data packet */ unsigned char syncmask[2]; /* sync. data bits in the header byte */ } mousemode_t; /* protocol */ /* * Serial protocols: * Microsoft, MouseSystems, Logitech, MM series, MouseMan, Hitachi Tablet, * GlidePoint, IntelliMouse, Thinking Mouse, MouseRemote, Kidspad, * VersaPad * Bus mouse protocols: * bus, InPort * PS/2 mouse protocol: * PS/2 */ #define MOUSE_PROTO_UNKNOWN (-1) #define MOUSE_PROTO_MS 0 /* Microsoft Serial, 3 bytes */ #define MOUSE_PROTO_MSC 1 /* Mouse Systems, 5 bytes */ #define MOUSE_PROTO_LOGI 2 /* Logitech, 3 bytes */ #define MOUSE_PROTO_MM 3 /* MM series, 3 bytes */ #define MOUSE_PROTO_LOGIMOUSEMAN 4 /* Logitech MouseMan 3/4 bytes */ #define MOUSE_PROTO_BUS 5 /* MS/Logitech bus mouse */ #define MOUSE_PROTO_INPORT 6 /* MS/ATI InPort mouse */ #define MOUSE_PROTO_PS2 7 /* PS/2 mouse, 3 bytes */ #define MOUSE_PROTO_HITTAB 8 /* Hitachi Tablet 3 bytes */ #define MOUSE_PROTO_GLIDEPOINT 9 /* ALPS GlidePoint, 3/4 bytes */ #define MOUSE_PROTO_INTELLI 10 /* MS IntelliMouse, 4 bytes */ #define MOUSE_PROTO_THINK 11 /* Kensington Thinking Mouse, 3/4 bytes */ #define MOUSE_PROTO_SYSMOUSE 12 /* /dev/sysmouse */ #define MOUSE_PROTO_X10MOUSEREM 13 /* X10 MouseRemote, 3 bytes */ #define MOUSE_PROTO_KIDSPAD 14 /* Genius Kidspad */ #define MOUSE_PROTO_VERSAPAD 15 /* Interlink VersaPad, 6 bytes */ #define MOUSE_PROTO_JOGDIAL 16 /* Vaio's JogDial */ #define MOUSE_PROTO_GTCO_DIGIPAD 17 #define MOUSE_RES_UNKNOWN (-1) #define MOUSE_RES_DEFAULT 0 #define MOUSE_RES_LOW (-2) #define MOUSE_RES_MEDIUMLOW (-3) #define MOUSE_RES_MEDIUMHIGH (-4) #define MOUSE_RES_HIGH (-5) typedef struct mousedata { int len; /* # of data in the buffer */ int buf[16]; /* data buffer */ } mousedata_t; #if (defined(MOUSE_GETVARS)) typedef struct mousevar { int var[16]; } mousevar_t; /* magic numbers in var[0] */ #define MOUSE_VARS_PS2_SIG 0x00325350 /* 'PS2' */ #define MOUSE_VARS_BUS_SIG 0x00535542 /* 'BUS' */ #define MOUSE_VARS_INPORT_SIG 0x00504e49 /* 'INP' */ #endif /* MOUSE_GETVARS */ /* Synaptics Touchpad */ #define MOUSE_SYNAPTICS_PACKETSIZE 6 /* '3' works better */ /* Elantech Touchpad */ #define MOUSE_ELANTECH_PACKETSIZE 6 /* Microsoft Serial mouse data packet */ #define MOUSE_MSS_PACKETSIZE 3 #define MOUSE_MSS_SYNCMASK 0x40 #define MOUSE_MSS_SYNC 0x40 #define MOUSE_MSS_BUTTONS 0x30 #define MOUSE_MSS_BUTTON1DOWN 0x20 /* left */ #define MOUSE_MSS_BUTTON2DOWN 0x00 /* no middle button */ #define MOUSE_MSS_BUTTON3DOWN 0x10 /* right */ /* Logitech MouseMan data packet (M+ protocol) */ #define MOUSE_LMAN_BUTTON2DOWN 0x20 /* middle button, the 4th byte */ /* ALPS GlidePoint extension (variant of M+ protocol) */ #define MOUSE_ALPS_BUTTON2DOWN 0x20 /* middle button, the 4th byte */ #define MOUSE_ALPS_TAP 0x10 /* `tapping' action, the 4th byte */ /* Kinsington Thinking Mouse extension (variant of M+ protocol) */ #define MOUSE_THINK_BUTTON2DOWN 0x20 /* lower-left button, the 4th byte */ #define MOUSE_THINK_BUTTON4DOWN 0x10 /* lower-right button, the 4th byte */ /* MS IntelliMouse (variant of MS Serial) */ #define MOUSE_INTELLI_PACKETSIZE 4 #define MOUSE_INTELLI_BUTTON2DOWN 0x10 /* middle button in the 4th byte */ /* Mouse Systems Corp. mouse data packet */ #define MOUSE_MSC_PACKETSIZE 5 #define MOUSE_MSC_SYNCMASK 0xf8 #define MOUSE_MSC_SYNC 0x80 #define MOUSE_MSC_BUTTONS 0x07 #define MOUSE_MSC_BUTTON1UP 0x04 /* left */ #define MOUSE_MSC_BUTTON2UP 0x02 /* middle */ #define MOUSE_MSC_BUTTON3UP 0x01 /* right */ #define MOUSE_MSC_MAXBUTTON 3 /* MM series mouse data packet */ #define MOUSE_MM_PACKETSIZE 3 #define MOUSE_MM_SYNCMASK 0xe0 #define MOUSE_MM_SYNC 0x80 #define MOUSE_MM_BUTTONS 0x07 #define MOUSE_MM_BUTTON1DOWN 0x04 /* left */ #define MOUSE_MM_BUTTON2DOWN 0x02 /* middle */ #define MOUSE_MM_BUTTON3DOWN 0x01 /* right */ #define MOUSE_MM_XPOSITIVE 0x10 #define MOUSE_MM_YPOSITIVE 0x08 /* PS/2 mouse data packet */ #define MOUSE_PS2_PACKETSIZE 3 #define MOUSE_PS2_SYNCMASK 0xc8 #define MOUSE_PS2_SYNC 0x08 #define MOUSE_PS2_BUTTONS 0x07 /* 0x03 for 2 button mouse */ #define MOUSE_PS2_BUTTON1DOWN 0x01 /* left */ #define MOUSE_PS2_BUTTON2DOWN 0x04 /* middle */ #define MOUSE_PS2_BUTTON3DOWN 0x02 /* right */ #define MOUSE_PS2_TAP MOUSE_PS2_SYNC /* GlidePoint (PS/2) `tapping' * Yes! this is the same bit * as SYNC! */ #define MOUSE_PS2_XNEG 0x10 #define MOUSE_PS2_YNEG 0x20 #define MOUSE_PS2_XOVERFLOW 0x40 #define MOUSE_PS2_YOVERFLOW 0x80 /* Logitech MouseMan+ (PS/2) data packet (PS/2++ protocol) */ #define MOUSE_PS2PLUS_SYNCMASK 0x48 #define MOUSE_PS2PLUS_SYNC 0x48 #define MOUSE_PS2PLUS_ZNEG 0x08 /* sign bit */ #define MOUSE_PS2PLUS_BUTTON4DOWN 0x10 /* 4th button on MouseMan+ */ #define MOUSE_PS2PLUS_BUTTON5DOWN 0x20 /* IBM ScrollPoint (PS/2) also uses PS/2++ protocol */ #define MOUSE_SPOINT_ZNEG 0x80 /* sign bits */ #define MOUSE_SPOINT_WNEG 0x08 /* MS IntelliMouse (PS/2) data packet */ #define MOUSE_PS2INTELLI_PACKETSIZE 4 /* some compatible mice have additional buttons */ #define MOUSE_PS2INTELLI_BUTTON4DOWN 0x40 #define MOUSE_PS2INTELLI_BUTTON5DOWN 0x80 /* MS IntelliMouse Explorer (PS/2) data packet (variation of IntelliMouse) */ #define MOUSE_EXPLORER_ZNEG 0x08 /* sign bit */ /* IntelliMouse Explorer has additional button data in the fourth byte */ #define MOUSE_EXPLORER_BUTTON4DOWN 0x10 #define MOUSE_EXPLORER_BUTTON5DOWN 0x20 /* Interlink VersaPad (serial I/F) data packet */ #define MOUSE_VERSA_PACKETSIZE 6 #define MOUSE_VERSA_IN_USE 0x04 #define MOUSE_VERSA_SYNCMASK 0xc3 #define MOUSE_VERSA_SYNC 0xc0 #define MOUSE_VERSA_BUTTONS 0x30 #define MOUSE_VERSA_BUTTON1DOWN 0x20 /* left */ #define MOUSE_VERSA_BUTTON2DOWN 0x00 /* middle */ #define MOUSE_VERSA_BUTTON3DOWN 0x10 /* right */ #define MOUSE_VERSA_TAP 0x08 /* Interlink VersaPad (PS/2 I/F) data packet */ #define MOUSE_PS2VERSA_PACKETSIZE 6 #define MOUSE_PS2VERSA_IN_USE 0x10 #define MOUSE_PS2VERSA_SYNCMASK 0xe8 #define MOUSE_PS2VERSA_SYNC 0xc8 #define MOUSE_PS2VERSA_BUTTONS 0x05 #define MOUSE_PS2VERSA_BUTTON1DOWN 0x04 /* left */ #define MOUSE_PS2VERSA_BUTTON2DOWN 0x00 /* middle */ #define MOUSE_PS2VERSA_BUTTON3DOWN 0x01 /* right */ #define MOUSE_PS2VERSA_TAP 0x02 /* A4 Tech 4D Mouse (PS/2) data packet */ #define MOUSE_4D_PACKETSIZE 3 #define MOUSE_4D_WHEELBITS 0xf0 /* A4 Tech 4D+ Mouse (PS/2) data packet */ #define MOUSE_4DPLUS_PACKETSIZE 3 #define MOUSE_4DPLUS_ZNEG 0x04 /* sign bit */ #define MOUSE_4DPLUS_BUTTON4DOWN 0x08 /* sysmouse extended data packet */ /* * /dev/sysmouse sends data in two formats, depending on the protocol * level. At the level 0, format is exactly the same as MousSystems' * five byte packet. At the level 1, the first five bytes are the same * as at the level 0. There are additional three bytes which shows * `dz' and the states of additional buttons. `dz' is expressed as the * sum of the byte 5 and 6 which contain signed seven bit values. * The states of the button 4 though 10 are in the bit 0 though 6 in * the byte 7 respectively: 1 indicates the button is up. */ #define MOUSE_SYS_PACKETSIZE 8 #define MOUSE_SYS_SYNCMASK 0xf8 #define MOUSE_SYS_SYNC 0x80 #define MOUSE_SYS_BUTTON1UP 0x04 /* left, 1st byte */ #define MOUSE_SYS_BUTTON2UP 0x02 /* middle, 1st byte */ #define MOUSE_SYS_BUTTON3UP 0x01 /* right, 1st byte */ #define MOUSE_SYS_BUTTON4UP 0x0001 /* 7th byte */ #define MOUSE_SYS_BUTTON5UP 0x0002 #define MOUSE_SYS_BUTTON6UP 0x0004 #define MOUSE_SYS_BUTTON7UP 0x0008 #define MOUSE_SYS_BUTTON8UP 0x0010 #define MOUSE_SYS_BUTTON9UP 0x0020 #define MOUSE_SYS_BUTTON10UP 0x0040 #define MOUSE_SYS_MAXBUTTON 10 #define MOUSE_SYS_STDBUTTONS 0x07 #define MOUSE_SYS_EXTBUTTONS 0x7f /* the others */ /* Mouse remote socket */ #define _PATH_MOUSEREMOTE "/var/run/MouseRemote" #endif /* _SYS_MOUSE_H_ */ Index: head/sys/sys/msg.h =================================================================== --- head/sys/sys/msg.h (revision 326822) +++ head/sys/sys/msg.h (revision 326823) @@ -1,183 +1,183 @@ /* $FreeBSD$ */ /* $NetBSD: msg.h,v 1.4 1994/06/29 06:44:43 cgd Exp $ */ /*- * SVID compatible msg.h file * - * SPDX-License-Identifier: 0BSD - * * Author: Daniel Boulet + * + * SPDX-License-Identifier: BSD-1-Clause * * Copyright 1993 Daniel Boulet and RTMX Inc. * * This system call was implemented by Daniel Boulet under contract from RTMX. * * Redistribution and use in source forms, with and without modification, * are permitted provided that this entire comment appears intact. * * Redistribution in binary form may occur without any restrictions. * Obviously, it would be nice if you gave credit where credit is due * but requiring it would be too onerous. * * This software is provided ``AS IS'' without any warranties of any kind. */ #ifndef _SYS_MSG_H_ #define _SYS_MSG_H_ #include #include #include /* * The MSG_NOERROR identifier value, the msqid_ds struct and the msg struct * are as defined by the SV API Intel 386 Processor Supplement. */ #define MSG_NOERROR 010000 /* don't complain about too long msgs */ typedef unsigned long msglen_t; typedef unsigned long msgqnum_t; #ifndef _PID_T_DECLARED typedef __pid_t pid_t; #define _PID_T_DECLARED #endif #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED #endif #ifndef _SSIZE_T_DECLARED typedef __ssize_t ssize_t; #define _SSIZE_T_DECLARED #endif #ifndef _TIME_T_DECLARED typedef __time_t time_t; #define _TIME_T_DECLARED #endif #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) struct msqid_ds_old { struct ipc_perm_old msg_perm; /* msg queue permission bits */ struct msg *msg_first; /* first message in the queue */ struct msg *msg_last; /* last message in the queue */ msglen_t msg_cbytes; /* number of bytes in use on the queue */ msgqnum_t msg_qnum; /* number of msgs in the queue */ msglen_t msg_qbytes; /* max # of bytes on the queue */ pid_t msg_lspid; /* pid of last msgsnd() */ pid_t msg_lrpid; /* pid of last msgrcv() */ time_t msg_stime; /* time of last msgsnd() */ long msg_pad1; time_t msg_rtime; /* time of last msgrcv() */ long msg_pad2; time_t msg_ctime; /* time of last msgctl() */ long msg_pad3; long msg_pad4[4]; }; #endif /* * XXX there seems to be no prefix reserved for this header, so the name * "msg" in "struct msg" and the names of all of the nonstandard members * (mainly "msg_pad*) are namespace pollution. */ struct msqid_ds { struct ipc_perm msg_perm; /* msg queue permission bits */ struct msg *msg_first; /* first message in the queue */ struct msg *msg_last; /* last message in the queue */ msglen_t msg_cbytes; /* number of bytes in use on the queue */ msgqnum_t msg_qnum; /* number of msgs in the queue */ msglen_t msg_qbytes; /* max # of bytes on the queue */ pid_t msg_lspid; /* pid of last msgsnd() */ pid_t msg_lrpid; /* pid of last msgrcv() */ time_t msg_stime; /* time of last msgsnd() */ time_t msg_rtime; /* time of last msgrcv() */ time_t msg_ctime; /* time of last msgctl() */ }; #if __BSD_VISIBLE /* * Structure describing a message. The SVID doesn't suggest any * particular name for this structure. There is a reference in the * msgop man page that reads "The structure mymsg is an example of what * this user defined buffer might look like, and includes the following * members:". This sentence is followed by two lines equivalent * to the mtype and mtext field declarations below. It isn't clear * if "mymsg" refers to the name of the structure type or the name of an * instance of the structure... */ struct mymsg { long mtype; /* message type (+ve integer) */ char mtext[1]; /* message body */ }; #endif #ifdef _KERNEL struct msg { struct msg *msg_next; /* next msg in the chain */ long msg_type; /* type of this message */ /* >0 -> type of this message */ /* 0 -> free header */ u_short msg_ts; /* size of this message */ short msg_spot; /* location of start of msg in buffer */ struct label *label; /* MAC Framework label */ }; /* * Based on the configuration parameters described in an SVR2 (yes, two) * config(1m) man page. * * Each message is broken up and stored in segments that are msgssz bytes * long. For efficiency reasons, this should be a power of two. Also, * it doesn't make sense if it is less than 8 or greater than about 256. * Consequently, msginit in kern/sysv_msg.c checks that msgssz is a power of * two between 8 and 1024 inclusive (and panic's if it isn't). */ struct msginfo { int msgmax, /* max chars in a message */ msgmni, /* max message queue identifiers */ msgmnb, /* max chars in a queue */ msgtql, /* max messages in system */ msgssz, /* size of a message segment (see notes above) */ msgseg; /* number of message segments */ }; extern struct msginfo msginfo; /* * Kernel wrapper for the user-level structure. */ struct msqid_kernel { /* * Data structure exposed to user space. */ struct msqid_ds u; /* * Kernel-private components of the message queue. */ struct label *label; /* MAC label */ struct ucred *cred; /* creator's credentials */ }; #endif /* _KERNEL */ #if !defined(_KERNEL) || defined(_WANT_MSG_PROTOTYPES) __BEGIN_DECLS int msgctl(int, int, struct msqid_ds *); int msgget(key_t, int); ssize_t msgrcv(int, void *, size_t, long, int); int msgsnd(int, const void *, size_t, int); #if __BSD_VISIBLE int msgsys(int, ...); #endif __END_DECLS #endif /* !_KERNEL || _WANT_MSG_PROTOTYPES */ #endif /* !_SYS_MSG_H_ */ Index: head/sys/sys/numa.h =================================================================== --- head/sys/sys/numa.h (revision 326822) +++ head/sys/sys/numa.h (revision 326823) @@ -1,41 +1,43 @@ /* + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 2015 Adrian Chadd . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef __SYS_NUMA_H__ #define __SYS_NUMA_H__ #include extern int numa_setaffinity(cpuwhich_t which, id_t id, struct vm_domain_policy_entry *vd); extern int numa_getaffinity(cpuwhich_t which, id_t id, struct vm_domain_policy_entry *vd); #endif /* __SYS_NUMA_H__ */ Index: head/sys/sys/nv.h =================================================================== --- head/sys/sys/nv.h (revision 326822) +++ head/sys/sys/nv.h (revision 326823) @@ -1,246 +1,248 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2009-2013 The FreeBSD Foundation * Copyright (c) 2013-2015 Mariusz Zaborski * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _NV_H_ #define _NV_H_ #include #ifndef _KERNEL #include #include #include #include #endif #ifndef _NVLIST_T_DECLARED #define _NVLIST_T_DECLARED struct nvlist; typedef struct nvlist nvlist_t; #endif #define NV_NAME_MAX 2048 #define NV_TYPE_NONE 0 #define NV_TYPE_NULL 1 #define NV_TYPE_BOOL 2 #define NV_TYPE_NUMBER 3 #define NV_TYPE_STRING 4 #define NV_TYPE_NVLIST 5 #define NV_TYPE_DESCRIPTOR 6 #define NV_TYPE_BINARY 7 #define NV_TYPE_BOOL_ARRAY 8 #define NV_TYPE_NUMBER_ARRAY 9 #define NV_TYPE_STRING_ARRAY 10 #define NV_TYPE_NVLIST_ARRAY 11 #define NV_TYPE_DESCRIPTOR_ARRAY 12 /* * Perform case-insensitive lookups of provided names. */ #define NV_FLAG_IGNORE_CASE 0x01 /* * Names don't have to be unique. */ #define NV_FLAG_NO_UNIQUE 0x02 #if defined(_KERNEL) && defined(MALLOC_DECLARE) MALLOC_DECLARE(M_NVLIST); #endif __BEGIN_DECLS nvlist_t *nvlist_create(int flags); void nvlist_destroy(nvlist_t *nvl); int nvlist_error(const nvlist_t *nvl); bool nvlist_empty(const nvlist_t *nvl); int nvlist_flags(const nvlist_t *nvl); void nvlist_set_error(nvlist_t *nvl, int error); nvlist_t *nvlist_clone(const nvlist_t *nvl); #ifndef _KERNEL void nvlist_dump(const nvlist_t *nvl, int fd); void nvlist_fdump(const nvlist_t *nvl, FILE *fp); #endif size_t nvlist_size(const nvlist_t *nvl); void *nvlist_pack(const nvlist_t *nvl, size_t *sizep); nvlist_t *nvlist_unpack(const void *buf, size_t size, int flags); int nvlist_send(int sock, const nvlist_t *nvl); nvlist_t *nvlist_recv(int sock, int flags); nvlist_t *nvlist_xfer(int sock, nvlist_t *nvl, int flags); const char *nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep); const nvlist_t *nvlist_get_parent(const nvlist_t *nvl, void **cookiep); const nvlist_t *nvlist_get_array_next(const nvlist_t *nvl); bool nvlist_in_array(const nvlist_t *nvl); const nvlist_t *nvlist_get_pararr(const nvlist_t *nvl, void **cookiep); /* * The nvlist_exists functions check if the given name (optionally of the given * type) exists on nvlist. */ bool nvlist_exists(const nvlist_t *nvl, const char *name); bool nvlist_exists_type(const nvlist_t *nvl, const char *name, int type); bool nvlist_exists_null(const nvlist_t *nvl, const char *name); bool nvlist_exists_bool(const nvlist_t *nvl, const char *name); bool nvlist_exists_number(const nvlist_t *nvl, const char *name); bool nvlist_exists_string(const nvlist_t *nvl, const char *name); bool nvlist_exists_nvlist(const nvlist_t *nvl, const char *name); bool nvlist_exists_binary(const nvlist_t *nvl, const char *name); bool nvlist_exists_bool_array(const nvlist_t *nvl, const char *name); bool nvlist_exists_number_array(const nvlist_t *nvl, const char *name); bool nvlist_exists_string_array(const nvlist_t *nvl, const char *name); bool nvlist_exists_nvlist_array(const nvlist_t *nvl, const char *name); #ifndef _KERNEL bool nvlist_exists_descriptor(const nvlist_t *nvl, const char *name); bool nvlist_exists_descriptor_array(const nvlist_t *nvl, const char *name); #endif /* * The nvlist_add functions add the given name/value pair. * If a pointer is provided, nvlist_add will internally allocate memory for the * given data (in other words it won't consume provided buffer). */ void nvlist_add_null(nvlist_t *nvl, const char *name); void nvlist_add_bool(nvlist_t *nvl, const char *name, bool value); void nvlist_add_number(nvlist_t *nvl, const char *name, uint64_t value); void nvlist_add_string(nvlist_t *nvl, const char *name, const char *value); void nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...) __printflike(3, 4); #if !defined(_KERNEL) || defined(_VA_LIST_DECLARED) void nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt, va_list valueap) __printflike(3, 0); #endif void nvlist_add_nvlist(nvlist_t *nvl, const char *name, const nvlist_t *value); void nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value, size_t size); void nvlist_add_bool_array(nvlist_t *nvl, const char *name, const bool *value, size_t nitems); void nvlist_add_number_array(nvlist_t *nvl, const char *name, const uint64_t *value, size_t nitems); void nvlist_add_string_array(nvlist_t *nvl, const char *name, const char * const *value, size_t nitems); void nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, const nvlist_t * const *value, size_t nitems); #ifndef _KERNEL void nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value); void nvlist_add_descriptor_array(nvlist_t *nvl, const char *name, const int *value, size_t nitems); #endif /* * The nvlist_move functions add the given name/value pair. * The functions consumes provided buffer. */ void nvlist_move_string(nvlist_t *nvl, const char *name, char *value); void nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value); void nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size); void nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value, size_t nitems); void nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value, size_t nitems); void nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value, size_t nitems); void nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value, size_t nitems); #ifndef _KERNEL void nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value); void nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value, size_t nitems); #endif /* * The nvlist_get functions returns value associated with the given name. * If it returns a pointer, the pointer represents internal buffer and should * not be freed by the caller. */ bool nvlist_get_bool(const nvlist_t *nvl, const char *name); uint64_t nvlist_get_number(const nvlist_t *nvl, const char *name); const char *nvlist_get_string(const nvlist_t *nvl, const char *name); const nvlist_t *nvlist_get_nvlist(const nvlist_t *nvl, const char *name); const void *nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep); const bool *nvlist_get_bool_array(const nvlist_t *nvl, const char *name, size_t *nitemsp); const uint64_t *nvlist_get_number_array(const nvlist_t *nvl, const char *name, size_t *nitemsp); const char * const *nvlist_get_string_array(const nvlist_t *nvl, const char *name, size_t *nitemsp); const nvlist_t * const *nvlist_get_nvlist_array(const nvlist_t *nvl, const char *name, size_t *nitemsp); #ifndef _KERNEL int nvlist_get_descriptor(const nvlist_t *nvl, const char *name); const int *nvlist_get_descriptor_array(const nvlist_t *nvl, const char *name, size_t *nitemsp); #endif /* * The nvlist_take functions returns value associated with the given name and * remove the given entry from the nvlist. * The caller is responsible for freeing received data. */ bool nvlist_take_bool(nvlist_t *nvl, const char *name); uint64_t nvlist_take_number(nvlist_t *nvl, const char *name); char *nvlist_take_string(nvlist_t *nvl, const char *name); nvlist_t *nvlist_take_nvlist(nvlist_t *nvl, const char *name); void *nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep); bool *nvlist_take_bool_array(nvlist_t *nvl, const char *name, size_t *nitemsp); uint64_t *nvlist_take_number_array(nvlist_t *nvl, const char *name, size_t *nitemsp); char **nvlist_take_string_array(nvlist_t *nvl, const char *name, size_t *nitemsp); nvlist_t **nvlist_take_nvlist_array(nvlist_t *nvl, const char *name, size_t *nitemsp); #ifndef _KERNEL int nvlist_take_descriptor(nvlist_t *nvl, const char *name); int *nvlist_take_descriptor_array(nvlist_t *nvl, const char *name, size_t *nitemsp); #endif /* * The nvlist_free functions removes the given name/value pair from the nvlist * and frees memory associated with it. */ void nvlist_free(nvlist_t *nvl, const char *name); void nvlist_free_type(nvlist_t *nvl, const char *name, int type); void nvlist_free_null(nvlist_t *nvl, const char *name); void nvlist_free_bool(nvlist_t *nvl, const char *name); void nvlist_free_number(nvlist_t *nvl, const char *name); void nvlist_free_string(nvlist_t *nvl, const char *name); void nvlist_free_nvlist(nvlist_t *nvl, const char *name); void nvlist_free_binary(nvlist_t *nvl, const char *name); void nvlist_free_bool_array(nvlist_t *nvl, const char *name); void nvlist_free_number_array(nvlist_t *nvl, const char *name); void nvlist_free_string_array(nvlist_t *nvl, const char *name); void nvlist_free_nvlist_array(nvlist_t *nvl, const char *name); void nvlist_free_binary_array(nvlist_t *nvl, const char *name); #ifndef _KERNEL void nvlist_free_descriptor(nvlist_t *nvl, const char *name); void nvlist_free_descriptor_array(nvlist_t *nvl, const char *name); #endif __END_DECLS #endif /* !_NV_H_ */ Index: head/sys/sys/rman.h =================================================================== --- head/sys/sys/rman.h (revision 326822) +++ head/sys/sys/rman.h (revision 326823) @@ -1,165 +1,167 @@ /*- + * SPDX-License-Identifier: MIT + * * Copyright 1998 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that both the above copyright notice and this * permission notice appear in all copies, that both the above * copyright notice and this permission notice appear in all * supporting documentation, and that the name of M.I.T. not be used * in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. M.I.T. makes * no representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. * * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_RMAN_H_ #define _SYS_RMAN_H_ 1 #ifndef _KERNEL #include #else #include #include #endif #define RF_ALLOCATED 0x0001 /* resource has been reserved */ #define RF_ACTIVE 0x0002 /* resource allocation has been activated */ #define RF_SHAREABLE 0x0004 /* resource permits contemporaneous sharing */ #define RF_SPARE1 0x0008 #define RF_SPARE2 0x0010 #define RF_FIRSTSHARE 0x0020 /* first in sharing list */ #define RF_PREFETCHABLE 0x0040 /* resource is prefetchable */ #define RF_OPTIONAL 0x0080 /* for bus_alloc_resources() */ #define RF_UNMAPPED 0x0100 /* don't map resource when activating */ #define RF_ALIGNMENT_SHIFT 10 /* alignment size bit starts bit 10 */ #define RF_ALIGNMENT_MASK (0x003F << RF_ALIGNMENT_SHIFT) /* resource address alignment size bit mask */ #define RF_ALIGNMENT_LOG2(x) ((x) << RF_ALIGNMENT_SHIFT) #define RF_ALIGNMENT(x) (((x) & RF_ALIGNMENT_MASK) >> RF_ALIGNMENT_SHIFT) enum rman_type { RMAN_UNINIT = 0, RMAN_GAUGE, RMAN_ARRAY }; /* * String length exported to userspace for resource names, etc. */ #define RM_TEXTLEN 32 #define RM_MAX_END (~(rman_res_t)0) #define RMAN_IS_DEFAULT_RANGE(s,e) ((s) == 0 && (e) == RM_MAX_END) /* * Userspace-exported structures. */ struct u_resource { uintptr_t r_handle; /* resource uniquifier */ uintptr_t r_parent; /* parent rman */ uintptr_t r_device; /* device owning this resource */ char r_devname[RM_TEXTLEN]; /* device name XXX obsolete */ rman_res_t r_start; /* offset in resource space */ rman_res_t r_size; /* size in resource space */ u_int r_flags; /* RF_* flags */ }; struct u_rman { uintptr_t rm_handle; /* rman uniquifier */ char rm_descr[RM_TEXTLEN]; /* rman description */ rman_res_t rm_start; /* base of managed region */ rman_res_t rm_size; /* size of managed region */ enum rman_type rm_type; /* region type */ }; #ifdef _KERNEL /* * The public (kernel) view of struct resource * * NB: Changing the offset/size/type of existing fields in struct resource * NB: breaks the device driver ABI and is strongly FORBIDDEN. * NB: Appending new fields is probably just misguided. */ struct resource { struct resource_i *__r_i; bus_space_tag_t r_bustag; /* bus_space tag */ bus_space_handle_t r_bushandle; /* bus_space handle */ }; struct resource_i; struct resource_map; TAILQ_HEAD(resource_head, resource_i); struct rman { struct resource_head rm_list; struct mtx *rm_mtx; /* mutex used to protect rm_list */ TAILQ_ENTRY(rman) rm_link; /* link in list of all rmans */ rman_res_t rm_start; /* index of globally first entry */ rman_res_t rm_end; /* index of globally last entry */ enum rman_type rm_type; /* what type of resource this is */ const char *rm_descr; /* text descripion of this resource */ }; TAILQ_HEAD(rman_head, rman); int rman_activate_resource(struct resource *r); int rman_adjust_resource(struct resource *r, rman_res_t start, rman_res_t end); int rman_first_free_region(struct rman *rm, rman_res_t *start, rman_res_t *end); bus_space_handle_t rman_get_bushandle(struct resource *); bus_space_tag_t rman_get_bustag(struct resource *); rman_res_t rman_get_end(struct resource *); device_t rman_get_device(struct resource *); u_int rman_get_flags(struct resource *); void rman_get_mapping(struct resource *, struct resource_map *); int rman_get_rid(struct resource *); rman_res_t rman_get_size(struct resource *); rman_res_t rman_get_start(struct resource *); void *rman_get_virtual(struct resource *); int rman_deactivate_resource(struct resource *r); int rman_fini(struct rman *rm); int rman_init(struct rman *rm); int rman_init_from_resource(struct rman *rm, struct resource *r); int rman_last_free_region(struct rman *rm, rman_res_t *start, rman_res_t *end); uint32_t rman_make_alignment_flags(uint32_t size); int rman_manage_region(struct rman *rm, rman_res_t start, rman_res_t end); int rman_is_region_manager(struct resource *r, struct rman *rm); int rman_release_resource(struct resource *r); struct resource *rman_reserve_resource(struct rman *rm, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags, device_t dev); struct resource *rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end, rman_res_t count, rman_res_t bound, u_int flags, device_t dev); void rman_set_bushandle(struct resource *_r, bus_space_handle_t _h); void rman_set_bustag(struct resource *_r, bus_space_tag_t _t); void rman_set_device(struct resource *_r, device_t _dev); void rman_set_end(struct resource *_r, rman_res_t _end); void rman_set_mapping(struct resource *, struct resource_map *); void rman_set_rid(struct resource *_r, int _rid); void rman_set_start(struct resource *_r, rman_res_t _start); void rman_set_virtual(struct resource *_r, void *_v); extern struct rman_head rman_head; #endif /* _KERNEL */ #endif /* !_SYS_RMAN_H_ */ Index: head/sys/sys/snoop.h =================================================================== --- head/sys/sys/snoop.h (revision 326822) +++ head/sys/sys/snoop.h (revision 326823) @@ -1,45 +1,45 @@ /*- - * SPDX-License-Identifier: 0BSD + * SPDX-License-Identifier: BSD-1-Clause * * Copyright (c) 1995 Ugen J.S.Antsilevich * * Redistribution and use in source forms, with and without modification, * are permitted provided that this entire comment appears intact. * * Redistribution in binary form may occur without any restrictions. * Obviously, it would be nice if you gave credit where credit is due * but requiring it would be too onerous. * * This software is provided ``AS IS'' without any warranties of any kind. * * Snoop stuff. * * $FreeBSD$ */ #ifndef _SYS_SNOOP_H_ #define _SYS_SNOOP_H_ #ifndef _KERNEL #include #endif #include /* * These are snoop io controls * SNPSTTY accepts a file descriptor as input. */ #define SNPSTTY _IOW('T', 90, int) #define SNPGTTY _IOR('T', 89, dev_t) /* * These values would be returned by FIONREAD ioctl * instead of number of characters in buffer in case * of specific errors. */ #define SNP_OFLOW -1 #define SNP_TTYCLOSE -2 #define SNP_DETACH -3 #endif /* !_SYS_SNOOP_H_ */ Index: head/sys/sys/soundcard.h =================================================================== --- head/sys/sys/soundcard.h (revision 326822) +++ head/sys/sys/soundcard.h (revision 326823) @@ -1,2004 +1,2006 @@ /* * soundcard.h */ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright by Hannu Savolainen 1993 / 4Front Technologies 1993-2006 * Modified for the new FreeBSD sound driver by Luigi Rizzo, 1997 * * 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$ */ /* * Unless coordinating changes with 4Front Technologies, do NOT make any * modifications to ioctl commands, types, etc. that would break * compatibility with the OSS API. */ #ifndef _SYS_SOUNDCARD_H_ #define _SYS_SOUNDCARD_H_ /* * If you make modifications to this file, please contact me before * distributing the modified version. There is already enough * diversity in the world. * * Regards, * Hannu Savolainen * hannu@voxware.pp.fi * ********************************************************************** * PS. The Hacker's Guide to VoxWare available from * nic.funet.fi:pub/Linux/ALPHA/sound. The file is * snd-sdk-doc-0.1.ps.gz (gzipped postscript). It contains * some useful information about programming with VoxWare. * (NOTE! The pub/Linux/ALPHA/ directories are hidden. You have * to cd inside them before the files are accessible.) ********************************************************************** */ /* * SOUND_VERSION is only used by the voxware driver. Hopefully apps * should not depend on it, but rather look at the capabilities * of the driver in the kernel! */ #define SOUND_VERSION 301 #define VOXWARE /* does this have any use ? */ /* * Supported card ID numbers (Should be somewhere else? We keep * them here just for compativility with the old driver, but these * constants are of little or no use). */ #define SNDCARD_ADLIB 1 #define SNDCARD_SB 2 #define SNDCARD_PAS 3 #define SNDCARD_GUS 4 #define SNDCARD_MPU401 5 #define SNDCARD_SB16 6 #define SNDCARD_SB16MIDI 7 #define SNDCARD_UART6850 8 #define SNDCARD_GUS16 9 #define SNDCARD_MSS 10 #define SNDCARD_PSS 11 #define SNDCARD_SSCAPE 12 #define SNDCARD_PSS_MPU 13 #define SNDCARD_PSS_MSS 14 #define SNDCARD_SSCAPE_MSS 15 #define SNDCARD_TRXPRO 16 #define SNDCARD_TRXPRO_SB 17 #define SNDCARD_TRXPRO_MPU 18 #define SNDCARD_MAD16 19 #define SNDCARD_MAD16_MPU 20 #define SNDCARD_CS4232 21 #define SNDCARD_CS4232_MPU 22 #define SNDCARD_MAUI 23 #define SNDCARD_PSEUDO_MSS 24 #define SNDCARD_AWE32 25 #define SNDCARD_NSS 26 #define SNDCARD_UART16550 27 #define SNDCARD_OPL 28 #include #include #ifndef _IOWR #include #endif /* !_IOWR */ /* * The first part of this file contains the new FreeBSD sound ioctl * interface. Tries to minimize the number of different ioctls, and * to be reasonably general. * * 970821: some of the new calls have not been implemented yet. */ /* * the following three calls extend the generic file descriptor * interface. AIONWRITE is the dual of FIONREAD, i.e. returns the max * number of bytes for a write operation to be non-blocking. * * AIOGSIZE/AIOSSIZE are used to change the behaviour of the device, * from a character device (default) to a block device. In block mode, * (not to be confused with blocking mode) the main difference for the * application is that select() will return only when a complete * block can be read/written to the device, whereas in character mode * select will return true when one byte can be exchanged. For audio * devices, character mode makes select almost useless since one byte * will always be ready by the next sample time (which is often only a * handful of microseconds away). * Use a size of 0 or 1 to return to character mode. */ #define AIONWRITE _IOR('A', 10, int) /* get # bytes to write */ struct snd_size { int play_size; int rec_size; }; #define AIOGSIZE _IOR('A', 11, struct snd_size)/* read current blocksize */ #define AIOSSIZE _IOWR('A', 11, struct snd_size) /* sets blocksize */ /* * The following constants define supported audio formats. The * encoding follows voxware conventions, i.e. 1 bit for each supported * format. We extend it by using bit 31 (RO) to indicate full-duplex * capability, and bit 29 (RO) to indicate that the card supports/ * needs different formats on capture & playback channels. * Bit 29 (RW) is used to indicate/ask stereo. * * The number of bits required to store the sample is: * o 4 bits for the IDA ADPCM format, * o 8 bits for 8-bit formats, mu-law and A-law, * o 16 bits for the 16-bit formats, and * o 32 bits for the 24/32-bit formats. * o undefined for the MPEG audio format. */ #define AFMT_QUERY 0x00000000 /* Return current format */ #define AFMT_MU_LAW 0x00000001 /* Logarithmic mu-law */ #define AFMT_A_LAW 0x00000002 /* Logarithmic A-law */ #define AFMT_IMA_ADPCM 0x00000004 /* A 4:1 compressed format where 16-bit * squence represented using the * the average 4 bits per sample */ #define AFMT_U8 0x00000008 /* Unsigned 8-bit */ #define AFMT_S16_LE 0x00000010 /* Little endian signed 16-bit */ #define AFMT_S16_BE 0x00000020 /* Big endian signed 16-bit */ #define AFMT_S8 0x00000040 /* Signed 8-bit */ #define AFMT_U16_LE 0x00000080 /* Little endian unsigned 16-bit */ #define AFMT_U16_BE 0x00000100 /* Big endian unsigned 16-bit */ #define AFMT_MPEG 0x00000200 /* MPEG MP2/MP3 audio */ #define AFMT_AC3 0x00000400 /* Dolby Digital AC3 */ /* * 32-bit formats below used for 24-bit audio data where the data is stored * in the 24 most significant bits and the least significant bits are not used * (should be set to 0). */ #define AFMT_S32_LE 0x00001000 /* Little endian signed 32-bit */ #define AFMT_S32_BE 0x00002000 /* Big endian signed 32-bit */ #define AFMT_U32_LE 0x00004000 /* Little endian unsigned 32-bit */ #define AFMT_U32_BE 0x00008000 /* Big endian unsigned 32-bit */ #define AFMT_S24_LE 0x00010000 /* Little endian signed 24-bit */ #define AFMT_S24_BE 0x00020000 /* Big endian signed 24-bit */ #define AFMT_U24_LE 0x00040000 /* Little endian unsigned 24-bit */ #define AFMT_U24_BE 0x00080000 /* Big endian unsigned 24-bit */ /* Machine dependent AFMT_* definitions. */ #if BYTE_ORDER == LITTLE_ENDIAN #define AFMT_S16_NE AFMT_S16_LE #define AFMT_S24_NE AFMT_S24_LE #define AFMT_S32_NE AFMT_S32_LE #define AFMT_U16_NE AFMT_U16_LE #define AFMT_U24_NE AFMT_U24_LE #define AFMT_U32_NE AFMT_U32_LE #define AFMT_S16_OE AFMT_S16_BE #define AFMT_S24_OE AFMT_S24_BE #define AFMT_S32_OE AFMT_S32_BE #define AFMT_U16_OE AFMT_U16_BE #define AFMT_U24_OE AFMT_U24_BE #define AFMT_U32_OE AFMT_U32_BE #else #define AFMT_S16_OE AFMT_S16_LE #define AFMT_S24_OE AFMT_S24_LE #define AFMT_S32_OE AFMT_S32_LE #define AFMT_U16_OE AFMT_U16_LE #define AFMT_U24_OE AFMT_U24_LE #define AFMT_U32_OE AFMT_U32_LE #define AFMT_S16_NE AFMT_S16_BE #define AFMT_S24_NE AFMT_S24_BE #define AFMT_S32_NE AFMT_S32_BE #define AFMT_U16_NE AFMT_U16_BE #define AFMT_U24_NE AFMT_U24_BE #define AFMT_U32_NE AFMT_U32_BE #endif #define AFMT_STEREO 0x10000000 /* can do/want stereo */ /* * the following are really capabilities */ #define AFMT_WEIRD 0x20000000 /* weird hardware... */ /* * AFMT_WEIRD reports that the hardware might need to operate * with different formats in the playback and capture * channels when operating in full duplex. * As an example, SoundBlaster16 cards only support U8 in one * direction and S16 in the other one, and applications should * be aware of this limitation. */ #define AFMT_FULLDUPLEX 0x80000000 /* can do full duplex */ /* * The following structure is used to get/set format and sampling rate. * While it would be better to have things such as stereo, bits per * sample, endiannes, etc split in different variables, it turns out * that formats are not that many, and not all combinations are possible. * So we followed the Voxware approach of associating one bit to each * format. */ typedef struct _snd_chan_param { u_long play_rate; /* sampling rate */ u_long rec_rate; /* sampling rate */ u_long play_format; /* everything describing the format */ u_long rec_format; /* everything describing the format */ } snd_chan_param; #define AIOGFMT _IOR('f', 12, snd_chan_param) /* get format */ #define AIOSFMT _IOWR('f', 12, snd_chan_param) /* sets format */ /* * The following structure is used to get/set the mixer setting. * Up to 32 mixers are supported, each one with up to 32 channels. */ typedef struct _snd_mix_param { u_char subdev; /* which output */ u_char line; /* which input */ u_char left,right; /* volumes, 0..255, 0 = mute */ } snd_mix_param ; /* XXX AIOGMIX, AIOSMIX not implemented yet */ #define AIOGMIX _IOWR('A', 13, snd_mix_param) /* return mixer status */ #define AIOSMIX _IOWR('A', 14, snd_mix_param) /* sets mixer status */ /* * channel specifiers used in AIOSTOP and AIOSYNC */ #define AIOSYNC_PLAY 0x1 /* play chan */ #define AIOSYNC_CAPTURE 0x2 /* capture chan */ /* AIOSTOP stop & flush a channel, returns the residual count */ #define AIOSTOP _IOWR ('A', 15, int) /* alternate method used to notify the sync condition */ #define AIOSYNC_SIGNAL 0x100 #define AIOSYNC_SELECT 0x200 /* what the 'pos' field refers to */ #define AIOSYNC_READY 0x400 #define AIOSYNC_FREE 0x800 typedef struct _snd_sync_parm { long chan ; /* play or capture channel, plus modifier */ long pos; } snd_sync_parm; #define AIOSYNC _IOWR ('A', 15, snd_sync_parm) /* misc. synchronization */ /* * The following is used to return device capabilities. If the structure * passed to the ioctl is zeroed, default values are returned for rate * and formats, a bitmap of available mixers is returned, and values * (inputs, different levels) for the first one are returned. * * If formats, mixers, inputs are instantiated, then detailed info * are returned depending on the call. */ typedef struct _snd_capabilities { u_long rate_min, rate_max; /* min-max sampling rate */ u_long formats; u_long bufsize; /* DMA buffer size */ u_long mixers; /* bitmap of available mixers */ u_long inputs; /* bitmap of available inputs (per mixer) */ u_short left, right; /* how many levels are supported */ } snd_capabilities; #define AIOGCAP _IOWR('A', 15, snd_capabilities) /* get capabilities */ /* * here is the old (Voxware) ioctl interface */ /* * IOCTL Commands for /dev/sequencer */ #define SNDCTL_SEQ_RESET _IO ('Q', 0) #define SNDCTL_SEQ_SYNC _IO ('Q', 1) #define SNDCTL_SYNTH_INFO _IOWR('Q', 2, struct synth_info) #define SNDCTL_SEQ_CTRLRATE _IOWR('Q', 3, int) /* Set/get timer res.(hz) */ #define SNDCTL_SEQ_GETOUTCOUNT _IOR ('Q', 4, int) #define SNDCTL_SEQ_GETINCOUNT _IOR ('Q', 5, int) #define SNDCTL_SEQ_PERCMODE _IOW ('Q', 6, int) #define SNDCTL_FM_LOAD_INSTR _IOW ('Q', 7, struct sbi_instrument) /* Valid for FM only */ #define SNDCTL_SEQ_TESTMIDI _IOW ('Q', 8, int) #define SNDCTL_SEQ_RESETSAMPLES _IOW ('Q', 9, int) #define SNDCTL_SEQ_NRSYNTHS _IOR ('Q',10, int) #define SNDCTL_SEQ_NRMIDIS _IOR ('Q',11, int) #define SNDCTL_MIDI_INFO _IOWR('Q',12, struct midi_info) #define SNDCTL_SEQ_THRESHOLD _IOW ('Q',13, int) #define SNDCTL_SEQ_TRESHOLD SNDCTL_SEQ_THRESHOLD /* there was once a typo */ #define SNDCTL_SYNTH_MEMAVL _IOWR('Q',14, int) /* in=dev#, out=memsize */ #define SNDCTL_FM_4OP_ENABLE _IOW ('Q',15, int) /* in=dev# */ #define SNDCTL_PMGR_ACCESS _IOWR('Q',16, struct patmgr_info) #define SNDCTL_SEQ_PANIC _IO ('Q',17) #define SNDCTL_SEQ_OUTOFBAND _IOW ('Q',18, struct seq_event_rec) #define SNDCTL_SEQ_GETTIME _IOR ('Q',19, int) struct seq_event_rec { u_char arr[8]; }; #define SNDCTL_TMR_TIMEBASE _IOWR('T', 1, int) #define SNDCTL_TMR_START _IO ('T', 2) #define SNDCTL_TMR_STOP _IO ('T', 3) #define SNDCTL_TMR_CONTINUE _IO ('T', 4) #define SNDCTL_TMR_TEMPO _IOWR('T', 5, int) #define SNDCTL_TMR_SOURCE _IOWR('T', 6, int) # define TMR_INTERNAL 0x00000001 # define TMR_EXTERNAL 0x00000002 # define TMR_MODE_MIDI 0x00000010 # define TMR_MODE_FSK 0x00000020 # define TMR_MODE_CLS 0x00000040 # define TMR_MODE_SMPTE 0x00000080 #define SNDCTL_TMR_METRONOME _IOW ('T', 7, int) #define SNDCTL_TMR_SELECT _IOW ('T', 8, int) /* * Endian aware patch key generation algorithm. */ #if defined(_AIX) || defined(AIX) # define _PATCHKEY(id) (0xfd00|id) #else # define _PATCHKEY(id) ((id<<8)|0xfd) #endif /* * Sample loading mechanism for internal synthesizers (/dev/sequencer) * The following patch_info structure has been designed to support * Gravis UltraSound. It tries to be universal format for uploading * sample based patches but is probably too limited. */ struct patch_info { /* u_short key; Use GUS_PATCH here */ short key; /* Use GUS_PATCH here */ #define GUS_PATCH _PATCHKEY(0x04) #define OBSOLETE_GUS_PATCH _PATCHKEY(0x02) short device_no; /* Synthesizer number */ short instr_no; /* Midi pgm# */ u_long mode; /* * The least significant byte has the same format than the GUS .PAT * files */ #define WAVE_16_BITS 0x01 /* bit 0 = 8 or 16 bit wave data. */ #define WAVE_UNSIGNED 0x02 /* bit 1 = Signed - Unsigned data. */ #define WAVE_LOOPING 0x04 /* bit 2 = looping enabled-1. */ #define WAVE_BIDIR_LOOP 0x08 /* bit 3 = Set is bidirectional looping. */ #define WAVE_LOOP_BACK 0x10 /* bit 4 = Set is looping backward. */ #define WAVE_SUSTAIN_ON 0x20 /* bit 5 = Turn sustaining on. (Env. pts. 3)*/ #define WAVE_ENVELOPES 0x40 /* bit 6 = Enable envelopes - 1 */ /* (use the env_rate/env_offs fields). */ /* Linux specific bits */ #define WAVE_VIBRATO 0x00010000 /* The vibrato info is valid */ #define WAVE_TREMOLO 0x00020000 /* The tremolo info is valid */ #define WAVE_SCALE 0x00040000 /* The scaling info is valid */ /* Other bits must be zeroed */ long len; /* Size of the wave data in bytes */ long loop_start, loop_end; /* Byte offsets from the beginning */ /* * The base_freq and base_note fields are used when computing the * playback speed for a note. The base_note defines the tone frequency * which is heard if the sample is played using the base_freq as the * playback speed. * * The low_note and high_note fields define the minimum and maximum note * frequencies for which this sample is valid. It is possible to define * more than one samples for an instrument number at the same time. The * low_note and high_note fields are used to select the most suitable one. * * The fields base_note, high_note and low_note should contain * the note frequency multiplied by 1000. For example value for the * middle A is 440*1000. */ u_int base_freq; u_long base_note; u_long high_note; u_long low_note; int panning; /* -128=left, 127=right */ int detuning; /* New fields introduced in version 1.99.5 */ /* Envelope. Enabled by mode bit WAVE_ENVELOPES */ u_char env_rate[ 6 ]; /* GUS HW ramping rate */ u_char env_offset[ 6 ]; /* 255 == 100% */ /* * The tremolo, vibrato and scale info are not supported yet. * Enable by setting the mode bits WAVE_TREMOLO, WAVE_VIBRATO or * WAVE_SCALE */ u_char tremolo_sweep; u_char tremolo_rate; u_char tremolo_depth; u_char vibrato_sweep; u_char vibrato_rate; u_char vibrato_depth; int scale_frequency; u_int scale_factor; /* from 0 to 2048 or 0 to 2 */ int volume; int spare[4]; char data[1]; /* The waveform data starts here */ }; struct sysex_info { short key; /* Use GUS_PATCH here */ #define SYSEX_PATCH _PATCHKEY(0x05) #define MAUI_PATCH _PATCHKEY(0x06) short device_no; /* Synthesizer number */ long len; /* Size of the sysex data in bytes */ u_char data[1]; /* Sysex data starts here */ }; /* * Patch management interface (/dev/sequencer, /dev/patmgr#) * Don't use these calls if you want to maintain compatibility with * the future versions of the driver. */ #define PS_NO_PATCHES 0 /* No patch support on device */ #define PS_MGR_NOT_OK 1 /* Plain patch support (no mgr) */ #define PS_MGR_OK 2 /* Patch manager supported */ #define PS_MANAGED 3 /* Patch manager running */ #define SNDCTL_PMGR_IFACE _IOWR('P', 1, struct patmgr_info) /* * The patmgr_info is a fixed size structure which is used for two * different purposes. The intended use is for communication between * the application using /dev/sequencer and the patch manager daemon * associated with a synthesizer device (ioctl(SNDCTL_PMGR_ACCESS)). * * This structure is also used with ioctl(SNDCTL_PGMR_IFACE) which allows * a patch manager daemon to read and write device parameters. This * ioctl available through /dev/sequencer also. Avoid using it since it's * extremely hardware dependent. In addition access trough /dev/sequencer * may confuse the patch manager daemon. */ struct patmgr_info { /* Note! size must be < 4k since kmalloc() is used */ u_long key; /* Don't worry. Reserved for communication between the patch manager and the driver. */ #define PM_K_EVENT 1 /* Event from the /dev/sequencer driver */ #define PM_K_COMMAND 2 /* Request from an application */ #define PM_K_RESPONSE 3 /* From patmgr to application */ #define PM_ERROR 4 /* Error returned by the patmgr */ int device; int command; /* * Commands 0x000 to 0xfff reserved for patch manager programs */ #define PM_GET_DEVTYPE 1 /* Returns type of the patch mgr interface of dev */ #define PMTYPE_FM2 1 /* 2 OP fm */ #define PMTYPE_FM4 2 /* Mixed 4 or 2 op FM (OPL-3) */ #define PMTYPE_WAVE 3 /* Wave table synthesizer (GUS) */ #define PM_GET_NRPGM 2 /* Returns max # of midi programs in parm1 */ #define PM_GET_PGMMAP 3 /* Returns map of loaded midi programs in data8 */ #define PM_GET_PGM_PATCHES 4 /* Return list of patches of a program (parm1) */ #define PM_GET_PATCH 5 /* Return patch header of patch parm1 */ #define PM_SET_PATCH 6 /* Set patch header of patch parm1 */ #define PM_READ_PATCH 7 /* Read patch (wave) data */ #define PM_WRITE_PATCH 8 /* Write patch (wave) data */ /* * Commands 0x1000 to 0xffff are for communication between the patch manager * and the client */ #define _PM_LOAD_PATCH 0x100 /* * Commands above 0xffff reserved for device specific use */ long parm1; long parm2; long parm3; union { u_char data8[4000]; u_short data16[2000]; u_long data32[1000]; struct patch_info patch; } data; }; /* * When a patch manager daemon is present, it will be informed by the * driver when something important happens. For example when the * /dev/sequencer is opened or closed. A record with key == PM_K_EVENT is * returned. The command field contains the event type: */ #define PM_E_OPENED 1 /* /dev/sequencer opened */ #define PM_E_CLOSED 2 /* /dev/sequencer closed */ #define PM_E_PATCH_RESET 3 /* SNDCTL_RESETSAMPLES called */ #define PM_E_PATCH_LOADED 4 /* A patch has been loaded by appl */ /* * /dev/sequencer input events. * * The data written to the /dev/sequencer is a stream of events. Events * are records of 4 or 8 bytes. The first byte defines the size. * Any number of events can be written with a write call. There * is a set of macros for sending these events. Use these macros if you * want to maximize portability of your program. * * Events SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO. Are also input events. * (All input events are currently 4 bytes long. Be prepared to support * 8 byte events also. If you receive any event having first byte >= 128, * it's a 8 byte event. * * The events are documented at the end of this file. * * Normal events (4 bytes) * There is also a 8 byte version of most of the 4 byte events. The * 8 byte one is recommended. */ #define SEQ_NOTEOFF 0 #define SEQ_FMNOTEOFF SEQ_NOTEOFF /* Just old name */ #define SEQ_NOTEON 1 #define SEQ_FMNOTEON SEQ_NOTEON #define SEQ_WAIT TMR_WAIT_ABS #define SEQ_PGMCHANGE 3 #define SEQ_FMPGMCHANGE SEQ_PGMCHANGE #define SEQ_SYNCTIMER TMR_START #define SEQ_MIDIPUTC 5 #define SEQ_DRUMON 6 /*** OBSOLETE ***/ #define SEQ_DRUMOFF 7 /*** OBSOLETE ***/ #define SEQ_ECHO TMR_ECHO /* For synching programs with output */ #define SEQ_AFTERTOUCH 9 #define SEQ_CONTROLLER 10 /* * Midi controller numbers * * Controllers 0 to 31 (0x00 to 0x1f) and 32 to 63 (0x20 to 0x3f) * are continuous controllers. * In the MIDI 1.0 these controllers are sent using two messages. * Controller numbers 0 to 31 are used to send the MSB and the * controller numbers 32 to 63 are for the LSB. Note that just 7 bits * are used in MIDI bytes. */ #define CTL_BANK_SELECT 0x00 #define CTL_MODWHEEL 0x01 #define CTL_BREATH 0x02 /* undefined 0x03 */ #define CTL_FOOT 0x04 #define CTL_PORTAMENTO_TIME 0x05 #define CTL_DATA_ENTRY 0x06 #define CTL_MAIN_VOLUME 0x07 #define CTL_BALANCE 0x08 /* undefined 0x09 */ #define CTL_PAN 0x0a #define CTL_EXPRESSION 0x0b /* undefined 0x0c - 0x0f */ #define CTL_GENERAL_PURPOSE1 0x10 #define CTL_GENERAL_PURPOSE2 0x11 #define CTL_GENERAL_PURPOSE3 0x12 #define CTL_GENERAL_PURPOSE4 0x13 /* undefined 0x14 - 0x1f */ /* undefined 0x20 */ /* * The controller numbers 0x21 to 0x3f are reserved for the * least significant bytes of the controllers 0x00 to 0x1f. * These controllers are not recognised by the driver. * * Controllers 64 to 69 (0x40 to 0x45) are on/off switches. * 0=OFF and 127=ON (intermediate values are possible) */ #define CTL_DAMPER_PEDAL 0x40 #define CTL_SUSTAIN CTL_DAMPER_PEDAL /* Alias */ #define CTL_HOLD CTL_DAMPER_PEDAL /* Alias */ #define CTL_PORTAMENTO 0x41 #define CTL_SOSTENUTO 0x42 #define CTL_SOFT_PEDAL 0x43 /* undefined 0x44 */ #define CTL_HOLD2 0x45 /* undefined 0x46 - 0x4f */ #define CTL_GENERAL_PURPOSE5 0x50 #define CTL_GENERAL_PURPOSE6 0x51 #define CTL_GENERAL_PURPOSE7 0x52 #define CTL_GENERAL_PURPOSE8 0x53 /* undefined 0x54 - 0x5a */ #define CTL_EXT_EFF_DEPTH 0x5b #define CTL_TREMOLO_DEPTH 0x5c #define CTL_CHORUS_DEPTH 0x5d #define CTL_DETUNE_DEPTH 0x5e #define CTL_CELESTE_DEPTH CTL_DETUNE_DEPTH /* Alias for the above one */ #define CTL_PHASER_DEPTH 0x5f #define CTL_DATA_INCREMENT 0x60 #define CTL_DATA_DECREMENT 0x61 #define CTL_NONREG_PARM_NUM_LSB 0x62 #define CTL_NONREG_PARM_NUM_MSB 0x63 #define CTL_REGIST_PARM_NUM_LSB 0x64 #define CTL_REGIST_PARM_NUM_MSB 0x65 /* undefined 0x66 - 0x78 */ /* reserved 0x79 - 0x7f */ /* Pseudo controllers (not midi compatible) */ #define CTRL_PITCH_BENDER 255 #define CTRL_PITCH_BENDER_RANGE 254 #define CTRL_EXPRESSION 253 /* Obsolete */ #define CTRL_MAIN_VOLUME 252 /* Obsolete */ #define SEQ_BALANCE 11 #define SEQ_VOLMODE 12 /* * Volume mode decides how volumes are used */ #define VOL_METHOD_ADAGIO 1 #define VOL_METHOD_LINEAR 2 /* * Note! SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO are used also as * input events. */ /* * Event codes 0xf0 to 0xfc are reserved for future extensions. */ #define SEQ_FULLSIZE 0xfd /* Long events */ /* * SEQ_FULLSIZE events are used for loading patches/samples to the * synthesizer devices. These events are passed directly to the driver * of the associated synthesizer device. There is no limit to the size * of the extended events. These events are not queued but executed * immediately when the write() is called (execution can take several * seconds of time). * * When a SEQ_FULLSIZE message is written to the device, it must * be written using exactly one write() call. Other events cannot * be mixed to the same write. * * For FM synths (YM3812/OPL3) use struct sbi_instrument and write * it to the /dev/sequencer. Don't write other data together with * the instrument structure Set the key field of the structure to * FM_PATCH. The device field is used to route the patch to the * corresponding device. * * For Gravis UltraSound use struct patch_info. Initialize the key field * to GUS_PATCH. */ #define SEQ_PRIVATE 0xfe /* Low level HW dependent events (8 bytes) */ #define SEQ_EXTENDED 0xff /* Extended events (8 bytes) OBSOLETE */ /* * Record for FM patches */ typedef u_char sbi_instr_data[32]; struct sbi_instrument { u_short key; /* FM_PATCH or OPL3_PATCH */ #define FM_PATCH _PATCHKEY(0x01) #define OPL3_PATCH _PATCHKEY(0x03) short device; /* Synth# (0-4) */ int channel; /* Program# to be initialized */ sbi_instr_data operators; /* Reg. settings for operator cells * (.SBI format) */ }; struct synth_info { /* Read only */ char name[30]; int device; /* 0-N. INITIALIZE BEFORE CALLING */ int synth_type; #define SYNTH_TYPE_FM 0 #define SYNTH_TYPE_SAMPLE 1 #define SYNTH_TYPE_MIDI 2 /* Midi interface */ int synth_subtype; #define FM_TYPE_ADLIB 0x00 #define FM_TYPE_OPL3 0x01 #define MIDI_TYPE_MPU401 0x401 #define SAMPLE_TYPE_BASIC 0x10 #define SAMPLE_TYPE_GUS SAMPLE_TYPE_BASIC #define SAMPLE_TYPE_AWE32 0x20 int perc_mode; /* No longer supported */ int nr_voices; int nr_drums; /* Obsolete field */ int instr_bank_size; u_long capabilities; #define SYNTH_CAP_PERCMODE 0x00000001 /* No longer used */ #define SYNTH_CAP_OPL3 0x00000002 /* Set if OPL3 supported */ #define SYNTH_CAP_INPUT 0x00000004 /* Input (MIDI) device */ int dummies[19]; /* Reserve space */ }; struct sound_timer_info { char name[32]; int caps; }; struct midi_info { char name[30]; int device; /* 0-N. INITIALIZE BEFORE CALLING */ u_long capabilities; /* To be defined later */ int dev_type; int dummies[18]; /* Reserve space */ }; /* * ioctl commands for the /dev/midi## */ typedef struct { u_char cmd; char nr_args, nr_returns; u_char data[30]; } mpu_command_rec; #define SNDCTL_MIDI_PRETIME _IOWR('m', 0, int) #define SNDCTL_MIDI_MPUMODE _IOWR('m', 1, int) #define SNDCTL_MIDI_MPUCMD _IOWR('m', 2, mpu_command_rec) #define MIOSPASSTHRU _IOWR('m', 3, int) #define MIOGPASSTHRU _IOWR('m', 4, int) /* * IOCTL commands for /dev/dsp and /dev/audio */ #define SNDCTL_DSP_HALT _IO ('P', 0) #define SNDCTL_DSP_RESET SNDCTL_DSP_HALT #define SNDCTL_DSP_SYNC _IO ('P', 1) #define SNDCTL_DSP_SPEED _IOWR('P', 2, int) #define SNDCTL_DSP_STEREO _IOWR('P', 3, int) #define SNDCTL_DSP_GETBLKSIZE _IOR('P', 4, int) #define SNDCTL_DSP_SETBLKSIZE _IOW('P', 4, int) #define SNDCTL_DSP_SETFMT _IOWR('P',5, int) /* Selects ONE fmt*/ /* * SOUND_PCM_WRITE_CHANNELS is not that different * from SNDCTL_DSP_STEREO */ #define SOUND_PCM_WRITE_CHANNELS _IOWR('P', 6, int) #define SNDCTL_DSP_CHANNELS SOUND_PCM_WRITE_CHANNELS #define SOUND_PCM_WRITE_FILTER _IOWR('P', 7, int) #define SNDCTL_DSP_POST _IO ('P', 8) /* * SNDCTL_DSP_SETBLKSIZE and the following two calls mostly do * the same thing, i.e. set the block size used in DMA transfers. */ #define SNDCTL_DSP_SUBDIVIDE _IOWR('P', 9, int) #define SNDCTL_DSP_SETFRAGMENT _IOWR('P',10, int) #define SNDCTL_DSP_GETFMTS _IOR ('P',11, int) /* Returns a mask */ /* * Buffer status queries. */ typedef struct audio_buf_info { int fragments; /* # of avail. frags (partly used ones not counted) */ int fragstotal; /* Total # of fragments allocated */ int fragsize; /* Size of a fragment in bytes */ int bytes; /* Avail. space in bytes (includes partly used fragments) */ /* Note! 'bytes' could be more than fragments*fragsize */ } audio_buf_info; #define SNDCTL_DSP_GETOSPACE _IOR ('P',12, audio_buf_info) #define SNDCTL_DSP_GETISPACE _IOR ('P',13, audio_buf_info) /* * SNDCTL_DSP_NONBLOCK is the same (but less powerful, since the * action cannot be undone) of FIONBIO. The same can be achieved * by opening the device with O_NDELAY */ #define SNDCTL_DSP_NONBLOCK _IO ('P',14) #define SNDCTL_DSP_GETCAPS _IOR ('P',15, int) # define PCM_CAP_REVISION 0x000000ff /* Bits for revision level (0 to 255) */ # define PCM_CAP_DUPLEX 0x00000100 /* Full duplex record/playback */ # define PCM_CAP_REALTIME 0x00000200 /* Not in use */ # define PCM_CAP_BATCH 0x00000400 /* Device has some kind of */ /* internal buffers which may */ /* cause some delays and */ /* decrease precision of timing */ # define PCM_CAP_COPROC 0x00000800 /* Has a coprocessor */ /* Sometimes it's a DSP */ /* but usually not */ # define PCM_CAP_TRIGGER 0x00001000 /* Supports SETTRIGGER */ # define PCM_CAP_MMAP 0x00002000 /* Supports mmap() */ # define PCM_CAP_MULTI 0x00004000 /* Supports multiple open */ # define PCM_CAP_BIND 0x00008000 /* Supports binding to front/rear/center/lfe */ # define PCM_CAP_INPUT 0x00010000 /* Supports recording */ # define PCM_CAP_OUTPUT 0x00020000 /* Supports playback */ # define PCM_CAP_VIRTUAL 0x00040000 /* Virtual device */ /* 0x00040000 and 0x00080000 reserved for future use */ /* Analog/digital control capabilities */ # define PCM_CAP_ANALOGOUT 0x00100000 # define PCM_CAP_ANALOGIN 0x00200000 # define PCM_CAP_DIGITALOUT 0x00400000 # define PCM_CAP_DIGITALIN 0x00800000 # define PCM_CAP_ADMASK 0x00f00000 /* * NOTE! (capabilities & PCM_CAP_ADMASK)==0 means just that the * digital/analog interface control features are not supported by the * device/driver. However the device still supports analog, digital or * both inputs/outputs (depending on the device). See the OSS Programmer's * Guide for full details. */ # define PCM_CAP_SPECIAL 0x01000000 /* Not for ordinary "multimedia" use */ # define PCM_CAP_SHADOW 0x00000000 /* OBSOLETE */ /* * Preferred channel usage. These bits can be used to * give recommendations to the application. Used by few drivers. * For example if ((caps & DSP_CH_MASK) == DSP_CH_MONO) means that * the device works best in mono mode. However it doesn't necessarily mean * that the device cannot be used in stereo. These bits should only be used * by special applications such as multi track hard disk recorders to find * out the initial setup. However the user should be able to override this * selection. * * To find out which modes are actually supported the application should * try to select them using SNDCTL_DSP_CHANNELS. */ # define DSP_CH_MASK 0x06000000 /* Mask */ # define DSP_CH_ANY 0x00000000 /* No preferred mode */ # define DSP_CH_MONO 0x02000000 # define DSP_CH_STEREO 0x04000000 # define DSP_CH_MULTI 0x06000000 /* More than two channels */ # define PCM_CAP_HIDDEN 0x08000000 /* Hidden device */ # define PCM_CAP_FREERATE 0x10000000 # define PCM_CAP_MODEM 0x20000000 /* Modem device */ # define PCM_CAP_DEFAULT 0x40000000 /* "Default" device */ /* * The PCM_CAP_* capability names were known as DSP_CAP_* prior OSS 4.0 * so it's necessary to define the older names too. */ #define DSP_CAP_ADMASK PCM_CAP_ADMASK #define DSP_CAP_ANALOGIN PCM_CAP_ANALOGIN #define DSP_CAP_ANALOGOUT PCM_CAP_ANALOGOUT #define DSP_CAP_BATCH PCM_CAP_BATCH #define DSP_CAP_BIND PCM_CAP_BIND #define DSP_CAP_COPROC PCM_CAP_COPROC #define DSP_CAP_DEFAULT PCM_CAP_DEFAULT #define DSP_CAP_DIGITALIN PCM_CAP_DIGITALIN #define DSP_CAP_DIGITALOUT PCM_CAP_DIGITALOUT #define DSP_CAP_DUPLEX PCM_CAP_DUPLEX #define DSP_CAP_FREERATE PCM_CAP_FREERATE #define DSP_CAP_HIDDEN PCM_CAP_HIDDEN #define DSP_CAP_INPUT PCM_CAP_INPUT #define DSP_CAP_MMAP PCM_CAP_MMAP #define DSP_CAP_MODEM PCM_CAP_MODEM #define DSP_CAP_MULTI PCM_CAP_MULTI #define DSP_CAP_OUTPUT PCM_CAP_OUTPUT #define DSP_CAP_REALTIME PCM_CAP_REALTIME #define DSP_CAP_REVISION PCM_CAP_REVISION #define DSP_CAP_SHADOW PCM_CAP_SHADOW #define DSP_CAP_TRIGGER PCM_CAP_TRIGGER #define DSP_CAP_VIRTUAL PCM_CAP_VIRTUAL /* * What do these function do ? */ #define SNDCTL_DSP_GETTRIGGER _IOR ('P',16, int) #define SNDCTL_DSP_SETTRIGGER _IOW ('P',16, int) #define PCM_ENABLE_INPUT 0x00000001 #define PCM_ENABLE_OUTPUT 0x00000002 typedef struct count_info { int bytes; /* Total # of bytes processed */ int blocks; /* # of fragment transitions since last time */ int ptr; /* Current DMA pointer value */ } count_info; /* * GETIPTR and GETISPACE are not that different... same for out. */ #define SNDCTL_DSP_GETIPTR _IOR ('P',17, count_info) #define SNDCTL_DSP_GETOPTR _IOR ('P',18, count_info) typedef struct buffmem_desc { caddr_t buffer; int size; } buffmem_desc; #define SNDCTL_DSP_MAPINBUF _IOR ('P', 19, buffmem_desc) #define SNDCTL_DSP_MAPOUTBUF _IOR ('P', 20, buffmem_desc) #define SNDCTL_DSP_SETSYNCRO _IO ('P', 21) #define SNDCTL_DSP_SETDUPLEX _IO ('P', 22) #define SNDCTL_DSP_GETODELAY _IOR ('P', 23, int) /* * I guess these are the readonly version of the same * functions that exist above as SNDCTL_DSP_... */ #define SOUND_PCM_READ_RATE _IOR ('P', 2, int) #define SOUND_PCM_READ_CHANNELS _IOR ('P', 6, int) #define SOUND_PCM_READ_BITS _IOR ('P', 5, int) #define SOUND_PCM_READ_FILTER _IOR ('P', 7, int) /* * ioctl calls to be used in communication with coprocessors and * DSP chips. */ typedef struct copr_buffer { int command; /* Set to 0 if not used */ int flags; #define CPF_NONE 0x0000 #define CPF_FIRST 0x0001 /* First block */ #define CPF_LAST 0x0002 /* Last block */ int len; int offs; /* If required by the device (0 if not used) */ u_char data[4000]; /* NOTE! 4000 is not 4k */ } copr_buffer; typedef struct copr_debug_buf { int command; /* Used internally. Set to 0 */ int parm1; int parm2; int flags; int len; /* Length of data in bytes */ } copr_debug_buf; typedef struct copr_msg { int len; u_char data[4000]; } copr_msg; #define SNDCTL_COPR_RESET _IO ('C', 0) #define SNDCTL_COPR_LOAD _IOWR('C', 1, copr_buffer) #define SNDCTL_COPR_RDATA _IOWR('C', 2, copr_debug_buf) #define SNDCTL_COPR_RCODE _IOWR('C', 3, copr_debug_buf) #define SNDCTL_COPR_WDATA _IOW ('C', 4, copr_debug_buf) #define SNDCTL_COPR_WCODE _IOW ('C', 5, copr_debug_buf) #define SNDCTL_COPR_RUN _IOWR('C', 6, copr_debug_buf) #define SNDCTL_COPR_HALT _IOWR('C', 7, copr_debug_buf) #define SNDCTL_COPR_SENDMSG _IOW ('C', 8, copr_msg) #define SNDCTL_COPR_RCVMSG _IOR ('C', 9, copr_msg) /* * IOCTL commands for /dev/mixer */ /* * Mixer devices * * There can be up to 20 different analog mixer channels. The * SOUND_MIXER_NRDEVICES gives the currently supported maximum. * The SOUND_MIXER_READ_DEVMASK returns a bitmask which tells * the devices supported by the particular mixer. */ #define SOUND_MIXER_NRDEVICES 25 #define SOUND_MIXER_VOLUME 0 /* Master output level */ #define SOUND_MIXER_BASS 1 /* Treble level of all output channels */ #define SOUND_MIXER_TREBLE 2 /* Bass level of all output channels */ #define SOUND_MIXER_SYNTH 3 /* Volume of synthesier input */ #define SOUND_MIXER_PCM 4 /* Output level for the audio device */ #define SOUND_MIXER_SPEAKER 5 /* Output level for the PC speaker * signals */ #define SOUND_MIXER_LINE 6 /* Volume level for the line in jack */ #define SOUND_MIXER_MIC 7 /* Volume for the signal coming from * the microphone jack */ #define SOUND_MIXER_CD 8 /* Volume level for the input signal * connected to the CD audio input */ #define SOUND_MIXER_IMIX 9 /* Recording monitor. It controls the * output volume of the selected * recording sources while recording */ #define SOUND_MIXER_ALTPCM 10 /* Volume of the alternative codec * device */ #define SOUND_MIXER_RECLEV 11 /* Global recording level */ #define SOUND_MIXER_IGAIN 12 /* Input gain */ #define SOUND_MIXER_OGAIN 13 /* Output gain */ /* * The AD1848 codec and compatibles have three line level inputs * (line, aux1 and aux2). Since each card manufacturer have assigned * different meanings to these inputs, it's inpractical to assign * specific meanings (line, cd, synth etc.) to them. */ #define SOUND_MIXER_LINE1 14 /* Input source 1 (aux1) */ #define SOUND_MIXER_LINE2 15 /* Input source 2 (aux2) */ #define SOUND_MIXER_LINE3 16 /* Input source 3 (line) */ #define SOUND_MIXER_DIGITAL1 17 /* Digital (input) 1 */ #define SOUND_MIXER_DIGITAL2 18 /* Digital (input) 2 */ #define SOUND_MIXER_DIGITAL3 19 /* Digital (input) 3 */ #define SOUND_MIXER_PHONEIN 20 /* Phone input */ #define SOUND_MIXER_PHONEOUT 21 /* Phone output */ #define SOUND_MIXER_VIDEO 22 /* Video/TV (audio) in */ #define SOUND_MIXER_RADIO 23 /* Radio in */ #define SOUND_MIXER_MONITOR 24 /* Monitor (usually mic) volume */ /* * Some on/off settings (SOUND_SPECIAL_MIN - SOUND_SPECIAL_MAX) * Not counted to SOUND_MIXER_NRDEVICES, but use the same number space */ #define SOUND_ONOFF_MIN 28 #define SOUND_ONOFF_MAX 30 #define SOUND_MIXER_MUTE 28 /* 0 or 1 */ #define SOUND_MIXER_ENHANCE 29 /* Enhanced stereo (0, 40, 60 or 80) */ #define SOUND_MIXER_LOUD 30 /* 0 or 1 */ /* Note! Number 31 cannot be used since the sign bit is reserved */ #define SOUND_MIXER_NONE 31 #define SOUND_DEVICE_LABELS { \ "Vol ", "Bass ", "Trebl", "Synth", "Pcm ", "Spkr ", "Line ", \ "Mic ", "CD ", "Mix ", "Pcm2 ", "Rec ", "IGain", "OGain", \ "Line1", "Line2", "Line3", "Digital1", "Digital2", "Digital3", \ "PhoneIn", "PhoneOut", "Video", "Radio", "Monitor"} #define SOUND_DEVICE_NAMES { \ "vol", "bass", "treble", "synth", "pcm", "speaker", "line", \ "mic", "cd", "mix", "pcm2", "rec", "igain", "ogain", \ "line1", "line2", "line3", "dig1", "dig2", "dig3", \ "phin", "phout", "video", "radio", "monitor"} /* Device bitmask identifiers */ #define SOUND_MIXER_RECSRC 0xff /* 1 bit per recording source */ #define SOUND_MIXER_DEVMASK 0xfe /* 1 bit per supported device */ #define SOUND_MIXER_RECMASK 0xfd /* 1 bit per supp. recording source */ #define SOUND_MIXER_CAPS 0xfc #define SOUND_CAP_EXCL_INPUT 0x00000001 /* Only 1 rec. src at a time */ #define SOUND_MIXER_STEREODEVS 0xfb /* Mixer channels supporting stereo */ /* Device mask bits */ #define SOUND_MASK_VOLUME (1 << SOUND_MIXER_VOLUME) #define SOUND_MASK_BASS (1 << SOUND_MIXER_BASS) #define SOUND_MASK_TREBLE (1 << SOUND_MIXER_TREBLE) #define SOUND_MASK_SYNTH (1 << SOUND_MIXER_SYNTH) #define SOUND_MASK_PCM (1 << SOUND_MIXER_PCM) #define SOUND_MASK_SPEAKER (1 << SOUND_MIXER_SPEAKER) #define SOUND_MASK_LINE (1 << SOUND_MIXER_LINE) #define SOUND_MASK_MIC (1 << SOUND_MIXER_MIC) #define SOUND_MASK_CD (1 << SOUND_MIXER_CD) #define SOUND_MASK_IMIX (1 << SOUND_MIXER_IMIX) #define SOUND_MASK_ALTPCM (1 << SOUND_MIXER_ALTPCM) #define SOUND_MASK_RECLEV (1 << SOUND_MIXER_RECLEV) #define SOUND_MASK_IGAIN (1 << SOUND_MIXER_IGAIN) #define SOUND_MASK_OGAIN (1 << SOUND_MIXER_OGAIN) #define SOUND_MASK_LINE1 (1 << SOUND_MIXER_LINE1) #define SOUND_MASK_LINE2 (1 << SOUND_MIXER_LINE2) #define SOUND_MASK_LINE3 (1 << SOUND_MIXER_LINE3) #define SOUND_MASK_DIGITAL1 (1 << SOUND_MIXER_DIGITAL1) #define SOUND_MASK_DIGITAL2 (1 << SOUND_MIXER_DIGITAL2) #define SOUND_MASK_DIGITAL3 (1 << SOUND_MIXER_DIGITAL3) #define SOUND_MASK_PHONEIN (1 << SOUND_MIXER_PHONEIN) #define SOUND_MASK_PHONEOUT (1 << SOUND_MIXER_PHONEOUT) #define SOUND_MASK_RADIO (1 << SOUND_MIXER_RADIO) #define SOUND_MASK_VIDEO (1 << SOUND_MIXER_VIDEO) #define SOUND_MASK_MONITOR (1 << SOUND_MIXER_MONITOR) /* Obsolete macros */ #define SOUND_MASK_MUTE (1 << SOUND_MIXER_MUTE) #define SOUND_MASK_ENHANCE (1 << SOUND_MIXER_ENHANCE) #define SOUND_MASK_LOUD (1 << SOUND_MIXER_LOUD) #define MIXER_READ(dev) _IOR('M', dev, int) #define SOUND_MIXER_READ_VOLUME MIXER_READ(SOUND_MIXER_VOLUME) #define SOUND_MIXER_READ_BASS MIXER_READ(SOUND_MIXER_BASS) #define SOUND_MIXER_READ_TREBLE MIXER_READ(SOUND_MIXER_TREBLE) #define SOUND_MIXER_READ_SYNTH MIXER_READ(SOUND_MIXER_SYNTH) #define SOUND_MIXER_READ_PCM MIXER_READ(SOUND_MIXER_PCM) #define SOUND_MIXER_READ_SPEAKER MIXER_READ(SOUND_MIXER_SPEAKER) #define SOUND_MIXER_READ_LINE MIXER_READ(SOUND_MIXER_LINE) #define SOUND_MIXER_READ_MIC MIXER_READ(SOUND_MIXER_MIC) #define SOUND_MIXER_READ_CD MIXER_READ(SOUND_MIXER_CD) #define SOUND_MIXER_READ_IMIX MIXER_READ(SOUND_MIXER_IMIX) #define SOUND_MIXER_READ_ALTPCM MIXER_READ(SOUND_MIXER_ALTPCM) #define SOUND_MIXER_READ_RECLEV MIXER_READ(SOUND_MIXER_RECLEV) #define SOUND_MIXER_READ_IGAIN MIXER_READ(SOUND_MIXER_IGAIN) #define SOUND_MIXER_READ_OGAIN MIXER_READ(SOUND_MIXER_OGAIN) #define SOUND_MIXER_READ_LINE1 MIXER_READ(SOUND_MIXER_LINE1) #define SOUND_MIXER_READ_LINE2 MIXER_READ(SOUND_MIXER_LINE2) #define SOUND_MIXER_READ_LINE3 MIXER_READ(SOUND_MIXER_LINE3) #define SOUND_MIXER_READ_DIGITAL1 MIXER_READ(SOUND_MIXER_DIGITAL1) #define SOUND_MIXER_READ_DIGITAL2 MIXER_READ(SOUND_MIXER_DIGITAL2) #define SOUND_MIXER_READ_DIGITAL3 MIXER_READ(SOUND_MIXER_DIGITAL3) #define SOUND_MIXER_READ_PHONEIN MIXER_READ(SOUND_MIXER_PHONEIN) #define SOUND_MIXER_READ_PHONEOUT MIXER_READ(SOUND_MIXER_PHONEOUT) #define SOUND_MIXER_READ_RADIO MIXER_READ(SOUND_MIXER_RADIO) #define SOUND_MIXER_READ_VIDEO MIXER_READ(SOUND_MIXER_VIDEO) #define SOUND_MIXER_READ_MONITOR MIXER_READ(SOUND_MIXER_MONITOR) /* Obsolete macros */ #define SOUND_MIXER_READ_MUTE MIXER_READ(SOUND_MIXER_MUTE) #define SOUND_MIXER_READ_ENHANCE MIXER_READ(SOUND_MIXER_ENHANCE) #define SOUND_MIXER_READ_LOUD MIXER_READ(SOUND_MIXER_LOUD) #define SOUND_MIXER_READ_RECSRC MIXER_READ(SOUND_MIXER_RECSRC) #define SOUND_MIXER_READ_DEVMASK MIXER_READ(SOUND_MIXER_DEVMASK) #define SOUND_MIXER_READ_RECMASK MIXER_READ(SOUND_MIXER_RECMASK) #define SOUND_MIXER_READ_STEREODEVS MIXER_READ(SOUND_MIXER_STEREODEVS) #define SOUND_MIXER_READ_CAPS MIXER_READ(SOUND_MIXER_CAPS) #define MIXER_WRITE(dev) _IOWR('M', dev, int) #define SOUND_MIXER_WRITE_VOLUME MIXER_WRITE(SOUND_MIXER_VOLUME) #define SOUND_MIXER_WRITE_BASS MIXER_WRITE(SOUND_MIXER_BASS) #define SOUND_MIXER_WRITE_TREBLE MIXER_WRITE(SOUND_MIXER_TREBLE) #define SOUND_MIXER_WRITE_SYNTH MIXER_WRITE(SOUND_MIXER_SYNTH) #define SOUND_MIXER_WRITE_PCM MIXER_WRITE(SOUND_MIXER_PCM) #define SOUND_MIXER_WRITE_SPEAKER MIXER_WRITE(SOUND_MIXER_SPEAKER) #define SOUND_MIXER_WRITE_LINE MIXER_WRITE(SOUND_MIXER_LINE) #define SOUND_MIXER_WRITE_MIC MIXER_WRITE(SOUND_MIXER_MIC) #define SOUND_MIXER_WRITE_CD MIXER_WRITE(SOUND_MIXER_CD) #define SOUND_MIXER_WRITE_IMIX MIXER_WRITE(SOUND_MIXER_IMIX) #define SOUND_MIXER_WRITE_ALTPCM MIXER_WRITE(SOUND_MIXER_ALTPCM) #define SOUND_MIXER_WRITE_RECLEV MIXER_WRITE(SOUND_MIXER_RECLEV) #define SOUND_MIXER_WRITE_IGAIN MIXER_WRITE(SOUND_MIXER_IGAIN) #define SOUND_MIXER_WRITE_OGAIN MIXER_WRITE(SOUND_MIXER_OGAIN) #define SOUND_MIXER_WRITE_LINE1 MIXER_WRITE(SOUND_MIXER_LINE1) #define SOUND_MIXER_WRITE_LINE2 MIXER_WRITE(SOUND_MIXER_LINE2) #define SOUND_MIXER_WRITE_LINE3 MIXER_WRITE(SOUND_MIXER_LINE3) #define SOUND_MIXER_WRITE_DIGITAL1 MIXER_WRITE(SOUND_MIXER_DIGITAL1) #define SOUND_MIXER_WRITE_DIGITAL2 MIXER_WRITE(SOUND_MIXER_DIGITAL2) #define SOUND_MIXER_WRITE_DIGITAL3 MIXER_WRITE(SOUND_MIXER_DIGITAL3) #define SOUND_MIXER_WRITE_PHONEIN MIXER_WRITE(SOUND_MIXER_PHONEIN) #define SOUND_MIXER_WRITE_PHONEOUT MIXER_WRITE(SOUND_MIXER_PHONEOUT) #define SOUND_MIXER_WRITE_RADIO MIXER_WRITE(SOUND_MIXER_RADIO) #define SOUND_MIXER_WRITE_VIDEO MIXER_WRITE(SOUND_MIXER_VIDEO) #define SOUND_MIXER_WRITE_MONITOR MIXER_WRITE(SOUND_MIXER_MONITOR) #define SOUND_MIXER_WRITE_MUTE MIXER_WRITE(SOUND_MIXER_MUTE) #define SOUND_MIXER_WRITE_ENHANCE MIXER_WRITE(SOUND_MIXER_ENHANCE) #define SOUND_MIXER_WRITE_LOUD MIXER_WRITE(SOUND_MIXER_LOUD) #define SOUND_MIXER_WRITE_RECSRC MIXER_WRITE(SOUND_MIXER_RECSRC) typedef struct mixer_info { char id[16]; char name[32]; int modify_counter; int fillers[10]; } mixer_info; #define SOUND_MIXER_INFO _IOR('M', 101, mixer_info) #define LEFT_CHN 0 #define RIGHT_CHN 1 /* * Level 2 event types for /dev/sequencer */ /* * The 4 most significant bits of byte 0 specify the class of * the event: * * 0x8X = system level events, * 0x9X = device/port specific events, event[1] = device/port, * The last 4 bits give the subtype: * 0x02 = Channel event (event[3] = chn). * 0x01 = note event (event[4] = note). * (0x01 is not used alone but always with bit 0x02). * event[2] = MIDI message code (0x80=note off etc.) * */ #define EV_SEQ_LOCAL 0x80 #define EV_TIMING 0x81 #define EV_CHN_COMMON 0x92 #define EV_CHN_VOICE 0x93 #define EV_SYSEX 0x94 /* * Event types 200 to 220 are reserved for application use. * These numbers will not be used by the driver. */ /* * Events for event type EV_CHN_VOICE */ #define MIDI_NOTEOFF 0x80 #define MIDI_NOTEON 0x90 #define MIDI_KEY_PRESSURE 0xA0 /* * Events for event type EV_CHN_COMMON */ #define MIDI_CTL_CHANGE 0xB0 #define MIDI_PGM_CHANGE 0xC0 #define MIDI_CHN_PRESSURE 0xD0 #define MIDI_PITCH_BEND 0xE0 #define MIDI_SYSTEM_PREFIX 0xF0 /* * Timer event types */ #define TMR_WAIT_REL 1 /* Time relative to the prev time */ #define TMR_WAIT_ABS 2 /* Absolute time since TMR_START */ #define TMR_STOP 3 #define TMR_START 4 #define TMR_CONTINUE 5 #define TMR_TEMPO 6 #define TMR_ECHO 8 #define TMR_CLOCK 9 /* MIDI clock */ #define TMR_SPP 10 /* Song position pointer */ #define TMR_TIMESIG 11 /* Time signature */ /* * Local event types */ #define LOCL_STARTAUDIO 1 #if !defined(_KERNEL) || defined(USE_SEQ_MACROS) /* * Some convenience macros to simplify programming of the * /dev/sequencer interface * * These macros define the API which should be used when possible. */ #ifndef USE_SIMPLE_MACROS void seqbuf_dump(void); /* This function must be provided by programs */ /* Sample seqbuf_dump() implementation: * * SEQ_DEFINEBUF (2048); -- Defines a buffer for 2048 bytes * * int seqfd; -- The file descriptor for /dev/sequencer. * * void * seqbuf_dump () * { * if (_seqbufptr) * if (write (seqfd, _seqbuf, _seqbufptr) == -1) * { * perror ("write /dev/sequencer"); * exit (-1); * } * _seqbufptr = 0; * } */ #define SEQ_DEFINEBUF(len) \ u_char _seqbuf[len]; int _seqbuflen = len;int _seqbufptr = 0 #define SEQ_USE_EXTBUF() \ extern u_char _seqbuf[]; \ extern int _seqbuflen;extern int _seqbufptr #define SEQ_DECLAREBUF() SEQ_USE_EXTBUF() #define SEQ_PM_DEFINES struct patmgr_info _pm_info #define _SEQ_NEEDBUF(len) \ if ((_seqbufptr+(len)) > _seqbuflen) \ seqbuf_dump() #define _SEQ_ADVBUF(len) _seqbufptr += len #define SEQ_DUMPBUF seqbuf_dump #else /* * This variation of the sequencer macros is used just to format one event * using fixed buffer. * * The program using the macro library must define the following macros before * using this library. * * #define _seqbuf name of the buffer (u_char[]) * #define _SEQ_ADVBUF(len) If the applic needs to know the exact * size of the event, this macro can be used. * Otherwise this must be defined as empty. * #define _seqbufptr Define the name of index variable or 0 if * not required. */ #define _SEQ_NEEDBUF(len) /* empty */ #endif #define PM_LOAD_PATCH(dev, bank, pgm) \ (SEQ_DUMPBUF(), _pm_info.command = _PM_LOAD_PATCH, \ _pm_info.device=dev, _pm_info.data.data8[0]=pgm, \ _pm_info.parm1 = bank, _pm_info.parm2 = 1, \ ioctl(seqfd, SNDCTL_PMGR_ACCESS, &_pm_info)) #define PM_LOAD_PATCHES(dev, bank, pgm) \ (SEQ_DUMPBUF(), _pm_info.command = _PM_LOAD_PATCH, \ _pm_info.device=dev, bcopy( pgm, _pm_info.data.data8, 128), \ _pm_info.parm1 = bank, _pm_info.parm2 = 128, \ ioctl(seqfd, SNDCTL_PMGR_ACCESS, &_pm_info)) #define SEQ_VOLUME_MODE(dev, mode) { \ _SEQ_NEEDBUF(8);\ _seqbuf[_seqbufptr] = SEQ_EXTENDED;\ _seqbuf[_seqbufptr+1] = SEQ_VOLMODE;\ _seqbuf[_seqbufptr+2] = (dev);\ _seqbuf[_seqbufptr+3] = (mode);\ _seqbuf[_seqbufptr+4] = 0;\ _seqbuf[_seqbufptr+5] = 0;\ _seqbuf[_seqbufptr+6] = 0;\ _seqbuf[_seqbufptr+7] = 0;\ _SEQ_ADVBUF(8);} /* * Midi voice messages */ #define _CHN_VOICE(dev, event, chn, note, parm) { \ _SEQ_NEEDBUF(8);\ _seqbuf[_seqbufptr] = EV_CHN_VOICE;\ _seqbuf[_seqbufptr+1] = (dev);\ _seqbuf[_seqbufptr+2] = (event);\ _seqbuf[_seqbufptr+3] = (chn);\ _seqbuf[_seqbufptr+4] = (note);\ _seqbuf[_seqbufptr+5] = (parm);\ _seqbuf[_seqbufptr+6] = (0);\ _seqbuf[_seqbufptr+7] = 0;\ _SEQ_ADVBUF(8);} #define SEQ_START_NOTE(dev, chn, note, vol) \ _CHN_VOICE(dev, MIDI_NOTEON, chn, note, vol) #define SEQ_STOP_NOTE(dev, chn, note, vol) \ _CHN_VOICE(dev, MIDI_NOTEOFF, chn, note, vol) #define SEQ_KEY_PRESSURE(dev, chn, note, pressure) \ _CHN_VOICE(dev, MIDI_KEY_PRESSURE, chn, note, pressure) /* * Midi channel messages */ #define _CHN_COMMON(dev, event, chn, p1, p2, w14) { \ _SEQ_NEEDBUF(8);\ _seqbuf[_seqbufptr] = EV_CHN_COMMON;\ _seqbuf[_seqbufptr+1] = (dev);\ _seqbuf[_seqbufptr+2] = (event);\ _seqbuf[_seqbufptr+3] = (chn);\ _seqbuf[_seqbufptr+4] = (p1);\ _seqbuf[_seqbufptr+5] = (p2);\ *(short *)&_seqbuf[_seqbufptr+6] = (w14);\ _SEQ_ADVBUF(8);} /* * SEQ_SYSEX permits sending of sysex messages. (It may look that it permits * sending any MIDI bytes but it's absolutely not possible. Trying to do * so _will_ cause problems with MPU401 intelligent mode). * * Sysex messages are sent in blocks of 1 to 6 bytes. Longer messages must be * sent by calling SEQ_SYSEX() several times (there must be no other events * between them). First sysex fragment must have 0xf0 in the first byte * and the last byte (buf[len-1] of the last fragment must be 0xf7. No byte * between these sysex start and end markers cannot be larger than 0x7f. Also * lengths of each fragments (except the last one) must be 6. * * Breaking the above rules may work with some MIDI ports but is likely to * cause fatal problems with some other devices (such as MPU401). */ #define SEQ_SYSEX(dev, buf, len) { \ int i, l=(len); if (l>6)l=6;\ _SEQ_NEEDBUF(8);\ _seqbuf[_seqbufptr] = EV_SYSEX;\ for(i=0;i struct spigen_transfer { struct iovec st_command; /* master to slave */ struct iovec st_data; /* slave to master and/or master to slave */ }; struct spigen_transfer_mmapped { size_t stm_command_length; /* at offset 0 in mmap(2) area */ size_t stm_data_length; /* at offset stm_command_length */ }; #define SPIGENIOC_BASE 'S' #define SPIGENIOC_TRANSFER _IOW(SPIGENIOC_BASE, 0, \ struct spigen_transfer) #define SPIGENIOC_TRANSFER_MMAPPED _IOW(SPIGENIOC_BASE, 1, \ struct spigen_transfer_mmapped) #define SPIGENIOC_GET_CLOCK_SPEED _IOR(SPIGENIOC_BASE, 2, uint32_t) #define SPIGENIOC_SET_CLOCK_SPEED _IOW(SPIGENIOC_BASE, 3, uint32_t) #endif /* !_SYS_SPIGENIO_H_ */ Index: head/sys/sys/tiio.h =================================================================== --- head/sys/sys/tiio.h (revision 326822) +++ head/sys/sys/tiio.h (revision 326823) @@ -1,335 +1,335 @@ /*- - * SPDX-License-Identifier: BSD-4-Clause AND BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: (BSD-2-Clause-FreeBSD AND BSD-4-Clause) * * Copyright (c) 1999, 2000 Kenneth D. Merry. * 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, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$ */ /* * The ti_stats structure below is from code with the following copyright, * and originally comes from the Alteon firmware documentation. */ /* * Copyright (c) 1997, 1998, 1999 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD * 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. * * from: if_tireg.h,v 1.8 1999/07/23 18:46:24 wpaul Exp $ */ #ifndef _SYS_TIIO_H_ #define _SYS_TIIO_H_ #include /* * Tigon statistics counters. */ struct ti_stats { /* * MAC stats, taken from RFC 1643, ethernet-like MIB */ volatile u_int32_t dot3StatsAlignmentErrors; /* 0 */ volatile u_int32_t dot3StatsFCSErrors; /* 1 */ volatile u_int32_t dot3StatsSingleCollisionFrames; /* 2 */ volatile u_int32_t dot3StatsMultipleCollisionFrames; /* 3 */ volatile u_int32_t dot3StatsSQETestErrors; /* 4 */ volatile u_int32_t dot3StatsDeferredTransmissions; /* 5 */ volatile u_int32_t dot3StatsLateCollisions; /* 6 */ volatile u_int32_t dot3StatsExcessiveCollisions; /* 7 */ volatile u_int32_t dot3StatsInternalMacTransmitErrors; /* 8 */ volatile u_int32_t dot3StatsCarrierSenseErrors; /* 9 */ volatile u_int32_t dot3StatsFrameTooLongs; /* 10 */ volatile u_int32_t dot3StatsInternalMacReceiveErrors; /* 11 */ /* * interface stats, taken from RFC 1213, MIB-II, interfaces group */ volatile u_int32_t ifIndex; /* 12 */ volatile u_int32_t ifType; /* 13 */ volatile u_int32_t ifMtu; /* 14 */ volatile u_int32_t ifSpeed; /* 15 */ volatile u_int32_t ifAdminStatus; /* 16 */ #define IF_ADMIN_STATUS_UP 1 #define IF_ADMIN_STATUS_DOWN 2 #define IF_ADMIN_STATUS_TESTING 3 volatile u_int32_t ifOperStatus; /* 17 */ #define IF_OPER_STATUS_UP 1 #define IF_OPER_STATUS_DOWN 2 #define IF_OPER_STATUS_TESTING 3 #define IF_OPER_STATUS_UNKNOWN 4 #define IF_OPER_STATUS_DORMANT 5 volatile u_int32_t ifLastChange; /* 18 */ volatile u_int32_t ifInDiscards; /* 19 */ volatile u_int32_t ifInErrors; /* 20 */ volatile u_int32_t ifInUnknownProtos; /* 21 */ volatile u_int32_t ifOutDiscards; /* 22 */ volatile u_int32_t ifOutErrors; /* 23 */ volatile u_int32_t ifOutQLen; /* deprecated */ /* 24 */ volatile u_int8_t ifPhysAddress[8]; /* 8 bytes */ /* 25 - 26 */ volatile u_int8_t ifDescr[32]; /* 27 - 34 */ u_int32_t alignIt; /* align to 64 bit for u_int64_ts following */ /* * more interface stats, taken from RFC 1573, MIB-IIupdate, * interfaces group */ volatile u_int64_t ifHCInOctets; /* 36 - 37 */ volatile u_int64_t ifHCInUcastPkts; /* 38 - 39 */ volatile u_int64_t ifHCInMulticastPkts; /* 40 - 41 */ volatile u_int64_t ifHCInBroadcastPkts; /* 42 - 43 */ volatile u_int64_t ifHCOutOctets; /* 44 - 45 */ volatile u_int64_t ifHCOutUcastPkts; /* 46 - 47 */ volatile u_int64_t ifHCOutMulticastPkts; /* 48 - 49 */ volatile u_int64_t ifHCOutBroadcastPkts; /* 50 - 51 */ volatile u_int32_t ifLinkUpDownTrapEnable; /* 52 */ volatile u_int32_t ifHighSpeed; /* 53 */ volatile u_int32_t ifPromiscuousMode; /* 54 */ volatile u_int32_t ifConnectorPresent; /* follow link state 55 */ /* * Host Commands */ volatile u_int32_t nicCmdsHostState; /* 56 */ volatile u_int32_t nicCmdsFDRFiltering; /* 57 */ volatile u_int32_t nicCmdsSetRecvProdIndex; /* 58 */ volatile u_int32_t nicCmdsUpdateGencommStats; /* 59 */ volatile u_int32_t nicCmdsResetJumboRing; /* 60 */ volatile u_int32_t nicCmdsAddMCastAddr; /* 61 */ volatile u_int32_t nicCmdsDelMCastAddr; /* 62 */ volatile u_int32_t nicCmdsSetPromiscMode; /* 63 */ volatile u_int32_t nicCmdsLinkNegotiate; /* 64 */ volatile u_int32_t nicCmdsSetMACAddr; /* 65 */ volatile u_int32_t nicCmdsClearProfile; /* 66 */ volatile u_int32_t nicCmdsSetMulticastMode; /* 67 */ volatile u_int32_t nicCmdsClearStats; /* 68 */ volatile u_int32_t nicCmdsSetRecvJumboProdIndex; /* 69 */ volatile u_int32_t nicCmdsSetRecvMiniProdIndex; /* 70 */ volatile u_int32_t nicCmdsRefreshStats; /* 71 */ volatile u_int32_t nicCmdsUnknown; /* 72 */ /* * NIC Events */ volatile u_int32_t nicEventsNICFirmwareOperational; /* 73 */ volatile u_int32_t nicEventsStatsUpdated; /* 74 */ volatile u_int32_t nicEventsLinkStateChanged; /* 75 */ volatile u_int32_t nicEventsError; /* 76 */ volatile u_int32_t nicEventsMCastListUpdated; /* 77 */ volatile u_int32_t nicEventsResetJumboRing; /* 78 */ /* * Ring manipulation */ volatile u_int32_t nicRingSetSendProdIndex; /* 79 */ volatile u_int32_t nicRingSetSendConsIndex; /* 80 */ volatile u_int32_t nicRingSetRecvReturnProdIndex; /* 81 */ /* * Interrupts */ volatile u_int32_t nicInterrupts; /* 82 */ volatile u_int32_t nicAvoidedInterrupts; /* 83 */ /* * BD Coalessing Thresholds */ volatile u_int32_t nicEventThresholdHit; /* 84 */ volatile u_int32_t nicSendThresholdHit; /* 85 */ volatile u_int32_t nicRecvThresholdHit; /* 86 */ /* * DMA Attentions */ volatile u_int32_t nicDmaRdOverrun; /* 87 */ volatile u_int32_t nicDmaRdUnderrun; /* 88 */ volatile u_int32_t nicDmaWrOverrun; /* 89 */ volatile u_int32_t nicDmaWrUnderrun; /* 90 */ volatile u_int32_t nicDmaWrMasterAborts; /* 91 */ volatile u_int32_t nicDmaRdMasterAborts; /* 92 */ /* * NIC Resources */ volatile u_int32_t nicDmaWriteRingFull; /* 93 */ volatile u_int32_t nicDmaReadRingFull; /* 94 */ volatile u_int32_t nicEventRingFull; /* 95 */ volatile u_int32_t nicEventProducerRingFull; /* 96 */ volatile u_int32_t nicTxMacDescrRingFull; /* 97 */ volatile u_int32_t nicOutOfTxBufSpaceFrameRetry; /* 98 */ volatile u_int32_t nicNoMoreWrDMADescriptors; /* 99 */ volatile u_int32_t nicNoMoreRxBDs; /* 100 */ volatile u_int32_t nicNoSpaceInReturnRing; /* 101 */ volatile u_int32_t nicSendBDs; /* current count 102 */ volatile u_int32_t nicRecvBDs; /* current count 103 */ volatile u_int32_t nicJumboRecvBDs; /* current count 104 */ volatile u_int32_t nicMiniRecvBDs; /* current count 105 */ volatile u_int32_t nicTotalRecvBDs; /* current count 106 */ volatile u_int32_t nicTotalSendBDs; /* current count 107 */ volatile u_int32_t nicJumboSpillOver; /* 108 */ volatile u_int32_t nicSbusHangCleared; /* 109 */ volatile u_int32_t nicEnqEventDelayed; /* 110 */ /* * Stats from MAC rx completion */ volatile u_int32_t nicMacRxLateColls; /* 111 */ volatile u_int32_t nicMacRxLinkLostDuringPkt; /* 112 */ volatile u_int32_t nicMacRxPhyDecodeErr; /* 113 */ volatile u_int32_t nicMacRxMacAbort; /* 114 */ volatile u_int32_t nicMacRxTruncNoResources; /* 115 */ /* * Stats from the mac_stats area */ volatile u_int32_t nicMacRxDropUla; /* 116 */ volatile u_int32_t nicMacRxDropMcast; /* 117 */ volatile u_int32_t nicMacRxFlowControl; /* 118 */ volatile u_int32_t nicMacRxDropSpace; /* 119 */ volatile u_int32_t nicMacRxColls; /* 120 */ /* * MAC RX Attentions */ volatile u_int32_t nicMacRxTotalAttns; /* 121 */ volatile u_int32_t nicMacRxLinkAttns; /* 122 */ volatile u_int32_t nicMacRxSyncAttns; /* 123 */ volatile u_int32_t nicMacRxConfigAttns; /* 124 */ volatile u_int32_t nicMacReset; /* 125 */ volatile u_int32_t nicMacRxBufDescrAttns; /* 126 */ volatile u_int32_t nicMacRxBufAttns; /* 127 */ volatile u_int32_t nicMacRxZeroFrameCleanup; /* 128 */ volatile u_int32_t nicMacRxOneFrameCleanup; /* 129 */ volatile u_int32_t nicMacRxMultipleFrameCleanup; /* 130 */ volatile u_int32_t nicMacRxTimerCleanup; /* 131 */ volatile u_int32_t nicMacRxDmaCleanup; /* 132 */ /* * Stats from the mac_stats area */ volatile u_int32_t nicMacTxCollisionHistogram[15]; /* 133 */ /* * MAC TX Attentions */ volatile u_int32_t nicMacTxTotalAttns; /* 134 */ /* * NIC Profile */ volatile u_int32_t nicProfile[32]; /* 135 */ /* * Pat to 1024 bytes. */ u_int32_t pad[75]; }; struct tg_reg { u_int32_t data; u_int32_t addr; }; struct tg_mem { u_int32_t tgAddr; caddr_t userAddr; int len; }; typedef enum { TI_PARAM_NONE = 0x00, TI_PARAM_STAT_TICKS = 0x01, TI_PARAM_RX_COAL_TICKS = 0x02, TI_PARAM_TX_COAL_TICKS = 0x04, TI_PARAM_RX_COAL_BDS = 0x08, TI_PARAM_TX_COAL_BDS = 0x10, TI_PARAM_TX_BUF_RATIO = 0x20, TI_PARAM_ALL = 0x2f } ti_param_mask; struct ti_params { u_int32_t ti_stat_ticks; u_int32_t ti_rx_coal_ticks; u_int32_t ti_tx_coal_ticks; u_int32_t ti_rx_max_coal_bds; u_int32_t ti_tx_max_coal_bds; u_int32_t ti_tx_buf_ratio; ti_param_mask param_mask; }; typedef enum { TI_TRACE_TYPE_NONE = 0x00000000, TI_TRACE_TYPE_SEND = 0x00000001, TI_TRACE_TYPE_RECV = 0x00000002, TI_TRACE_TYPE_DMA = 0x00000004, TI_TRACE_TYPE_EVENT = 0x00000008, TI_TRACE_TYPE_COMMAND = 0x00000010, TI_TRACE_TYPE_MAC = 0x00000020, TI_TRACE_TYPE_STATS = 0x00000040, TI_TRACE_TYPE_TIMER = 0x00000080, TI_TRACE_TYPE_DISP = 0x00000100, TI_TRACE_TYPE_MAILBOX = 0x00000200, TI_TRACE_TYPE_RECV_BD = 0x00000400, TI_TRACE_TYPE_LNK_PHY = 0x00000800, TI_TRACE_TYPE_LNK_NEG = 0x00001000, TI_TRACE_LEVEL_1 = 0x10000000, TI_TRACE_LEVEL_2 = 0x20000000 } ti_trace_type; struct ti_trace_buf { u_long *buf; int buf_len; int fill_len; u_long cur_trace_ptr; }; #define TIIOCGETSTATS _IOR('T', 1, struct ti_stats) #define TIIOCGETPARAMS _IOR('T', 2, struct ti_params) #define TIIOCSETPARAMS _IOW('T', 3, struct ti_params) #define TIIOCSETTRACE _IOW('T', 11, ti_trace_type) #define TIIOCGETTRACE _IOWR('T', 12, struct ti_trace_buf) /* * Taken from Alteon's altioctl.h. Alteon's ioctl numbers 1-6 aren't * used by the FreeBSD driver. */ #define ALT_ATTACH _IO('a', 7) #define ALT_READ_TG_MEM _IOWR('a', 10, struct tg_mem) #define ALT_WRITE_TG_MEM _IOWR('a', 11, struct tg_mem) #define ALT_READ_TG_REG _IOWR('a', 12, struct tg_reg) #define ALT_WRITE_TG_REG _IOWR('a', 13, struct tg_reg) #endif /* _SYS_TIIO_H_ */ Index: head/sys/sys/timetc.h =================================================================== --- head/sys/sys/timetc.h (revision 326822) +++ head/sys/sys/timetc.h (revision 326823) @@ -1,97 +1,99 @@ /*- + * SPDX-License-Identifier: Beerware + * * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * * $FreeBSD$ */ #ifndef _SYS_TIMETC_H_ #define _SYS_TIMETC_H_ #ifndef _KERNEL #error "no user-serviceable parts inside" #endif /*- * `struct timecounter' is the interface between the hardware which implements * a timecounter and the MI code which uses this to keep track of time. * * A timecounter is a binary counter which has two properties: * * it runs at a fixed, known frequency. * * it has sufficient bits to not roll over in less than approximately * max(2 msec, 2/HZ seconds). (The value 2 here is really 1 + delta, * for some indeterminate value of delta.) */ struct timecounter; struct vdso_timehands; struct vdso_timehands32; typedef u_int timecounter_get_t(struct timecounter *); typedef void timecounter_pps_t(struct timecounter *); typedef uint32_t timecounter_fill_vdso_timehands_t(struct vdso_timehands *, struct timecounter *); typedef uint32_t timecounter_fill_vdso_timehands32_t(struct vdso_timehands32 *, struct timecounter *); struct timecounter { timecounter_get_t *tc_get_timecount; /* * This function reads the counter. It is not required to * mask any unimplemented bits out, as long as they are * constant. */ timecounter_pps_t *tc_poll_pps; /* * This function is optional. It will be called whenever the * timecounter is rewound, and is intended to check for PPS * events. Normal hardware does not need it but timecounters * which latch PPS in hardware (like sys/pci/xrpu.c) do. */ u_int tc_counter_mask; /* This mask should mask off any unimplemented bits. */ uint64_t tc_frequency; /* Frequency of the counter in Hz. */ const char *tc_name; /* Name of the timecounter. */ int tc_quality; /* * Used to determine if this timecounter is better than * another timecounter higher means better. Negative * means "only use at explicit request". */ u_int tc_flags; #define TC_FLAGS_C2STOP 1 /* Timer dies in C2+. */ #define TC_FLAGS_SUSPEND_SAFE 2 /* * Timer functional across * suspend/resume. */ void *tc_priv; /* Pointer to the timecounter's private parts. */ struct timecounter *tc_next; /* Pointer to the next timecounter. */ timecounter_fill_vdso_timehands_t *tc_fill_vdso_timehands; timecounter_fill_vdso_timehands32_t *tc_fill_vdso_timehands32; }; extern struct timecounter *timecounter; extern int tc_min_ticktock_freq; /* * Minimal tc_ticktock() call frequency, * required to handle counter wraps. */ u_int64_t tc_getfrequency(void); void tc_init(struct timecounter *tc); void tc_setclock(struct timespec *ts); void tc_ticktock(int cnt); void cpu_tick_calibration(void); #ifdef SYSCTL_DECL SYSCTL_DECL(_kern_timecounter); #endif #endif /* !_SYS_TIMETC_H_ */ Index: head/sys/sys/zlib.h =================================================================== --- head/sys/sys/zlib.h (revision 326822) +++ head/sys/sys/zlib.h (revision 326823) @@ -1,1018 +1,1020 @@ /* $FreeBSD$ */ /* * This file is derived from zlib.h and zconf.h from the zlib-1.0.4 * distribution by Jean-loup Gailly and Mark Adler, with some additions * by Paul Mackerras to aid in implementing Deflate compression and * decompression for PPP packets. */ /* * ==FILEVERSION 971127== * * This marker is used by the Linux installation script to determine * whether an up-to-date version of this file is already installed. */ /* +++ zlib.h */ /*- + SPDX-License-Identifier: BSD-3-Clause + zlib.h -- interface of the 'zlib' general purpose compression library version 1.0.4, Jul 24th, 1996. Copyright (C) 1995-1996 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler gzip@prep.ai.mit.edu madler@alumni.caltech.edu */ /* The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). */ #ifndef _ZLIB_H #define _ZLIB_H #ifdef __cplusplus extern "C" { #endif /* +++ zconf.h */ /* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-1996 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* From: zconf.h,v 1.20 1996/07/02 15:09:28 me Exp $ */ #ifndef _ZCONF_H #define _ZCONF_H /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. */ #ifdef Z_PREFIX # define deflateInit_ z_deflateInit_ # define deflate z_deflate # define deflateEnd z_deflateEnd # define inflateInit_ z_inflateInit_ # define inflate z_inflate # define inflateEnd z_inflateEnd # define deflateInit2_ z_deflateInit2_ # define deflateSetDictionary z_deflateSetDictionary # define deflateCopy z_deflateCopy # define deflateReset z_deflateReset # define deflateParams z_deflateParams # define inflateInit2_ z_inflateInit2_ # define inflateSetDictionary z_inflateSetDictionary # define inflateSync z_inflateSync # define inflateReset z_inflateReset # define compress z_compress # define uncompress z_uncompress # define adler32 z_adler32 #if 0 # define crc32 z_crc32 # define get_crc_table z_get_crc_table #endif # define Byte z_Byte # define uInt z_uInt # define uLong z_uLong # define Bytef z_Bytef # define charf z_charf # define intf z_intf # define uIntf z_uIntf # define uLongf z_uLongf # define voidpf z_voidpf # define voidp z_voidp #endif #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) # define WIN32 #endif #if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(__i386__) # ifndef __32BIT__ # define __32BIT__ # endif #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #if defined(MSDOS) && !defined(__32BIT__) # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) # define STDC #endif #if (defined(__STDC__) || defined(__cplusplus)) && !defined(STDC) # define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const # endif #endif /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) # define NO_DUMMY_DECL #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2 */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): 1 << (windowBits+2) + 1 << (memLevel+9) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus a few kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR __far # else # define FAR far # endif #endif #if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) # ifndef __32BIT__ # define SMALL_MEDIUM # define FAR __far # endif #endif #ifndef FAR # define FAR #endif typedef unsigned char Byte; /* 8 bits */ typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #if defined(__BORLANDC__) && defined(SMALL_MEDIUM) /* Borland C/C++ ignores FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte FAR *voidpf; typedef Byte *voidp; #endif /* Compile with -DZLIB_DLL for Windows DLL support */ #if (defined(_WINDOWS) || defined(WINDOWS)) && defined(ZLIB_DLL) # include # define EXPORT WINAPI #else # define EXPORT #endif #endif /* _ZCONF_H */ /* --- zconf.h */ #define ZLIB_VERSION "1.0.4P" /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms may be added later and will have the same stream interface. For compression the application must provide the output buffer and may optionally provide the input buffer for optimization. For decompression, the application must provide the input buffer and may optionally provide the output buffer for optimization. Compression can be done in a single step if the buffers are large enough (for example if an input file is mmap'ed), or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. The library does not install any signal handler. It is recommended to add at least a handler for SIGSEGV when decompressing; the library checks the consistency of the input data whenever possible but may go nuts for some forms of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total nb of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total nb of bytes output so far */ const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: ascii or binary */ uLong adler; /* adler32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The opaque value provided by the application will be passed as the first parameter for calls of zalloc and zfree. This can be useful for custom memory management. The compression library attaches no meaning to the opaque value. zalloc must return Z_NULL if there is not enough memory for the object. On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers returned by zalloc for objects of exactly 65536 bytes *must* have their offset normalized to zero. The default allocation function provided by this library ensures this (see zutil.c). To reduce memory requirements and avoid any allocation of 64K objects, at the expense of compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use in the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 #define Z_PACKET_FLUSH 2 #define Z_SYNC_FLUSH 3 #define Z_FULL_FLUSH 4 #define Z_FINISH 5 /* Allowed flush values; see deflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative * values are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_ASCII 1 #define Z_UNKNOWN 2 /* Possible values of the data_type field */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ /* basic functions */ extern const char * EXPORT zlibVersion OF((void)); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* extern int EXPORT deflateInit OF((z_streamp strm, int level)); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level, Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ extern int EXPORT deflate OF((z_streamp strm, int flush)); /* Performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary (in interactive applications). Some output may be provided even if flush is not set. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression block is terminated and flushed to the output buffer so that the decompressor can get all input data available so far. For method 9, a future variant on method 8, the current block will be flushed but not terminated. Z_SYNC_FLUSH has the same effect as partial flush except that the compressed output is byte aligned (the compressor can clear its internal bit buffer) and the current block is always terminated; this can be useful if the compressor has to be restarted from scratch after an interruption (in which case the internal state of the compressor may be lost). If flush is set to Z_FULL_FLUSH, the compression block is terminated, a special marker is output and the compression dictionary is discarded; this is useful to allow the decompressor to synchronize if one compressed block has been damaged (see inflateSync below). Flushing degrades compression and so should be used only when necessary. Using Z_FULL_FLUSH too often can seriously degrade the compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). If the parameter flush is set to Z_PACKET_FLUSH, the compression block is terminated, and a zero-length stored block is output, omitting the length bytes (the effect of this is that the 3-bit type code 000 for a stored block is output, and the output is then byte-aligned). This is designed for use at the end of a PPP packet. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space; if deflate returns with Z_OK, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd. Z_FINISH can be used immediately after deflateInit if all the compression is to be done in a single step. In this case, avail_out must be at least 0.1% larger than avail_in plus 12 bytes. If deflate does not return Z_STREAM_END, then it must be called again as described above. deflate() may update data_type if it can make a good guess about the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible. */ extern int EXPORT deflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded). In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* extern int EXPORT inflateInit OF((z_streamp strm)); Initializes the internal stream state for decompression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, inflateInit updates them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller. msg is set to null if there is no error message. inflateInit does not perform any decompression: this will be done by inflate(). */ #if defined(__FreeBSD__) && defined(_KERNEL) #define inflate _zlib104_inflate /* FreeBSD already has an inflate :-( */ #endif extern int EXPORT inflate OF((z_streamp strm, int flush)); /* Performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in is updated and processing will resume at this point for the next call of inflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH, inflate flushes as much output as possible to the output buffer. The flushing behavior of inflate is not specified for values of the flush parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the current implementation actually flushes as much output as possible anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data has been consumed, it is expecting to see the length field of a stored block; if not, it returns Z_DATA_ERROR. inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all the uncompressed data. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The next operation on this stream must be inflateEnd to deallocate the decompression state. The use of Z_FINISH is never required, but can be used to inform inflate that a faster routine may be used for the single inflate() call. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point (see inflateSetDictionary below), Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if the stream structure was inconsistent (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no progress is possible or if there was not enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then call inflateSync to look for a good compression block. In the Z_NEED_DICT case, strm->adler is set to the Adler32 value of the dictionary chosen by the compressor. */ extern int EXPORT inflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent. In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* Advanced functions */ /* The following functions are needed only in some special applications. */ /* extern int EXPORT deflateInit2 OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy)); This is another version of deflateInit with more compression options. The fields next_in, zalloc, zfree and opaque must be initialized before by the caller. The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. (Method 9 will allow a 64K history buffer and partial block flushes.) The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this version of the library (the value 16 will be allowed for method 9). Larger values of this parameter result in better compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory for optimal speed. The default value is 8. See zconf.h for total memory usage as a function of windowBits and memLevel. The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no string match). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of Z_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. If next_in is not null, the library will use this buffer to hold also some history information; the buffer must either hold the entire input data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in is null, the library will allocate its own history buffer (and leave next_in null). next_out need not be provided here but must be provided by the application for the next call of deflate(). If the history buffer is provided by the application, next_in must must never be changed by the application since the compressor maintains information inside this buffer from call to call; the application must provide more input only by increasing avail_in. next_in is always reset by the library in this case. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid method). msg is set to null if there is no error message. deflateInit2 does not perform any compression: this will be done by deflate(). */ extern int EXPORT deflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength)); /* Initializes the compression dictionary (history buffer) from the given byte sequence without producing any compressed output. This function must be called immediately after deflateInit or deflateInit2, before any call of deflate. The compressor and decompressor must use exactly the same dictionary (see inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. In this version of the library, only the last 32K bytes of the dictionary are used. Upon return of this function, strm->adler is set to the Adler32 value of the dictionary; the decompressor may later use this value to determine which dictionary has been used by the compressor. (The Adler32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (such as NULL dictionary) or the stream state is inconsistent (for example if deflate has already been called for this stream). deflateSetDictionary does not perform any compression: this will be done by deflate(). */ extern int EXPORT deflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. If the source stream is using an application-supplied history buffer, a new buffer is allocated for the destination stream. The compressed output buffer is always application-supplied. It's the responsibility of the application to provide the correct values of next_out and avail_out for the next call of deflate. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal compression state which can be quite large, so this strategy is slow and can consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being NULL). msg is left unchanged in both source and destination. */ extern int EXPORT deflateReset OF((z_streamp strm)); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate all the internal compression state. The stream will keep the same compression level and any other attributes that may have been set by deflateInit2. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being NULL). */ extern int EXPORT deflateParams OF((z_streamp strm, int level, int strategy)); /* Dynamically update the compression level and compression strategy. This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression level is changed, the input available so far is compressed with the old level (and may be flushed); the new level will take effect only at the next call of deflate(). Before the call of deflateParams, the stream state must be set as for a call of deflate(), since the currently available input may have to be compressed and flushed. In particular, strm->avail_out must be non-zero. deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if strm->avail_out was zero. */ extern int EXPORT deflateOutputPending OF((z_streamp strm)); /* Returns the number of bytes of output which are immediately available from the compressor (i.e. without any further input or flush). */ /* extern int EXPORT inflateInit2 OF((z_streamp strm, int windowBits)); This is another version of inflateInit with more compression options. The fields next_out, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for this version of the library (the value 16 will be allowed soon). The default value is 15 if inflateInit is used instead. If a compressed stream with a larger window size is given as input, inflate() will return with the error code Z_DATA_ERROR instead of trying to allocate a larger window. If next_out is not null, the library will use this buffer for the history buffer; the buffer must either be large enough to hold the entire output data, or have at least 1< #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "layer.h" #include "mbuf.h" #include "log.h" #include "id.h" #include "timer.h" #include "fsm.h" #include "defs.h" #include "iplist.h" #include "throughput.h" #include "slcompress.h" #include "lqr.h" #include "hdlc.h" #include "ncpaddr.h" #include "ipcp.h" #include "ipv6cp.h" #include "descriptor.h" #include "lcp.h" #include "ccp.h" #include "link.h" #include "mp.h" #include "ncp.h" #include "filter.h" #ifndef NORADIUS #include "radius.h" #endif #include "bundle.h" #include "iface.h" #include "arp.h" /* * SET_SA_FAMILY - set the sa_family field of a struct sockaddr, * if it exists. */ #define SET_SA_FAMILY(addr, family) \ memset((char *) &(addr), '\0', sizeof(addr)); \ addr.sa_family = (family); \ addr.sa_len = sizeof(addr); #if RTM_VERSION >= 3 /* * arp_SetProxy - Make a proxy ARP entry for the peer. */ static struct { struct rt_msghdr hdr; struct sockaddr_in dst; struct sockaddr_dl hwa; char extra[128]; } arpmsg; static int arp_ProxySub(struct bundle *bundle, struct in_addr addr, int add) { int routes; /* * Get the hardware address of an interface on the same subnet as our local * address. */ memset(&arpmsg, 0, sizeof arpmsg); if (!arp_EtherAddr(addr, &arpmsg.hwa, 0)) { log_Printf(LogWARN, "%s: Cannot determine ethernet address for proxy ARP\n", inet_ntoa(addr)); return 0; } routes = ID0socket(PF_ROUTE, SOCK_RAW, AF_INET); if (routes < 0) { log_Printf(LogERROR, "arp_SetProxy: opening routing socket: %s\n", strerror(errno)); return 0; } arpmsg.hdr.rtm_type = add ? RTM_ADD : RTM_DELETE; arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC | RTF_LLDATA; arpmsg.hdr.rtm_version = RTM_VERSION; arpmsg.hdr.rtm_seq = ++bundle->routing_seq; arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; arpmsg.hdr.rtm_inits = RTV_EXPIRE; arpmsg.dst.sin_len = sizeof(struct sockaddr_in); arpmsg.dst.sin_family = AF_INET; arpmsg.dst.sin_addr.s_addr = addr.s_addr; arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg + arpmsg.hwa.sdl_len; if (ID0write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0 && !(!add && errno == ESRCH)) { log_Printf(LogERROR, "%s proxy arp entry %s: %s\n", add ? "Add" : "Delete", inet_ntoa(addr), strerror(errno)); close(routes); return 0; } close(routes); return 1; } int arp_SetProxy(struct bundle *bundle, struct in_addr addr) { return (arp_ProxySub(bundle, addr, 1)); } /* * arp_ClearProxy - Delete the proxy ARP entry for the peer. */ int arp_ClearProxy(struct bundle *bundle, struct in_addr addr) { return (arp_ProxySub(bundle, addr, 0)); } #else /* RTM_VERSION */ /* * arp_SetProxy - Make a proxy ARP entry for the peer. */ int arp_SetProxy(struct bundle *bundle, struct in_addr addr, int s) { struct arpreq arpreq; struct { struct sockaddr_dl sdl; char space[128]; } dls; memset(&arpreq, '\0', sizeof arpreq); /* * Get the hardware address of an interface on the same subnet as our local * address. */ if (!arp_EtherAddr(addr, &dls.sdl, 1)) { log_Printf(LOG_PHASE_BIT, "Cannot determine ethernet address for " "proxy ARP\n"); return 0; } arpreq.arp_ha.sa_len = sizeof(struct sockaddr); arpreq.arp_ha.sa_family = AF_UNSPEC; memcpy(arpreq.arp_ha.sa_data, LLADDR(&dls.sdl), dls.sdl.sdl_alen); SET_SA_FAMILY(arpreq.arp_pa, AF_INET); ((struct sockaddr_in *)&arpreq.arp_pa)->sin_addr.s_addr = addr.s_addr; arpreq.arp_flags = ATF_PERM | ATF_PUBL; if (ID0ioctl(s, SIOCSARP, (caddr_t) & arpreq) < 0) { log_Printf(LogERROR, "arp_SetProxy: ioctl(SIOCSARP): %s\n", strerror(errno)); return 0; } return 1; } /* * arp_ClearProxy - Delete the proxy ARP entry for the peer. */ int arp_ClearProxy(struct bundle *bundle, struct in_addr addr, int s) { struct arpreq arpreq; memset(&arpreq, '\0', sizeof arpreq); SET_SA_FAMILY(arpreq.arp_pa, AF_INET); ((struct sockaddr_in *)&arpreq.arp_pa)->sin_addr.s_addr = addr.s_addr; if (ID0ioctl(s, SIOCDARP, (caddr_t) & arpreq) < 0) { log_Printf(LogERROR, "arp_ClearProxy: ioctl(SIOCDARP): %s\n", strerror(errno)); return 0; } return 1; } #endif /* RTM_VERSION */ /* * arp_EtherAddr - get the hardware address of an interface on the * the same subnet as ipaddr. */ int arp_EtherAddr(struct in_addr ipaddr, struct sockaddr_dl *hwaddr, int verbose) { int mib[6], skip; size_t needed; char *buf, *ptr, *end; struct if_msghdr *ifm; struct ifa_msghdr *ifam; struct sockaddr_dl *dl; struct sockaddr *sa[RTAX_MAX]; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = 0; mib[4] = NET_RT_IFLIST; mib[5] = 0; if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { log_Printf(LogERROR, "arp_EtherAddr: sysctl: estimate: %s\n", strerror(errno)); return 0; } if ((buf = malloc(needed)) == NULL) return 0; if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { free(buf); return 0; } end = buf + needed; ptr = buf; while (ptr < end) { ifm = (struct if_msghdr *)ptr; /* On if_msghdr */ if (ifm->ifm_type != RTM_IFINFO) break; dl = (struct sockaddr_dl *)(ifm + 1); /* Single _dl at end */ skip = (ifm->ifm_flags & (IFF_UP | IFF_BROADCAST | IFF_POINTOPOINT | IFF_NOARP | IFF_LOOPBACK)) != (IFF_UP | IFF_BROADCAST); ptr += ifm->ifm_msglen; /* First ifa_msghdr */ while (ptr < end) { ifam = (struct ifa_msghdr *)ptr; /* Next ifa_msghdr (alias) */ if (ifam->ifam_type != RTM_NEWADDR) /* finished ? */ break; ptr += ifam->ifam_msglen; if (skip || (ifam->ifam_addrs & (RTA_NETMASK|RTA_IFA)) != (RTA_NETMASK|RTA_IFA)) continue; /* Found a candidate. Do the addresses match ? */ if (log_IsKept(LogDEBUG) && ptr == (char *)ifm + ifm->ifm_msglen + ifam->ifam_msglen) log_Printf(LogDEBUG, "%.*s interface is a candidate for proxy\n", dl->sdl_nlen, dl->sdl_data); iface_ParseHdr(ifam, sa); if (sa[RTAX_IFA]->sa_family == AF_INET) { struct sockaddr_in *ifa, *netmask; ifa = (struct sockaddr_in *)sa[RTAX_IFA]; netmask = (struct sockaddr_in *)sa[RTAX_NETMASK]; if (log_IsKept(LogDEBUG)) { char a[16]; strncpy(a, inet_ntoa(netmask->sin_addr), sizeof a - 1); a[sizeof a - 1] = '\0'; log_Printf(LogDEBUG, "Check addr %s, mask %s\n", inet_ntoa(ifa->sin_addr), a); } if ((ifa->sin_addr.s_addr & netmask->sin_addr.s_addr) == (ipaddr.s_addr & netmask->sin_addr.s_addr)) { log_Printf(verbose ? LogPHASE : LogDEBUG, "Found interface %.*s for %s\n", dl->sdl_nlen, dl->sdl_data, inet_ntoa(ipaddr)); memcpy(hwaddr, dl, dl->sdl_len); free(buf); return 1; } } } } free(buf); return 0; } Index: head/usr.sbin/rarpd/rarpd.c =================================================================== --- head/usr.sbin/rarpd/rarpd.c (revision 326822) +++ head/usr.sbin/rarpd/rarpd.c (revision 326823) @@ -1,1007 +1,1007 @@ /*- - * SPDX-License-Identifier: 0BSD + * SPDX-License-Identifier: BSD-1-Clause * * Copyright (c) 1990, 1991, 1992, 1993, 1996 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if 0 #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1990, 1991, 1992, 1993, 1996\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); /* * rarpd - Reverse ARP Daemon * * Usage: rarpd -a [-dfsv] [-t directory] [-P pidfile] [hostname] * rarpd [-dfsv] [-t directory] [-P pidfile] interface [hostname] * * 'hostname' is optional solely for backwards compatibility with Sun's rarpd. * Currently, the argument is ignored. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Cast a struct sockaddr to a struct sockaddr_in */ #define SATOSIN(sa) ((struct sockaddr_in *)(sa)) #ifndef TFTP_DIR #define TFTP_DIR "/tftpboot" #endif #define ARPSECS (20 * 60) /* as per code in netinet/if_ether.c */ #define REVARP_REQUEST ARPOP_REVREQUEST #define REVARP_REPLY ARPOP_REVREPLY /* * The structure for each interface. */ struct if_info { struct if_info *ii_next; int ii_fd; /* BPF file descriptor */ in_addr_t ii_ipaddr; /* IP address */ in_addr_t ii_netmask; /* subnet or net mask */ u_char ii_eaddr[ETHER_ADDR_LEN]; /* ethernet address */ char ii_ifname[IF_NAMESIZE]; }; /* * The list of all interfaces that are being listened to. rarp_loop() * "selects" on the descriptors in this list. */ static struct if_info *iflist; static int verbose; /* verbose messages */ static const char *tftp_dir = TFTP_DIR; /* tftp directory */ static int dflag; /* messages to stdout/stderr, not syslog(3) */ static int sflag; /* ignore /tftpboot */ static u_char zero[6]; static char pidfile_buf[PATH_MAX]; static char *pidfile; #define RARPD_PIDFILE "/var/run/rarpd.%s.pid" static struct pidfh *pidfile_fh; static int bpf_open(void); static in_addr_t choose_ipaddr(in_addr_t **, in_addr_t, in_addr_t); static char *eatoa(u_char *); static int expand_syslog_m(const char *fmt, char **newfmt); static void init(char *); static void init_one(struct ifaddrs *, char *, int); static char *intoa(in_addr_t); static in_addr_t ipaddrtonetmask(in_addr_t); static void logmsg(int, const char *, ...) __printflike(2, 3); static int rarp_bootable(in_addr_t); static int rarp_check(u_char *, u_int); static void rarp_loop(void); static int rarp_open(char *); static void rarp_process(struct if_info *, u_char *, u_int); static void rarp_reply(struct if_info *, struct ether_header *, in_addr_t, u_int); static void update_arptab(u_char *, in_addr_t); static void usage(void); int main(int argc, char *argv[]) { int op; char *ifname, *name; int aflag = 0; /* listen on "all" interfaces */ int fflag = 0; /* don't fork */ if ((name = strrchr(argv[0], '/')) != NULL) ++name; else name = argv[0]; if (*name == '-') ++name; /* * All error reporting is done through syslog, unless -d is specified */ openlog(name, LOG_PID | LOG_CONS, LOG_DAEMON); opterr = 0; while ((op = getopt(argc, argv, "adfsP:t:v")) != -1) switch (op) { case 'a': ++aflag; break; case 'd': ++dflag; break; case 'f': ++fflag; break; case 's': ++sflag; break; case 'P': strncpy(pidfile_buf, optarg, sizeof(pidfile_buf) - 1); pidfile_buf[sizeof(pidfile_buf) - 1] = '\0'; pidfile = pidfile_buf; break; case 't': tftp_dir = optarg; break; case 'v': ++verbose; break; default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; ifname = (aflag == 0) ? argv[0] : NULL; if ((aflag && ifname) || (!aflag && ifname == NULL)) usage(); init(ifname); if (!fflag) { if (pidfile == NULL && ifname != NULL && aflag == 0) { snprintf(pidfile_buf, sizeof(pidfile_buf) - 1, RARPD_PIDFILE, ifname); pidfile_buf[sizeof(pidfile_buf) - 1] = '\0'; pidfile = pidfile_buf; } /* If pidfile == NULL, /var/run/.pid will be used. */ pidfile_fh = pidfile_open(pidfile, 0600, NULL); if (pidfile_fh == NULL) logmsg(LOG_ERR, "Cannot open or create pidfile: %s", (pidfile == NULL) ? "/var/run/rarpd.pid" : pidfile); if (daemon(0,0)) { logmsg(LOG_ERR, "cannot fork"); pidfile_remove(pidfile_fh); exit(1); } pidfile_write(pidfile_fh); } rarp_loop(); return(0); } /* * Add to the interface list. */ static void init_one(struct ifaddrs *ifa, char *target, int pass1) { struct if_info *ii, *ii2; struct sockaddr_dl *ll; int family; family = ifa->ifa_addr->sa_family; switch (family) { case AF_INET: if (pass1) /* Consider only AF_LINK during pass1. */ return; /* FALLTHROUGH */ case AF_LINK: if (!(ifa->ifa_flags & IFF_UP) || (ifa->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) return; break; default: return; } /* Don't bother going any further if not the target interface */ if (target != NULL && strcmp(ifa->ifa_name, target) != 0) return; /* Look for interface in list */ for (ii = iflist; ii != NULL; ii = ii->ii_next) if (strcmp(ifa->ifa_name, ii->ii_ifname) == 0) break; if (pass1 && ii != NULL) /* We've already seen that interface once. */ return; /* Allocate a new one if not found */ if (ii == NULL) { ii = (struct if_info *)malloc(sizeof(*ii)); if (ii == NULL) { logmsg(LOG_ERR, "malloc: %m"); pidfile_remove(pidfile_fh); exit(1); } bzero(ii, sizeof(*ii)); ii->ii_fd = -1; strlcpy(ii->ii_ifname, ifa->ifa_name, sizeof(ii->ii_ifname)); ii->ii_next = iflist; iflist = ii; } else if (!pass1 && ii->ii_ipaddr != 0) { /* * Second AF_INET definition for that interface: clone * the existing one, and work on that cloned one. * This must be another IP address for this interface, * so avoid killing the previous configuration. */ ii2 = (struct if_info *)malloc(sizeof(*ii2)); if (ii2 == NULL) { logmsg(LOG_ERR, "malloc: %m"); pidfile_remove(pidfile_fh); exit(1); } memcpy(ii2, ii, sizeof(*ii2)); ii2->ii_fd = -1; ii2->ii_next = iflist; iflist = ii2; ii = ii2; } switch (family) { case AF_INET: ii->ii_ipaddr = SATOSIN(ifa->ifa_addr)->sin_addr.s_addr; ii->ii_netmask = SATOSIN(ifa->ifa_netmask)->sin_addr.s_addr; if (ii->ii_netmask == 0) ii->ii_netmask = ipaddrtonetmask(ii->ii_ipaddr); if (ii->ii_fd < 0) ii->ii_fd = rarp_open(ii->ii_ifname); break; case AF_LINK: ll = (struct sockaddr_dl *)ifa->ifa_addr; switch (ll->sdl_type) { case IFT_ETHER: case IFT_L2VLAN: bcopy(LLADDR(ll), ii->ii_eaddr, 6); } break; } } /* * Initialize all "candidate" interfaces that are in the system * configuration list. A "candidate" is up, not loopback and not * point to point. */ static void init(char *target) { struct if_info *ii, *nii, *lii; struct ifaddrs *ifhead, *ifa; int error; error = getifaddrs(&ifhead); if (error) { logmsg(LOG_ERR, "getifaddrs: %m"); pidfile_remove(pidfile_fh); exit(1); } /* * We make two passes over the list we have got. In the first * one, we only collect AF_LINK interfaces, and initialize our * list of interfaces from them. In the second pass, we * collect the actual IP addresses from the AF_INET * interfaces, and allow for the same interface name to appear * multiple times (in case of more than one IP address). */ for (ifa = ifhead; ifa != NULL; ifa = ifa->ifa_next) init_one(ifa, target, 1); for (ifa = ifhead; ifa != NULL; ifa = ifa->ifa_next) init_one(ifa, target, 0); freeifaddrs(ifhead); /* Throw away incomplete interfaces */ lii = NULL; for (ii = iflist; ii != NULL; ii = nii) { nii = ii->ii_next; if (ii->ii_ipaddr == 0 || bcmp(ii->ii_eaddr, zero, 6) == 0) { if (lii == NULL) iflist = nii; else lii->ii_next = nii; if (ii->ii_fd >= 0) close(ii->ii_fd); free(ii); continue; } lii = ii; } /* Verbose stuff */ if (verbose) for (ii = iflist; ii != NULL; ii = ii->ii_next) logmsg(LOG_DEBUG, "%s %s 0x%08x %s", ii->ii_ifname, intoa(ntohl(ii->ii_ipaddr)), (in_addr_t)ntohl(ii->ii_netmask), eatoa(ii->ii_eaddr)); } static void usage(void) { (void)fprintf(stderr, "%s\n%s\n", "usage: rarpd -a [-dfsv] [-t directory] [-P pidfile]", " rarpd [-dfsv] [-t directory] [-P pidfile] interface"); exit(1); } static int bpf_open(void) { int fd; int n = 0; char device[sizeof "/dev/bpf000"]; /* * Go through all the minors and find one that isn't in use. */ do { (void)sprintf(device, "/dev/bpf%d", n++); fd = open(device, O_RDWR); } while ((fd == -1) && (errno == EBUSY)); if (fd == -1) { logmsg(LOG_ERR, "%s: %m", device); pidfile_remove(pidfile_fh); exit(1); } return fd; } /* * Open a BPF file and attach it to the interface named 'device'. * Set immediate mode, and set a filter that accepts only RARP requests. */ static int rarp_open(char *device) { int fd; struct ifreq ifr; u_int dlt; int immediate; static struct bpf_insn insns[] = { BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 12), BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ETHERTYPE_REVARP, 0, 3), BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 20), BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, REVARP_REQUEST, 0, 1), BPF_STMT(BPF_RET|BPF_K, sizeof(struct ether_arp) + sizeof(struct ether_header)), BPF_STMT(BPF_RET|BPF_K, 0), }; static struct bpf_program filter = { sizeof insns / sizeof(insns[0]), insns }; fd = bpf_open(); /* * Set immediate mode so packets are processed as they arrive. */ immediate = 1; if (ioctl(fd, BIOCIMMEDIATE, &immediate) == -1) { logmsg(LOG_ERR, "BIOCIMMEDIATE: %m"); goto rarp_open_err; } strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) == -1) { logmsg(LOG_ERR, "BIOCSETIF: %m"); goto rarp_open_err; } /* * Check that the data link layer is an Ethernet; this code won't * work with anything else. */ if (ioctl(fd, BIOCGDLT, (caddr_t)&dlt) == -1) { logmsg(LOG_ERR, "BIOCGDLT: %m"); goto rarp_open_err; } if (dlt != DLT_EN10MB) { logmsg(LOG_ERR, "%s is not an ethernet", device); goto rarp_open_err; } /* * Set filter program. */ if (ioctl(fd, BIOCSETF, (caddr_t)&filter) == -1) { logmsg(LOG_ERR, "BIOCSETF: %m"); goto rarp_open_err; } return fd; rarp_open_err: pidfile_remove(pidfile_fh); exit(1); } /* * Perform various sanity checks on the RARP request packet. Return * false on failure and log the reason. */ static int rarp_check(u_char *p, u_int len) { struct ether_header *ep = (struct ether_header *)p; struct ether_arp *ap = (struct ether_arp *)(p + sizeof(*ep)); if (len < sizeof(*ep) + sizeof(*ap)) { logmsg(LOG_ERR, "truncated request, got %u, expected %lu", len, (u_long)(sizeof(*ep) + sizeof(*ap))); return 0; } /* * XXX This test might be better off broken out... */ if (ntohs(ep->ether_type) != ETHERTYPE_REVARP || ntohs(ap->arp_hrd) != ARPHRD_ETHER || ntohs(ap->arp_op) != REVARP_REQUEST || ntohs(ap->arp_pro) != ETHERTYPE_IP || ap->arp_hln != 6 || ap->arp_pln != 4) { logmsg(LOG_DEBUG, "request fails sanity check"); return 0; } if (bcmp((char *)&ep->ether_shost, (char *)&ap->arp_sha, 6) != 0) { logmsg(LOG_DEBUG, "ether/arp sender address mismatch"); return 0; } if (bcmp((char *)&ap->arp_sha, (char *)&ap->arp_tha, 6) != 0) { logmsg(LOG_DEBUG, "ether/arp target address mismatch"); return 0; } return 1; } /* * Loop indefinitely listening for RARP requests on the * interfaces in 'iflist'. */ static void rarp_loop(void) { u_char *buf, *bp, *ep; int cc, fd; fd_set fds, listeners; int bufsize, maxfd = 0; struct if_info *ii; if (iflist == NULL) { logmsg(LOG_ERR, "no interfaces"); goto rarpd_loop_err; } if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t)&bufsize) == -1) { logmsg(LOG_ERR, "BIOCGBLEN: %m"); goto rarpd_loop_err; } buf = malloc(bufsize); if (buf == NULL) { logmsg(LOG_ERR, "malloc: %m"); goto rarpd_loop_err; } while (1) { /* * Find the highest numbered file descriptor for select(). * Initialize the set of descriptors to listen to. */ FD_ZERO(&fds); for (ii = iflist; ii != NULL; ii = ii->ii_next) { FD_SET(ii->ii_fd, &fds); if (ii->ii_fd > maxfd) maxfd = ii->ii_fd; } listeners = fds; if (select(maxfd + 1, &listeners, NULL, NULL, NULL) == -1) { /* Don't choke when we get ptraced */ if (errno == EINTR) continue; logmsg(LOG_ERR, "select: %m"); goto rarpd_loop_err; } for (ii = iflist; ii != NULL; ii = ii->ii_next) { fd = ii->ii_fd; if (!FD_ISSET(fd, &listeners)) continue; again: cc = read(fd, (char *)buf, bufsize); /* Don't choke when we get ptraced */ if ((cc == -1) && (errno == EINTR)) goto again; /* Loop through the packet(s) */ #define bhp ((struct bpf_hdr *)bp) bp = buf; ep = bp + cc; while (bp < ep) { u_int caplen, hdrlen; caplen = bhp->bh_caplen; hdrlen = bhp->bh_hdrlen; if (rarp_check(bp + hdrlen, caplen)) rarp_process(ii, bp + hdrlen, caplen); bp += BPF_WORDALIGN(hdrlen + caplen); } } } #undef bhp return; rarpd_loop_err: pidfile_remove(pidfile_fh); exit(1); } /* * True if this server can boot the host whose IP address is 'addr'. * This check is made by looking in the tftp directory for the * configuration file. */ static int rarp_bootable(in_addr_t addr) { struct dirent *dent; DIR *d; char ipname[9]; static DIR *dd = NULL; (void)sprintf(ipname, "%08X", (in_addr_t)ntohl(addr)); /* * If directory is already open, rewind it. Otherwise, open it. */ if ((d = dd) != NULL) rewinddir(d); else { if (chdir(tftp_dir) == -1) { logmsg(LOG_ERR, "chdir: %s: %m", tftp_dir); goto rarp_bootable_err; } d = opendir("."); if (d == NULL) { logmsg(LOG_ERR, "opendir: %m"); goto rarp_bootable_err; } dd = d; } while ((dent = readdir(d)) != NULL) if (strncmp(dent->d_name, ipname, 8) == 0) return 1; return 0; rarp_bootable_err: pidfile_remove(pidfile_fh); exit(1); } /* * Given a list of IP addresses, 'alist', return the first address that * is on network 'net'; 'netmask' is a mask indicating the network portion * of the address. */ static in_addr_t choose_ipaddr(in_addr_t **alist, in_addr_t net, in_addr_t netmask) { for (; *alist; ++alist) if ((**alist & netmask) == net) return **alist; return 0; } /* * Answer the RARP request in 'pkt', on the interface 'ii'. 'pkt' has * already been checked for validity. The reply is overlaid on the request. */ static void rarp_process(struct if_info *ii, u_char *pkt, u_int len) { struct ether_header *ep; struct hostent *hp; in_addr_t target_ipaddr; char ename[256]; ep = (struct ether_header *)pkt; /* should this be arp_tha? */ if (ether_ntohost(ename, (struct ether_addr *)&ep->ether_shost) != 0) { logmsg(LOG_ERR, "cannot map %s to name", eatoa(ep->ether_shost)); return; } if ((hp = gethostbyname(ename)) == NULL) { logmsg(LOG_ERR, "cannot map %s to IP address", ename); return; } /* * Choose correct address from list. */ if (hp->h_addrtype != AF_INET) { logmsg(LOG_ERR, "cannot handle non IP addresses for %s", ename); return; } target_ipaddr = choose_ipaddr((in_addr_t **)hp->h_addr_list, ii->ii_ipaddr & ii->ii_netmask, ii->ii_netmask); if (target_ipaddr == 0) { logmsg(LOG_ERR, "cannot find %s on net %s", ename, intoa(ntohl(ii->ii_ipaddr & ii->ii_netmask))); return; } if (sflag || rarp_bootable(target_ipaddr)) rarp_reply(ii, ep, target_ipaddr, len); else if (verbose > 1) logmsg(LOG_INFO, "%s %s at %s DENIED (not bootable)", ii->ii_ifname, eatoa(ep->ether_shost), intoa(ntohl(target_ipaddr))); } /* * Poke the kernel arp tables with the ethernet/ip address combinataion * given. When processing a reply, we must do this so that the booting * host (i.e. the guy running rarpd), won't try to ARP for the hardware * address of the guy being booted (he cannot answer the ARP). */ static struct sockaddr_in sin_inarp = { sizeof(struct sockaddr_in), AF_INET, 0, {0}, {0}, }; static struct sockaddr_dl sin_dl = { sizeof(struct sockaddr_dl), AF_LINK, 0, IFT_ETHER, 0, 6, 0, "" }; static struct { struct rt_msghdr rthdr; char rtspace[512]; } rtmsg; static void update_arptab(u_char *ep, in_addr_t ipaddr) { struct timespec tp; int cc; struct sockaddr_in *ar, *ar2; struct sockaddr_dl *ll, *ll2; struct rt_msghdr *rt; int xtype, xindex; static pid_t pid; int r; static int seq; r = socket(PF_ROUTE, SOCK_RAW, 0); if (r == -1) { logmsg(LOG_ERR, "raw route socket: %m"); pidfile_remove(pidfile_fh); exit(1); } pid = getpid(); ar = &sin_inarp; ar->sin_addr.s_addr = ipaddr; ll = &sin_dl; bcopy(ep, LLADDR(ll), 6); /* Get the type and interface index */ rt = &rtmsg.rthdr; bzero(&rtmsg, sizeof(rtmsg)); rt->rtm_version = RTM_VERSION; rt->rtm_addrs = RTA_DST; rt->rtm_type = RTM_GET; rt->rtm_seq = ++seq; ar2 = (struct sockaddr_in *)rtmsg.rtspace; bcopy(ar, ar2, sizeof(*ar)); rt->rtm_msglen = sizeof(*rt) + sizeof(*ar); errno = 0; if ((write(r, rt, rt->rtm_msglen) == -1) && (errno != ESRCH)) { logmsg(LOG_ERR, "rtmsg get write: %m"); close(r); return; } do { cc = read(r, rt, sizeof(rtmsg)); } while (cc > 0 && (rt->rtm_type != RTM_GET || rt->rtm_seq != seq || rt->rtm_pid != pid)); if (cc == -1) { logmsg(LOG_ERR, "rtmsg get read: %m"); close(r); return; } ll2 = (struct sockaddr_dl *)((u_char *)ar2 + ar2->sin_len); if (ll2->sdl_family != AF_LINK) { /* * XXX I think this means the ip address is not on a * directly connected network (the family is AF_INET in * this case). */ logmsg(LOG_ERR, "bogus link family (%d) wrong net for %08X?\n", ll2->sdl_family, ipaddr); close(r); return; } xtype = ll2->sdl_type; xindex = ll2->sdl_index; /* Set the new arp entry */ bzero(rt, sizeof(rtmsg)); rt->rtm_version = RTM_VERSION; rt->rtm_addrs = RTA_DST | RTA_GATEWAY; rt->rtm_inits = RTV_EXPIRE; clock_gettime(CLOCK_MONOTONIC, &tp); rt->rtm_rmx.rmx_expire = tp.tv_sec + ARPSECS; rt->rtm_flags = RTF_HOST | RTF_STATIC; rt->rtm_type = RTM_ADD; rt->rtm_seq = ++seq; bcopy(ar, ar2, sizeof(*ar)); ll2 = (struct sockaddr_dl *)((u_char *)ar2 + sizeof(*ar2)); bcopy(ll, ll2, sizeof(*ll)); ll2->sdl_type = xtype; ll2->sdl_index = xindex; rt->rtm_msglen = sizeof(*rt) + sizeof(*ar2) + sizeof(*ll2); errno = 0; if ((write(r, rt, rt->rtm_msglen) == -1) && (errno != EEXIST)) { logmsg(LOG_ERR, "rtmsg add write: %m"); close(r); return; } do { cc = read(r, rt, sizeof(rtmsg)); } while (cc > 0 && (rt->rtm_type != RTM_ADD || rt->rtm_seq != seq || rt->rtm_pid != pid)); close(r); if (cc == -1) { logmsg(LOG_ERR, "rtmsg add read: %m"); return; } } /* * Build a reverse ARP packet and sent it out on the interface. * 'ep' points to a valid REVARP_REQUEST. The REVARP_REPLY is built * on top of the request, then written to the network. * * RFC 903 defines the ether_arp fields as follows. The following comments * are taken (more or less) straight from this document. * * REVARP_REQUEST * * arp_sha is the hardware address of the sender of the packet. * arp_spa is undefined. * arp_tha is the 'target' hardware address. * In the case where the sender wishes to determine his own * protocol address, this, like arp_sha, will be the hardware * address of the sender. * arp_tpa is undefined. * * REVARP_REPLY * * arp_sha is the hardware address of the responder (the sender of the * reply packet). * arp_spa is the protocol address of the responder (see the note below). * arp_tha is the hardware address of the target, and should be the same as * that which was given in the request. * arp_tpa is the protocol address of the target, that is, the desired address. * * Note that the requirement that arp_spa be filled in with the responder's * protocol is purely for convenience. For instance, if a system were to use * both ARP and RARP, then the inclusion of the valid protocol-hardware * address pair (arp_spa, arp_sha) may eliminate the need for a subsequent * ARP request. */ static void rarp_reply(struct if_info *ii, struct ether_header *ep, in_addr_t ipaddr, u_int len) { u_int n; struct ether_arp *ap = (struct ether_arp *)(ep + 1); update_arptab((u_char *)&ap->arp_sha, ipaddr); /* * Build the rarp reply by modifying the rarp request in place. */ ap->arp_op = htons(REVARP_REPLY); #ifdef BROKEN_BPF ep->ether_type = ETHERTYPE_REVARP; #endif bcopy((char *)&ap->arp_sha, (char *)&ep->ether_dhost, 6); bcopy((char *)ii->ii_eaddr, (char *)&ep->ether_shost, 6); bcopy((char *)ii->ii_eaddr, (char *)&ap->arp_sha, 6); bcopy((char *)&ipaddr, (char *)ap->arp_tpa, 4); /* Target hardware is unchanged. */ bcopy((char *)&ii->ii_ipaddr, (char *)ap->arp_spa, 4); /* Zero possible garbage after packet. */ bzero((char *)ep + (sizeof(*ep) + sizeof(*ap)), len - (sizeof(*ep) + sizeof(*ap))); n = write(ii->ii_fd, (char *)ep, len); if (n != len) logmsg(LOG_ERR, "write: only %d of %d bytes written", n, len); if (verbose) logmsg(LOG_INFO, "%s %s at %s REPLIED", ii->ii_ifname, eatoa(ap->arp_tha), intoa(ntohl(ipaddr))); } /* * Get the netmask of an IP address. This routine is used if * SIOCGIFNETMASK doesn't work. */ static in_addr_t ipaddrtonetmask(in_addr_t addr) { addr = ntohl(addr); if (IN_CLASSA(addr)) return htonl(IN_CLASSA_NET); if (IN_CLASSB(addr)) return htonl(IN_CLASSB_NET); if (IN_CLASSC(addr)) return htonl(IN_CLASSC_NET); logmsg(LOG_DEBUG, "unknown IP address class: %08X", addr); return htonl(0xffffffff); } /* * A faster replacement for inet_ntoa(). */ static char * intoa(in_addr_t addr) { char *cp; u_int byte; int n; static char buf[sizeof(".xxx.xxx.xxx.xxx")]; cp = &buf[sizeof buf]; *--cp = '\0'; n = 4; do { byte = addr & 0xff; *--cp = byte % 10 + '0'; byte /= 10; if (byte > 0) { *--cp = byte % 10 + '0'; byte /= 10; if (byte > 0) *--cp = byte + '0'; } *--cp = '.'; addr >>= 8; } while (--n > 0); return cp + 1; } static char * eatoa(u_char *ea) { static char buf[sizeof("xx:xx:xx:xx:xx:xx")]; (void)sprintf(buf, "%x:%x:%x:%x:%x:%x", ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]); return (buf); } static void logmsg(int pri, const char *fmt, ...) { va_list v; FILE *fp; char *newfmt; va_start(v, fmt); if (dflag) { if (pri == LOG_ERR) fp = stderr; else fp = stdout; if (expand_syslog_m(fmt, &newfmt) == -1) { vfprintf(fp, fmt, v); } else { vfprintf(fp, newfmt, v); free(newfmt); } fputs("\n", fp); fflush(fp); } else { vsyslog(pri, fmt, v); } va_end(v); } static int expand_syslog_m(const char *fmt, char **newfmt) { const char *str, *m; char *p, *np; p = strdup(""); str = fmt; while ((m = strstr(str, "%m")) != NULL) { asprintf(&np, "%s%.*s%s", p, (int)(m - str), str, strerror(errno)); free(p); if (np == NULL) { errno = ENOMEM; return (-1); } p = np; str = m + 2; } if (*str != '\0') { asprintf(&np, "%s%s", p, str); free(p); if (np == NULL) { errno = ENOMEM; return (-1); } p = np; } *newfmt = p; return (0); } Index: head/usr.sbin/watch/watch.c =================================================================== --- head/usr.sbin/watch/watch.c (revision 326822) +++ head/usr.sbin/watch/watch.c (revision 326823) @@ -1,443 +1,443 @@ /*- - * SPDX-License-Identifier: 0BSD + * SPDX-License-Identifier: BSD-1-Clause * * Copyright (c) 1995 Ugen J.S.Antsilevich * * Redistribution and use in source forms, with and without modification, * are permitted provided that this entire comment appears intact. * * Redistribution in binary form may occur without any restrictions. * Obviously, it would be nice if you gave credit where credit is due * but requiring it would be too onerous. * * This software is provided ``AS IS'' without any warranties of any kind. * * Snoop stuff. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MSG_INIT "Snoop started." #define MSG_OFLOW "Snoop stopped due to overflow. Reconnecting." #define MSG_CLOSED "Snoop stopped due to tty close. Reconnecting." #define MSG_CHANGE "Snoop device change by user request." #define MSG_NOWRITE "Snoop device change due to write failure." #define DEV_NAME_LEN 1024 /* for /dev/ttyXX++ */ #define MIN_SIZE 256 #define CHR_SWITCH 24 /* Ctrl+X */ #define CHR_CLEAR 23 /* Ctrl+V */ static void clear(void); static void timestamp(const char *); static void set_tty(void); static void unset_tty(void); static void fatal(int, const char *); static int open_snp(void); static void cleanup(int); static void usage(void) __dead2; static void setup_scr(void); static void attach_snp(void); static void detach_snp(void); static void set_dev(const char *); static void ask_dev(char *, const char *); int opt_reconn_close = 0; int opt_reconn_oflow = 0; int opt_interactive = 1; int opt_timestamp = 0; int opt_write = 0; int opt_no_switch = 0; const char *opt_snpdev; char dev_name[DEV_NAME_LEN]; int snp_io; int std_in = 0, std_out = 1; int clear_ok = 0; struct termios otty; char tbuf[1024], gbuf[1024]; static void clear(void) { if (clear_ok) tputs(gbuf, 1, putchar); fflush(stdout); } static void timestamp(const char *buf) { time_t t; char btmp[1024]; clear(); printf("\n---------------------------------------------\n"); t = time(NULL); strftime(btmp, 1024, "Time: %d %b %H:%M", localtime(&t)); printf("%s\n", btmp); printf("%s\n", buf); printf("---------------------------------------------\n"); fflush(stdout); } static void set_tty(void) { struct termios ntty; ntty = otty; ntty.c_lflag &= ~ICANON; /* disable canonical operation */ ntty.c_lflag &= ~ECHO; #ifdef FLUSHO ntty.c_lflag &= ~FLUSHO; #endif #ifdef PENDIN ntty.c_lflag &= ~PENDIN; #endif #ifdef IEXTEN ntty.c_lflag &= ~IEXTEN; #endif ntty.c_cc[VMIN] = 1; /* minimum of one character */ ntty.c_cc[VTIME] = 0; /* timeout value */ ntty.c_cc[VINTR] = 07; /* ^G */ ntty.c_cc[VQUIT] = 07; /* ^G */ tcsetattr(std_in, TCSANOW, &ntty); } static void unset_tty(void) { tcsetattr(std_in, TCSANOW, &otty); } static void fatal(int error, const char *buf) { unset_tty(); if (buf) errx(error, "fatal: %s", buf); else exit(error); } static int open_snp(void) { int f, mode; if (opt_write) mode = O_RDWR; else mode = O_RDONLY; if (opt_snpdev == NULL) f = open(_PATH_DEV "snp", mode); else f = open(opt_snpdev, mode); if (f == -1) fatal(EX_OSFILE, "cannot open snoop device"); return (f); } static void cleanup(int signo __unused) { if (opt_timestamp) timestamp("Logging Exited."); close(snp_io); unset_tty(); exit(EX_OK); } static void usage(void) { fprintf(stderr, "usage: watch [-ciotnW] [tty name]\n"); exit(EX_USAGE); } static void setup_scr(void) { char *cbuf = gbuf, *term; if (!opt_interactive) return; if ((term = getenv("TERM"))) if (tgetent(tbuf, term) == 1) if (tgetstr("cl", &cbuf)) clear_ok = 1; set_tty(); clear(); } static void detach_snp(void) { int fd; fd = -1; ioctl(snp_io, SNPSTTY, &fd); } static void attach_snp(void) { int snp_tty; snp_tty = open(dev_name, O_RDONLY | O_NONBLOCK); if (snp_tty < 0) fatal(EX_DATAERR, "can't open device"); if (ioctl(snp_io, SNPSTTY, &snp_tty) != 0) fatal(EX_UNAVAILABLE, "cannot attach to tty"); close(snp_tty); if (opt_timestamp) timestamp("Logging Started."); } static void set_dev(const char *name) { char buf[DEV_NAME_LEN]; struct stat sb; if (strlen(name) > 5 && !strncmp(name, _PATH_DEV, sizeof _PATH_DEV - 1)) { snprintf(buf, sizeof buf, "%s", name); } else { if (strlen(name) == 2) sprintf(buf, "%s%s", _PATH_TTY, name); else sprintf(buf, "%s%s", _PATH_DEV, name); } if (*name == '\0' || stat(buf, &sb) < 0) fatal(EX_DATAERR, "bad device name"); if ((sb.st_mode & S_IFMT) != S_IFCHR) fatal(EX_DATAERR, "must be a character device"); strlcpy(dev_name, buf, sizeof(dev_name)); attach_snp(); } void ask_dev(char *dbuf, const char *msg) { char buf[DEV_NAME_LEN]; int len; clear(); unset_tty(); if (msg) printf("%s\n", msg); if (dbuf) printf("Enter device name [%s]:", dbuf); else printf("Enter device name:"); if (fgets(buf, DEV_NAME_LEN - 1, stdin)) { len = strlen(buf); if (buf[len - 1] == '\n') buf[len - 1] = '\0'; if (buf[0] != '\0' && buf[0] != ' ') strcpy(dbuf, buf); } set_tty(); } #define READB_LEN 5 int main(int ac, char *av[]) { int ch, res, rv, nread; size_t b_size = MIN_SIZE; char *buf, chb[READB_LEN]; fd_set fd_s; (void) setlocale(LC_TIME, ""); if (isatty(std_out)) opt_interactive = 1; else opt_interactive = 0; while ((ch = getopt(ac, av, "Wciotnf:")) != -1) switch (ch) { case 'W': opt_write = 1; break; case 'c': opt_reconn_close = 1; break; case 'i': opt_interactive = 1; break; case 'o': opt_reconn_oflow = 1; break; case 't': opt_timestamp = 1; break; case 'n': opt_no_switch = 1; break; case 'f': opt_snpdev = optarg; break; case '?': default: usage(); } tcgetattr(std_in, &otty); if (modfind("snp") == -1) if (kldload("snp") == -1 || modfind("snp") == -1) warn("snp module not available"); signal(SIGINT, cleanup); snp_io = open_snp(); setup_scr(); if (*(av += optind) == NULL) { if (opt_interactive && !opt_no_switch) ask_dev(dev_name, MSG_INIT); else fatal(EX_DATAERR, "no device name given"); } else strlcpy(dev_name, *av, sizeof(dev_name)); set_dev(dev_name); if (!(buf = (char *) malloc(b_size))) fatal(EX_UNAVAILABLE, "malloc failed"); FD_ZERO(&fd_s); for (;;) { if (opt_interactive) FD_SET(std_in, &fd_s); FD_SET(snp_io, &fd_s); res = select(snp_io + 1, &fd_s, NULL, NULL, NULL); if (opt_interactive && FD_ISSET(std_in, &fd_s)) { if ((res = ioctl(std_in, FIONREAD, &nread)) != 0) fatal(EX_OSERR, "ioctl(FIONREAD)"); if (nread > READB_LEN) nread = READB_LEN; rv = read(std_in, chb, nread); if (rv == -1 || rv != nread) fatal(EX_IOERR, "read (stdin) failed"); switch (chb[0]) { case CHR_CLEAR: clear(); break; case CHR_SWITCH: if (!opt_no_switch) { detach_snp(); ask_dev(dev_name, MSG_CHANGE); set_dev(dev_name); break; } default: if (opt_write) { rv = write(snp_io, chb, nread); if (rv == -1 || rv != nread) { detach_snp(); if (opt_no_switch) fatal(EX_IOERR, "write failed"); ask_dev(dev_name, MSG_NOWRITE); set_dev(dev_name); } } } } if (!FD_ISSET(snp_io, &fd_s)) continue; if ((res = ioctl(snp_io, FIONREAD, &nread)) != 0) fatal(EX_OSERR, "ioctl(FIONREAD)"); switch (nread) { case SNP_OFLOW: if (opt_reconn_oflow) attach_snp(); else if (opt_interactive && !opt_no_switch) { ask_dev(dev_name, MSG_OFLOW); set_dev(dev_name); } else cleanup(-1); break; case SNP_DETACH: case SNP_TTYCLOSE: if (opt_reconn_close) attach_snp(); else if (opt_interactive && !opt_no_switch) { ask_dev(dev_name, MSG_CLOSED); set_dev(dev_name); } else cleanup(-1); break; default: if (nread < (b_size / 2) && (b_size / 2) > MIN_SIZE) { free(buf); if (!(buf = (char *) malloc(b_size / 2))) fatal(EX_UNAVAILABLE, "malloc failed"); b_size = b_size / 2; } if (nread > b_size) { b_size = (nread % 2) ? (nread + 1) : (nread); free(buf); if (!(buf = (char *) malloc(b_size))) fatal(EX_UNAVAILABLE, "malloc failed"); } rv = read(snp_io, buf, nread); if (rv == -1 || rv != nread) fatal(EX_IOERR, "read failed"); rv = write(std_out, buf, nread); if (rv == -1 || rv != nread) fatal(EX_IOERR, "write failed"); } } /* While */ return(0); }