diff options
230 files changed, 10136 insertions, 11438 deletions
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 9e2baf525f22..6db60ca13866 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -36,6 +36,11 @@ # xargs -n1 | sort | uniq -d; # done +# 20200729: remove long expired serial drivers +OLD_FILES+=usr/share/man/man4/cy.4.gz +OLD_FILES+=usr/share/man/man4/rc.4.gz +OLD_FILES+=usr/share/man/man4/rp.4.gz + # 20200715: rework of devstat(9) man page OLD_FILES+=usr/share/man/man9/devstat_add_entry.9.gz @@ -10,6 +10,10 @@ newline. Entries should be separated by a newline. Changes to this file should not be MFCed. +r363679: + Applications using regex(3), e.g. sed/grep, will no longer accept + redundant escapes for most ordinary characters. + r363253: SCTP support has been removed from GENERIC kernel configurations. The SCTP stack is now built as sctp.ko and can be dynamically loaded. @@ -26,6 +26,18 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW: disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20200729: + r363679 has redefined some undefined behavior in regcomp(3); notably, + extraneous escapes of most ordinary characters will no longer be + accepted. An exp-run has identified all of the problems with this in + ports, but other non-ports software may need extra escapes removed to + continue to function. + + Because of this change, installworld may encounter the following error + from rtld: Undefined symbol "regcomp@FBSD_1.6" -- It is imperative that + you do not halt installworld. Instead, let it run to completion (whether + successful or not) and run installworld once more. + 20200627: A new implementation of bc and dc has been imorted in r362681. This implementation corrects non-conformant behavior of the previous bc diff --git a/bin/ps/ps.c b/bin/ps/ps.c index f6d32e5411fe..d3cfc669d581 100644 --- a/bin/ps/ps.c +++ b/bin/ps/ps.c @@ -1264,6 +1264,7 @@ fmt(char **(*fn)(kvm_t *, const struct kinfo_proc *, int), KINFO *ki, static void saveuser(KINFO *ki) { + char tdname[COMMLEN + 1]; char *argsp; if (ki->ki_p->ki_flag & P_INMEM) { @@ -1280,12 +1281,14 @@ saveuser(KINFO *ki) * save arguments if needed */ if (needcomm) { - if (ki->ki_p->ki_stat == SZOMB) + if (ki->ki_p->ki_stat == SZOMB) { ki->ki_args = strdup("<defunct>"); - else if (UREADOK(ki) || (ki->ki_p->ki_args != NULL)) + } else if (UREADOK(ki) || (ki->ki_p->ki_args != NULL)) { + (void)snprintf(tdname, sizeof(tdname), "%s%s", + ki->ki_p->ki_tdname, ki->ki_p->ki_moretdname); ki->ki_args = fmt(kvm_getargv, ki, - ki->ki_p->ki_comm, ki->ki_p->ki_tdname, MAXCOMLEN); - else { + ki->ki_p->ki_comm, tdname, COMMLEN * 2 + 1); + } else { asprintf(&argsp, "(%s)", ki->ki_p->ki_comm); ki->ki_args = argsp; } diff --git a/bin/sh/main.c b/bin/sh/main.c index 4d0aae96215f..8df24dba312e 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -228,6 +228,10 @@ cmdloop(int top) } } popstackmark(&smark); + if (top && iflag) { + out2c('\n'); + flushout(out2); + } } diff --git a/cddl/lib/Makefile b/cddl/lib/Makefile index 69a0e381dfec..b65983dd64a7 100644 --- a/cddl/lib/Makefile +++ b/cddl/lib/Makefile @@ -2,10 +2,10 @@ .include <src.opts.mk> -SUBDIR= ${_drti} \ +SUBDIR= drti \ libavl \ libctf \ - ${_libdtrace} \ + libdtrace \ libnvpair \ libumem \ libuutil \ @@ -23,11 +23,6 @@ _libzpool= libzpool .endif .endif -.if ${MACHINE_CPUARCH} != "sparc64" -_drti= drti -_libdtrace= libdtrace -.endif - SUBDIR_DEPEND_libdtrace= libctf SUBDIR_DEPEND_libzfs_core= libnvpair SUBDIR_DEPEND_libzfs= libavl libnvpair libumem libuutil libzfs_core diff --git a/cddl/lib/libdtrace/Makefile b/cddl/lib/libdtrace/Makefile index bc58855ffc5d..11565b03b0ac 100644 --- a/cddl/lib/libdtrace/Makefile +++ b/cddl/lib/libdtrace/Makefile @@ -103,9 +103,6 @@ CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/powerpc CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/riscv .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/riscv .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/riscv -.elif ${MACHINE_CPUARCH} == "sparc64" -CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/sparc -.PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/sparc .else # temporary hack CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/intel diff --git a/cddl/lib/libzpool/Makefile b/cddl/lib/libzpool/Makefile index 1c545e0260d1..576b89b7725a 100644 --- a/cddl/lib/libzpool/Makefile +++ b/cddl/lib/libzpool/Makefile @@ -18,9 +18,7 @@ .if exists(${SRCTOP}/sys/cddl/contrib/opensolaris/common/atomic/${MACHINE_ARCH}/opensolaris_atomic.S) .PATH: ${SRCTOP}/sys/cddl/contrib/opensolaris/common/atomic/${MACHINE_ARCH} ATOMIC_SRCS= opensolaris_atomic.S -.if ${MACHINE_ARCH} != "sparc64" ACFLAGS+= -Wa,--noexecstack -.endif .else .PATH: ${SRCTOP}/sys/cddl/compat/opensolaris/kern ATOMIC_SRCS= opensolaris_atomic.c diff --git a/contrib/ipfilter/iplang/iplang_y.y b/contrib/ipfilter/iplang/iplang_y.y index 98c8f1a983ea..f223b1eb8b32 100644 --- a/contrib/ipfilter/iplang/iplang_y.y +++ b/contrib/ipfilter/iplang/iplang_y.y @@ -45,11 +45,6 @@ #include "ipf.h" #include "iplang.h" -#if !defined(__NetBSD__) && (!defined(__FreeBSD_version) && \ - __FreeBSD_version < 400020) && (!SOLARIS || SOLARIS2 < 10) -extern struct ether_addr *ether_aton __P((char *)); -#endif - extern int opts; extern struct ipopt_names ionames[]; extern int state, state, lineNum, token; @@ -58,11 +53,7 @@ extern char yytext[]; extern FILE *yyin; int yylex __P((void)); #define YYDEBUG 1 -#if !defined(ultrix) && !defined(hpux) int yydebug = 1; -#else -extern int yydebug; -#endif iface_t *iflist = NULL, **iftail = &iflist; iface_t *cifp = NULL; diff --git a/contrib/ipfilter/ipsend/arp.c b/contrib/ipfilter/ipsend/arp.c index 05f255ea47d2..31b70d3e8987 100644 --- a/contrib/ipfilter/ipsend/arp.c +++ b/contrib/ipfilter/ipsend/arp.c @@ -11,17 +11,13 @@ static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/types.h> #include <sys/socket.h> -#if !defined(ultrix) && !defined(hpux) && !defined(__hpux) && !defined(__osf__) && !defined(_AIX51) # include <sys/sockio.h> -#endif #include <sys/ioctl.h> #include <netinet/in_systm.h> #include <netinet/in.h> #include <net/if.h> #include <netinet/if_ether.h> -#ifndef ultrix # include <net/if_arp.h> -#endif #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_var.h> diff --git a/contrib/ipfilter/ipsend/ipresend.c b/contrib/ipfilter/ipsend/ipresend.c index ea0b4211c101..1e7b9049169a 100644 --- a/contrib/ipfilter/ipsend/ipresend.c +++ b/contrib/ipfilter/ipsend/ipresend.c @@ -38,15 +38,7 @@ int opts = 0; # ifdef sun char default_device[] = "le0"; # else -# ifdef ultrix -char default_device[] = "ln0"; -# else -# ifdef __bsdi__ -char default_device[] = "ef0"; -# else char default_device[] = "lan0"; -# endif -# endif # endif #else char default_device[] = DEFAULT_DEVICE; diff --git a/contrib/ipfilter/ipsend/ipsend.c b/contrib/ipfilter/ipsend/ipsend.c index 95a1bb1e5c78..b7617734f66e 100644 --- a/contrib/ipfilter/ipsend/ipsend.c +++ b/contrib/ipfilter/ipsend/ipsend.c @@ -33,15 +33,7 @@ extern void iplang __P((FILE *)); char options[68]; int opts; -# ifdef ultrix -char default_device[] = "ln0"; -# else -# ifdef __bsdi__ -char default_device[] = "ef0"; -# else char default_device[] = "le0"; -# endif /* __bsdi__ */ -# endif /* ultrix */ static void usage __P((char *)); diff --git a/contrib/ipfilter/ipsend/iptest.c b/contrib/ipfilter/ipsend/iptest.c index bc93106c8b89..ffabaf37b5bc 100644 --- a/contrib/ipfilter/ipsend/iptest.c +++ b/contrib/ipfilter/ipsend/iptest.c @@ -34,15 +34,7 @@ char options[68]; # ifdef sun char default_device[] = "le0"; # else -# ifdef ultrix -char default_device[] = "ln0"; -# else -# ifdef __bsdi__ -char default_device[] = "ef0"; -# else char default_device[] = "lan0"; -# endif -# endif # endif static void usage __P((char *)); diff --git a/contrib/ipfilter/ipsend/iptests.c b/contrib/ipfilter/ipsend/iptests.c index af8772cc2097..86b850d319bb 100644 --- a/contrib/ipfilter/ipsend/iptests.c +++ b/contrib/ipfilter/ipsend/iptests.c @@ -36,18 +36,13 @@ typedef int boolean_t; # endif # undef _KERNEL # undef KERNEL -#if !defined(solaris) && !defined(linux) && !defined(__sgi) +#if !defined(solaris) # include <nlist.h> # include <sys/user.h> # include <sys/proc.h> #endif -#if !defined(ultrix) && !defined(hpux) && !defined(linux) && \ - !defined(__sgi) && !defined(__osf__) && !defined(_AIX51) # include <kvm.h> -#endif -#ifndef ultrix # include <sys/socket.h> -#endif #if defined(solaris) # include <sys/stream.h> #else @@ -57,11 +52,9 @@ typedef int boolean_t; #include <sys/systm.h> #include <sys/session.h> #endif -#if BSD >= 199103 # include <sys/sysctl.h> # include <sys/filedesc.h> # include <paths.h> -#endif #include <netinet/in_systm.h> #include <sys/socket.h> #include <net/if.h> @@ -74,7 +67,7 @@ typedef int boolean_t; #include <netinet/in.h> #include <arpa/inet.h> #include <netinet/ip.h> -#if defined(__SVR4) || defined(__svr4__) || defined(__sgi) +#if defined(__SVR4) || defined(__svr4__) # include <sys/sysmacros.h> #endif #include <stdio.h> @@ -82,7 +75,7 @@ typedef int boolean_t; #include <stdlib.h> #include <string.h> # include <netinet/ip_var.h> -# if !defined(__hpux) && !defined(solaris) +# if !defined(solaris) # include <netinet/in_pcb.h> # endif #include "ipsend.h" diff --git a/contrib/ipfilter/ipsend/sock.c b/contrib/ipfilter/ipsend/sock.c index d7eae8a13196..66e1a0aa897e 100644 --- a/contrib/ipfilter/ipsend/sock.c +++ b/contrib/ipfilter/ipsend/sock.c @@ -21,14 +21,8 @@ static const char rcsid[] = "@(#)$Id$"; */ typedef int boolean_t; #endif -#ifndef ultrix #include <fcntl.h> -#endif -#if (__FreeBSD_version >= 300000) # include <sys/dirent.h> -#else -# include <sys/dir.h> -#endif # ifdef __NetBSD__ # include <machine/lock.h> # endif @@ -38,10 +32,6 @@ typedef int boolean_t; # define _KERNEL # define KERNEL # endif -# ifdef ultrix -# undef LOCORE -# include <sys/smp_lock.h> -# endif # include <sys/file.h> # ifdef __FreeBSD__ # undef _WANT_FILE @@ -54,18 +44,14 @@ typedef int boolean_t; #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/proc.h> -#if !defined(ultrix) && !defined(hpux) && !defined(__osf__) # include <kvm.h> -#endif #ifdef sun #include <sys/systm.h> #include <sys/session.h> #endif -#if BSD >= 199103 #include <sys/sysctl.h> #include <sys/filedesc.h> #include <paths.h> -#endif #include <math.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -143,128 +129,10 @@ int kmemcpy(buf, pos, n) struct nlist names[4] = { { "_proc" }, { "_nproc" }, -#ifdef ultrix - { "_u" }, -#else { NULL }, -#endif { NULL } }; -#if BSD < 199103 -static struct proc *getproc() -{ - struct proc *p; - pid_t pid = getpid(); - int siz, n; - - n = nlist(KERNEL, names); - if (n != 0) - { - fprintf(stderr, "nlist(%#x) == %d\n", names, n); - return NULL; - } - if (KMCPY(&nproc, names[1].n_value, sizeof(nproc)) == -1) - { - fprintf(stderr, "read nproc (%#x)\n", names[1].n_value); - return NULL; - } - siz = nproc * sizeof(struct proc); - if (KMCPY(&p, names[0].n_value, sizeof(p)) == -1) - { - fprintf(stderr, "read(%#x,%#x,%d) proc\n", - names[0].n_value, &p, sizeof(p)); - return NULL; - } - proc = (struct proc *)malloc(siz); - if (KMCPY(proc, p, siz) == -1) - { - fprintf(stderr, "read(%#x,%#x,%d) proc\n", - p, proc, siz); - return NULL; - } - - p = proc; - - for (n = nproc; n; n--, p++) - if (p->p_pid == pid) - break; - if (!n) - return NULL; - - return p; -} - - -struct tcpcb *find_tcp(fd, ti) - int fd; - struct tcpiphdr *ti; -{ - struct tcpcb *t; - struct inpcb *i; - struct socket *s; - struct user *up; - struct proc *p; - struct file *f, **o; - - if (!(p = getproc())) - return NULL; - up = (struct user *)malloc(sizeof(*up)); -#ifndef ultrix - if (KMCPY(up, p->p_uarea, sizeof(*up)) == -1) - { - fprintf(stderr, "read(%#x,%#x) failed\n", p, p->p_uarea); - return NULL; - } -#else - if (KMCPY(up, names[2].n_value, sizeof(*up)) == -1) - { - fprintf(stderr, "read(%#x,%#x) failed\n", p, names[2].n_value); - return NULL; - } -#endif - - o = (struct file **)calloc(up->u_lastfile + 1, sizeof(*o)); - if (KMCPY(o, up->u_ofile, (up->u_lastfile + 1) * sizeof(*o)) == -1) - { - fprintf(stderr, "read(%#x,%#x,%d) - u_ofile - failed\n", - up->u_ofile, o, sizeof(*o)); - return NULL; - } - f = (struct file *)calloc(1, sizeof(*f)); - if (KMCPY(f, o[fd], sizeof(*f)) == -1) - { - fprintf(stderr, "read(%#x,%#x,%d) - o[fd] - failed\n", - up->u_ofile[fd], f, sizeof(*f)); - return NULL; - } - - s = (struct socket *)calloc(1, sizeof(*s)); - if (KMCPY(s, f->f_data, sizeof(*s)) == -1) - { - fprintf(stderr, "read(%#x,%#x,%d) - f_data - failed\n", - o[fd], s, sizeof(*s)); - return NULL; - } - - i = (struct inpcb *)calloc(1, sizeof(*i)); - if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1) - { - fprintf(stderr, "kvm_read(%#x,%#x,%d) - so_pcb - failed\n", - s->so_pcb, i, sizeof(*i)); - return NULL; - } - - t = (struct tcpcb *)calloc(1, sizeof(*t)); - if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1) - { - fprintf(stderr, "read(%#x,%#x,%d) - inp_ppcb - failed\n", - i->inp_ppcb, t, sizeof(*t)); - return NULL; - } - return (struct tcpcb *)i->inp_ppcb; -} -#else static struct kinfo_proc *getproc() { static struct kinfo_proc kp; @@ -304,7 +172,7 @@ struct tcpcb *find_tcp(tfd, ti) fd = (struct filedesc *)malloc(sizeof(*fd)); if (fd == NULL) return NULL; -#if defined( __FreeBSD_version) && __FreeBSD_version >= 500013 +#if defined( __FreeBSD_version) if (KMCPY(fd, p->ki_fd, sizeof(*fd)) == -1) { fprintf(stderr, "read(%#lx,%#lx) failed\n", @@ -381,7 +249,6 @@ finderror: free(t); return NULL; } -#endif /* BSD < 199301 */ int do_socket(dev, mtu, ti, gwip) char *dev; diff --git a/contrib/netbsd-tests/lib/libc/regex/data/meta.in b/contrib/netbsd-tests/lib/libc/regex/data/meta.in index 4533d3591bc6..eb24075aea62 100644 --- a/contrib/netbsd-tests/lib/libc/regex/data/meta.in +++ b/contrib/netbsd-tests/lib/libc/regex/data/meta.in @@ -4,7 +4,9 @@ a[bc]d & abd abd a\*c & a*c a*c a\\b & a\b a\b a\\\*b & a\*b a\*b -a\bc & abc abc +# Begin FreeBSD +a\bc &C EESCAPE +# End FreeBSD a\ &C EESCAPE a\\bc & a\bc a\bc \{ bC BADRPT diff --git a/contrib/netbsd-tests/lib/libc/regex/data/subexp.in b/contrib/netbsd-tests/lib/libc/regex/data/subexp.in index d3efe2eab270..e3d376bb7cb3 100644 --- a/contrib/netbsd-tests/lib/libc/regex/data/subexp.in +++ b/contrib/netbsd-tests/lib/libc/regex/data/subexp.in @@ -12,7 +12,7 @@ a(b+)c - abbbc abbbc bbb a(b*)c - ac ac @c (a|ab)(bc([de]+)f|cde) - abcdef abcdef a,bcdef,de # Begin FreeBSD -a\(b\|c\)d b ab|cd ab|cd b|c +a\(b|c\)d b ab|cd ab|cd b|c # End FreeBSD # the regression tester only asks for 9 subexpressions a(b)(c)(d)(e)(f)(g)(h)(i)(j)k - abcdefghijk abcdefghijk b,c,d,e,f,g,h,i,j diff --git a/contrib/openbsm/CREDITS b/contrib/openbsm/CREDITS index 18b3ad7dc03f..2721de1e487d 100644 --- a/contrib/openbsm/CREDITS +++ b/contrib/openbsm/CREDITS @@ -36,6 +36,9 @@ the development of OpenBSM: Ryan Steinmetz The FreeBSD Foundation Brooks Davis + Mateusz Piotrowski + Alan Somers + Aniket Pandey In addition, Coverity, Inc.'s Prevent(tm) static analysis tool and Gimpel Software's FlexeLint tool were used to identify a number of bugs in the diff --git a/contrib/openbsm/bin/auditd/auditd.c b/contrib/openbsm/bin/auditd/auditd.c index a165cf314e08..bd00a6b16191 100644 --- a/contrib/openbsm/bin/auditd/auditd.c +++ b/contrib/openbsm/bin/auditd/auditd.c @@ -712,7 +712,7 @@ auditd_config_controls(void) */ err = auditd_set_qsize(); if (err) { - auditd_log_err("audit_set_qsize() %s: %m", + auditd_log_err("auditd_set_qsize() %s: %m", auditd_strerror(err)); ret = -1; } else diff --git a/contrib/openbsm/bin/auditdistd/auditdistd.c b/contrib/openbsm/bin/auditdistd/auditdistd.c index 696f0488b27a..8468353f4cbc 100644 --- a/contrib/openbsm/bin/auditdistd/auditdistd.c +++ b/contrib/openbsm/bin/auditdistd/auditdistd.c @@ -523,7 +523,7 @@ main_loop(void) } TAILQ_FOREACH(adhost, &adcfg->adc_hosts, adh_next) { if (adhost->adh_role == ADIST_ROLE_SENDER) { - /* Only sender workers asks for connections. */ + /* Only sender workers ask for connections. */ PJDLOG_ASSERT(adhost->adh_conn != NULL); fd = proto_descriptor(adhost->adh_conn); PJDLOG_ASSERT(fd >= 0); diff --git a/contrib/openbsm/bin/auditdistd/proto_tls.c b/contrib/openbsm/bin/auditdistd/proto_tls.c index ff251c5b0c81..31673084d5b5 100644 --- a/contrib/openbsm/bin/auditdistd/proto_tls.c +++ b/contrib/openbsm/bin/auditdistd/proto_tls.c @@ -413,7 +413,7 @@ tls_exec_client(const char *user, int startfd, const char *srcaddr, tls_certificate_verify(ssl, fingerprint); /* - * The following byte is send to make proto_connect_wait() to work. + * The following byte is sent to make proto_connect_wait() work. */ connected = 1; for (;;) { @@ -460,7 +460,7 @@ tls_call_exec_client(struct proto_conn *sock, const char *srcaddr, proto_close(sock); } else { /* - * The FD_CLOEXEC is cleared by dup2(2), so when we not + * The FD_CLOEXEC is cleared by dup2(2), so when we do not * call it, we have to clear it by hand in case it is set. */ if (fcntl(startfd, F_SETFD, 0) == -1) diff --git a/contrib/openbsm/libauditd/auditd_lib.c b/contrib/openbsm/libauditd/auditd_lib.c index 1e21adb39bb7..e6c1312bf49f 100644 --- a/contrib/openbsm/libauditd/auditd_lib.c +++ b/contrib/openbsm/libauditd/auditd_lib.c @@ -498,7 +498,7 @@ auditd_expire_trails(int (*warn_expired)(char *)) * update the mtime of the trail file to the current * time. This is so we don't prematurely remove a trail * file that was created while the system clock reset - * to the * "beginning of time" but later the system + * to the "beginning of time" but later the system * clock is set to the correct current time. */ if (current_time >= JAN_01_2000 && diff --git a/contrib/openbsm/libbsm/au_control.3 b/contrib/openbsm/libbsm/au_control.3 index fbf37b50b21c..c5a28f557222 100644 --- a/contrib/openbsm/libbsm/au_control.3 +++ b/contrib/openbsm/libbsm/au_control.3 @@ -201,7 +201,7 @@ converts an audit policy flags string, .Fa polstr , to a numeric audit policy mask returned via .Fa policy . -.Sh RETURN VALULES +.Sh RETURN VALUES The .Fn getacfilesz , .Fn getacdir , diff --git a/contrib/openbsm/libbsm/au_domain.3 b/contrib/openbsm/libbsm/au_domain.3 index 2f16b3848151..9d3415fb3c30 100644 --- a/contrib/openbsm/libbsm/au_domain.3 +++ b/contrib/openbsm/libbsm/au_domain.3 @@ -62,7 +62,7 @@ The function accepts a local domain, and returns the BSM domain for it. This call cannot fail, and instead returns a BSM domain indicating to a later decoder that the domain could not be encoded. -.Sh RETURN VALULES +.Sh RETURN VALUES On success, .Fn au_bsm_to_domain returns 0 and a converted domain; on failure, it returns -1 but does not set diff --git a/contrib/openbsm/libbsm/au_errno.3 b/contrib/openbsm/libbsm/au_errno.3 index 93873cec7323..9a3d51db0123 100644 --- a/contrib/openbsm/libbsm/au_errno.3 +++ b/contrib/openbsm/libbsm/au_errno.3 @@ -76,7 +76,7 @@ function converts a BSM error value to a string, generally by converting first t local error number and using the local .Xr strerror 3 function, but will also work for errors that are not locally defined. -.Sh RETURN VALULES +.Sh RETURN VALUES On success, .Fn au_bsm_to_errno returns 0 and a converted error value; on failure, it returns -1 but does not diff --git a/contrib/openbsm/libbsm/au_socket_type.3 b/contrib/openbsm/libbsm/au_socket_type.3 index 5668569f7b4d..54534b3fe80f 100644 --- a/contrib/openbsm/libbsm/au_socket_type.3 +++ b/contrib/openbsm/libbsm/au_socket_type.3 @@ -61,7 +61,7 @@ operating system. function accepts a local socket type, and returns the BSM socket type for it. This call cannot fail, and instead returns a BSM socket type indicating to a later decoder that the socket type could not be encoded. -.Sh RETURN VALULES +.Sh RETURN VALUES On success, .Fn au_bsm_to_socket_type returns 0 and a converted socket type; on failure, it returns -1 but does not diff --git a/contrib/openbsm/man/audit.log.5 b/contrib/openbsm/man/audit.log.5 index d85fdccb2bf0..a1db9981acd6 100644 --- a/contrib/openbsm/man/audit.log.5 +++ b/contrib/openbsm/man/audit.log.5 @@ -102,7 +102,7 @@ token can be created using .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Record Byte Count 4 bytes Number of bytes in record" -.It "Version Number 2 bytes Record version number" +.It "Version Number 1 byte Record version number" .It "Event Type 2 bytes Event type" .It "Event Modifier 2 bytes Event sub-type" .It "Seconds 4/8 bytes Record time stamp (32/64-bits)" @@ -126,7 +126,7 @@ token can be created using .It Sy "Field Bytes Description" .It "Token ID 1 byte Token ID" .It "Record Byte Count 4 bytes Number of bytes in record" -.It "Version Number 2 bytes Record version number" +.It "Version Number 1 byte Record version number" .It "Event Type 2 bytes Event type" .It "Event Modifier 2 bytes Event sub-type" .It "Address Type/Length 1 byte Host address type and length" @@ -325,7 +325,7 @@ or .It "Process ID 4 bytes Process ID" .It "Session ID 4 bytes Audit session ID" .It "Terminal Port ID 4/8 bytes Terminal port ID (32/64-bits)" -.It "Terminal Address Type/Length 1 byte Length of machine address" +.It "Terminal Address Type/Length 4 bytes Length of machine address" .It "Terminal Machine Address 4 bytes IPv4 or IPv6 address of machine" .El .Ss Return Token diff --git a/contrib/openbsm/man/getaudit.2 b/contrib/openbsm/man/getaudit.2 index ae5843d45a25..8165c8819007 100644 --- a/contrib/openbsm/man/getaudit.2 +++ b/contrib/openbsm/man/getaudit.2 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 19, 2008 +.Dd March 14, 2018 .Dt GETAUDIT 2 .Os .Sh NAME @@ -62,6 +62,7 @@ struct auditinfo { au_mask_t ai_mask; /* Audit masks */ au_tid_t ai_termid; /* Terminal ID */ au_asid_t ai_asid; /* Audit session ID */ + au_asflgs_t ai_flags; /* Audit session flags. */ }; typedef struct auditinfo auditinfo_t; .Ed diff --git a/contrib/openbsm/sys/bsm/audit.h b/contrib/openbsm/sys/bsm/audit.h index 73077b33bd53..26ac4cbf7584 100644 --- a/contrib/openbsm/sys/bsm/audit.h +++ b/contrib/openbsm/sys/bsm/audit.h @@ -46,7 +46,7 @@ #define MIN_AUDIT_FILE_SIZE (512 * 1024) /* - * Minimum noumber of free blocks on the filesystem containing the audit + * Minimum number of free blocks on the filesystem containing the audit * log necessary to avoid a hard log rotation. DO NOT SET THIS VALUE TO 0 * as the kernel does an unsigned compare, plus we want to leave a few blocks * free so userspace can terminate the log, etc. @@ -249,14 +249,14 @@ typedef struct au_token token_t; /* * Kernel audit queue control parameters: * Default: Maximum: - * aq_hiwater: AQ_HIWATER (100) AQ_MAXHIGH (10000) + * aq_hiwater: AQ_HIWATER (100) AQ_MAXHIGH (10000) * aq_lowater: AQ_LOWATER (10) <aq_hiwater * aq_bufsz: AQ_BUFSZ (32767) AQ_MAXBUFSZ (1048576) - * aq_delay: 20 20000 (not used) + * aq_delay: 20 20000 (not used) */ struct au_qctrl { int aq_hiwater; /* Max # of audit recs in queue when */ - /* threads with new ARs get blocked. */ + /* threads with new ARs get blocked. */ int aq_lowater; /* # of audit recs in queue when */ /* blocked threads get unblocked. */ diff --git a/crypto/openssh/FREEBSD-upgrade b/crypto/openssh/FREEBSD-upgrade index 6dcfae91fb1d..27e738bee2d4 100644 --- a/crypto/openssh/FREEBSD-upgrade +++ b/crypto/openssh/FREEBSD-upgrade @@ -168,13 +168,6 @@ ignore HPN-related configuration options to avoid breaking existing configurations. -9) AES-CBC - - The AES-CBC ciphers were removed from the server-side proposal list - in 6.7p1 due to theoretical weaknesses and the availability of - superior ciphers (including AES-CTR and AES-GCM). We have re-added - them for compatibility with third-party clients. - This port was brought to you by (in no particular order) DARPA, NAI diff --git a/crypto/openssh/myproposal.h b/crypto/openssh/myproposal.h index d5a1b7a2fa24..27b4a15a1279 100644 --- a/crypto/openssh/myproposal.h +++ b/crypto/openssh/myproposal.h @@ -1,5 +1,4 @@ /* $OpenBSD: myproposal.h,v 1.57 2018/09/12 01:34:02 djm Exp $ */ -/* $FreeBSD$ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -122,8 +121,7 @@ #define KEX_SERVER_ENCRYPT \ "chacha20-poly1305@openssh.com," \ "aes128-ctr,aes192-ctr,aes256-ctr" \ - AESGCM_CIPHER_MODES \ - ",aes128-cbc,aes192-cbc,aes256-cbc" + AESGCM_CIPHER_MODES #define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT diff --git a/crypto/openssh/servconf.c b/crypto/openssh/servconf.c index 5032fa6556d0..8b07e4b923ae 100644 --- a/crypto/openssh/servconf.c +++ b/crypto/openssh/servconf.c @@ -660,6 +660,7 @@ static struct { { "rdomain", sRDomain, SSHCFG_ALL }, { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, { "useblacklist", sUseBlacklist, SSHCFG_GLOBAL }, + { "useblocklist", sUseBlacklist, SSHCFG_GLOBAL }, /* alias */ { "noneenabled", sUnsupported, SSHCFG_ALL }, { "hpndisabled", sDeprecated, SSHCFG_ALL }, { "hpnbuffersize", sDeprecated, SSHCFG_ALL }, diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5 index 8176078319d1..d28622d984a1 100644 --- a/crypto/openssh/sshd_config.5 +++ b/crypto/openssh/sshd_config.5 @@ -35,7 +35,7 @@ .\" .\" $OpenBSD: sshd_config.5,v 1.282 2018/09/20 03:28:06 djm Exp $ .\" $FreeBSD$ -.Dd $Mdocdate: September 20 2018 $ +.Dd $Mdocdate: July 28 2020 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -495,8 +495,7 @@ The default is: .Bd -literal -offset indent chacha20-poly1305@openssh.com, aes128-ctr,aes192-ctr,aes256-ctr, -aes128-gcm@openssh.com,aes256-gcm@openssh.com, -aes128-cbc,aes192-cbc,aes256-cbc +aes128-gcm@openssh.com,aes256-gcm@openssh.com .Ed .Pp The list of available ciphers may also be obtained using @@ -1603,6 +1602,11 @@ to the daemon. The default is .Cm no . +For forward compatibility with an upcoming +.Xr blacklistd +rename, the +.Cm UseBlocklist +alias can be used instead. .It Cm UseDNS Specifies whether .Xr sshd 8 diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist index 3c7350ea24e1..e3164c7d76ba 100644 --- a/etc/mtree/BSD.usr.dist +++ b/etc/mtree/BSD.usr.dist @@ -864,8 +864,6 @@ .. powerpc .. - sparc64 - .. .. man5 .. @@ -880,8 +878,6 @@ .. powerpc .. - sparc64 - .. .. man9 .. diff --git a/include/regex.h b/include/regex.h index 6b0838a9bd97..3bea3df4f3d4 100644 --- a/include/regex.h +++ b/include/regex.h @@ -71,6 +71,7 @@ typedef struct { #define REG_NOSPEC 0020 #define REG_PEND 0040 #define REG_DUMP 0200 +#define REG_POSIX 0400 /* only POSIX-compliant regex (libregex) */ /* regerror() flags */ #define REG_ENOSYS (-1) diff --git a/lib/libc/regex/Symbol.map b/lib/libc/regex/Symbol.map index 5821f62b6430..1da7b81ba11b 100644 --- a/lib/libc/regex/Symbol.map +++ b/lib/libc/regex/Symbol.map @@ -3,8 +3,11 @@ */ FBSD_1.0 { - regcomp; regerror; regexec; regfree; }; + +FBSD_1.6 { + regcomp; +}; diff --git a/lib/libc/regex/regcomp.c b/lib/libc/regex/regcomp.c index 5e772c21d381..28bad13ac365 100644 --- a/lib/libc/regex/regcomp.c +++ b/lib/libc/regex/regcomp.c @@ -102,11 +102,14 @@ struct parse { sopno pend[NPAREN]; /* -> ) ([0] unused) */ bool allowbranch; /* can this expression branch? */ bool bre; /* convenience; is this a BRE? */ + int pflags; /* other parsing flags -- legacy escapes? */ bool (*parse_expr)(struct parse *, struct branchc *); void (*pre_parse)(struct parse *, struct branchc *); void (*post_parse)(struct parse *, struct branchc *); }; +#define PFLAG_LEGACY_ESC 0x00000001 + /* ========= begin header generated by ./mkh ========= */ #ifdef __cplusplus extern "C" { @@ -132,6 +135,7 @@ static void p_b_cclass(struct parse *p, cset *cs); static void p_b_eclass(struct parse *p, cset *cs); static wint_t p_b_symbol(struct parse *p); static wint_t p_b_coll_elem(struct parse *p, wint_t endc); +static bool may_escape(struct parse *p, const wint_t ch); static wint_t othercase(wint_t ch); static void bothcases(struct parse *p, wint_t ch); static void ordinary(struct parse *p, wint_t ch); @@ -199,22 +203,10 @@ static char nuls[10]; /* place to point scanner in event of error */ /* Macro used by computejump()/computematchjump() */ #define MIN(a,b) ((a)<(b)?(a):(b)) -/* - - regcomp - interface for parser and compilation - = extern int regcomp(regex_t *, const char *, int); - = #define REG_BASIC 0000 - = #define REG_EXTENDED 0001 - = #define REG_ICASE 0002 - = #define REG_NOSUB 0004 - = #define REG_NEWLINE 0010 - = #define REG_NOSPEC 0020 - = #define REG_PEND 0040 - = #define REG_DUMP 0200 - */ -int /* 0 success, otherwise REG_something */ -regcomp(regex_t * __restrict preg, +static int /* 0 success, otherwise REG_something */ +regcomp_internal(regex_t * __restrict preg, const char * __restrict pattern, - int cflags) + int cflags, int pflags) { struct parse pa; struct re_guts *g; @@ -273,6 +265,7 @@ regcomp(regex_t * __restrict preg, p->end = p->next + len; p->error = 0; p->ncsalloc = 0; + p->pflags = pflags; for (i = 0; i < NPAREN; i++) { p->pbegin[i] = 0; p->pend[i] = 0; @@ -346,6 +339,43 @@ regcomp(regex_t * __restrict preg, } /* + - regcomp - interface for parser and compilation + = extern int regcomp(regex_t *, const char *, int); + = #define REG_BASIC 0000 + = #define REG_EXTENDED 0001 + = #define REG_ICASE 0002 + = #define REG_NOSUB 0004 + = #define REG_NEWLINE 0010 + = #define REG_NOSPEC 0020 + = #define REG_PEND 0040 + = #define REG_DUMP 0200 + */ +int /* 0 success, otherwise REG_something */ +regcomp(regex_t * __restrict preg, + const char * __restrict pattern, + int cflags) +{ + + return (regcomp_internal(preg, pattern, cflags, 0)); +} + +#ifndef LIBREGEX +/* + * Legacy interface that requires more lax escaping behavior. + */ +int +freebsd12_regcomp(regex_t * __restrict preg, + const char * __restrict pattern, + int cflags, int pflags) +{ + + return (regcomp_internal(preg, pattern, cflags, PFLAG_LEGACY_ESC)); +} + +__sym_compat(regcomp, freebsd12_regcomp, FBSD_1.0); +#endif /* !LIBREGEX */ + +/* - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op, - return whether we should terminate or not == static bool p_ere_exp(struct parse *p); @@ -435,7 +465,10 @@ p_ere_exp(struct parse *p, struct branchc *bc) EMIT(OEOW, 0); break; default: - ordinary(p, wc); + if (may_escape(p, wc)) + ordinary(p, wc); + else + SETERROR(REG_EESCAPE); break; } break; @@ -797,7 +830,10 @@ p_simp_re(struct parse *p, struct branchc *bc) return (false); /* Definitely not $... */ p->next--; wc = WGETNEXT(); - ordinary(p, wc); + if ((c & BACKSL) == 0 || may_escape(p, wc)) + ordinary(p, wc); + else + SETERROR(REG_EESCAPE); break; } @@ -1095,6 +1131,55 @@ p_b_coll_elem(struct parse *p, } /* + - may_escape - determine whether 'ch' is escape-able in the current context + == static int may_escape(struct parse *p, const wint_t ch) + */ +static bool +may_escape(struct parse *p, const wint_t ch) +{ + + if ((p->pflags & PFLAG_LEGACY_ESC) != 0) + return (true); + if (isalpha(ch) || ch == '\'' || ch == '`') + return (false); + return (true); +#ifdef NOTYET + /* + * Build a whitelist of characters that may be escaped to produce an + * ordinary in the current context. This assumes that these have not + * been otherwise interpreted as a special character. Escaping an + * ordinary character yields undefined results according to + * IEEE 1003.1-2008. Some extensions (notably, some GNU extensions) take + * advantage of this and use escaped ordinary characters to provide + * special meaning, e.g. \b, \B, \w, \W, \s, \S. + */ + switch(ch) { + case '|': + case '+': + case '?': + /* The above characters may not be escaped in BREs */ + if (!(p->g->cflags®_EXTENDED)) + return (false); + /* Fallthrough */ + case '(': + case ')': + case '{': + case '}': + case '.': + case '[': + case ']': + case '\\': + case '*': + case '^': + case '$': + return (true); + default: + return (false); + } +#endif +} + +/* - othercase - return the case counterpart of an alphabetic == static wint_t othercase(wint_t ch); */ diff --git a/lib/libpmc/libpmc_pmu_util.c b/lib/libpmc/libpmc_pmu_util.c index 11949a3ad3cd..d652573a883f 100644 --- a/lib/libpmc/libpmc_pmu_util.c +++ b/lib/libpmc/libpmc_pmu_util.c @@ -30,6 +30,7 @@ #include <sys/types.h> #include <sys/errno.h> +#include <sys/pmc.h> #include <sys/sysctl.h> #include <stddef.h> #include <stdlib.h> @@ -89,20 +90,13 @@ static struct pmu_alias pmu_amd_alias_table[] = { static pmu_mfr_t pmu_events_mfr(void) { - char *buf; - size_t s; + char buf[PMC_CPUID_LEN]; + size_t s = sizeof(buf); pmu_mfr_t mfr; - if (sysctlbyname("kern.hwpmc.cpuid", (void *)NULL, &s, - (void *)NULL, 0) == -1) - return (PMU_INVALID); - if ((buf = malloc(s + 1)) == NULL) - return (PMU_INVALID); if (sysctlbyname("kern.hwpmc.cpuid", buf, &s, - (void *)NULL, 0) == -1) { - free(buf); + (void *)NULL, 0) == -1) return (PMU_INVALID); - } if (strcasestr(buf, "AuthenticAMD") != NULL || strcasestr(buf, "HygonGenuine") != NULL) mfr = PMU_AMD; @@ -110,7 +104,6 @@ pmu_events_mfr(void) mfr = PMU_INTEL; else mfr = PMU_INVALID; - free(buf); return (mfr); } @@ -169,17 +162,14 @@ pmu_events_map_get(const char *cpuid) { regex_t re; regmatch_t pmatch[1]; - size_t s; - char buf[64]; + char buf[PMC_CPUID_LEN]; + size_t s = sizeof(buf); int match; const struct pmu_events_map *pme; if (cpuid != NULL) { - memcpy(buf, cpuid, 64); + strlcpy(buf, cpuid, s); } else { - if (sysctlbyname("kern.hwpmc.cpuid", (void *)NULL, &s, - (void *)NULL, 0) == -1) - return (NULL); if (sysctlbyname("kern.hwpmc.cpuid", buf, &s, (void *)NULL, 0) == -1) return (NULL); diff --git a/release/sparc64/mkisoimages.sh b/release/sparc64/mkisoimages.sh deleted file mode 100644 index 80894096f01e..000000000000 --- a/release/sparc64/mkisoimages.sh +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/sh -# -# Module: mkisoimages.sh -# Author: Jordan K Hubbard -# Date: 22 June 2001 -# -# $FreeBSD$ -# -# This script is used by release/Makefile to build the (optional) ISO images -# for a FreeBSD release. It is considered architecture dependent since each -# platform has a slightly unique way of making bootable CDs. This script -# is also allowed to generate any number of images since that is more of -# publishing decision than anything else. -# -# Usage: -# -# mkisoimages.sh [-b] image-label image-name base-bits-dir [extra-bits-dir] -# -# Where -b is passed if the ISO image should be made "bootable" by -# whatever standards this architecture supports (may be unsupported), -# image-label is the ISO image label, image-name is the filename of the -# resulting ISO image, base-bits-dir contains the image contents and -# extra-bits-dir, if provided, contains additional files to be merged -# into base-bits-dir as part of making the image. -set -e - -if [ $# -lt 3 ]; then - echo "Usage: $0 [-b] image-label image-name base-bits-dir [extra-bits-dir]" > /dev/stderr - exit 1 -fi - -case "$1" in --b) BOPT="$1"; shift ;; -esac -LABEL=`echo "$1" | tr '[:lower:]' '[:upper:]'`; shift -NAME="$1"; shift -BASEBITSDIR="$1" - -# Create an ISO image -publisher="The FreeBSD Project. https://www.FreeBSD.org/" -echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > "$BASEBITSDIR/etc/fstab" -makefs -t cd9660 -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME.tmp" "$@" -rm -f "$BASEBITSDIR/etc/fstab" - -if [ "$BOPT" != "-b" ]; then - mv "$NAME.tmp" "$NAME" - exit 0 -fi - -TMPIMGDIR=`mktemp -d /tmp/bootfs.XXXXXXXX` || exit 1 -BOOTFSDIR="$TMPIMGDIR/bootfs" -BOOTFSIMG="$TMPIMGDIR/bootfs.img" - -# Create a boot filesystem -mkdir -p "$BOOTFSDIR/boot" -cp -p "$BASEBITSDIR/boot/loader" "$BOOTFSDIR/boot" -makefs -t ffs -B be -M 512k "$BOOTFSIMG" "$BOOTFSDIR" -dd if="$BASEBITSDIR/boot/boot1" of="$BOOTFSIMG" bs=512 conv=notrunc,sync - -# Create a boot ISO image -: ${CYLSIZE:=640} -ISOSIZE=$(stat -f %z "$NAME.tmp") -ISOBLKS=$((($ISOSIZE + 511) / 512)) -ISOCYLS=$((($ISOBLKS + ($CYLSIZE - 1)) / $CYLSIZE)) - -BOOTFSSIZE=$(stat -f %z "$BOOTFSIMG") -BOOTFSBLKS=$((($BOOTFSSIZE + 511) / 512)) -BOOTFSCYLS=$((($BOOTFSBLKS + ($CYLSIZE - 1)) / $CYLSIZE)) - -ENDCYL=$(($ISOCYLS + $BOOTFSCYLS)) -NSECTS=$(($ENDCYL * 1 * $CYLSIZE)) - -dd if="$NAME.tmp" of="$NAME" bs="${CYLSIZE}b" conv=notrunc,sync -dd if="$BOOTFSIMG" of="$NAME" bs="${CYLSIZE}b" seek=$ISOCYLS conv=notrunc,sync -# The number of alternative cylinders is always 2. -dd if=/dev/zero of="$NAME" bs="${CYLSIZE}b" seek=$ENDCYL count=2 conv=notrunc,sync -rm -rf "$NAME.tmp" "$TMPIMGDIR" - -# Write VTOC8 label to boot ISO image -MD=`mdconfig -a -t vnode -S 512 -y 1 -x "$CYLSIZE" -f "$NAME"` -gpart create -s VTOC8 $MD -# !4: usr, for ISO image part -gpart add -i 1 -s "$(($ISOCYLS * $CYLSIZE * 512))b" -t \!4 $MD -# !2: root, for bootfs part. -gpart add -i 6 -s "$(($BOOTFSCYLS * $CYLSIZE * 512))b" -t \!2 $MD -mdconfig -d -u ${MD#md} diff --git a/release/sparc64/sparc64.conf b/release/sparc64/sparc64.conf deleted file mode 100644 index c0579eaadb4b..000000000000 --- a/release/sparc64/sparc64.conf +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# -# $FreeBSD$ -# - -# Configuration file for release/release.sh to build sparc64/sparc64. - -TARGET="sparc64" -TARGET_ARCH="sparc64" -KERNEL="GENERIC" diff --git a/rescue/rescue/Makefile b/rescue/rescue/Makefile index 9249e00a7250..9681ebaddfa3 100644 --- a/rescue/rescue/Makefile +++ b/rescue/rescue/Makefile @@ -147,10 +147,6 @@ CRUNCH_ALIAS_bsdlabel= disklabel #CRUNCH_LIBS+= -lsmb .endif -.if ${MACHINE_CPUARCH} == "sparc64" -CRUNCH_PROGS_sbin+= bsdlabel sunlabel -.endif - .if ${MACHINE_CPUARCH} == "amd64" CRUNCH_PROGS_sbin+= bsdlabel fdisk CRUNCH_ALIAS_bsdlabel= disklabel diff --git a/sbin/init/ttys.sparc64 b/sbin/init/ttys.sparc64 deleted file mode 100644 index 5c7f3cff6a3f..000000000000 --- a/sbin/init/ttys.sparc64 +++ /dev/null @@ -1,54 +0,0 @@ -# -# $FreeBSD$ -# @(#)ttys 5.1 (Berkeley) 4/17/89 -# -# This file specifies various information about terminals on the system. -# It is used by several different programs. Common entries for the -# various columns include: -# -# name The name of the terminal device. -# -# getty The program to start running on the terminal. Typically a -# getty program, as the name implies. Other common entries -# include none, when no getty is needed, and xdm, to start the -# X Window System. -# -# type The initial terminal type for this port. For hardwired -# terminal lines, this will contain the type of terminal used. -# For virtual consoles, the correct type is typically xterm. -# Other common values include dialup for incoming modem ports, and -# unknown when the terminal type cannot be predetermined. -# -# status Must be on or off. If on, init will run the getty program on -# the specified port. If the word "secure" appears, this tty -# allows root login. -# -# name getty type status comments -# -# If console is marked "insecure", then init will ask for the root password -# when going to single-user mode. -console none unknown off secure -# ofw_console(4) -screen "/usr/libexec/getty Pc" vt100 off secure -ttya "/usr/libexec/getty 3wire.9600" vt100 off secure -ttyb "/usr/libexec/getty 3wire.9600" vt100 off secure -# syscons(4) -ttyv0 "/usr/libexec/getty Pc" xterm onifexists secure -# Virtual terminals -ttyv1 "/usr/libexec/getty Pc" xterm onifexists secure -ttyv2 "/usr/libexec/getty Pc" xterm onifexists secure -ttyv3 "/usr/libexec/getty Pc" xterm onifexists secure -ttyv4 "/usr/libexec/getty Pc" xterm onifexists secure -ttyv5 "/usr/libexec/getty Pc" xterm onifexists secure -ttyv6 "/usr/libexec/getty Pc" xterm onifexists secure -ttyv7 "/usr/libexec/getty Pc" xterm onifexists secure -ttyv8 "/usr/local/bin/xdm -nodaemon" xterm off secure -# Serial terminals -# The 'dialup' keyword identifies dialin lines to login, fingerd etc. -# uart(4) -ttyu0 "/usr/libexec/getty 3wire" vt100 onifconsole secure -ttyu1 "/usr/libexec/getty 3wire" vt100 onifconsole secure -ttyu2 "/usr/libexec/getty 3wire" vt100 onifconsole secure -ttyu3 "/usr/libexec/getty 3wire" vt100 onifconsole secure -# Dumb console -dcons "/usr/libexec/getty std.9600" vt100 off secure diff --git a/share/man/man3/siginfo.3 b/share/man/man3/siginfo.3 index f0cc9aa2487b..fc4ea2ba1df7 100644 --- a/share/man/man3/siginfo.3 +++ b/share/man/man3/siginfo.3 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 8, 2020 +.Dd July 28, 2020 .Dt SIGINFO 3 .Os .Sh NAME @@ -68,7 +68,7 @@ sending process ID .It Vt uid_t Ta Va si_uid Ta sending process's real user ID .It Vt void Ta Va *si_addr Ta -address of faulting instruction +virtual address .It Vt int Ta Va si_status Ta exit value or signal .It Vt long Ta Va si_band Ta @@ -208,25 +208,24 @@ signal sent by .Xr pthread_kill 3 .El .Pp +For synchronous signals, +.Va si_addr +is generally set to the address of the faulting instruction. +However, synchronous signals raised by a faulting memory access such as +.Dv SIGSEGV +and +.Dv SIGBUS +may report the address of the faulting memory access (if available) in +.Va si_addr +instead. +.Pp +Sychronous signals set +.Va si_trapno +to a machine-dependent trap number. +.Pp In addition, the following signal-specific information is available: .Bl -column ".Dv SIGPOLL" ".Dv CLD_CONTINUED" .It Sy Signal Ta Sy Member Ta Sy Value -.It Dv SIGILL Ta Va si_addr Ta -address of faulting instruction -.It Ta Va si_trapno Ta -machine dependent of trap code -.It Dv SIGFPE Ta Va si_addr Ta -address of faulting instruction -.It Ta Va si_trapno Ta -machine dependent of trap code -.It Dv SIGSEGV Ta Va si_addr Ta -address of faulting memory reference -.It Ta Va si_trapno Ta -machine dependent of trap code -.It Dv SIGBUS Ta Va si_addr Ta -address of faulting instruction -.It Ta Va si_trapno Ta -machine dependent of trap code .It Dv SIGCHLD Ta Va si_pid Ta child process ID .It Ta Va si_status Ta diff --git a/share/man/man3/tree.3 b/share/man/man3/tree.3 index e6ecc6e44237..a29f06d3c21e 100644 --- a/share/man/man3/tree.3 +++ b/share/man/man3/tree.3 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 25, 2020 +.Dd July 27, 2020 .Dt TREE 3 .Os .Sh NAME @@ -371,7 +371,7 @@ Each tree node has an associated rank. Balance conditions are expressed by conditions on the differences in rank between any node and its children. Rank differences are stored in each tree node. -.Pp +.Pp The balance conditions implemented by the RB macros lead to weak AVL (wavl) trees, which combine the best aspects of AVL and red-black trees. @@ -380,7 +380,8 @@ with the same worst-case time as red-black trees offer, and with better balance in the resulting tree. Wavl trees rebalance after a removal in a way that requires less restructuring, in the worst case, than either AVL or red-black trees -do. Removals can lead to a tree almost as unbalanced as a red-black +do. +Removals can lead to a tree almost as unbalanced as a red-black tree; insertions lead to a tree becoming as balanced as an AVL tree. .Pp A rank-balanced tree is headed by a structure defined by the diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index fe715f48288d..9049f3feb5e3 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -121,7 +121,6 @@ MAN= aac.4 \ cxgb.4 \ cxgbe.4 \ cxgbev.4 \ - cy.4 \ cyapa.4 \ da.4 \ dc.4 \ @@ -434,7 +433,6 @@ MAN= aac.4 \ ${_qlnxe.4} \ ral.4 \ random.4 \ - rc.4 \ rctl.4 \ re.4 \ rgephy.4 \ @@ -442,7 +440,6 @@ MAN= aac.4 \ rl.4 \ rndtest.4 \ route.4 \ - rp.4 \ rtwn.4 \ rtwnfw.4 \ rtwn_pci.4 \ diff --git a/share/man/man4/aesni.4 b/share/man/man4/aesni.4 index aacbe79cc337..08465bdf5e88 100644 --- a/share/man/man4/aesni.4 +++ b/share/man/man4/aesni.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 26, 2017 +.Dd July 29, 2020 .Dt AESNI 4 .Os .Sh NAME @@ -88,6 +88,7 @@ implementations. .Xr ipsec 4 , .Xr padlock 4 , .Xr random 4 , +.Xr crypto 7 , .Xr crypto 9 .Sh HISTORY The diff --git a/share/man/man4/cy.4 b/share/man/man4/cy.4 deleted file mode 100644 index c0c807286f1e..000000000000 --- a/share/man/man4/cy.4 +++ /dev/null @@ -1,257 +0,0 @@ -.\" Copyright (c) 1990, 1991 The Regents of the University of California. -.\" All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Systems Programming Group of the University of Utah Computer -.\" Science Department. -.\" 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 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. -.\" -.\" from: @(#)dca.4 5.2 (Berkeley) 3/27/91 -.\" from: com.4,v 1.1 1993/08/06 11:19:07 cgd Exp -.\" from: sio.4,v 1.16 1995/06/26 06:05:30 bde Exp $ -.\" $FreeBSD$ -.\" -.Dd May 24, 2004 -.Dt CY 4 -.Os -.Sh NAME -.Nm cy -.Nd Cyclades Cyclom-Y serial driver -.Sh SYNOPSIS -For one ISA card: -.Bd -ragged -offset indent -compact -.Cd "device cy" -.Pp -In -.Pa /boot/device.hints : -.Cd hint.cy.0.at="isa" -.Cd hint.cy.0.irq="10" -.Cd hint.cy.0.maddr="0xd4000" -.Cd hint.cy.0.msize="0x2000" -.Ed -.Pp -For two ISA cards: -.Bd -ragged -offset indent -compact -.Cd "device cy" -.Pp -In -.Pa /boot/device.hints : -.Cd hint.cy.0.at="isa" -.Cd hint.cy.0.irq="10" -.Cd hint.cy.0.maddr="0xd4000" -.Cd hint.cy.0.msize="0x2000" -.Cd hint.cy.1.at="isa" -.Cd hint.cy.1.irq="11" -.Cd hint.cy.1.maddr="0xd6000" -.Cd hint.cy.1.msize="0x2000" -.Ed -.Pp -For PCI cards: -.Bd -ragged -offset indent -compact -.Cd "device cy" -.Cd "options CY_PCI_FASTINTR" -.Pp -No lines are required in -.Pa /boot/device.hints -for PCI cards. -.Ed -.Pp -Minor numbering: -.Bd -literal -offset indent -compact -0b\fIMMMMMMMMMMMMMMMMxxxxxxxxOLIMMMMM\fR - call\fBO\fRut - \fBL\fRock - \fBI\fRnitial - \fBMMMMMMMMMMMMMMMM MMMMMM\fRinor -.Ed -.Sh DESCRIPTION -The -.Nm -driver provides support for Cirrus Logic CD1400-based -.Tn EIA -.Tn RS-232C -.Pf ( Tn CCITT -.Tn V.24 ) -communications interfaces (ports) on Cyclades Cyclom-Y boards. -Each CD1400 provides 4 ports. -Cyclom-Y boards with various numbers of CD1400's are available. -This driver supports up to 8 CD1400's (32 ports) per board. -.Pp -Input and output for each line may set independently -to the following speeds: -50, 75, 110, 134.5, 150, 300, 600, 1200, 1800, 2400, 4800, 9600, -19200, 38400, 57600, or 115200 bps. -Other speeds of up to 150000 are supported by the termios interface -but not by the sgttyb compatibility interface. -The CD1400 is not fast enough to handle speeds above 115200 bps -effectively. -It can transmit on a single line at slightly more than 115200 bps, -but when 4 lines are active in both directions its limit is about -90000 bps on each line. -.\" XXX the following should be true for all serial drivers and -.\" should not be repeated in the man pages for all serial drivers. -.\" It was copied from sio.4. The only change was s/sio/cy/g. -.Pp -Serial ports controlled by the -.Nm -driver can be used for both `callin' and `callout'. -For each port there is a callin device and a callout device. -The minor number of the callout device is 128 higher -than that of the corresponding callin port. -The callin device is general purpose. -Processes opening it normally wait for carrier -and for the callout device to become inactive. -The callout device is used to steal the port from -processes waiting for carrier on the callin device. -Processes opening it do not wait for carrier -and put any processes waiting for carrier on the callin device into -a deeper sleep so that they do not conflict with the callout session. -The callout device is abused for handling programs that are supposed -to work on general ports and need to open the port without waiting -but are too stupid to do so. -.Pp -The -.Nm -driver also supports an initial-state and a lock-state control -device for each of the callin and the callout "data" devices. -The minor number of the initial-state device is 32 higher -than that of the corresponding data device. -The minor number of the lock-state device is 64 higher -than that of the corresponding data device. -The termios settings of a data device are copied -from those of the corresponding initial-state device -on first opens and are not inherited from previous opens. -Use -.Xr stty 1 -in the normal way on the initial-state devices to program -initial termios states suitable for your setup. -.Pp -The lock termios state acts as flags to disable changing -the termios state. -E.g., to lock a flag variable such as -CRTSCTS, use -.Em "stty crtscts" -on the lock-state device. -Speeds and special characters -may be locked by setting the corresponding value in the lock-state -device to any nonzero value. -.Pp -Correct programs talking to correctly wired external devices -work with almost arbitrary initial states and almost no locking, -but other setups may benefit from changing some of the default -initial state and locking the state. -In particular, the initial states for non (POSIX) standard flags -should be set to suit the devices attached and may need to be -locked to prevent buggy programs from changing them. -E.g., CRTSCTS should be locked on for devices that support -RTS/CTS handshaking at all times and off for devices that do not -support it at all. -CLOCAL should be locked on for devices -that do not support carrier. -HUPCL may be locked off if you do not -want to hang up for some reason. -In general, very bad things happen -if something is locked to the wrong state, and things should not -be locked for devices that support more than one setting. -The -CLOCAL flag on callin ports should be locked off for logins -to avoid certain security holes, but this needs to be done by -getty if the callin port is used for anything else. -.Ss Kernel Configuration Options -The -.Em CY_PCI_FASTINTR -option should be used to avoid suboptimal interrupt handling for -PCI Cyclades boards. -The PCI BIOS must be configured with the -.Nm -interrupt not shared with any other active device -for this option to work. -This option is not the default because it is currently harmful in -certain cases where it does not work. -.Sh FILES -.\" XXX more cloning: s/d/c/g and add a ? for the card number. -.Bl -tag -width /dev/ttyic?? -compact -.It Pa /dev/ttyc?? -for callin ports -.It Pa /dev/ttyic?? -.It Pa /dev/ttylc?? -corresponding callin initial-state and lock-state devices -.Pp -.\" XXX more cloning: s/a/c/g. No consistency :-(. -.It Pa /dev/cuac?? -for callout ports -.It Pa /dev/cuaic?? -.It Pa /dev/cualc?? -corresponding callout initial-state and lock-state devices -.El -.Pp -.Bl -tag -width /etc/rc.serial -compact -.It Pa /etc/rc.serial -examples of setting the initial-state and lock-state devices -.El -.Pp -The first question mark in these device names is short for the -card number -(a decimal number between 0 and 65535 inclusive). -The second question mark is short for the port number -(a letter in the range [0-9a-v]). -.Sh DIAGNOSTICS -.Bl -diag -.\" XXX back to s/sio/cy/g. -.It cy%d: silo overflow. -Problem in the interrupt handler. -.El -.Bl -diag -.It cy%d: interrupt-level buffer overflow. -Problem in the bottom half of the driver. -.El -.Bl -diag -.It cy%d: tty-level buffer overflow. -Problem in the application. -Input has arrived faster than the given module could process it -and some has been lost. -.El -.\" .Bl -diag -.\" .It sio%d: reduced fifo trigger level to %d. -.\" Attempting to avoid further silo overflows. -.\" .El -.Sh SEE ALSO -.Xr stty 1 , -.Xr termios 4 , -.Xr tty 4 , -.Xr comcontrol 8 , -.Xr pstat 8 -.Sh HISTORY -The -.Nm -driver is derived from the -.Nm sio -driver and the -.Nx -.Nm -driver and is -.Ud -.Sh BUGS -Serial consoles are not implemented. diff --git a/share/man/man4/hifn.4 b/share/man/man4/hifn.4 index f9952ac153ad..a9a06c1fbd91 100644 --- a/share/man/man4/hifn.4 +++ b/share/man/man4/hifn.4 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 11, 2020 +.Dd July 29, 2020 .Dt HIFN 4 .Os .Sh NAME @@ -101,11 +101,11 @@ See Contains a 7955 and supports symmetric and random number operations. .El .Sh SEE ALSO -.Xr crypt 3 , .Xr crypto 4 , .Xr intro 4 , .Xr ipsec 4 , .Xr random 4 , +.Xr crypto 7 , .Xr crypto 9 .Sh HISTORY The diff --git a/share/man/man4/man4.aarch64/armv8crypto.4 b/share/man/man4/man4.aarch64/armv8crypto.4 index 5b91049d404e..a80b0801d722 100644 --- a/share/man/man4/man4.aarch64/armv8crypto.4 +++ b/share/man/man4/man4.aarch64/armv8crypto.4 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 20, 2016 +.Dd July 29, 2020 .Dt ARMV8CRYPTO 4 .Os .Sh NAME @@ -69,6 +69,7 @@ driver registers itself to accelerate AES operations for .Xr intro 4 , .Xr ipsec 4 , .Xr random 4 , +.Xr crypto 7 , .Xr crypto 9 .Sh HISTORY The diff --git a/share/man/man4/man4.i386/glxsb.4 b/share/man/man4/man4.i386/glxsb.4 index d2a30352fe7f..c08d57906136 100644 --- a/share/man/man4/man4.i386/glxsb.4 +++ b/share/man/man4/man4.i386/glxsb.4 @@ -16,7 +16,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 8, 2008 +.Dd July 29, 2020 .Dt GLXSB 4 i386 .Os .Sh NAME @@ -73,6 +73,7 @@ device driver with AES keys of length != 128 bits. .Xr ipsec 4 , .Xr pci 4 , .Xr random 4 , +.Xr crypto 7 , .Xr crypto 9 .Sh HISTORY The diff --git a/share/man/man4/ng_iface.4 b/share/man/man4/ng_iface.4 index 0b406cdd298f..2259ea1076d3 100644 --- a/share/man/man4/ng_iface.4 +++ b/share/man/man4/ng_iface.4 @@ -35,7 +35,7 @@ .\" $FreeBSD$ .\" $Whistle: ng_iface.8,v 1.5 1999/01/25 23:46:26 archie Exp $ .\" -.Dd February 6, 2019 +.Dd July 31, 2020 .Dt NG_IFACE 4 .Os .Sh NAME @@ -70,7 +70,7 @@ Packets transmitted via the interface flow out the corresponding protocol-specific hook. Similarly, packets received on a hook appear on the interface as packets received into the corresponding protocol stack. -The currently supported protocols are IP, IPv6, ATM, NATM, and NS. +The currently supported protocols are IP and IPv6. .Pp An .Nm iface @@ -87,12 +87,6 @@ This node type supports the following hooks: Transmission and reception of IP packets. .It Va inet6 Transmission and reception of IPv6 packets. -.It Va atm -Transmission and reception of ATM packets. -.It Va natm -Transmission and reception of NATM packets. -.It Va ns -Transmission and reception of NS packets. .El .Sh CONTROL MESSAGES This node type supports the generic control messages, plus the following: diff --git a/share/man/man4/padlock.4 b/share/man/man4/padlock.4 index ad648af9d946..44963d0fd140 100644 --- a/share/man/man4/padlock.4 +++ b/share/man/man4/padlock.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 8, 2010 +.Dd July 29, 2020 .Dt PADLOCK 4 .Os .Sh NAME @@ -72,6 +72,7 @@ subsystem. .Xr intro 4 , .Xr ipsec 4 , .Xr random 4 , +.Xr crypto 7 , .Xr crypto 9 .Sh HISTORY The diff --git a/share/man/man4/rc.4 b/share/man/man4/rc.4 deleted file mode 100644 index 95bcae6c3981..000000000000 --- a/share/man/man4/rc.4 +++ /dev/null @@ -1,124 +0,0 @@ -.\" -.\" Copyright (c) 2004 Tom Rhodes -.\" 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$ -.\" -.Dd March 18, 2005 -.Dt RC 4 -.Os -.Sh NAME -.Nm rc -.Nd RISCom/8 multiport card -.Sh SYNOPSIS -.Cd device isa -.Cd device rc -.Sh DESCRIPTION -The -.Tn RISCom/8 -is an eight port -.Tn ISA -.Tn RS-232C -communications multiplexer with a built in -.Tn RISC -processor. -It uses a block of sixteen -.Tn I/O -ports in the range 0x200 to 0x3f0 selectable by on-board -switches or jumpers. -The block must be aligned on a sixteen port boundary. -The jumper-selectable hardware interrupt level may be set to -be detected during system -initialization using settings found in the -.Pa /boot/device.hints -file. -.Pp -This driver is mostly based on the Cirrus Logic CL-CD180 driver. -.Sh HARDWARE -The -.Nm -driver provides support for the -.Tn SDL -Communications -.Tn RISCom/8 -boards. -.Sh DIAGNOSTICS -The following driver specific error messages -may be reported: -.Bl -diag -.It "rc%d channel%d: interrupt-level buffer overflow" -An internal buffer overflow error has occurred on -the listed channel. -The -.Nm -driver will need to be reloaded to correct this. -.It "rc%d: Bad char chan %d" -The channel has obtained a bad set of characters. -.It "rc%d: Got extra chars chan %d" -The -.Nm -driver got more characters than expected on the channel shown. -.It "rc%d: data mismatch chan %d ptr %d (%d != %d)" -Data sent from channel -.Ar %d -to the rx buffer was different then expected. -.It "rc%d: channel %d command timeout, rc.c line: %d" -A command timeout has occurred on the channel, the -.Pa src/sys/dev/rc/rc.c -file can be consulted for more information. -.El -.Sh SEE ALSO -.Xr tty 1 , -.Xr ttyname 3 , -.Xr tty 4 , -.Xr device.hints 5 , -.Xr comcontrol 8 , -.Xr getty 8 , -.Xr mutex 9 , -.Xr splx 9 -.Pp -.Pa http://www.sdlcomm.com -.Sh HISTORY -The -.Nm -driver first appeared in -.Fx 2.0.5 . -This manual page first appeared in -.Fx 5.3 . -.Sh AUTHORS -This manual page was written by -.An Tom Rhodes Aq Mt trhodes@FreeBSD.org . -.Sh BUGS -The -.Nm -driver code still uses the -.Xr spl 9 -functions. -These should be replaced by -.Xr mutex 9 -functions. -.Pp -The various -.Fn ttyld_* -functions should be documented. diff --git a/share/man/man4/rp.4 b/share/man/man4/rp.4 deleted file mode 100644 index d8a130c810b3..000000000000 --- a/share/man/man4/rp.4 +++ /dev/null @@ -1,195 +0,0 @@ -.\" Copyright (c) 1995 Comtrol, Inc. -.\" All rights reserved. -.\" -.\" $FreeBSD$ -.Dd November 15, 1995 -.Dt RP 4 -.Os -.Sh NAME -.Nm rp -.Nd "driver for Comtrol RocketPort Intelligent Serial Port Cards" -.Sh SYNOPSIS -.Cd "device rp" -.Pp -For ISA cards, you must specify the port address in -.Pa /boot/device.hints : -.Cd hint.rp.0.at="isa" -.Cd hint.rp.0.port="0x100" -.Sh DESCRIPTION -This driver provides a kernel device driver for the -.Tn RocketPort -and -.Tn RocketPort RA -serial boards. -These boards provide 8, 16, or 32 high-speed serial ports -while requiring only 68 bytes of I/O space for all 8, 16, -or 32 ports, and do not require an interrupt channel. -This driver supports up to four -.Tn RocketPort -or -.Tn RocketPort RA -boards in one machine simultaneously. -If you are using four 32 port -.Tn RocketPort -boards, you can put as many as 128 intelligent serial ports -on your system. -.Pp -The -.Nm -driver supports the following speeds: 50, 75, 110, 134, 150, -200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 7200, -14400, 57600, 76800, 115200, and 230400. -(You must use -.Xr termios 4 , -rather than the old style ioctl interface to use non-traditional -speeds.) -.Pp -An open on the -.Nm -driver will block until carrier is present, unless -.Dv O_NONBLOCK -or -.Dv CLOCAL -is set. -.Sh HARDWARE CONFIGURATION -The first -.Tn RocketPort -or -.Tn RocketPort RA -card requires a 68-byte contiguous block of I/O addresses, -starting at one of the following: -0x100h, 0x140h, 0x180h, 0x200h, 0x240h, 0x280h, 0x300h, 0x340h, -0x380h. -The second, third, and fourth -.Tn RocketPort -cards require only a -64-byte contiguous block of I/O addresses, starting at one of the -above address ranges. -The I/O address range used by any of the -.Tn RocketPort -cards must not conflict with any other cards in the system, -including other -.Tn RocketPort -cards. -The starting range of the I/O ports used by each card -must match with the I/O address specified in -.Pa /boot/device.hints . -.Pp -Since the first -.Tn RocketPort -uses 68 I/O addresses, if the first card is -set to use an I/O block starting at 0x100, -it will occupy the I/O ports between 0x100 and 0x143. -This means that the second, third, or fourth -.Tn RocketPort -board may not use the block of addresses starting at 0x140, -since the first three I/O addresses of that range -are used by the first board. -This is an important point to keep in mind. -.Pp -If you have two ISA cards, one installed at 0x100 and the -second installed at 0x180, then you should add the following to -.Pa /boot/device.hints : -.Pp -.Dl hint.rp.0.at="isa" -.Dl hint.rp.0.port="0x100" -.Dl hint.rp.1.at="isa" -.Dl hint.rp.1.port="0x180" -.Pp -The configuration of the -.Tn RocketPort -cards is done via the set of 8 DIP switches, -labeled SW1 on the -.Tn RocketPort -card: -.Bd -literal -offset indent -+-------------------------------+ -| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | -+-------+-------+---------------+ -| Unused| Card | I/O Port Block| -+-------------------------------+ -.Ed -.Pp -DIP switches 7 and 8 are unused, and must be left on. -.Pp -DIP switches 6 and 5 identify the card number of each -.Tn RocketPort -card. -The first card installed in the system must have its DIP switches set -as card number one; the second card installed in the system must have -its DIP switches set as card number two; and so on. -As shipped from -the factory, DIP switches 6 and 5 are both on by default, indicating -that this is the first card installed on the system: -.Bd -literal -offset indent -DIP Switches -6 5 -=================== -On On First Card -On Off Second Card -Off On Third Card -Off Off Fourth Card -.Ed -.Pp -DIP switches 4, 3, 2, and 1 indicate the I/O address range used by the -first -.Tn RocketPort -card. -If there are more than one -.Tn RocketPort -cards installed in a system, -the second, third and fourth -.Tn RocketPort -cards must -also be set to the I/O address range used by the first -.Tn RocketPort -card; -all cards must have these DIP switches set identically -for proper operation. -As shipped from the factory, DIP switch 4 is on, -and switches 3, 2, and 1 are off by default, -indicating an I/O address range used by the first -card which starts at 0x180 and extends to 0x1C3. -.Bd -literal -offset indent -DIP Switches I/O Address Range -4 3 2 1 Used by the First Card -===================================== -On Off On Off 100-143 -On Off Off On 140-183 -On Off Off Off 180-1C3 -Off On On Off 200-243 -Off On Off On 240-283 -Off On Off Off 280-2C3 -Off Off On Off 300-343 -Off Off Off On 340-383 -Off Off Off Off 380-3C3 -.Ed -.Sh FILES -.Bl -tag -width ".Pa /dev/ttyR[0-4][0-9a-f]" -.It Pa /dev/ttyR[0-4][0-9a-f] -.El -.Sh AUTHORS -.An Theodore Ts'o Aq Mt tytso@mit.edu -.Pp -This driver was written under contract for Comtrol Corporation. -For dealer, distributor and other information regarding Comtrol -.Tn RocketPort , -contact Comtrol Corporation at (800) 926-6876 or send email to -.Aq Mt info@comtrol.com . -To report bugs for this driver, please send email to -.Aq Mt bug-bsdi-rocketport@comtrol.com . -.Sh BUGS -If incoming software flow control is enabled on a 486 or Pentium -machine, and the flow control is very heavily exercised, on rare occasions -a character will get dropped. -This problem does not occur on a 386, and -it is not currently known whether the bug is in the -.Nm -driver -or in the -.Bsx -tty layer. -.\" (Although my bet is that it's in the higher-level tty layer; -.\" given the bugs I found while writing this driver, it's clear -.\" the BSD software flow control code has not been tested very much -.\" at all! -- TYT) diff --git a/share/man/man4/safe.4 b/share/man/man4/safe.4 index 4680a9b3710f..3d5cbec03784 100644 --- a/share/man/man4/safe.4 +++ b/share/man/man4/safe.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\"/ -.Dd May 11, 2020 +.Dd July 29, 2020 .Dt SAFE 4 .Os .Sh NAME @@ -124,6 +124,7 @@ A faster version of the 1141. .Xr intro 4 , .Xr ipsec 4 , .Xr random 4 , +.Xr crypto 7 , .Xr crypto 9 .Sh BUGS Public key support is not implemented. diff --git a/share/man/man4/safexcel.4 b/share/man/man4/safexcel.4 index 6751570713f9..774dfddfb053 100644 --- a/share/man/man4/safexcel.4 +++ b/share/man/man4/safexcel.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 23, 2020 +.Dd July 29, 2020 .Dt SAFEXCEL 4 .Os .Sh NAME @@ -75,6 +75,7 @@ with SHA1-HMAC and SHA2-HMAC for encrypt-then-authenticate operations. .Xr crypto 4 , .Xr ipsec 4 , .Xr random 4 , +.Xr crypto 7 , .Xr geli 8 , .Xr crypto 9 .Sh HISTORY diff --git a/share/man/man8/rc.subr.8 b/share/man/man8/rc.subr.8 index fd23ca20c36c..f522a5d162c3 100644 --- a/share/man/man8/rc.subr.8 +++ b/share/man/man8/rc.subr.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 24, 2020 +.Dd July 31, 2020 .Dt RC.SUBR 8 .Os .Sh NAME @@ -882,7 +882,11 @@ Prevent booting to multiuser mode. If the .Va autoboot variable is set to -.Ql yes , +.Ql yes +(see +.Xr rc 8 +to learn more about +.Va autoboot ) , or .Ic checkyesno Ar always indicates a truth value, then a diff --git a/share/misc/committers-doc.dot b/share/misc/committers-doc.dot index 691248727521..4edffffeed1b 100644 --- a/share/misc/committers-doc.dot +++ b/share/misc/committers-doc.dot @@ -62,6 +62,7 @@ carlavilla [label="Sergio Carlavilla\ncarlavilla@FreeBSD.org\n2019/05/16"] chinsan [label="Chinsan Huang\nchinsan@FreeBSD.org\n2006/09/20"] crees [label="Chris Rees\ncrees@FreeBSD.org\n2013/05/27"] danger [label="Daniel Gerzo\ndanger@FreeBSD.org\n2006/08/20"] +debdrup [label="Daniel Ebdrup Jensen\ndebdrup@FreeBSD.org\n2020/07/26"] delphij [label="Xin Li\ndelphij@FreeBSD.org\n2004/09/14"] dexter [label="Michael Dexter\ndexter@FreeBSD.org\n2016/11/15"] dru [label="Dru Lavigne\ndru@FreeBSD.org\n2013/01/22"] @@ -103,6 +104,10 @@ zeising [label="Niclas Zeising\nzeising@FreeBSD.org\n2012/07/03"] # Group together all the mentees for a particular mentor. # Keep the list sorted by mentor login. +"0mp" -> debdrup + +allanjude -> debdrup + bcr -> gavin bcr -> wblock bcr -> eadler @@ -117,6 +122,7 @@ bcr -> sg bcr -> carlavilla bcr -> "0mp" bcr -> gbe +bcr -> debdrup blackend -> ale diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot index a7550b9a6ce2..212c1b613029 100644 --- a/share/misc/committers-src.dot +++ b/share/misc/committers-src.dot @@ -300,6 +300,7 @@ ram [label="Ram Kishore Vegesna\nram@FreeBSD.org\n2018/04/04"] ray [label="Aleksandr Rybalko\nray@FreeBSD.org\n2011/05/25"] rdivacky [label="Roman Divacky\nrdivacky@FreeBSD.org\n2008/03/13"] remko [label="Remko Lodder\nremko@FreeBSD.org\n2007/02/23"] +rew [label="Robert Wing\nrew@FreeBSD.org\n2020/07/23"] rgrimes [label="Rodney W. Grimes\nrgrimes@FreeBSD.org\n1993/06/12\n2017/03/03"] rik [label="Roman Kurakin\nrik@FreeBSD.org\n2003/12/18"] rlibby [label="Ryan Libby\nrlibby@FreeBSD.org\n2017/06/07"] @@ -404,6 +405,7 @@ adrian -> sgalabov ae -> melifaro +allanjude -> rew allanjude -> tsoome alc -> davide @@ -673,6 +675,8 @@ ken -> ram ken -> slm ken -> will +kevans -> rew + kib -> ae kib -> badger kib -> dchagin diff --git a/stand/common/install.c b/stand/common/install.c index de0fd88fc4e3..ea6eaaa7cebc 100644 --- a/stand/common/install.c +++ b/stand/common/install.c @@ -286,10 +286,6 @@ install(char *pkgname) setenv("serverip", inet_ntoa(servip), 1); - if (proto == &tftp_fsops) { - tftpip.s_addr = servip.s_addr; - } - *pkgname = '/'; } else pkgname = s; @@ -340,7 +336,7 @@ install(char *pkgname) fd = open(s, O_RDONLY); if (fd != -1) { close(fd); - error = inter_include(s); + error = interp_include(s); if (error == CMD_ERROR) goto fail; } diff --git a/sys/arm/allwinner/clkng/ccu_sun8i_r.c b/sys/arm/allwinner/clkng/ccu_sun8i_r.c index 74f822ca761d..a0b7093ea8fd 100644 --- a/sys/arm/allwinner/clkng/ccu_sun8i_r.c +++ b/sys/arm/allwinner/clkng/ccu_sun8i_r.c @@ -122,7 +122,7 @@ NM_CLK(r_ccu_ir_clk, 16, 2, 0, 0, /* M flags */ 24, 2, /* mux */ 31, /* gate */ - AW_CLK_HAS_MUX | AW_CLK_REPARENT); /* flags */ + AW_CLK_HAS_MUX | AW_CLK_REPARENT | AW_CLK_HAS_GATE);/* flags */ static const char *a83t_ir_parents[] = {"osc16M", "osc24M"}; static struct aw_clk_nm_def a83t_ir_clk = { diff --git a/sys/arm/arm/trap-v6.c b/sys/arm/arm/trap-v6.c index 84acf479bfe1..7ade224f949e 100644 --- a/sys/arm/arm/trap-v6.c +++ b/sys/arm/arm/trap-v6.c @@ -169,7 +169,8 @@ static const struct abort aborts[] = { }; static __inline void -call_trapsignal(struct thread *td, int sig, int code, vm_offset_t addr) +call_trapsignal(struct thread *td, int sig, int code, vm_offset_t addr, + int trapno) { ksiginfo_t ksi; @@ -185,6 +186,7 @@ call_trapsignal(struct thread *td, int sig, int code, vm_offset_t addr) ksi.ksi_signo = sig; ksi.ksi_code = code; ksi.ksi_addr = (void *)addr; + ksi.ksi_trapno = trapno; trapsignal(td, &ksi); } @@ -252,7 +254,7 @@ abort_debug(struct trapframe *tf, u_int fsr, u_int prefetch, bool usermode, struct thread *td; td = curthread; - call_trapsignal(td, SIGTRAP, TRAP_BRKPT, far); + call_trapsignal(td, SIGTRAP, TRAP_BRKPT, far, FAULT_DEBUG); userret(td, tf); } else { #ifdef KDB @@ -523,7 +525,7 @@ nogo: ksig.addr = far; do_trapsignal: - call_trapsignal(td, ksig.sig, ksig.code, ksig.addr); + call_trapsignal(td, ksig.sig, ksig.code, ksig.addr, idx); out: if (usermode) userret(td, tf); diff --git a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c index 1b5e3a63e09e..15c1106cf36f 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c @@ -47,12 +47,10 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> -#include <arm/broadcom/bcm2835/bcm2835_mbox.h> -#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h> +#include <arm/broadcom/bcm2835/bcm2835_firmware.h> #include <arm/broadcom/bcm2835/bcm2835_vcbus.h> #include "cpufreq_if.h" -#include "mbox_if.h" #ifdef DEBUG #define DPRINTF(fmt, ...) do { \ @@ -101,6 +99,7 @@ static struct sysctl_ctx_list bcm2835_sysctl_ctx; struct bcm2835_cpufreq_softc { device_t dev; + device_t firmware; int arm_max_freq; int arm_min_freq; int core_max_freq; @@ -161,7 +160,7 @@ static int bcm2835_cpufreq_get_clock_rate(struct bcm2835_cpufreq_softc *sc, uint32_t clock_id) { - struct msg_get_clock_rate msg; + union msg_get_clock_rate_body msg; int rate; int err; @@ -181,16 +180,11 @@ bcm2835_cpufreq_get_clock_rate(struct bcm2835_cpufreq_softc *sc, /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_CLOCK_RATE; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.clock_id = clock_id; - msg.end_tag = 0; + msg.req.clock_id = clock_id; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_GET_CLOCK_RATE, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't get clock rate (id=%u)\n", clock_id); @@ -198,7 +192,7 @@ bcm2835_cpufreq_get_clock_rate(struct bcm2835_cpufreq_softc *sc, } /* result (Hz) */ - rate = (int)msg.body.resp.rate_hz; + rate = (int)msg.resp.rate_hz; DPRINTF("clock = %d(Hz)\n", rate); return (rate); } @@ -207,7 +201,7 @@ static int bcm2835_cpufreq_get_max_clock_rate(struct bcm2835_cpufreq_softc *sc, uint32_t clock_id) { - struct msg_get_max_clock_rate msg; + union msg_get_clock_rate_body msg; int rate; int err; @@ -227,16 +221,11 @@ bcm2835_cpufreq_get_max_clock_rate(struct bcm2835_cpufreq_softc *sc, /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MAX_CLOCK_RATE; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.clock_id = clock_id; - msg.end_tag = 0; + msg.req.clock_id = clock_id; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_GET_MAX_CLOCK_RATE, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't get max clock rate (id=%u)\n", clock_id); @@ -244,7 +233,7 @@ bcm2835_cpufreq_get_max_clock_rate(struct bcm2835_cpufreq_softc *sc, } /* result (Hz) */ - rate = (int)msg.body.resp.rate_hz; + rate = (int)msg.resp.rate_hz; DPRINTF("clock = %d(Hz)\n", rate); return (rate); } @@ -253,7 +242,7 @@ static int bcm2835_cpufreq_get_min_clock_rate(struct bcm2835_cpufreq_softc *sc, uint32_t clock_id) { - struct msg_get_min_clock_rate msg; + union msg_get_clock_rate_body msg; int rate; int err; @@ -273,16 +262,11 @@ bcm2835_cpufreq_get_min_clock_rate(struct bcm2835_cpufreq_softc *sc, /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MIN_CLOCK_RATE; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.clock_id = clock_id; - msg.end_tag = 0; + msg.req.clock_id = clock_id; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_GET_MIN_CLOCK_RATE, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't get min clock rate (id=%u)\n", clock_id); @@ -290,7 +274,7 @@ bcm2835_cpufreq_get_min_clock_rate(struct bcm2835_cpufreq_softc *sc, } /* result (Hz) */ - rate = (int)msg.body.resp.rate_hz; + rate = (int)msg.resp.rate_hz; DPRINTF("clock = %d(Hz)\n", rate); return (rate); } @@ -299,7 +283,7 @@ static int bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc, uint32_t clock_id, uint32_t rate_hz) { - struct msg_set_clock_rate msg; + union msg_set_clock_rate_body msg; int rate; int err; @@ -320,17 +304,12 @@ bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc, /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_CLOCK_RATE; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.clock_id = clock_id; - msg.body.req.rate_hz = rate_hz; - msg.end_tag = 0; + msg.req.clock_id = clock_id; + msg.req.rate_hz = rate_hz; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_SET_CLOCK_RATE, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't set clock rate (id=%u)\n", clock_id); @@ -338,7 +317,7 @@ bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc, } /* workaround for core clock */ - if (clock_id == BCM2835_MBOX_CLOCK_ID_CORE) { + if (clock_id == BCM2835_FIRMWARE_CLOCK_ID_CORE) { /* for safety (may change voltage without changing clock) */ DELAY(TRANSITION_LATENCY); @@ -349,17 +328,12 @@ bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc, /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_CLOCK_RATE; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.clock_id = clock_id; - msg.body.req.rate_hz = rate_hz; - msg.end_tag = 0; + msg.req.clock_id = clock_id; + msg.req.rate_hz = rate_hz; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_SET_CLOCK_RATE, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't set clock rate (id=%u)\n", clock_id); @@ -368,7 +342,7 @@ bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc, } /* result (Hz) */ - rate = (int)msg.body.resp.rate_hz; + rate = (int)msg.resp.rate_hz; DPRINTF("clock = %d(Hz)\n", rate); return (rate); } @@ -376,7 +350,7 @@ bcm2835_cpufreq_set_clock_rate(struct bcm2835_cpufreq_softc *sc, static int bcm2835_cpufreq_get_turbo(struct bcm2835_cpufreq_softc *sc) { - struct msg_get_turbo msg; + union msg_get_turbo_body msg; int level; int err; @@ -396,23 +370,18 @@ bcm2835_cpufreq_get_turbo(struct bcm2835_cpufreq_softc *sc) /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_TURBO; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.id = 0; - msg.end_tag = 0; + msg.req.id = 0; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_GET_TURBO, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't get turbo\n"); return (MSG_ERROR); } /* result 0=non-turbo, 1=turbo */ - level = (int)msg.body.resp.level; + level = (int)msg.resp.level; DPRINTF("level = %d\n", level); return (level); } @@ -420,7 +389,7 @@ bcm2835_cpufreq_get_turbo(struct bcm2835_cpufreq_softc *sc) static int bcm2835_cpufreq_set_turbo(struct bcm2835_cpufreq_softc *sc, uint32_t level) { - struct msg_set_turbo msg; + union msg_set_turbo_body msg; int value; int err; @@ -440,29 +409,25 @@ bcm2835_cpufreq_set_turbo(struct bcm2835_cpufreq_softc *sc, uint32_t level) */ /* replace unknown value to OFF */ - if (level != BCM2835_MBOX_TURBO_ON && level != BCM2835_MBOX_TURBO_OFF) - level = BCM2835_MBOX_TURBO_OFF; + if (level != BCM2835_FIRMWARE_TURBO_ON && + level != BCM2835_FIRMWARE_TURBO_OFF) + level = BCM2835_FIRMWARE_TURBO_OFF; /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_TURBO; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.id = 0; - msg.body.req.level = level; - msg.end_tag = 0; + msg.req.id = 0; + msg.req.level = level; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_SET_TURBO, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't set turbo\n"); return (MSG_ERROR); } /* result 0=non-turbo, 1=turbo */ - value = (int)msg.body.resp.level; + value = (int)msg.resp.level; DPRINTF("level = %d\n", value); return (value); } @@ -471,7 +436,7 @@ static int bcm2835_cpufreq_get_voltage(struct bcm2835_cpufreq_softc *sc, uint32_t voltage_id) { - struct msg_get_voltage msg; + union msg_get_voltage_body msg; int value; int err; @@ -491,23 +456,18 @@ bcm2835_cpufreq_get_voltage(struct bcm2835_cpufreq_softc *sc, /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_VOLTAGE; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.voltage_id = voltage_id; - msg.end_tag = 0; + msg.req.voltage_id = voltage_id; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_GET_VOLTAGE, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't get voltage\n"); return (MSG_ERROR); } /* result (offset from 1.2V) */ - value = (int)msg.body.resp.value; + value = (int)msg.resp.value; DPRINTF("value = %d\n", value); return (value); } @@ -516,7 +476,7 @@ static int bcm2835_cpufreq_get_max_voltage(struct bcm2835_cpufreq_softc *sc, uint32_t voltage_id) { - struct msg_get_max_voltage msg; + union msg_get_voltage_body msg; int value; int err; @@ -536,23 +496,18 @@ bcm2835_cpufreq_get_max_voltage(struct bcm2835_cpufreq_softc *sc, /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MAX_VOLTAGE; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.voltage_id = voltage_id; - msg.end_tag = 0; + msg.req.voltage_id = voltage_id; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_GET_MAX_VOLTAGE, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't get max voltage\n"); return (MSG_ERROR); } /* result (offset from 1.2V) */ - value = (int)msg.body.resp.value; + value = (int)msg.resp.value; DPRINTF("value = %d\n", value); return (value); } @@ -560,7 +515,7 @@ static int bcm2835_cpufreq_get_min_voltage(struct bcm2835_cpufreq_softc *sc, uint32_t voltage_id) { - struct msg_get_min_voltage msg; + union msg_get_voltage_body msg; int value; int err; @@ -580,23 +535,18 @@ bcm2835_cpufreq_get_min_voltage(struct bcm2835_cpufreq_softc *sc, /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_MIN_VOLTAGE; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.voltage_id = voltage_id; - msg.end_tag = 0; + msg.req.voltage_id = voltage_id; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_GET_MIN_VOLTAGE, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't get min voltage\n"); return (MSG_ERROR); } /* result (offset from 1.2V) */ - value = (int)msg.body.resp.value; + value = (int)msg.resp.value; DPRINTF("value = %d\n", value); return (value); } @@ -605,7 +555,7 @@ static int bcm2835_cpufreq_set_voltage(struct bcm2835_cpufreq_softc *sc, uint32_t voltage_id, int32_t value) { - struct msg_set_voltage msg; + union msg_set_voltage_body msg; int err; /* @@ -636,24 +586,19 @@ bcm2835_cpufreq_set_voltage(struct bcm2835_cpufreq_softc *sc, /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_VOLTAGE; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.voltage_id = voltage_id; - msg.body.req.value = (uint32_t)value; - msg.end_tag = 0; + msg.req.voltage_id = voltage_id; + msg.req.value = (uint32_t)value; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_SET_VOLTAGE, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't set voltage\n"); return (MSG_ERROR); } /* result (offset from 1.2V) */ - value = (int)msg.body.resp.value; + value = (int)msg.resp.value; DPRINTF("value = %d\n", value); return (value); } @@ -661,7 +606,7 @@ bcm2835_cpufreq_set_voltage(struct bcm2835_cpufreq_softc *sc, static int bcm2835_cpufreq_get_temperature(struct bcm2835_cpufreq_softc *sc) { - struct msg_get_temperature msg; + union msg_get_temperature_body msg; int value; int err; @@ -681,23 +626,18 @@ bcm2835_cpufreq_get_temperature(struct bcm2835_cpufreq_softc *sc) /* setup single tag buffer */ memset(&msg, 0, sizeof(msg)); - msg.hdr.buf_size = sizeof(msg); - msg.hdr.code = BCM2835_MBOX_CODE_REQ; - msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_TEMPERATURE; - msg.tag_hdr.val_buf_size = sizeof(msg.body); - msg.tag_hdr.val_len = sizeof(msg.body.req); - msg.body.req.temperature_id = 0; - msg.end_tag = 0; + msg.req.temperature_id = 0; /* call mailbox property */ - err = bcm2835_mbox_property(&msg, sizeof(msg)); + err = bcm2835_firmware_property(sc->firmware, + BCM2835_FIRMWARE_TAG_GET_TEMPERATURE, &msg, sizeof(msg)); if (err) { device_printf(sc->dev, "can't get temperature\n"); return (MSG_ERROR); } /* result (temperature of degree C) */ - value = (int)msg.body.resp.value; + value = (int)msg.resp.value; DPRINTF("value = %d\n", value); return (value); } @@ -713,7 +653,7 @@ sysctl_bcm2835_cpufreq_arm_freq(SYSCTL_HANDLER_ARGS) /* get realtime value */ VC_LOCK(sc); - val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM); + val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_FIRMWARE_CLOCK_ID_ARM); VC_UNLOCK(sc); if (val == MSG_ERROR) return (EIO); @@ -724,7 +664,7 @@ sysctl_bcm2835_cpufreq_arm_freq(SYSCTL_HANDLER_ARGS) /* write request */ VC_LOCK(sc); - err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM, + err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_FIRMWARE_CLOCK_ID_ARM, val); VC_UNLOCK(sc); if (err == MSG_ERROR) { @@ -745,7 +685,8 @@ sysctl_bcm2835_cpufreq_core_freq(SYSCTL_HANDLER_ARGS) /* get realtime value */ VC_LOCK(sc); - val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE); + val = bcm2835_cpufreq_get_clock_rate(sc, + BCM2835_FIRMWARE_CLOCK_ID_CORE); VC_UNLOCK(sc); if (val == MSG_ERROR) return (EIO); @@ -756,7 +697,7 @@ sysctl_bcm2835_cpufreq_core_freq(SYSCTL_HANDLER_ARGS) /* write request */ VC_LOCK(sc); - err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE, + err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_FIRMWARE_CLOCK_ID_CORE, val); if (err == MSG_ERROR) { VC_UNLOCK(sc); @@ -778,7 +719,8 @@ sysctl_bcm2835_cpufreq_sdram_freq(SYSCTL_HANDLER_ARGS) /* get realtime value */ VC_LOCK(sc); - val = bcm2835_cpufreq_get_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_SDRAM); + val = bcm2835_cpufreq_get_clock_rate(sc, + BCM2835_FIRMWARE_CLOCK_ID_SDRAM); VC_UNLOCK(sc); if (val == MSG_ERROR) return (EIO); @@ -789,8 +731,8 @@ sysctl_bcm2835_cpufreq_sdram_freq(SYSCTL_HANDLER_ARGS) /* write request */ VC_LOCK(sc); - err = bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_SDRAM, - val); + err = bcm2835_cpufreq_set_clock_rate(sc, + BCM2835_FIRMWARE_CLOCK_ID_SDRAM, val); VC_UNLOCK(sc); if (err == MSG_ERROR) { device_printf(sc->dev, "set clock sdram_freq error\n"); @@ -821,9 +763,9 @@ sysctl_bcm2835_cpufreq_turbo(SYSCTL_HANDLER_ARGS) /* write request */ if (val > 0) - sc->turbo_mode = BCM2835_MBOX_TURBO_ON; + sc->turbo_mode = BCM2835_FIRMWARE_TURBO_ON; else - sc->turbo_mode = BCM2835_MBOX_TURBO_OFF; + sc->turbo_mode = BCM2835_FIRMWARE_TURBO_OFF; VC_LOCK(sc); err = bcm2835_cpufreq_set_turbo(sc, sc->turbo_mode); @@ -846,7 +788,7 @@ sysctl_bcm2835_cpufreq_voltage_core(SYSCTL_HANDLER_ARGS) /* get realtime value */ VC_LOCK(sc); - val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_CORE); + val = bcm2835_cpufreq_get_voltage(sc, BCM2835_FIRMWARE_VOLTAGE_ID_CORE); VC_UNLOCK(sc); if (val == MSG_ERROR) return (EIO); @@ -861,7 +803,7 @@ sysctl_bcm2835_cpufreq_voltage_core(SYSCTL_HANDLER_ARGS) sc->voltage_core = val; VC_LOCK(sc); - err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_CORE, + err = bcm2835_cpufreq_set_voltage(sc, BCM2835_FIRMWARE_VOLTAGE_ID_CORE, sc->voltage_core); VC_UNLOCK(sc); if (err == MSG_ERROR) { @@ -882,7 +824,8 @@ sysctl_bcm2835_cpufreq_voltage_sdram_c(SYSCTL_HANDLER_ARGS) /* get realtime value */ VC_LOCK(sc); - val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C); + val = bcm2835_cpufreq_get_voltage(sc, + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C); VC_UNLOCK(sc); if (val == MSG_ERROR) return (EIO); @@ -897,7 +840,8 @@ sysctl_bcm2835_cpufreq_voltage_sdram_c(SYSCTL_HANDLER_ARGS) sc->voltage_sdram_c = val; VC_LOCK(sc); - err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C, + err = bcm2835_cpufreq_set_voltage(sc, + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C, sc->voltage_sdram_c); VC_UNLOCK(sc); if (err == MSG_ERROR) { @@ -918,7 +862,8 @@ sysctl_bcm2835_cpufreq_voltage_sdram_i(SYSCTL_HANDLER_ARGS) /* get realtime value */ VC_LOCK(sc); - val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I); + val = bcm2835_cpufreq_get_voltage(sc, + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I); VC_UNLOCK(sc); if (val == MSG_ERROR) return (EIO); @@ -933,8 +878,8 @@ sysctl_bcm2835_cpufreq_voltage_sdram_i(SYSCTL_HANDLER_ARGS) sc->voltage_sdram_i = val; VC_LOCK(sc); - err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I, - sc->voltage_sdram_i); + err = bcm2835_cpufreq_set_voltage(sc, + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I, sc->voltage_sdram_i); VC_UNLOCK(sc); if (err == MSG_ERROR) { device_printf(sc->dev, "set voltage sdram_i error\n"); @@ -954,7 +899,8 @@ sysctl_bcm2835_cpufreq_voltage_sdram_p(SYSCTL_HANDLER_ARGS) /* get realtime value */ VC_LOCK(sc); - val = bcm2835_cpufreq_get_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P); + val = bcm2835_cpufreq_get_voltage(sc, + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P); VC_UNLOCK(sc); if (val == MSG_ERROR) return (EIO); @@ -969,8 +915,8 @@ sysctl_bcm2835_cpufreq_voltage_sdram_p(SYSCTL_HANDLER_ARGS) sc->voltage_sdram_p = val; VC_LOCK(sc); - err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P, - sc->voltage_sdram_p); + err = bcm2835_cpufreq_set_voltage(sc, + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P, sc->voltage_sdram_p); VC_UNLOCK(sc); if (err == MSG_ERROR) { device_printf(sc->dev, "set voltage sdram_p error\n"); @@ -1002,22 +948,22 @@ sysctl_bcm2835_cpufreq_voltage_sdram(SYSCTL_HANDLER_ARGS) sc->voltage_sdram = val; VC_LOCK(sc); - err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_C, - val); + err = bcm2835_cpufreq_set_voltage(sc, + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C, val); if (err == MSG_ERROR) { VC_UNLOCK(sc); device_printf(sc->dev, "set voltage sdram_c error\n"); return (EIO); } - err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_I, - val); + err = bcm2835_cpufreq_set_voltage(sc, + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I, val); if (err == MSG_ERROR) { VC_UNLOCK(sc); device_printf(sc->dev, "set voltage sdram_i error\n"); return (EIO); } - err = bcm2835_cpufreq_set_voltage(sc, BCM2835_MBOX_VOLTAGE_ID_SDRAM_P, - val); + err = bcm2835_cpufreq_set_voltage(sc, + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P, val); if (err == MSG_ERROR) { VC_UNLOCK(sc); device_printf(sc->dev, "set voltage sdram_p error\n"); @@ -1097,42 +1043,42 @@ bcm2835_cpufreq_init(void *arg) /* current clock */ arm_freq = bcm2835_cpufreq_get_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_ARM); + BCM2835_FIRMWARE_CLOCK_ID_ARM); core_freq = bcm2835_cpufreq_get_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_CORE); + BCM2835_FIRMWARE_CLOCK_ID_CORE); sdram_freq = bcm2835_cpufreq_get_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_SDRAM); + BCM2835_FIRMWARE_CLOCK_ID_SDRAM); /* max/min clock */ arm_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_ARM); + BCM2835_FIRMWARE_CLOCK_ID_ARM); arm_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_ARM); + BCM2835_FIRMWARE_CLOCK_ID_ARM); core_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_CORE); + BCM2835_FIRMWARE_CLOCK_ID_CORE); core_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_CORE); + BCM2835_FIRMWARE_CLOCK_ID_CORE); sdram_max_freq = bcm2835_cpufreq_get_max_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_SDRAM); + BCM2835_FIRMWARE_CLOCK_ID_SDRAM); sdram_min_freq = bcm2835_cpufreq_get_min_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_SDRAM); + BCM2835_FIRMWARE_CLOCK_ID_SDRAM); /* turbo mode */ turbo = bcm2835_cpufreq_get_turbo(sc); if (turbo > 0) - sc->turbo_mode = BCM2835_MBOX_TURBO_ON; + sc->turbo_mode = BCM2835_FIRMWARE_TURBO_ON; else - sc->turbo_mode = BCM2835_MBOX_TURBO_OFF; + sc->turbo_mode = BCM2835_FIRMWARE_TURBO_OFF; /* voltage */ voltage_core = bcm2835_cpufreq_get_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_CORE); + BCM2835_FIRMWARE_VOLTAGE_ID_CORE); voltage_sdram_c = bcm2835_cpufreq_get_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_SDRAM_C); + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C); voltage_sdram_i = bcm2835_cpufreq_get_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_SDRAM_I); + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I); voltage_sdram_p = bcm2835_cpufreq_get_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_SDRAM_P); + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P); /* current values (offset from 1.2V) */ sc->voltage_core = voltage_core; @@ -1143,21 +1089,21 @@ bcm2835_cpufreq_init(void *arg) /* max/min voltage */ max_voltage_core = bcm2835_cpufreq_get_max_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_CORE); + BCM2835_FIRMWARE_VOLTAGE_ID_CORE); min_voltage_core = bcm2835_cpufreq_get_min_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_CORE); + BCM2835_FIRMWARE_VOLTAGE_ID_CORE); max_voltage_sdram_c = bcm2835_cpufreq_get_max_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_SDRAM_C); + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C); max_voltage_sdram_i = bcm2835_cpufreq_get_max_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_SDRAM_I); + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I); max_voltage_sdram_p = bcm2835_cpufreq_get_max_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_SDRAM_P); + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P); min_voltage_sdram_c = bcm2835_cpufreq_get_min_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_SDRAM_C); + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C); min_voltage_sdram_i = bcm2835_cpufreq_get_min_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_SDRAM_I); + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I); min_voltage_sdram_p = bcm2835_cpufreq_get_min_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_SDRAM_P); + BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P); /* temperature */ temperature = bcm2835_cpufreq_get_temperature(sc); @@ -1168,7 +1114,7 @@ bcm2835_cpufreq_init(void *arg) device_printf(sc->dev, "current ARM %dMHz, Core %dMHz, SDRAM %dMHz, Turbo %s\n", HZ2MHZ(arm_freq), HZ2MHZ(core_freq), HZ2MHZ(sdram_freq), - (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) ? "ON" : "OFF"); + (sc->turbo_mode == BCM2835_FIRMWARE_TURBO_ON) ? "ON":"OFF"); device_printf(sc->dev, "max/min ARM %d/%dMHz, Core %d/%dMHz, SDRAM %d/%dMHz\n", @@ -1202,7 +1148,7 @@ bcm2835_cpufreq_init(void *arg) device_printf(sc->dev, "ARM %dMHz, Core %dMHz, SDRAM %dMHz, Turbo %s\n", HZ2MHZ(arm_freq), HZ2MHZ(core_freq), HZ2MHZ(sdram_freq), - (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) ? "ON" : "OFF"); + (sc->turbo_mode == BCM2835_FIRMWARE_TURBO_ON) ? "ON":"OFF"); } /* keep in softc (MHz/mV) */ @@ -1216,25 +1162,25 @@ bcm2835_cpufreq_init(void *arg) sc->min_voltage_core = OFFSET2MVOLT(min_voltage_core); /* if turbo is on, set to max values */ - if (sc->turbo_mode == BCM2835_MBOX_TURBO_ON) { - bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM, - arm_max_freq); + if (sc->turbo_mode == BCM2835_FIRMWARE_TURBO_ON) { + bcm2835_cpufreq_set_clock_rate(sc, + BCM2835_FIRMWARE_CLOCK_ID_ARM, arm_max_freq); DELAY(TRANSITION_LATENCY); - bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE, - core_max_freq); + bcm2835_cpufreq_set_clock_rate(sc, + BCM2835_FIRMWARE_CLOCK_ID_CORE, core_max_freq); DELAY(TRANSITION_LATENCY); bcm2835_cpufreq_set_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_SDRAM, sdram_max_freq); + BCM2835_FIRMWARE_CLOCK_ID_SDRAM, sdram_max_freq); DELAY(TRANSITION_LATENCY); } else { - bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_ARM, - arm_min_freq); + bcm2835_cpufreq_set_clock_rate(sc, + BCM2835_FIRMWARE_CLOCK_ID_ARM, arm_min_freq); DELAY(TRANSITION_LATENCY); - bcm2835_cpufreq_set_clock_rate(sc, BCM2835_MBOX_CLOCK_ID_CORE, - core_min_freq); + bcm2835_cpufreq_set_clock_rate(sc, + BCM2835_FIRMWARE_CLOCK_ID_CORE, core_min_freq); DELAY(TRANSITION_LATENCY); bcm2835_cpufreq_set_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_SDRAM, sdram_min_freq); + BCM2835_FIRMWARE_CLOCK_ID_SDRAM, sdram_min_freq); DELAY(TRANSITION_LATENCY); } @@ -1297,6 +1243,12 @@ bcm2835_cpufreq_attach(device_t dev) /* set self dev */ sc = device_get_softc(dev); sc->dev = dev; + sc->firmware = devclass_get_device( + devclass_find("bcm2835_firmware"), 0); + if (sc->firmware == NULL) { + device_printf(dev, "Unable to find firmware device\n"); + return (ENXIO); + } /* initial values */ sc->arm_max_freq = -1; @@ -1430,7 +1382,7 @@ bcm2835_cpufreq_set(device_t dev, const struct cf_setting *cf) /* adjust min freq */ min_freq = sc->arm_min_freq; - if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON) + if (sc->turbo_mode != BCM2835_FIRMWARE_TURBO_ON) if (min_freq > cpufreq_lowest_freq) min_freq = cpufreq_lowest_freq; @@ -1441,28 +1393,28 @@ bcm2835_cpufreq_set(device_t dev, const struct cf_setting *cf) VC_LOCK(sc); #ifdef DEBUG cur_freq = bcm2835_cpufreq_get_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_ARM); + BCM2835_FIRMWARE_CLOCK_ID_ARM); #endif resp_freq = bcm2835_cpufreq_set_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_ARM, rate_hz); + BCM2835_FIRMWARE_CLOCK_ID_ARM, rate_hz); DELAY(TRANSITION_LATENCY); arm_freq = bcm2835_cpufreq_get_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_ARM); + BCM2835_FIRMWARE_CLOCK_ID_ARM); /* * if non-turbo and lower than or equal min_freq, * clock down core and sdram to default first. */ - if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON) { + if (sc->turbo_mode != BCM2835_FIRMWARE_TURBO_ON) { core_freq = bcm2835_cpufreq_get_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_CORE); + BCM2835_FIRMWARE_CLOCK_ID_CORE); if (rate_hz > MHZ2HZ(sc->arm_min_freq)) { bcm2835_cpufreq_set_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_CORE, + BCM2835_FIRMWARE_CLOCK_ID_CORE, MHZ2HZ(sc->core_max_freq)); DELAY(TRANSITION_LATENCY); bcm2835_cpufreq_set_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_SDRAM, + BCM2835_FIRMWARE_CLOCK_ID_SDRAM, MHZ2HZ(sc->sdram_max_freq)); DELAY(TRANSITION_LATENCY); } else { @@ -1471,20 +1423,20 @@ bcm2835_cpufreq_set(device_t dev, const struct cf_setting *cf) /* first, down to 250, then down to min */ DELAY(TRANSITION_LATENCY); bcm2835_cpufreq_set_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_CORE, + BCM2835_FIRMWARE_CLOCK_ID_CORE, MHZ2HZ(DEFAULT_CORE_FREQUENCY)); DELAY(TRANSITION_LATENCY); /* reset core voltage */ bcm2835_cpufreq_set_voltage(sc, - BCM2835_MBOX_VOLTAGE_ID_CORE, 0); + BCM2835_FIRMWARE_VOLTAGE_ID_CORE, 0); DELAY(TRANSITION_LATENCY); } bcm2835_cpufreq_set_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_CORE, + BCM2835_FIRMWARE_CLOCK_ID_CORE, MHZ2HZ(sc->core_min_freq)); DELAY(TRANSITION_LATENCY); bcm2835_cpufreq_set_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_SDRAM, + BCM2835_FIRMWARE_CLOCK_ID_SDRAM, MHZ2HZ(sc->sdram_min_freq)); DELAY(TRANSITION_LATENCY); } @@ -1517,7 +1469,7 @@ bcm2835_cpufreq_get(device_t dev, struct cf_setting *cf) /* get cuurent value */ VC_LOCK(sc); arm_freq = bcm2835_cpufreq_get_clock_rate(sc, - BCM2835_MBOX_CLOCK_ID_ARM); + BCM2835_FIRMWARE_CLOCK_ID_ARM); VC_UNLOCK(sc); if (arm_freq < 0) { device_printf(dev, "can't get clock\n"); @@ -1557,7 +1509,7 @@ bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets, freq = min_freq; /* if non-turbo, add extra low freq */ - if (sc->turbo_mode != BCM2835_MBOX_TURBO_ON) + if (sc->turbo_mode != BCM2835_FIRMWARE_TURBO_ON) if (min_freq > cpufreq_lowest_freq) min_freq = cpufreq_lowest_freq; @@ -1654,3 +1606,4 @@ static driver_t bcm2835_cpufreq_driver = { DRIVER_MODULE(bcm2835_cpufreq, cpu, bcm2835_cpufreq_driver, bcm2835_cpufreq_devclass, 0, 0); +MODULE_DEPEND(bcm2835_cpufreq, bcm2835_firmware, 1, 1, 1); diff --git a/sys/arm/broadcom/bcm2835/bcm2835_firmware.c b/sys/arm/broadcom/bcm2835/bcm2835_firmware.c index dcc23fe1cd61..44201ec80f7d 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_firmware.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_firmware.c @@ -177,5 +177,6 @@ static driver_t bcm2835_firmware_driver = { sizeof(struct bcm2835_firmware_softc), }; -DRIVER_MODULE(bcm2835_firmware, simplebus, bcm2835_firmware_driver, - bcm2835_firmware_devclass, 0, 0); +EARLY_DRIVER_MODULE(bcm2835_firmware, simplebus, bcm2835_firmware_driver, + bcm2835_firmware_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST); +MODULE_DEPEND(bcm2835_firmware, mbox, 1, 1, 1); diff --git a/sys/arm/broadcom/bcm2835/bcm2835_firmware.h b/sys/arm/broadcom/bcm2835/bcm2835_firmware.h index da6a137083ed..666e450914f8 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_firmware.h +++ b/sys/arm/broadcom/bcm2835/bcm2835_firmware.h @@ -33,6 +33,170 @@ #ifndef _BCM2835_FIRMWARE_H_ #define _BCM2835_FIRMWARE_H_ +#define BCM2835_FIRMWARE_TAG_GET_CLOCK_RATE 0x00030002 +#define BCM2835_FIRMWARE_TAG_SET_CLOCK_RATE 0x00038002 +#define BCM2835_FIRMWARE_TAG_GET_MAX_CLOCK_RATE 0x00030004 +#define BCM2835_FIRMWARE_TAG_GET_MIN_CLOCK_RATE 0x00030007 + +#define BCM2835_FIRMWARE_CLOCK_ID_EMMC 0x00000001 +#define BCM2835_FIRMWARE_CLOCK_ID_UART 0x00000002 +#define BCM2835_FIRMWARE_CLOCK_ID_ARM 0x00000003 +#define BCM2835_FIRMWARE_CLOCK_ID_CORE 0x00000004 +#define BCM2835_FIRMWARE_CLOCK_ID_V3D 0x00000005 +#define BCM2835_FIRMWARE_CLOCK_ID_H264 0x00000006 +#define BCM2835_FIRMWARE_CLOCK_ID_ISP 0x00000007 +#define BCM2835_FIRMWARE_CLOCK_ID_SDRAM 0x00000008 +#define BCM2835_FIRMWARE_CLOCK_ID_PIXEL 0x00000009 +#define BCM2835_FIRMWARE_CLOCK_ID_PWM 0x0000000a +#define BCM2838_FIRMWARE_CLOCK_ID_EMMC2 0x0000000c + +union msg_get_clock_rate_body { + struct { + uint32_t clock_id; + } req; + struct { + uint32_t clock_id; + uint32_t rate_hz; + } resp; +}; + +union msg_set_clock_rate_body { + struct { + uint32_t clock_id; + uint32_t rate_hz; + } req; + struct { + uint32_t clock_id; + uint32_t rate_hz; + } resp; +}; + +#define BCM2835_FIRMWARE_TAG_GET_VOLTAGE 0x00030003 +#define BCM2835_FIRMWARE_TAG_SET_VOLTAGE 0x00038003 +#define BCM2835_FIRMWARE_TAG_GET_MAX_VOLTAGE 0x00030005 +#define BCM2835_FIRMWARE_TAG_GET_MIN_VOLTAGE 0x00030008 + +#define BCM2835_FIRMWARE_VOLTAGE_ID_CORE 0x00000001 +#define BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_C 0x00000002 +#define BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_P 0x00000003 +#define BCM2835_FIRMWARE_VOLTAGE_ID_SDRAM_I 0x00000004 + +union msg_get_voltage_body { + struct { + uint32_t voltage_id; + } req; + struct { + uint32_t voltage_id; + uint32_t value; + } resp; +}; + +union msg_set_voltage_body { + struct { + uint32_t voltage_id; + uint32_t value; + } req; + struct { + uint32_t voltage_id; + uint32_t value; + } resp; +}; + +#define BCM2835_FIRMWARE_TAG_GET_TEMPERATURE 0x00030006 +#define BCM2835_FIRMWARE_TAG_GET_MAX_TEMPERATURE 0x0003000a + +union msg_get_temperature_body { + struct { + uint32_t temperature_id; + } req; + struct { + uint32_t temperature_id; + uint32_t value; + } resp; +}; + +#define BCM2835_FIRMWARE_TAG_GET_TURBO 0x00030009 +#define BCM2835_FIRMWARE_TAG_SET_TURBO 0x00038009 + +#define BCM2835_FIRMWARE_TURBO_ON 1 +#define BCM2835_FIRMWARE_TURBO_OFF 0 + +union msg_get_turbo_body { + struct { + uint32_t id; + } req; + struct { + uint32_t id; + uint32_t level; + } resp; +}; + +union msg_set_turbo_body { + struct { + uint32_t id; + uint32_t level; + } req; + struct { + uint32_t id; + uint32_t level; + } resp; +}; + +#define BCM2835_FIRMWARE_TAG_GET_GPIO_STATE 0x00030041 +#define BCM2835_FIRMWARE_TAG_SET_GPIO_STATE 0x00038041 +#define BCM2835_FIRMWARE_TAG_GET_GPIO_CONFIG 0x00030043 +#define BCM2835_FIRMWARE_TAG_SET_GPIO_CONFIG 0x00038043 + +#define BCM2835_FIRMWARE_GPIO_IN 0 +#define BCM2835_FIRMWARE_GPIO_OUT 1 + +union msg_get_gpio_state { + struct { + uint32_t gpio; + } req; + struct { + uint32_t gpio; + uint32_t state; + } resp; +}; + +union msg_set_gpio_state { + struct { + uint32_t gpio; + uint32_t state; + } req; + struct { + uint32_t gpio; + } resp; +}; + +union msg_get_gpio_config { + struct { + uint32_t gpio; + } req; + struct { + uint32_t gpio; + uint32_t dir; + uint32_t pol; + uint32_t term_en; + uint32_t term_pull_up; + } resp; +}; + +union msg_set_gpio_config { + struct { + uint32_t gpio; + uint32_t dir; + uint32_t pol; + uint32_t term_en; + uint32_t term_pull_up; + uint32_t state; + } req; + struct { + uint32_t gpio; + } resp; +}; + int bcm2835_firmware_property(device_t, uint32_t, void *, size_t); #endif diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c index 4d6ab7e9a6c3..d722c7aae7a7 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> +#include <arm/broadcom/bcm2835/bcm2835_firmware.h> #include <arm/broadcom/bcm2835/bcm2835_mbox.h> #include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h> #include <arm/broadcom/bcm2835/bcm2835_vcbus.h> @@ -293,7 +294,8 @@ static driver_t bcm_mbox_driver = { static devclass_t bcm_mbox_devclass; -DRIVER_MODULE(mbox, simplebus, bcm_mbox_driver, bcm_mbox_devclass, 0, 0); +EARLY_DRIVER_MODULE(mbox, simplebus, bcm_mbox_driver, bcm_mbox_devclass, 0, 0, + BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST); static void bcm2835_mbox_dma_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err) @@ -361,6 +363,16 @@ bcm2835_mbox_err(device_t dev, bus_addr_t msg_phys, uint32_t resp_phys, tag = (struct bcm2835_mbox_tag_hdr *)(msg + 1); last = (uint8_t *)msg + len; for (idx = 0; tag->tag != 0; idx++) { + /* + * When setting the GPIO config or state the firmware doesn't + * set tag->val_len correctly. + */ + if ((tag->tag == BCM2835_FIRMWARE_TAG_SET_GPIO_CONFIG || + tag->tag == BCM2835_FIRMWARE_TAG_SET_GPIO_STATE) && + tag->val_len == 0) { + tag->val_len = BCM2835_MBOX_TAG_VAL_LEN_RESPONSE | + tag->val_buf_size; + } if ((tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE) == 0) { device_printf(dev, "tag %d response error\n", idx); return (EIO); diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h b/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h index 211820c09c31..15f48aefa536 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h +++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h @@ -113,21 +113,9 @@ struct msg_set_power_state { int bcm2835_mbox_set_power_state(uint32_t, boolean_t); #define BCM2835_MBOX_CLOCK_ID_EMMC 0x00000001 -#define BCM2835_MBOX_CLOCK_ID_UART 0x00000002 -#define BCM2835_MBOX_CLOCK_ID_ARM 0x00000003 -#define BCM2835_MBOX_CLOCK_ID_CORE 0x00000004 -#define BCM2835_MBOX_CLOCK_ID_V3D 0x00000005 -#define BCM2835_MBOX_CLOCK_ID_H264 0x00000006 -#define BCM2835_MBOX_CLOCK_ID_ISP 0x00000007 -#define BCM2835_MBOX_CLOCK_ID_SDRAM 0x00000008 -#define BCM2835_MBOX_CLOCK_ID_PIXEL 0x00000009 -#define BCM2835_MBOX_CLOCK_ID_PWM 0x0000000a #define BCM2838_MBOX_CLOCK_ID_EMMC2 0x0000000c #define BCM2835_MBOX_TAG_GET_CLOCK_RATE 0x00030002 -#define BCM2835_MBOX_TAG_SET_CLOCK_RATE 0x00038002 -#define BCM2835_MBOX_TAG_GET_MAX_CLOCK_RATE 0x00030004 -#define BCM2835_MBOX_TAG_GET_MIN_CLOCK_RATE 0x00030007 struct msg_get_clock_rate { struct bcm2835_mbox_hdr hdr; @@ -144,52 +132,6 @@ struct msg_get_clock_rate { uint32_t end_tag; }; -struct msg_set_clock_rate { - struct bcm2835_mbox_hdr hdr; - struct bcm2835_mbox_tag_hdr tag_hdr; - union { - struct { - uint32_t clock_id; - uint32_t rate_hz; - } req; - struct { - uint32_t clock_id; - uint32_t rate_hz; - } resp; - } body; - uint32_t end_tag; -}; - -struct msg_get_max_clock_rate { - struct bcm2835_mbox_hdr hdr; - struct bcm2835_mbox_tag_hdr tag_hdr; - union { - struct { - uint32_t clock_id; - } req; - struct { - uint32_t clock_id; - uint32_t rate_hz; - } resp; - } body; - uint32_t end_tag; -}; - -struct msg_get_min_clock_rate { - struct bcm2835_mbox_hdr hdr; - struct bcm2835_mbox_tag_hdr tag_hdr; - union { - struct { - uint32_t clock_id; - } req; - struct { - uint32_t clock_id; - uint32_t rate_hz; - } resp; - } body; - uint32_t end_tag; -}; - int bcm2835_mbox_get_clock_rate(uint32_t, uint32_t *); #define BCM2835_MBOX_TURBO_ON 1 diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c index 0140afcc4a97..cd9b60743be3 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <dev/mmc/bridge.h> #include <dev/mmc/mmcreg.h> +#include <dev/mmc/mmc_fdt_helpers.h> #include <dev/sdhci/sdhci.h> @@ -155,6 +156,7 @@ struct bcm_sdhci_softc { void * sc_intrhand; struct mmc_request * sc_req; struct sdhci_slot sc_slot; + struct mmc_fdt_helper sc_mmc_helper; int sc_dma_ch; bus_dma_tag_t sc_dma_tag; bus_dmamap_t sc_dma_map; @@ -315,6 +317,7 @@ bcm_sdhci_attach(device_t dev) sc->sc_slot.quirks = sc->conf->quirks; sdhci_init_slot(dev, &sc->sc_slot, 0); + mmc_fdt_parse(dev, 0, &sc->sc_mmc_helper, &sc->sc_slot.host); sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_ANY); if (sc->sc_dma_ch == BCM_DMA_CH_INVALID) @@ -389,6 +392,43 @@ bcm_sdhci_intr(void *arg) } static int +bcm_sdhci_update_ios(device_t bus, device_t child) +{ +#ifdef EXT_RESOURCES + struct bcm_sdhci_softc *sc; + struct mmc_ios *ios; +#endif + int rv; + +#ifdef EXT_RESOURCES + sc = device_get_softc(bus); + ios = &sc->sc_slot.host.ios; + + if (ios->power_mode == power_up) { + if (sc->sc_mmc_helper.vmmc_supply) + regulator_enable(sc->sc_mmc_helper.vmmc_supply); + if (sc->sc_mmc_helper.vqmmc_supply) + regulator_enable(sc->sc_mmc_helper.vqmmc_supply); + } +#endif + + rv = sdhci_generic_update_ios(bus, child); + if (rv != 0) + return (rv); + +#ifdef EXT_RESOURCES + if (ios->power_mode == power_off) { + if (sc->sc_mmc_helper.vmmc_supply) + regulator_disable(sc->sc_mmc_helper.vmmc_supply); + if (sc->sc_mmc_helper.vqmmc_supply) + regulator_disable(sc->sc_mmc_helper.vqmmc_supply); + } +#endif + + return (0); +} + +static int bcm_sdhci_get_ro(device_t bus, device_t child) { @@ -787,7 +827,7 @@ static device_method_t bcm_sdhci_methods[] = { DEVMETHOD(bus_add_child, bus_generic_add_child), /* MMC bridge interface */ - DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios), + DEVMETHOD(mmcbr_update_ios, bcm_sdhci_update_ios), DEVMETHOD(mmcbr_request, sdhci_generic_request), DEVMETHOD(mmcbr_get_ro, bcm_sdhci_get_ro), DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host), diff --git a/sys/arm/ti/am335x/am3359_cppi41.c b/sys/arm/ti/am335x/am3359_cppi41.c new file mode 100644 index 000000000000..a3e4e8bee155 --- /dev/null +++ b/sys/arm/ti/am335x/am3359_cppi41.c @@ -0,0 +1,192 @@ +/*- + * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org> + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +/* Based on sys/arm/ti/ti_sysc.c */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/resource.h> +#include <sys/rman.h> +#include <sys/lock.h> +#include <sys/mutex.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#include <dev/fdt/simplebus.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <arm/ti/ti_sysc.h> + +#if 0 +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +struct ti_am3359_cppi41_softc { + device_t dev; + struct syscon * syscon; + struct resource * res[4]; + bus_space_tag_t bst; + bus_space_handle_t bsh; + struct mtx mtx; +}; + +static struct resource_spec ti_am3359_cppi41_res_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE }, + { SYS_RES_MEMORY, 1, RF_ACTIVE | RF_SHAREABLE }, + { SYS_RES_MEMORY, 2, RF_ACTIVE | RF_SHAREABLE }, + { SYS_RES_MEMORY, 3, RF_ACTIVE | RF_SHAREABLE }, + { -1, 0 } +}; + +/* Device */ +static struct ofw_compat_data compat_data[] = { + { "ti,am3359-cppi41", 1 }, + { NULL, 0 } +}; + +static int +ti_am3359_cppi41_write_4(device_t dev, bus_addr_t addr, uint32_t val) +{ + struct ti_am3359_cppi41_softc *sc; + + sc = device_get_softc(dev); + DPRINTF(sc->dev, "offset=%lx write %x\n", addr, val); + mtx_lock(&sc->mtx); + bus_space_write_4(sc->bst, sc->bsh, addr, val); + mtx_unlock(&sc->mtx); + return (0); +} + +static uint32_t +ti_am3359_cppi41_read_4(device_t dev, bus_addr_t addr) +{ + struct ti_am3359_cppi41_softc *sc; + uint32_t val; + + sc = device_get_softc(dev); + + mtx_lock(&sc->mtx); + val = bus_space_read_4(sc->bst, sc->bsh, addr); + mtx_unlock(&sc->mtx); + DPRINTF(sc->dev, "offset=%lx Read %x\n", addr, val); + return (val); +} + +/* device interface */ +static int +ti_am3359_cppi41_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "TI AM3359 CPPI 41"); + return(BUS_PROBE_DEFAULT); +} + +static int +ti_am3359_cppi41_attach(device_t dev) +{ + struct ti_am3359_cppi41_softc *sc; + phandle_t node; + uint32_t reg, reset_bit, timeout=10; + uint64_t sysc_address; + device_t parent; + + sc = device_get_softc(dev); + sc->dev = dev; + + if (bus_alloc_resources(dev, ti_am3359_cppi41_res_spec, sc->res)) { + device_printf(sc->dev, "Cant allocate resources\n"); + return (ENXIO); + } + + sc->dev = dev; + sc->bst = rman_get_bustag(sc->res[0]); + sc->bsh = rman_get_bushandle(sc->res[0]); + + mtx_init(&sc->mtx, device_get_nameunit(sc->dev), NULL, MTX_DEF); + node = ofw_bus_get_node(sc->dev); + + /* variant of am335x_usbss.c */ + DPRINTF(dev, "-- RESET USB --\n"); + parent = device_get_parent(dev); + reset_bit = ti_sysc_get_soft_reset_bit(parent); + if (reset_bit == 0) { + DPRINTF(dev, "Dont have reset bit\n"); + return (0); + } + sysc_address = ti_sysc_get_sysc_address_offset_host(parent); + DPRINTF(dev, "sysc_address %x\n", sysc_address); + ti_am3359_cppi41_write_4(dev, sysc_address, reset_bit); + DELAY(100); + reg = ti_am3359_cppi41_read_4(dev, sysc_address); + if ((reg & reset_bit) && timeout--) { + DPRINTF(dev, "Reset still ongoing - wait a little bit longer\n"); + DELAY(100); + reg = ti_am3359_cppi41_read_4(dev, sysc_address); + } + if (timeout == 0) + device_printf(dev, "USB Reset timeout\n"); + + return (0); +} + + +static device_method_t ti_am3359_cppi41_methods[] = { + DEVMETHOD(device_probe, ti_am3359_cppi41_probe), + DEVMETHOD(device_attach, ti_am3359_cppi41_attach), + + DEVMETHOD_END +}; + + +DEFINE_CLASS_1(ti_am3359_cppi41, ti_am3359_cppi41_driver, + ti_am3359_cppi41_methods,sizeof(struct ti_am3359_cppi41_softc), + simplebus_driver); + +static devclass_t ti_am3359_cppi41_devclass; + +EARLY_DRIVER_MODULE(ti_am3359_cppi41, simplebus, ti_am3359_cppi41_driver, + ti_am3359_cppi41_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +MODULE_VERSION(ti_am3359_cppi41, 1); +MODULE_DEPEND(ti_am3359_cppi41, ti_sysc, 1, 1, 1); diff --git a/sys/arm/ti/am335x/am335x_dmtimer.c b/sys/arm/ti/am335x/am335x_dmtimer.c index a36c66e56ed0..eb869ca88b94 100644 --- a/sys/arm/ti/am335x/am335x_dmtimer.c +++ b/sys/arm/ti/am335x/am335x_dmtimer.c @@ -42,12 +42,13 @@ __FBSDID("$FreeBSD$"); #include <machine/machdep.h> /* For arm_set_delay */ +#include <dev/extres/clk/clk.h> + #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> -#include <arm/ti/ti_prcm.h> -#include <arm/ti/ti_hwmods.h> +#include <arm/ti/ti_sysc.h> #include "am335x_dmtreg.h" @@ -58,7 +59,8 @@ struct am335x_dmtimer_softc { int tmr_irq_rid; struct resource * tmr_irq_res; void *tmr_irq_handler; - uint32_t sysclk_freq; + clk_t clk_fck; + uint64_t sysclk_freq; uint32_t tclr; /* Cached TCLR register. */ union { struct timecounter tc; @@ -251,6 +253,7 @@ am335x_dmtimer_probe(device_t dev) { char strbuf[32]; int tmr_num; + uint64_t rev_address; if (!ofw_bus_status_okay(dev)) return (ENXIO); @@ -259,13 +262,22 @@ am335x_dmtimer_probe(device_t dev) return (ENXIO); /* - * Get the hardware unit number (the N from ti,hwmods="timerN"). + * Get the hardware unit number from address of rev register. * If this isn't the hardware unit we're going to use for either the * eventtimer or the timecounter, no point in instantiating the device. */ - tmr_num = ti_hwmods_get_unit(dev, "timer"); - if (tmr_num != ET_TMR_NUM && tmr_num != TC_TMR_NUM) - return (ENXIO); + rev_address = ti_sysc_get_rev_address(device_get_parent(dev)); + switch (rev_address) { + case DMTIMER2_REV: + tmr_num = 2; + break; + case DMTIMER3_REV: + tmr_num = 3; + break; + default: + /* Not DMTIMER2 or DMTIMER3 */ + return (ENXIO); + } snprintf(strbuf, sizeof(strbuf), "AM335x DMTimer%d", tmr_num); device_set_desc_copy(dev, strbuf); @@ -277,23 +289,46 @@ static int am335x_dmtimer_attach(device_t dev) { struct am335x_dmtimer_softc *sc; - clk_ident_t timer_id; int err; + uint64_t rev_address; + clk_t sys_clkin; sc = device_get_softc(dev); sc->dev = dev; - /* Get the base clock frequency. */ - if ((err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq)) != 0) - return (err); + /* expect one clock */ + err = clk_get_by_ofw_index(dev, 0, 0, &sc->clk_fck); + if (err != 0) { + device_printf(dev, "Cant find clock index 0. err: %d\n", err); + return (ENXIO); + } + + err = clk_get_by_name(dev, "sys_clkin_ck@40", &sys_clkin); + if (err != 0) { + device_printf(dev, "Cant find sys_clkin_ck@40 err: %d\n", err); + return (ENXIO); + } + + /* Select M_OSC as DPLL parent */ + err = clk_set_parent_by_clk(sc->clk_fck, sys_clkin); + if (err != 0) { + device_printf(dev, "Cant set mux to CLK_M_OSC\n"); + return (ENXIO); + } /* Enable clocks and power on the device. */ - if ((timer_id = ti_hwmods_get_clock(dev)) == INVALID_CLK_IDENT) + err = ti_sysc_clock_enable(device_get_parent(dev)); + if (err != 0) { + device_printf(dev, "Cant enable sysc clkctrl, err %d\n", err); return (ENXIO); - if ((err = ti_prcm_clk_set_source(timer_id, SYSCLK_CLK)) != 0) - return (err); - if ((err = ti_prcm_clk_enable(timer_id)) != 0) - return (err); + } + + /* Get the base clock frequency. */ + err = clk_get_freq(sc->clk_fck, &sc->sysclk_freq); + if (err != 0) { + device_printf(dev, "Cant get sysclk frequency, err %d\n", err); + return (ENXIO); + } /* Request the memory resources. */ sc->tmr_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, @@ -302,7 +337,20 @@ am335x_dmtimer_attach(device_t dev) return (ENXIO); } - sc->tmr_num = ti_hwmods_get_unit(dev, "timer"); + rev_address = ti_sysc_get_rev_address(device_get_parent(dev)); + switch (rev_address) { + case DMTIMER2_REV: + sc->tmr_num = 2; + break; + case DMTIMER3_REV: + sc->tmr_num = 3; + break; + default: + device_printf(dev, "Not timer 2 or 3! %#jx\n", + rev_address); + return (ENXIO); + } + snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num); /* @@ -334,7 +382,7 @@ static driver_t am335x_dmtimer_driver = { static devclass_t am335x_dmtimer_devclass; DRIVER_MODULE(am335x_dmtimer, simplebus, am335x_dmtimer_driver, am335x_dmtimer_devclass, 0, 0); -MODULE_DEPEND(am335x_dmtimer, am335x_prcm, 1, 1, 1); +MODULE_DEPEND(am335x_dmtimer, ti_sysc, 1, 1, 1); static void am335x_dmtimer_delay(int usec, void *arg) diff --git a/sys/arm/ti/am335x/am335x_dmtpps.c b/sys/arm/ti/am335x/am335x_dmtpps.c index 6aa374a0f76f..24d83f248eef 100644 --- a/sys/arm/ti/am335x/am335x_dmtpps.c +++ b/sys/arm/ti/am335x/am335x_dmtpps.c @@ -43,6 +43,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_platform.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> @@ -60,9 +62,9 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> +#include <dev/extres/clk/clk.h> -#include <arm/ti/ti_prcm.h> -#include <arm/ti/ti_hwmods.h> +#include <arm/ti/ti_sysc.h> #include <arm/ti/ti_pinmux.h> #include <arm/ti/am335x/am335x_scm_padconf.h> @@ -82,6 +84,8 @@ struct dmtpps_softc { struct cdev * pps_cdev; struct pps_state pps_state; struct mtx pps_mtx; + clk_t clk_fck; + uint64_t sysclk_freq; }; static int dmtpps_tmr_num; /* Set by probe() */ @@ -383,6 +387,7 @@ dmtpps_probe(device_t dev) { char strbuf[64]; int tmr_num; + uint64_t rev_address; if (!ofw_bus_status_okay(dev)) return (ENXIO); @@ -402,7 +407,33 @@ dmtpps_probe(device_t dev) * Figure out which hardware timer is being probed and see if it matches * the configured timer number determined earlier. */ - tmr_num = ti_hwmods_get_unit(dev, "timer"); + rev_address = ti_sysc_get_rev_address(device_get_parent(dev)); + switch (rev_address) { + case DMTIMER1_1MS_REV: + tmr_num = 1; + break; + case DMTIMER2_REV: + tmr_num = 2; + break; + case DMTIMER3_REV: + tmr_num = 3; + break; + case DMTIMER4_REV: + tmr_num = 4; + break; + case DMTIMER5_REV: + tmr_num = 5; + break; + case DMTIMER6_REV: + tmr_num = 6; + break; + case DMTIMER7_REV: + tmr_num = 7; + break; + default: + return (ENXIO); + } + if (dmtpps_tmr_num != tmr_num) return (ENXIO); @@ -418,23 +449,73 @@ dmtpps_attach(device_t dev) { struct dmtpps_softc *sc; struct make_dev_args mda; - clk_ident_t timer_id; - int err, sysclk_freq; + int err; + clk_t sys_clkin; + uint64_t rev_address; sc = device_get_softc(dev); sc->dev = dev; - /* Get the base clock frequency. */ - err = ti_prcm_clk_get_source_freq(SYS_CLK, &sysclk_freq); + /* Figure out which hardware timer this is and set the name string. */ + rev_address = ti_sysc_get_rev_address(device_get_parent(dev)); + switch (rev_address) { + case DMTIMER1_1MS_REV: + sc->tmr_num = 1; + break; + case DMTIMER2_REV: + sc->tmr_num = 2; + break; + case DMTIMER3_REV: + sc->tmr_num = 3; + break; + case DMTIMER4_REV: + sc->tmr_num = 4; + break; + case DMTIMER5_REV: + sc->tmr_num = 5; + break; + case DMTIMER6_REV: + sc->tmr_num = 6; + break; + case DMTIMER7_REV: + sc->tmr_num = 7; + break; + } + snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num); + + /* expect one clock */ + err = clk_get_by_ofw_index(dev, 0, 0, &sc->clk_fck); + if (err != 0) { + device_printf(dev, "Cant find clock index 0. err: %d\n", err); + return (ENXIO); + } + + err = clk_get_by_name(dev, "sys_clkin_ck@40", &sys_clkin); + if (err != 0) { + device_printf(dev, "Cant find sys_clkin_ck@40 err: %d\n", err); + return (ENXIO); + } + + /* Select M_OSC as DPLL parent */ + err = clk_set_parent_by_clk(sc->clk_fck, sys_clkin); + if (err != 0) { + device_printf(dev, "Cant set mux to CLK_M_OSC\n"); + return (ENXIO); + } /* Enable clocks and power on the device. */ - if ((timer_id = ti_hwmods_get_clock(dev)) == INVALID_CLK_IDENT) + err = ti_sysc_clock_enable(device_get_parent(dev)); + if (err != 0) { + device_printf(dev, "Cant enable sysc clkctrl, err %d\n", err); return (ENXIO); - if ((err = ti_prcm_clk_set_source(timer_id, SYSCLK_CLK)) != 0) - return (err); - if ((err = ti_prcm_clk_enable(timer_id)) != 0) - return (err); + } + /* Get the base clock frequency. */ + err = clk_get_freq(sc->clk_fck, &sc->sysclk_freq); + if (err != 0) { + device_printf(dev, "Cant get sysclk frequency, err %d\n", err); + return (ENXIO); + } /* Request the memory resources. */ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, RF_ACTIVE); @@ -442,10 +523,6 @@ dmtpps_attach(device_t dev) return (ENXIO); } - /* Figure out which hardware timer this is and set the name string. */ - sc->tmr_num = ti_hwmods_get_unit(dev, "timer"); - snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num); - /* * Configure the timer pulse/capture pin to input/capture mode. This is * required in addition to configuring the pin as input with the pinmux @@ -468,7 +545,7 @@ dmtpps_attach(device_t dev) sc->tc.tc_name = sc->tmr_name; sc->tc.tc_get_timecount = dmtpps_get_timecount; sc->tc.tc_counter_mask = ~0u; - sc->tc.tc_frequency = sysclk_freq; + sc->tc.tc_frequency = sc->sysclk_freq; sc->tc.tc_quality = 1000; sc->tc.tc_priv = sc; @@ -541,5 +618,4 @@ static driver_t dmtpps_driver = { static devclass_t dmtpps_devclass; DRIVER_MODULE(am335x_dmtpps, simplebus, dmtpps_driver, dmtpps_devclass, 0, 0); -MODULE_DEPEND(am335x_dmtpps, am335x_prcm, 1, 1, 1); - +MODULE_DEPEND(am335x_dmtpps, ti_sysc, 1, 1, 1); diff --git a/sys/arm/ti/am335x/am335x_dmtreg.h b/sys/arm/ti/am335x/am335x_dmtreg.h index f2ef54ddb917..c91a30570bd8 100644 --- a/sys/arm/ti/am335x/am335x_dmtreg.h +++ b/sys/arm/ti/am335x/am335x_dmtreg.h @@ -73,4 +73,16 @@ #define DMT_TSICR_RESET (1 << 1) /* TSICR perform soft reset */ #define DMT_TCAR2 0x48 /* Capture Reg */ +/* Location of revision register from TRM Memory map chapter 2 */ +/* L4_WKUP */ +#define DMTIMER0_REV 0x05000 +#define DMTIMER1_1MS_REV 0x31000 +/* L4_PER */ +#define DMTIMER2_REV 0x40000 +#define DMTIMER3_REV 0x42000 +#define DMTIMER4_REV 0x44000 +#define DMTIMER5_REV 0x46000 +#define DMTIMER6_REV 0x48000 +#define DMTIMER7_REV 0x4A000 + #endif /* AM335X_DMTREG_H */ diff --git a/sys/arm/ti/am335x/am335x_gpio.c b/sys/arm/ti/am335x/am335x_gpio.c index cbfde175c2e7..beb169b3e4b5 100644 --- a/sys/arm/ti/am335x/am335x_gpio.c +++ b/sys/arm/ti/am335x/am335x_gpio.c @@ -155,3 +155,4 @@ DEFINE_CLASS_1(gpio, am335x_gpio_driver, am335x_gpio_methods, sizeof(struct ti_gpio_softc), ti_gpio_driver); DRIVER_MODULE(am335x_gpio, simplebus, am335x_gpio_driver, am335x_gpio_devclass, 0, 0); +MODULE_DEPEND(am335x_gpio, ti_sysc, 1, 1, 1); diff --git a/sys/arm/ti/am335x/am335x_lcd.c b/sys/arm/ti/am335x/am335x_lcd.c index 5c60bf4be6bf..387bd37e3ebf 100644 --- a/sys/arm/ti/am335x/am335x_lcd.c +++ b/sys/arm/ti/am335x/am335x_lcd.c @@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> +#include <dev/extres/clk/clk.h> + #include <dev/fdt/fdt_common.h> #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_bus.h> @@ -65,7 +67,7 @@ __FBSDID("$FreeBSD$"); #include <dev/vt/vt.h> #endif -#include <arm/ti/ti_prcm.h> +#include <arm/ti/ti_sysc.h> #include <arm/ti/ti_scm.h> #include "am335x_lcd.h" @@ -219,6 +221,9 @@ struct am335x_lcd_softc { /* HDMI framer */ phandle_t sc_hdmi_framer; eventhandler_tag sc_hdmi_evh; + + /* Clock */ + clk_t sc_clk_dpll_disp_ck; }; static void @@ -615,24 +620,28 @@ am335x_lcd_configure(struct am335x_lcd_softc *sc) uint32_t hbp, hfp, hsw; uint32_t vbp, vfp, vsw; uint32_t width, height; - unsigned int ref_freq; + uint64_t ref_freq; int err; /* * try to adjust clock to get double of requested frequency * HDMI/DVI displays are very sensitive to error in frequncy value */ - if (ti_prcm_clk_set_source_freq(LCDC_CLK, sc->sc_panel.panel_pxl_clk*2)) { + + err = clk_set_freq(sc->sc_clk_dpll_disp_ck, sc->sc_panel.panel_pxl_clk*2, + CLK_SET_ROUND_ANY); + if (err != 0) { device_printf(sc->sc_dev, "can't set source frequency\n"); return (ENXIO); } - if (ti_prcm_clk_get_source_freq(LCDC_CLK, &ref_freq)) { + err = clk_get_freq(sc->sc_clk_dpll_disp_ck, &ref_freq); + if (err != 0) { device_printf(sc->sc_dev, "can't get reference frequency\n"); return (ENXIO); } - /* Panle initialization */ + /* Panel initialization */ dma_size = round_page(sc->sc_panel.panel_width*sc->sc_panel.panel_height*sc->sc_panel.bpp/8); /* @@ -967,6 +976,13 @@ am335x_lcd_attach(device_t dev) return (ENXIO); } + /* Fixme: Cant find any reference in DTS for dpll_disp_ck@498 for now. */ + err = clk_get_by_name(dev, "dpll_disp_ck@498", &sc->sc_clk_dpll_disp_ck); + if (err != 0) { + device_printf(dev, "Cant get dpll_disp_ck@49\n"); + return (ENXIO); + } + sc->sc_panel.ac_bias = 255; sc->sc_panel.ac_bias_intrpt = 0; sc->sc_panel.dma_burst_sz = 16; @@ -989,7 +1005,11 @@ am335x_lcd_attach(device_t dev) } } - ti_prcm_clk_enable(LCDC_CLK); + err = ti_sysc_clock_enable(device_get_parent(dev)); + if (err != 0) { + device_printf(dev, "Failed to enable sysc clkctrl, err %d\n", err); + return (ENXIO); + } rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, @@ -1081,3 +1101,4 @@ static devclass_t am335x_lcd_devclass; DRIVER_MODULE(am335x_lcd, simplebus, am335x_lcd_driver, am335x_lcd_devclass, 0, 0); MODULE_VERSION(am335x_lcd, 1); MODULE_DEPEND(am335x_lcd, simplebus, 1, 1, 1); +MODULE_DEPEND(am335x_lcd, ti_sysc, 1, 1, 1); diff --git a/sys/arm/ti/am335x/am335x_musb.c b/sys/arm/ti/am335x/am335x_musb.c index cbe4d06338c9..d868e8a64f8b 100644 --- a/sys/arm/ti/am335x/am335x_musb.c +++ b/sys/arm/ti/am335x/am335x_musb.c @@ -66,9 +66,11 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> -#include <arm/ti/ti_prcm.h> -#include <arm/ti/ti_scm.h> #include <arm/ti/am335x/am335x_scm.h> +#include <arm/ti/ti_sysc.h> +#include <dev/extres/clk/clk.h> +#include <dev/extres/syscon/syscon.h> +#include "syscon_if.h" #define USBCTRL_REV 0x00 #define USBCTRL_CTRL 0x14 @@ -130,6 +132,7 @@ struct musbotg_super_softc { struct musbotg_softc sc_otg; struct resource *sc_mem_res[2]; int sc_irq_rid; + struct syscon *syscon; }; static void @@ -155,30 +158,33 @@ static void musbotg_clocks_on(void *arg) { struct musbotg_softc *sc; - uint32_t c, reg; + struct musbotg_super_softc *ssc; + uint32_t reg; sc = arg; - reg = USB_CTRL[sc->sc_id]; + ssc = sc->sc_platform_data; + + reg = SYSCON_READ_4(ssc->syscon, USB_CTRL[sc->sc_id]); + reg &= ~3; /* Enable power */ + reg |= 1 << 19; /* VBUS detect enable */ + reg |= 1 << 20; /* Session end enable */ - ti_scm_reg_read_4(reg, &c); - c &= ~3; /* Enable power */ - c |= 1 << 19; /* VBUS detect enable */ - c |= 1 << 20; /* Session end enable */ - ti_scm_reg_write_4(reg, c); + SYSCON_WRITE_4(ssc->syscon, USB_CTRL[sc->sc_id], reg); } static void musbotg_clocks_off(void *arg) { struct musbotg_softc *sc; - uint32_t c, reg; + struct musbotg_super_softc *ssc; + uint32_t reg; sc = arg; - reg = USB_CTRL[sc->sc_id]; + ssc = sc->sc_platform_data; /* Disable power to PHY */ - ti_scm_reg_read_4(reg, &c); - ti_scm_reg_write_4(reg, c | 3); + reg = SYSCON_READ_4(ssc->syscon, USB_CTRL[sc->sc_id]); + SYSCON_WRITE_4(ssc->syscon, USB_CTRL[sc->sc_id], reg | 3); } static void @@ -241,9 +247,42 @@ musbotg_attach(device_t dev) char mode[16]; int err; uint32_t reg; + phandle_t opp_table; + clk_t clk_usbotg_fck; sc->sc_otg.sc_id = device_get_unit(dev); + /* FIXME: The devicetree needs to be updated to get a handle to the gate + * usbotg_fck@47c. see TRM 8.1.12.2 CM_WKUP CM_CLKDCOLDO_DPLL_PER. + */ + err = clk_get_by_name(dev, "usbotg_fck@47c", &clk_usbotg_fck); + if (err) { + device_printf(dev, "Can not find usbotg_fck@47c\n"); + return (ENXIO); + } + + err = clk_enable(clk_usbotg_fck); + if (err) { + device_printf(dev, "Can not enable usbotg_fck@47c\n"); + return (ENXIO); + } + + /* FIXME: For now; Go and kidnap syscon from opp-table */ + opp_table = OF_finddevice("/opp-table"); + if (opp_table == -1) { + device_printf(dev, "Cant find /opp-table\n"); + return (ENXIO); + } + if (!OF_hasprop(opp_table, "syscon")) { + device_printf(dev, "/opp-table missing syscon property\n"); + return (ENXIO); + } + err = syscon_get_by_ofw_property(dev, opp_table, "syscon", &sc->syscon); + if (err) { + device_printf(dev, "Failed to get syscon\n"); + return (ENXIO); + } + /* Request the memory resources */ err = bus_alloc_resources(dev, am335x_musbotg_mem_spec, sc->sc_mem_res); @@ -417,5 +456,7 @@ static driver_t musbotg_driver = { static devclass_t musbotg_devclass; -DRIVER_MODULE(musbotg, usbss, musbotg_driver, musbotg_devclass, 0, 0); -MODULE_DEPEND(musbotg, usbss, 1, 1, 1); +DRIVER_MODULE(musbotg, ti_sysc, musbotg_driver, musbotg_devclass, 0, 0); +MODULE_DEPEND(musbotg, ti_sysc, 1, 1, 1); +MODULE_DEPEND(musbotg, ti_am3359_cppi41, 1, 1, 1); +MODULE_DEPEND(usbss, usb, 1, 1, 1); diff --git a/sys/arm/ti/am335x/am335x_prcm.c b/sys/arm/ti/am335x/am335x_prcm.c deleted file mode 100644 index 875be72f4937..000000000000 --- a/sys/arm/ti/am335x/am335x_prcm.c +++ /dev/null @@ -1,884 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org> - * 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. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/malloc.h> -#include <sys/rman.h> -#include <sys/timeet.h> -#include <sys/timetc.h> -#include <sys/watchdog.h> -#include <machine/bus.h> -#include <machine/cpu.h> -#include <machine/intr.h> - -#include <arm/ti/tivar.h> -#include <arm/ti/ti_scm.h> -#include <arm/ti/ti_prcm.h> - -#include <dev/ofw/openfirm.h> -#include <dev/ofw/ofw_bus.h> -#include <dev/ofw/ofw_bus_subr.h> - -#include <machine/bus.h> - -#include "am335x_scm.h" - -#define CM_PER 0 -#define CM_PER_L4LS_CLKSTCTRL (CM_PER + 0x000) -#define CM_PER_L3S_CLKSTCTRL (CM_PER + 0x004) -#define CM_PER_L3_CLKSTCTRL (CM_PER + 0x00C) -#define CM_PER_CPGMAC0_CLKCTRL (CM_PER + 0x014) -#define CM_PER_LCDC_CLKCTRL (CM_PER + 0x018) -#define CM_PER_USB0_CLKCTRL (CM_PER + 0x01C) -#define CM_PER_TPTC0_CLKCTRL (CM_PER + 0x024) -#define CM_PER_UART5_CLKCTRL (CM_PER + 0x038) -#define CM_PER_MMC0_CLKCTRL (CM_PER + 0x03C) -#define CM_PER_I2C2_CLKCTRL (CM_PER + 0x044) -#define CM_PER_I2C1_CLKCTRL (CM_PER + 0x048) -#define CM_PER_SPI0_CLKCTRL (CM_PER + 0x04C) -#define CM_PER_SPI1_CLKCTRL (CM_PER + 0x050) -#define CM_PER_UART1_CLKCTRL (CM_PER + 0x06C) -#define CM_PER_UART2_CLKCTRL (CM_PER + 0x070) -#define CM_PER_UART3_CLKCTRL (CM_PER + 0x074) -#define CM_PER_UART4_CLKCTRL (CM_PER + 0x078) -#define CM_PER_TIMER7_CLKCTRL (CM_PER + 0x07C) -#define CM_PER_TIMER2_CLKCTRL (CM_PER + 0x080) -#define CM_PER_TIMER3_CLKCTRL (CM_PER + 0x084) -#define CM_PER_TIMER4_CLKCTRL (CM_PER + 0x088) -#define CM_PER_GPIO1_CLKCTRL (CM_PER + 0x0AC) -#define CM_PER_GPIO2_CLKCTRL (CM_PER + 0x0B0) -#define CM_PER_GPIO3_CLKCTRL (CM_PER + 0x0B4) -#define CM_PER_TPCC_CLKCTRL (CM_PER + 0x0BC) -#define CM_PER_EPWMSS1_CLKCTRL (CM_PER + 0x0CC) -#define CM_PER_EPWMSS0_CLKCTRL (CM_PER + 0x0D4) -#define CM_PER_EPWMSS2_CLKCTRL (CM_PER + 0x0D8) -#define CM_PER_L3_INSTR_CLKCTRL (CM_PER + 0x0DC) -#define CM_PER_L3_CLKCTRL (CM_PER + 0x0E0) -#define CM_PER_PRUSS_CLKCTRL (CM_PER + 0x0E8) -#define CM_PER_TIMER5_CLKCTRL (CM_PER + 0x0EC) -#define CM_PER_TIMER6_CLKCTRL (CM_PER + 0x0F0) -#define CM_PER_MMC1_CLKCTRL (CM_PER + 0x0F4) -#define CM_PER_MMC2_CLKCTRL (CM_PER + 0x0F8) -#define CM_PER_TPTC1_CLKCTRL (CM_PER + 0x0FC) -#define CM_PER_TPTC2_CLKCTRL (CM_PER + 0x100) -#define CM_PER_SPINLOCK0_CLKCTRL (CM_PER + 0x10C) -#define CM_PER_MAILBOX0_CLKCTRL (CM_PER + 0x110) -#define CM_PER_OCPWP_L3_CLKSTCTRL (CM_PER + 0x12C) -#define CM_PER_OCPWP_CLKCTRL (CM_PER + 0x130) -#define CM_PER_CPSW_CLKSTCTRL (CM_PER + 0x144) -#define CM_PER_PRUSS_CLKSTCTRL (CM_PER + 0x140) - -#define CM_WKUP 0x400 -#define CM_WKUP_CLKSTCTRL (CM_WKUP + 0x000) -#define CM_WKUP_CONTROL_CLKCTRL (CM_WKUP + 0x004) -#define CM_WKUP_GPIO0_CLKCTRL (CM_WKUP + 0x008) -#define CM_WKUP_CM_L3_AON_CLKSTCTRL (CM_WKUP + 0x01C) -#define CM_WKUP_CM_CLKSEL_DPLL_MPU (CM_WKUP + 0x02C) -#define CM_WKUP_CM_IDLEST_DPLL_DISP (CM_WKUP + 0x048) -#define CM_WKUP_CM_CLKSEL_DPLL_DISP (CM_WKUP + 0x054) -#define CM_WKUP_CM_CLKDCOLDO_DPLL_PER (CM_WKUP + 0x07C) -#define CM_WKUP_CM_CLKMODE_DPLL_DISP (CM_WKUP + 0x098) -#define CM_WKUP_I2C0_CLKCTRL (CM_WKUP + 0x0B8) -#define CM_WKUP_ADC_TSC_CLKCTRL (CM_WKUP + 0x0BC) - -#define CM_DPLL 0x500 -#define CLKSEL_TIMER7_CLK (CM_DPLL + 0x004) -#define CLKSEL_TIMER2_CLK (CM_DPLL + 0x008) -#define CLKSEL_TIMER3_CLK (CM_DPLL + 0x00C) -#define CLKSEL_TIMER4_CLK (CM_DPLL + 0x010) -#define CLKSEL_TIMER5_CLK (CM_DPLL + 0x018) -#define CLKSEL_TIMER6_CLK (CM_DPLL + 0x01C) -#define CLKSEL_PRUSS_OCP_CLK (CM_DPLL + 0x030) - -#define CM_RTC 0x800 -#define CM_RTC_RTC_CLKCTRL (CM_RTC + 0x000) -#define CM_RTC_CLKSTCTRL (CM_RTC + 0x004) - -#define PRM_PER 0xC00 -#define PRM_PER_RSTCTRL (PRM_PER + 0x00) - -#define PRM_DEVICE_OFFSET 0xF00 -#define PRM_RSTCTRL (PRM_DEVICE_OFFSET + 0x00) - -struct am335x_prcm_softc { - struct resource * res[2]; - bus_space_tag_t bst; - bus_space_handle_t bsh; - int attach_done; -}; - -static struct resource_spec am335x_prcm_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, - { -1, 0 } -}; - -static struct am335x_prcm_softc *am335x_prcm_sc = NULL; - -static int am335x_clk_noop_activate(struct ti_clock_dev *clkdev); -static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev); -static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev); -static int am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev); -static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev); -static int am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc); -static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc); -static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq); -static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); -static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); -static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq); -static int am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq); -static void am335x_prcm_reset(void); -static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev); -static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev); -static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev); -static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev); - -#define AM335X_NOOP_CLOCK_DEV(i) \ - { .id = (i), \ - .clk_activate = am335x_clk_noop_activate, \ - .clk_deactivate = am335x_clk_noop_deactivate, \ - .clk_set_source = am335x_clk_noop_set_source, \ - .clk_accessible = NULL, \ - .clk_get_source_freq = NULL, \ - .clk_set_source_freq = NULL \ - } - -#define AM335X_GENERIC_CLOCK_DEV(i) \ - { .id = (i), \ - .clk_activate = am335x_clk_generic_activate, \ - .clk_deactivate = am335x_clk_generic_deactivate, \ - .clk_set_source = am335x_clk_generic_set_source, \ - .clk_accessible = NULL, \ - .clk_get_source_freq = NULL, \ - .clk_set_source_freq = NULL \ - } - -#define AM335X_GPIO_CLOCK_DEV(i) \ - { .id = (i), \ - .clk_activate = am335x_clk_gpio_activate, \ - .clk_deactivate = am335x_clk_generic_deactivate, \ - .clk_set_source = am335x_clk_generic_set_source, \ - .clk_accessible = NULL, \ - .clk_get_source_freq = NULL, \ - .clk_set_source_freq = NULL \ - } - -#define AM335X_MMCHS_CLOCK_DEV(i) \ - { .id = (i), \ - .clk_activate = am335x_clk_generic_activate, \ - .clk_deactivate = am335x_clk_generic_deactivate, \ - .clk_set_source = am335x_clk_generic_set_source, \ - .clk_accessible = NULL, \ - .clk_get_source_freq = am335x_clk_hsmmc_get_source_freq, \ - .clk_set_source_freq = NULL \ - } - -struct ti_clock_dev ti_am335x_clk_devmap[] = { - /* System clocks */ - { .id = SYS_CLK, - .clk_activate = NULL, - .clk_deactivate = NULL, - .clk_set_source = NULL, - .clk_accessible = NULL, - .clk_get_source_freq = am335x_clk_get_sysclk_freq, - .clk_set_source_freq = NULL, - }, - /* MPU (ARM) core clocks */ - { .id = MPU_CLK, - .clk_activate = NULL, - .clk_deactivate = NULL, - .clk_set_source = NULL, - .clk_accessible = NULL, - .clk_get_source_freq = am335x_clk_get_arm_fclk_freq, - .clk_set_source_freq = NULL, - }, - /* CPSW Ethernet Switch core clocks */ - { .id = CPSW_CLK, - .clk_activate = am335x_clk_cpsw_activate, - .clk_deactivate = NULL, - .clk_set_source = NULL, - .clk_accessible = NULL, - .clk_get_source_freq = NULL, - .clk_set_source_freq = NULL, - }, - - /* Mentor USB HS controller core clocks */ - { .id = MUSB0_CLK, - .clk_activate = am335x_clk_musb0_activate, - .clk_deactivate = NULL, - .clk_set_source = NULL, - .clk_accessible = NULL, - .clk_get_source_freq = NULL, - .clk_set_source_freq = NULL, - }, - - /* LCD controller clocks */ - { .id = LCDC_CLK, - .clk_activate = am335x_clk_lcdc_activate, - .clk_deactivate = NULL, - .clk_set_source = NULL, - .clk_accessible = NULL, - .clk_get_source_freq = am335x_clk_get_arm_disp_freq, - .clk_set_source_freq = am335x_clk_set_arm_disp_freq, - }, - - /* UART */ - AM335X_NOOP_CLOCK_DEV(UART1_CLK), - AM335X_GENERIC_CLOCK_DEV(UART2_CLK), - AM335X_GENERIC_CLOCK_DEV(UART3_CLK), - AM335X_GENERIC_CLOCK_DEV(UART4_CLK), - AM335X_GENERIC_CLOCK_DEV(UART5_CLK), - AM335X_GENERIC_CLOCK_DEV(UART6_CLK), - - /* DMTimer */ - AM335X_GENERIC_CLOCK_DEV(TIMER2_CLK), - AM335X_GENERIC_CLOCK_DEV(TIMER3_CLK), - AM335X_GENERIC_CLOCK_DEV(TIMER4_CLK), - AM335X_GENERIC_CLOCK_DEV(TIMER5_CLK), - AM335X_GENERIC_CLOCK_DEV(TIMER6_CLK), - AM335X_GENERIC_CLOCK_DEV(TIMER7_CLK), - - /* GPIO, we use hwmods as reference, not units in spec */ - AM335X_GPIO_CLOCK_DEV(GPIO1_CLK), - AM335X_GPIO_CLOCK_DEV(GPIO2_CLK), - AM335X_GPIO_CLOCK_DEV(GPIO3_CLK), - AM335X_GPIO_CLOCK_DEV(GPIO4_CLK), - - /* I2C we use hwmods as reference, not units in spec */ - AM335X_GENERIC_CLOCK_DEV(I2C1_CLK), - AM335X_GENERIC_CLOCK_DEV(I2C2_CLK), - AM335X_GENERIC_CLOCK_DEV(I2C3_CLK), - - /* McSPI we use hwmods as reference, not units in spec */ - AM335X_GENERIC_CLOCK_DEV(SPI0_CLK), - AM335X_GENERIC_CLOCK_DEV(SPI1_CLK), - - /* TSC_ADC */ - AM335X_GENERIC_CLOCK_DEV(TSC_ADC_CLK), - - /* EDMA */ - AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK), - AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK), - AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK), - AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK), - - /* MMCHS */ - AM335X_MMCHS_CLOCK_DEV(MMC1_CLK), - AM335X_MMCHS_CLOCK_DEV(MMC2_CLK), - AM335X_MMCHS_CLOCK_DEV(MMC3_CLK), - - /* PWMSS */ - AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK), - AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK), - AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK), - - /* System Mailbox clock */ - AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK), - - /* SPINLOCK */ - AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK), - - /* PRU-ICSS */ - { .id = PRUSS_CLK, - .clk_activate = am335x_clk_pruss_activate, - .clk_deactivate = NULL, - .clk_set_source = NULL, - .clk_accessible = NULL, - .clk_get_source_freq = NULL, - .clk_set_source_freq = NULL, - }, - - /* RTC */ - AM335X_GENERIC_CLOCK_DEV(RTC_CLK), - - { INVALID_CLK_IDENT, NULL, NULL, NULL, NULL } -}; - -struct am335x_clk_details { - clk_ident_t id; - uint32_t clkctrl_reg; - uint32_t clksel_reg; -}; - -#define _CLK_DETAIL(i, c, s) \ - { .id = (i), \ - .clkctrl_reg = (c), \ - .clksel_reg = (s), \ - } - -static struct am335x_clk_details g_am335x_clk_details[] = { - - /* UART. UART0 clock not controllable. */ - _CLK_DETAIL(UART1_CLK, 0, 0), - _CLK_DETAIL(UART2_CLK, CM_PER_UART1_CLKCTRL, 0), - _CLK_DETAIL(UART3_CLK, CM_PER_UART2_CLKCTRL, 0), - _CLK_DETAIL(UART4_CLK, CM_PER_UART3_CLKCTRL, 0), - _CLK_DETAIL(UART5_CLK, CM_PER_UART4_CLKCTRL, 0), - _CLK_DETAIL(UART6_CLK, CM_PER_UART5_CLKCTRL, 0), - - /* DMTimer modules */ - _CLK_DETAIL(TIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK), - _CLK_DETAIL(TIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK), - _CLK_DETAIL(TIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK), - _CLK_DETAIL(TIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK), - _CLK_DETAIL(TIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK), - _CLK_DETAIL(TIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK), - - /* GPIO modules, hwmods start with gpio1 */ - _CLK_DETAIL(GPIO1_CLK, CM_WKUP_GPIO0_CLKCTRL, 0), - _CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO1_CLKCTRL, 0), - _CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO2_CLKCTRL, 0), - _CLK_DETAIL(GPIO4_CLK, CM_PER_GPIO3_CLKCTRL, 0), - - /* I2C modules, hwmods start with i2c1 */ - _CLK_DETAIL(I2C1_CLK, CM_WKUP_I2C0_CLKCTRL, 0), - _CLK_DETAIL(I2C2_CLK, CM_PER_I2C1_CLKCTRL, 0), - _CLK_DETAIL(I2C3_CLK, CM_PER_I2C2_CLKCTRL, 0), - - /* McSPI modules, hwmods start with spi0 */ - _CLK_DETAIL(SPI0_CLK, CM_PER_SPI0_CLKCTRL, 0), - _CLK_DETAIL(SPI1_CLK, CM_PER_SPI1_CLKCTRL, 0), - - /* TSC_ADC module */ - _CLK_DETAIL(TSC_ADC_CLK, CM_WKUP_ADC_TSC_CLKCTRL, 0), - - /* EDMA modules */ - _CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0), - _CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0), - _CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0), - _CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0), - - /* MMCHS modules, hwmods start with mmc1*/ - _CLK_DETAIL(MMC1_CLK, CM_PER_MMC0_CLKCTRL, 0), - _CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0), - _CLK_DETAIL(MMC3_CLK, CM_PER_MMC1_CLKCTRL, 0), - - /* PWMSS modules */ - _CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0), - _CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0), - _CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0), - - _CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0), - _CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0), - - /* RTC module */ - _CLK_DETAIL(RTC_CLK, CM_RTC_RTC_CLKCTRL, 0), - - { INVALID_CLK_IDENT, 0}, -}; - -/* Read/Write macros */ -#define prcm_read_4(reg) \ - bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg) -#define prcm_write_4(reg, val) \ - bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val) - -void am335x_prcm_setup_dmtimer(int); - -static int -am335x_prcm_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (ofw_bus_is_compatible(dev, "ti,am3-prcm")) { - device_set_desc(dev, "AM335x Power and Clock Management"); - return(BUS_PROBE_DEFAULT); - } - - return (ENXIO); -} - -static int -am335x_prcm_attach(device_t dev) -{ - struct am335x_prcm_softc *sc = device_get_softc(dev); - - if (am335x_prcm_sc) - return (ENXIO); - - if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) { - device_printf(dev, "could not allocate resources\n"); - return (ENXIO); - } - - sc->bst = rman_get_bustag(sc->res[0]); - sc->bsh = rman_get_bushandle(sc->res[0]); - - am335x_prcm_sc = sc; - ti_cpu_reset = am335x_prcm_reset; - - return (0); -} - -static void -am335x_prcm_new_pass(device_t dev) -{ - struct am335x_prcm_softc *sc = device_get_softc(dev); - unsigned int sysclk, fclk; - - sc = device_get_softc(dev); - if (sc->attach_done || - bus_current_pass < (BUS_PASS_TIMER + BUS_PASS_ORDER_EARLY)) { - bus_generic_new_pass(dev); - return; - } - - sc->attach_done = 1; - - if (am335x_clk_get_sysclk_freq(NULL, &sysclk) != 0) - sysclk = 0; - if (am335x_clk_get_arm_fclk_freq(NULL, &fclk) != 0) - fclk = 0; - if (sysclk && fclk) - device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n", - sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000); - else { - device_printf(dev, "can't read frequencies yet (SCM device not ready?)\n"); - goto fail; - } - - return; - -fail: - device_detach(dev); - return; -} - -static device_method_t am335x_prcm_methods[] = { - DEVMETHOD(device_probe, am335x_prcm_probe), - DEVMETHOD(device_attach, am335x_prcm_attach), - - /* Bus interface */ - DEVMETHOD(bus_new_pass, am335x_prcm_new_pass), - { 0, 0 } -}; - -static driver_t am335x_prcm_driver = { - "am335x_prcm", - am335x_prcm_methods, - sizeof(struct am335x_prcm_softc), -}; - -static devclass_t am335x_prcm_devclass; - -EARLY_DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver, - am335x_prcm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); -MODULE_VERSION(am335x_prcm, 1); -MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1); - -static struct am335x_clk_details* -am335x_clk_details(clk_ident_t id) -{ - struct am335x_clk_details *walker; - - for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) { - if (id == walker->id) - return (walker); - } - - return NULL; -} - -static int -am335x_clk_noop_activate(struct ti_clock_dev *clkdev) -{ - - return (0); -} - -static int -am335x_clk_generic_activate(struct ti_clock_dev *clkdev) -{ - struct am335x_prcm_softc *sc = am335x_prcm_sc; - struct am335x_clk_details* clk_details; - - if (sc == NULL) - return ENXIO; - - clk_details = am335x_clk_details(clkdev->id); - - if (clk_details == NULL) - return (ENXIO); - - /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */ - prcm_write_4(clk_details->clkctrl_reg, 2); - while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2) - DELAY(10); - - return (0); -} - -static int -am335x_clk_gpio_activate(struct ti_clock_dev *clkdev) -{ - struct am335x_prcm_softc *sc = am335x_prcm_sc; - struct am335x_clk_details* clk_details; - - if (sc == NULL) - return ENXIO; - - clk_details = am335x_clk_details(clkdev->id); - - if (clk_details == NULL) - return (ENXIO); - - /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */ - /* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */ - prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18)); - while ((prcm_read_4(clk_details->clkctrl_reg) & - (3 | (1 << 18) )) != (2 | (1 << 18))) - DELAY(10); - - return (0); -} - -static int -am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev) -{ - - return(0); -} - -static int -am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev) -{ - struct am335x_prcm_softc *sc = am335x_prcm_sc; - struct am335x_clk_details* clk_details; - - if (sc == NULL) - return ENXIO; - - clk_details = am335x_clk_details(clkdev->id); - - if (clk_details == NULL) - return (ENXIO); - - /* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */ - prcm_write_4(clk_details->clkctrl_reg, 0); - while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0) - DELAY(10); - - return (0); -} - -static int -am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc) -{ - - return (0); -} - -static int -am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc) -{ - struct am335x_prcm_softc *sc = am335x_prcm_sc; - struct am335x_clk_details* clk_details; - uint32_t reg; - - if (sc == NULL) - return ENXIO; - - clk_details = am335x_clk_details(clkdev->id); - - if (clk_details == NULL) - return (ENXIO); - - switch (clksrc) { - case EXT_CLK: - reg = 0; /* SEL2: TCLKIN clock */ - break; - case SYSCLK_CLK: - reg = 1; /* SEL1: CLK_M_OSC clock */ - break; - case F32KHZ_CLK: - reg = 2; /* SEL3: CLK_32KHZ clock */ - break; - default: - return (ENXIO); - } - - prcm_write_4(clk_details->clksel_reg, reg); - while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg) - DELAY(10); - - return (0); -} - -static int -am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq) -{ - *freq = 96000000; - return (0); -} - -static int -am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq) -{ - uint32_t ctrl_status; - - /* Read the input clock freq from the control module. */ - if (ti_scm_reg_read_4(SCM_CTRL_STATUS, &ctrl_status)) - return (ENXIO); - - switch ((ctrl_status>>22) & 0x3) { - case 0x0: - /* 19.2Mhz */ - *freq = 19200000; - break; - case 0x1: - /* 24Mhz */ - *freq = 24000000; - break; - case 0x2: - /* 25Mhz */ - *freq = 25000000; - break; - case 0x3: - /* 26Mhz */ - *freq = 26000000; - break; - } - - return (0); -} - -#define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1) -#define DPLL_DIV(reg) ((reg & 0x7f)+1) -#define DPLL_MULT(reg) ((reg>>8) & 0x7FF) -#define DPLL_MAX_MUL 0x800 -#define DPLL_MAX_DIV 0x80 - -static int -am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq) -{ - uint32_t reg; - uint32_t sysclk; - - reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU); - - /*Check if we are running in bypass */ - if (DPLL_BYP_CLKSEL(reg)) - return ENXIO; - - am335x_clk_get_sysclk_freq(NULL, &sysclk); - *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg)); - return(0); -} - -static int -am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq) -{ - uint32_t reg; - uint32_t sysclk; - - reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP); - - /*Check if we are running in bypass */ - if (DPLL_BYP_CLKSEL(reg)) - return ENXIO; - - am335x_clk_get_sysclk_freq(NULL, &sysclk); - *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg)); - return(0); -} - -static int -am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq) -{ - uint32_t sysclk; - uint32_t mul, div; - uint32_t i, j; - unsigned int delta, min_delta; - - am335x_clk_get_sysclk_freq(NULL, &sysclk); - - /* Bypass mode */ - prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4); - - /* Make sure it's in bypass mode */ - while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) - & (1 << 8))) - DELAY(10); - - /* Dumb and non-optimal implementation */ - min_delta = freq; - for (i = 1; i < DPLL_MAX_MUL; i++) { - for (j = 1; j < DPLL_MAX_DIV; j++) { - delta = abs(freq - i*(sysclk/j)); - if (delta < min_delta) { - mul = i; - div = j; - min_delta = delta; - } - if (min_delta == 0) - break; - } - } - - prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (mul << 8) | (div - 1)); - - /* Locked mode */ - prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7); - - int timeout = 10000; - while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) - & (1 << 0))) && timeout--) - DELAY(10); - - return(0); -} - -static void -am335x_prcm_reset(void) -{ - prcm_write_4(PRM_RSTCTRL, (1<<1)); -} - -static int -am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev) -{ - struct am335x_prcm_softc *sc = am335x_prcm_sc; - - if (sc == NULL) - return ENXIO; - - /* set MODULENAME to ENABLE */ - prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2); - - /* wait for IDLEST to become Func(0) */ - while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16)); - - /*set CLKTRCTRL to SW_WKUP(2) */ - prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2); - - /* wait for 125 MHz OCP clock to become active */ - while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0); - return(0); -} - -static int -am335x_clk_musb0_activate(struct ti_clock_dev *clkdev) -{ - struct am335x_prcm_softc *sc = am335x_prcm_sc; - - if (sc == NULL) - return ENXIO; - - /* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */ - /* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/ - prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300); - - /*set MODULEMODE to ENABLE(2) */ - prcm_write_4(CM_PER_USB0_CLKCTRL, 2); - - /* wait for MODULEMODE to become ENABLE(2) */ - while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2) - DELAY(10); - - /* wait for IDLEST to become Func(0) */ - while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16)) - DELAY(10); - - return(0); -} - -static int -am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev) -{ - struct am335x_prcm_softc *sc = am335x_prcm_sc; - - if (sc == NULL) - return (ENXIO); - - /* - * For now set frequency to 2*VGA_PIXEL_CLOCK - */ - am335x_clk_set_arm_disp_freq(clkdev, 25175000*2); - - /*set MODULEMODE to ENABLE(2) */ - prcm_write_4(CM_PER_LCDC_CLKCTRL, 2); - - /* wait for MODULEMODE to become ENABLE(2) */ - while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2) - DELAY(10); - - /* wait for IDLEST to become Func(0) */ - while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16)) - DELAY(10); - - return (0); -} - -static int -am335x_clk_pruss_activate(struct ti_clock_dev *clkdev) -{ - struct am335x_prcm_softc *sc = am335x_prcm_sc; - - if (sc == NULL) - return (ENXIO); - - /* Set MODULEMODE to ENABLE(2) */ - prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2); - - /* Wait for MODULEMODE to become ENABLE(2) */ - while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2) - DELAY(10); - - /* Set CLKTRCTRL to SW_WKUP(2) */ - prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2); - - /* Wait for the 200 MHz OCP clock to become active */ - while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0) - DELAY(10); - - /* Wait for the 200 MHz IEP clock to become active */ - while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0) - DELAY(10); - - /* Wait for the 192 MHz UART clock to become active */ - while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0) - DELAY(10); - - /* Select L3F as OCP clock */ - prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 0); - while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 0) - DELAY(10); - - /* Clear the RESET bit */ - prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2); - - return (0); -} diff --git a/sys/arm/ti/am335x/am335x_pwmss.c b/sys/arm/ti/am335x/am335x_pwmss.c index 814865d6b762..287b6ce9e8fe 100644 --- a/sys/arm/ti/am335x/am335x_pwmss.c +++ b/sys/arm/ti/am335x/am335x_pwmss.c @@ -46,9 +46,10 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> -#include <arm/ti/ti_prcm.h> -#include <arm/ti/ti_hwmods.h> -#include <arm/ti/ti_scm.h> +#include <arm/ti/ti_sysc.h> + +#include <dev/extres/syscon/syscon.h> +#include "syscon_if.h" #include "am335x_pwm.h" #include "am335x_scm.h" @@ -59,6 +60,11 @@ __FBSDID("$FreeBSD$"); #define CLKCONFIG_EPWMCLK_EN (1 << 8) #define PWMSS_CLKSTATUS 0x0C +/* TRM chapter 2 memory map table 2-3 + VER register location */ +#define PWMSS_REV_0 0x0000 +#define PWMSS_REV_1 0x2000 +#define PWMSS_REV_2 0x4000 + static device_probe_t am335x_pwmss_probe; static device_attach_t am335x_pwmss_attach; static device_detach_t am335x_pwmss_detach; @@ -66,7 +72,7 @@ static device_detach_t am335x_pwmss_detach; struct am335x_pwmss_softc { struct simplebus_softc sc_simplebus; device_t sc_dev; - clk_ident_t sc_clk; + struct syscon *syscon; }; static device_method_t am335x_pwmss_methods[] = { @@ -97,36 +103,45 @@ am335x_pwmss_attach(device_t dev) { struct am335x_pwmss_softc *sc; uint32_t reg, id; - phandle_t node; + uint64_t rev_address; + phandle_t node, opp_table; sc = device_get_softc(dev); sc->sc_dev = dev; - sc->sc_clk = ti_hwmods_get_clock(dev); - if (sc->sc_clk == INVALID_CLK_IDENT) { - device_printf(dev, "failed to get device id based on ti,hwmods\n"); - return (EINVAL); + /* FIXME: For now; Go and kidnap syscon from opp-table */ + opp_table = OF_finddevice("/opp-table"); + if (opp_table == -1) { + device_printf(dev, "Cant find /opp-table\n"); + return (ENXIO); + } + if (!OF_hasprop(opp_table, "syscon")) { + device_printf(dev, "/opp-table doesnt have required syscon property\n"); + return (ENXIO); + } + if (syscon_get_by_ofw_property(dev, opp_table, "syscon", &sc->syscon) != 0) { + device_printf(dev, "Failed to get syscon\n"); + return (ENXIO); } - ti_prcm_clk_enable(sc->sc_clk); - ti_scm_reg_read_4(SCM_PWMSS_CTRL, ®); - switch (sc->sc_clk) { - case PWMSS0_CLK: - id = 0; - break; - case PWMSS1_CLK: - id = 1; - break; - - case PWMSS2_CLK: - id = 2; - break; - default: - device_printf(dev, "unknown pwmss clock id: %d\n", sc->sc_clk); - return (EINVAL); + ti_sysc_clock_enable(device_get_parent(dev)); + + rev_address = ti_sysc_get_rev_address(device_get_parent(dev)); + switch (rev_address) { + case PWMSS_REV_0: + id = 0; + break; + case PWMSS_REV_1: + id = 1; + break; + case PWMSS_REV_2: + id = 2; + break; } + + reg = SYSCON_READ_4(sc->syscon, SCM_PWMSS_CTRL); reg |= (1 << id); - ti_scm_reg_write_4(SCM_PWMSS_CTRL, reg); + SYSCON_WRITE_4(sc->syscon, SCM_PWMSS_CTRL, reg); node = ofw_bus_get_node(dev); @@ -161,3 +176,4 @@ DEFINE_CLASS_1(am335x_pwmss, am335x_pwmss_driver, am335x_pwmss_methods, static devclass_t am335x_pwmss_devclass; DRIVER_MODULE(am335x_pwmss, simplebus, am335x_pwmss_driver, am335x_pwmss_devclass, 0, 0); MODULE_VERSION(am335x_pwmss, 1); +MODULE_DEPEND(am335x_pwmss, ti_sysc, 1, 1, 1); diff --git a/sys/arm/ti/am335x/am335x_rtc.c b/sys/arm/ti/am335x/am335x_rtc.c index 9620f5284e84..c2612d2fc7a9 100644 --- a/sys/arm/ti/am335x/am335x_rtc.c +++ b/sys/arm/ti/am335x/am335x_rtc.c @@ -39,8 +39,9 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> +#include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> -#include <arm/ti/ti_prcm.h> +#include <arm/ti/ti_sysc.h> #include <arm/ti/am335x/am335x_rtcvar.h> #include <arm/ti/am335x/am335x_rtcreg.h> @@ -110,7 +111,7 @@ am335x_rtc_attach(device_t dev) RTC_LOCK_INIT(sc); /* Enable the RTC module. */ - ti_prcm_clk_enable(RTC_CLK); + ti_sysc_clock_enable(device_get_parent(dev)); rev = RTC_READ4(sc, RTC_REVISION); device_printf(dev, "AM335X RTC v%d.%d.%d\n", (rev >> 8) & 0x7, (rev >> 6) & 0x3, rev & 0x3f); @@ -209,3 +210,4 @@ static devclass_t am335x_rtc_devclass; DRIVER_MODULE(am335x_rtc, simplebus, am335x_rtc_driver, am335x_rtc_devclass, 0, 0); MODULE_VERSION(am335x_rtc, 1); MODULE_DEPEND(am335x_rtc, simplebus, 1, 1, 1); +MODULE_DEPEND(am335x_rtc, ti_sysc, 1, 1, 1); diff --git a/sys/arm/ti/am335x/am335x_scm.c b/sys/arm/ti/am335x/am335x_scm.c index 6f040ed74b7d..e72c14ba58ad 100644 --- a/sys/arm/ti/am335x/am335x_scm.c +++ b/sys/arm/ti/am335x/am335x_scm.c @@ -40,11 +40,15 @@ __FBSDID("$FreeBSD$"); #include <arm/ti/ti_cpuid.h> #include <arm/ti/ti_scm.h> +#include <dev/extres/syscon/syscon.h> +#include "syscon_if.h" + #define TZ_ZEROC 2731 struct am335x_scm_softc { int sc_last_temp; struct sysctl_oid *sc_temp_oid; + struct syscon *syscon; }; static int @@ -60,7 +64,7 @@ am335x_scm_temp_sysctl(SYSCTL_HANDLER_ARGS) /* Read the temperature and convert to Kelvin. */ for(i = 50; i > 0; i--) { - ti_scm_reg_read_4(SCM_BGAP_CTRL, ®); + reg = SYSCON_READ_4(sc->syscon, SCM_BGAP_CTRL); if ((reg & SCM_BGAP_EOCZ) == 0) break; DELAY(50); @@ -96,6 +100,9 @@ am335x_scm_identify(driver_t *driver, device_t parent) static int am335x_scm_probe(device_t dev) { + /* Just allow the first one */ + if (strcmp(device_get_nameunit(dev), "am335x_scm0") != 0) + return (ENXIO); device_set_desc(dev, "AM335x Control Module Extension"); @@ -109,21 +116,40 @@ am335x_scm_attach(device_t dev) struct sysctl_ctx_list *ctx; struct sysctl_oid_list *tree; uint32_t reg; + phandle_t opp_table; + int err; + + sc = device_get_softc(dev); + + /* FIXME: For now; Go and kidnap syscon from opp-table */ + opp_table = OF_finddevice("/opp-table"); + if (opp_table == -1) { + device_printf(dev, "Cant find /opp-table\n"); + return (ENXIO); + } + if (!OF_hasprop(opp_table, "syscon")) { + device_printf(dev, "/opp-table missing syscon property\n"); + return (ENXIO); + } + err = syscon_get_by_ofw_property(dev, opp_table, "syscon", &sc->syscon); + if (err) { + device_printf(dev, "Failed to get syscon\n"); + return (ENXIO); + } /* Reset the digital outputs. */ - ti_scm_reg_write_4(SCM_BGAP_CTRL, 0); - ti_scm_reg_read_4(SCM_BGAP_CTRL, ®); + SYSCON_WRITE_4(sc->syscon, SCM_BGAP_CTRL, 0); + reg = SYSCON_READ_4(sc->syscon, SCM_BGAP_CTRL); DELAY(500); /* Set continous mode. */ - ti_scm_reg_write_4(SCM_BGAP_CTRL, SCM_BGAP_CONTCONV); - ti_scm_reg_read_4(SCM_BGAP_CTRL, ®); + SYSCON_WRITE_4(sc->syscon, SCM_BGAP_CTRL, SCM_BGAP_CONTCONV); + reg = SYSCON_READ_4(sc->syscon, SCM_BGAP_CTRL); DELAY(500); /* Start the ADC conversion. */ reg = SCM_BGAP_CLRZ | SCM_BGAP_CONTCONV | SCM_BGAP_SOC; - ti_scm_reg_write_4(SCM_BGAP_CTRL, reg); + SYSCON_WRITE_4(sc->syscon, SCM_BGAP_CTRL, reg); /* Temperature sysctl. */ - sc = device_get_softc(dev); ctx = device_get_sysctl_ctx(dev); tree = SYSCTL_CHILDREN(device_get_sysctl_tree(dev)); sc->sc_temp_oid = SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, @@ -145,7 +171,7 @@ am335x_scm_detach(device_t dev) sysctl_remove_oid(sc->sc_temp_oid, 1, 0); /* Stop the bandgap ADC. */ - ti_scm_reg_write_4(SCM_BGAP_CTRL, SCM_BGAP_BGOFF); + SYSCON_WRITE_4(sc->syscon, SCM_BGAP_CTRL, SCM_BGAP_BGOFF); return (0); } @@ -169,4 +195,4 @@ static devclass_t am335x_scm_devclass; DRIVER_MODULE(am335x_scm, ti_scm, am335x_scm_driver, am335x_scm_devclass, 0, 0); MODULE_VERSION(am335x_scm, 1); -MODULE_DEPEND(am335x_scm, ti_scm, 1, 1, 1); +MODULE_DEPEND(am335x_scm, ti_scm_syscon, 1, 1, 1); diff --git a/sys/arm/ti/am335x/am335x_usb_phy.c b/sys/arm/ti/am335x/am335x_usb_phy.c new file mode 100644 index 000000000000..00e28122dcec --- /dev/null +++ b/sys/arm/ti/am335x/am335x_usb_phy.c @@ -0,0 +1,121 @@ +/*- + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/fbio.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/resource.h> +#include <machine/bus.h> +#include <vm/vm.h> +#include <vm/vm_extern.h> +#include <vm/vm_kern.h> +#include <vm/pmap.h> + +#include <dev/fdt/simplebus.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#define TI_AM335X_USB_PHY 1 +#define TI_AM335X_USB_PHY_END 0 + +static struct ofw_compat_data compat_data[] = { + { "ti,am335x-usb-phy", TI_AM335X_USB_PHY }, + { NULL, TI_AM335X_USB_PHY_END } +}; + +struct ti_usb_phy_softc { + device_t dev; +}; + +static int ti_usb_phy_probe(device_t dev); +static int ti_usb_phy_attach(device_t dev); +static int ti_usb_phy_detach(device_t dev); + +static int +ti_usb_phy_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "TI AM335x USB PHY"); + if (!bootverbose) + device_quiet(dev); + + return (BUS_PROBE_DEFAULT); +} + +static int +ti_usb_phy_attach(device_t dev) +{ + struct ti_usb_phy_softc *sc; + phandle_t node; + + sc = device_get_softc(dev); + sc->dev = dev; + node = ofw_bus_get_node(dev); + + /* FIXME: Add dev/extres/phy/ interface */ + + return (bus_generic_attach(dev)); +} + +static int +ti_usb_phy_detach(device_t dev) +{ + return (EBUSY); +} + +static device_method_t ti_usb_phy_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ti_usb_phy_probe), + DEVMETHOD(device_attach, ti_usb_phy_attach), + DEVMETHOD(device_detach, ti_usb_phy_detach), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(ti_usb_phy, ti_usb_phy_driver, ti_usb_phy_methods, + sizeof(struct ti_usb_phy_softc), simplebus_driver); + +static devclass_t ti_usb_phy_devclass; + +EARLY_DRIVER_MODULE(ti_usb_phy, simplebus, ti_usb_phy_driver, + ti_usb_phy_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST); +MODULE_VERSION(ti_usb_phy, 1); +MODULE_DEPEND(ti_usb_phy, ti_sysc, 1, 1, 1); diff --git a/sys/arm/ti/am335x/am335x_usbss.c b/sys/arm/ti/am335x/am335x_usbss.c deleted file mode 100644 index ce78a7b64315..000000000000 --- a/sys/arm/ti/am335x/am335x_usbss.c +++ /dev/null @@ -1,226 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2013 Oleksandr Tymoshenko <gonzo@freebsd.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/stdint.h> -#include <sys/stddef.h> -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/types.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/bus.h> -#include <sys/module.h> -#include <sys/lock.h> -#include <sys/mutex.h> -#include <sys/condvar.h> -#include <sys/sysctl.h> -#include <sys/sx.h> -#include <sys/unistd.h> -#include <sys/callout.h> -#include <sys/malloc.h> -#include <sys/priv.h> - -#include <dev/fdt/simplebus.h> -#include <dev/ofw/openfirm.h> -#include <dev/ofw/ofw_bus.h> -#include <dev/ofw/ofw_bus_subr.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> - -#include <dev/usb/usb_core.h> -#include <dev/usb/usb_busdma.h> -#include <dev/usb/usb_process.h> -#include <dev/usb/usb_util.h> - -#include <dev/usb/usb_controller.h> -#include <dev/usb/usb_bus.h> -#include <dev/usb/controller/musb_otg.h> -#include <dev/usb/usb_debug.h> - -#include <sys/rman.h> - -#include <arm/ti/ti_prcm.h> -#include <arm/ti/ti_scm.h> -#include <arm/ti/am335x/am335x_scm.h> - -#define AM335X_USB_PORTS 2 - -#define USBSS_REVREG 0x00 -#define USBSS_SYSCONFIG 0x10 -#define USBSS_SYSCONFIG_SRESET 1 - -#define USBCTRL_REV 0x00 -#define USBCTRL_CTRL 0x14 -#define USBCTRL_STAT 0x18 -#define USBCTRL_IRQ_STAT0 0x30 -#define IRQ_STAT0_RXSHIFT 16 -#define IRQ_STAT0_TXSHIFT 0 -#define USBCTRL_IRQ_STAT1 0x34 -#define IRQ_STAT1_DRVVBUS (1 << 8) -#define USBCTRL_INTEN_SET0 0x38 -#define USBCTRL_INTEN_SET1 0x3C -#define USBCTRL_INTEN_USB_ALL 0x1ff -#define USBCTRL_INTEN_USB_SOF (1 << 3) -#define USBCTRL_INTEN_CLR0 0x40 -#define USBCTRL_INTEN_CLR1 0x44 -#define USBCTRL_UTMI 0xE0 -#define USBCTRL_UTMI_FSDATAEXT (1 << 1) -#define USBCTRL_MODE 0xE8 -#define USBCTRL_MODE_IDDIG (1 << 8) -#define USBCTRL_MODE_IDDIGMUX (1 << 7) - -#define USBSS_WRITE4(sc, reg, val) \ - bus_write_4((sc)->sc_mem_res, (reg), (val)) -#define USBSS_READ4(sc, reg) \ - bus_read_4((sc)->sc_mem_res, (reg)) - -static device_probe_t usbss_probe; -static device_attach_t usbss_attach; -static device_detach_t usbss_detach; - -struct usbss_softc { - struct simplebus_softc simplebus_sc; - struct resource *sc_mem_res; - int sc_mem_rid; -}; - -static int -usbss_probe(device_t dev) -{ - - if (!ofw_bus_status_okay(dev)) - return (ENXIO); - - if (!ofw_bus_is_compatible(dev, "ti,am33xx-usb")) - return (ENXIO); - - device_set_desc(dev, "TI AM33xx integrated USB OTG controller"); - - return (BUS_PROBE_DEFAULT); -} - -static int -usbss_attach(device_t dev) -{ - struct usbss_softc *sc = device_get_softc(dev); - int i; - uint32_t rev; - phandle_t node; - - /* Request the memory resources */ - sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->sc_mem_rid, RF_ACTIVE); - if (sc->sc_mem_res == NULL) { - device_printf(dev, - "Error: could not allocate mem resources\n"); - return (ENXIO); - } - - /* Enable device clocks. */ - ti_prcm_clk_enable(MUSB0_CLK); - - /* - * Reset USBSS, USB0 and USB1. - * The registers of USB subsystem must not be accessed while the - * reset pulse is active (200ns). - */ - USBSS_WRITE4(sc, USBSS_SYSCONFIG, USBSS_SYSCONFIG_SRESET); - DELAY(100); - i = 10; - while (USBSS_READ4(sc, USBSS_SYSCONFIG) & USBSS_SYSCONFIG_SRESET) { - DELAY(100); - if (i-- == 0) { - device_printf(dev, "reset timeout.\n"); - return (ENXIO); - } - } - - /* Read the module revision. */ - rev = USBSS_READ4(sc, USBSS_REVREG); - device_printf(dev, "TI AM335X USBSS v%d.%d.%d\n", - (rev >> 8) & 7, (rev >> 6) & 3, rev & 63); - - node = ofw_bus_get_node(dev); - - if (node == -1) { - usbss_detach(dev); - return (ENXIO); - } - - simplebus_init(dev, node); - - /* - * Allow devices to identify. - */ - bus_generic_probe(dev); - - /* - * Now walk the OFW tree and attach top-level devices. - */ - for (node = OF_child(node); node > 0; node = OF_peer(node)) - simplebus_add_device(dev, node, 0, NULL, -1, NULL); - - return (bus_generic_attach(dev)); -} - -static int -usbss_detach(device_t dev) -{ - struct usbss_softc *sc = device_get_softc(dev); - - /* Free resources if any */ - if (sc->sc_mem_res) - bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, - sc->sc_mem_res); - - /* during module unload there are lots of children leftover */ - device_delete_children(dev); - - return (0); -} - -static device_method_t usbss_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, usbss_probe), - DEVMETHOD(device_attach, usbss_attach), - DEVMETHOD(device_detach, usbss_detach), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - - DEVMETHOD_END -}; - -DEFINE_CLASS_1(usbss, usbss_driver, usbss_methods, - sizeof(struct usbss_softc), simplebus_driver); -static devclass_t usbss_devclass; -DRIVER_MODULE(usbss, simplebus, usbss_driver, usbss_devclass, 0, 0); -MODULE_DEPEND(usbss, usb, 1, 1, 1); diff --git a/sys/arm/ti/am335x/files.am335x b/sys/arm/ti/am335x/files.am335x index 66af0d867847..4ecdc1e35b43 100644 --- a/sys/arm/ti/am335x/files.am335x +++ b/sys/arm/ti/am335x/files.am335x @@ -8,7 +8,6 @@ arm/ti/am335x/am335x_gpio.c optional gpio arm/ti/am335x/am335x_lcd.c optional sc | vt arm/ti/am335x/am335x_lcd_syscons.c optional sc arm/ti/am335x/am335x_pmic.c optional am335x_pmic -arm/ti/am335x/am335x_prcm.c standard arm/ti/am335x/am335x_pwmss.c standard dev/pwm/pwmbus_if.m standard arm/ti/am335x/am335x_ehrpwm.c standard @@ -16,8 +15,9 @@ arm/ti/am335x/am335x_ecap.c standard arm/ti/am335x/am335x_rtc.c optional am335x_rtc arm/ti/am335x/am335x_scm.c standard arm/ti/am335x/am335x_scm_padconf.c standard -arm/ti/am335x/am335x_usbss.c optional musb fdt arm/ti/am335x/am335x_musb.c optional musb fdt +arm/ti/am335x/am335x_usb_phy.c optional musb fdt +arm/ti/am335x/am3359_cppi41.c optional musb fdt arm/ti/am335x/tda19988.c optional hdmi diff --git a/sys/arm/ti/clk/clock_common.c b/sys/arm/ti/clk/clock_common.c new file mode 100644 index 000000000000..15b0e75a8a1e --- /dev/null +++ b/sys/arm/ti/clk/clock_common.c @@ -0,0 +1,152 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/systm.h> +#include <sys/libkern.h> +#include <sys/types.h> +#include <sys/malloc.h> + +#include <machine/bus.h> +#include <dev/fdt/simplebus.h> + +#include <dev/extres/clk/clk_mux.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include "clock_common.h" + +#if 0 +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +void +read_clock_cells(device_t dev, struct clock_cell_info *clk) { + ssize_t numbytes_clocks; + phandle_t node, parent, *cells; + int index, ncells, rv; + + node = ofw_bus_get_node(dev); + + /* Get names of parent clocks */ + numbytes_clocks = OF_getproplen(node, "clocks"); + clk->num_clock_cells = numbytes_clocks / sizeof(cell_t); + + /* Allocate space and get clock cells content */ + /* clock_cells / clock_cells_ncells will be freed in + * find_parent_clock_names() + */ + clk->clock_cells = malloc(numbytes_clocks, M_DEVBUF, M_WAITOK|M_ZERO); + clk->clock_cells_ncells = malloc(clk->num_clock_cells*sizeof(uint8_t), + M_DEVBUF, M_WAITOK|M_ZERO); + OF_getencprop(node, "clocks", clk->clock_cells, numbytes_clocks); + + /* Count number of clocks */ + clk->num_real_clocks = 0; + for (index = 0; index < clk->num_clock_cells; index++) { + rv = ofw_bus_parse_xref_list_alloc(node, "clocks", "#clock-cells", + clk->num_real_clocks, &parent, &ncells, &cells); + if (rv != 0) + continue; + + if (cells != NULL) + OF_prop_free(cells); + + clk->clock_cells_ncells[index] = ncells; + index += ncells; + clk->num_real_clocks++; + } +} + +int +find_parent_clock_names(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def) { + int index, clock_index, err; + bool found_all = true; + clk_t parent; + + /* Figure out names */ + for (index = 0, clock_index = 0; index < clk->num_clock_cells; index++) { + /* Get name of parent clock */ + err = clk_get_by_ofw_index(dev, 0, clock_index, &parent); + if (err != 0) { + clock_index++; + found_all = false; + DPRINTF(dev, "Failed to find clock_cells[%d]=0x%x\n", + index, clk->clock_cells[index]); + + index += clk->clock_cells_ncells[index]; + continue; + } + + def->parent_names[clock_index] = clk_get_name(parent); + clk_release(parent); + + DPRINTF(dev, "Found parent clock[%d/%d]: %s\n", + clock_index, clk->num_real_clocks, + def->parent_names[clock_index]); + + clock_index++; + index += clk->clock_cells_ncells[index]; + } + + if (!found_all) { + return 1; + } + + free(clk->clock_cells, M_DEVBUF); + free(clk->clock_cells_ncells, M_DEVBUF); + return 0; +} + +void +create_clkdef(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def) { + def->id = 1; + + clk_parse_ofw_clk_name(dev, ofw_bus_get_node(dev), &def->name); + + DPRINTF(dev, "node name: %s\n", def->name); + + def->parent_cnt = clk->num_real_clocks; + def->parent_names = malloc(clk->num_real_clocks*sizeof(char *), + M_OFWPROP, M_WAITOK); +} +void +free_clkdef(struct clknode_init_def *def) { + OF_prop_free(__DECONST(char *, def->name)); + OF_prop_free(def->parent_names); +} diff --git a/sys/arm/ti/clk/clock_common.h b/sys/arm/ti/clk/clock_common.h new file mode 100644 index 000000000000..148494f90331 --- /dev/null +++ b/sys/arm/ti/clk/clock_common.h @@ -0,0 +1,43 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +struct clock_cell_info { + cell_t *clock_cells; + uint8_t *clock_cells_ncells; + uint32_t num_clock_cells; + uint8_t num_real_clocks; +}; + +void read_clock_cells(device_t dev, struct clock_cell_info *clk); +int find_parent_clock_names(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def); +void create_clkdef(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def); +void free_clkdef(struct clknode_init_def *def); diff --git a/sys/arm/ti/clk/ti_clk_clkctrl.c b/sys/arm/ti/clk/ti_clk_clkctrl.c new file mode 100644 index 000000000000..6b2fff5e12bb --- /dev/null +++ b/sys/arm/ti/clk/ti_clk_clkctrl.c @@ -0,0 +1,219 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/malloc.h> + +#include <dev/extres/clk/clk.h> + +#include <arm/ti/clk/ti_clk_clkctrl.h> + +#include "clkdev_if.h" + +#if 0 +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +/* + * clknode for clkctrl, implements gate and mux (for gpioc) + */ + +#define GPIO_X_GDBCLK_MASK 0x00040000 +#define IDLEST_MASK 0x00030000 +#define MODULEMODE_MASK 0x00000003 + +#define GPIOX_GDBCLK_ENABLE 0x00040000 +#define GPIOX_GDBCLK_DISABLE 0x00000000 +#define IDLEST_FUNC 0x00000000 +#define IDLEST_TRANS 0x00010000 +#define IDLEST_IDLE 0x00020000 +#define IDLEST_DISABLE 0x00030000 + +#define MODULEMODE_DISABLE 0x0 +#define MODULEMODE_ENABLE 0x2 + +struct ti_clkctrl_clknode_sc { + device_t dev; + bool gdbclk; + /* omap4-cm range.host + ti,clkctrl reg[0] */ + uint32_t register_offset; +}; + +#define WRITE4(_clk, off, val) \ + CLKDEV_WRITE_4(clknode_get_device(_clk), off, val) +#define READ4(_clk, off, val) \ + CLKDEV_READ_4(clknode_get_device(_clk), off, val) +#define DEVICE_LOCK(_clk) \ + CLKDEV_DEVICE_LOCK(clknode_get_device(_clk)) +#define DEVICE_UNLOCK(_clk) \ + CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk)) + +static int +ti_clkctrl_init(struct clknode *clk, device_t dev) +{ + struct ti_clkctrl_clknode_sc *sc; + + sc = clknode_get_softc(clk); + sc->dev = dev; + + clknode_init_parent_idx(clk, 0); + return (0); +} + +static int +ti_clkctrl_set_gdbclk_gate(struct clknode *clk, bool enable) +{ + struct ti_clkctrl_clknode_sc *sc; + uint32_t val, gpio_x_gdbclk; + uint32_t timeout = 100; + + sc = clknode_get_softc(clk); + + READ4(clk, sc->register_offset, &val); + DPRINTF(sc->dev, "val(%x) & (%x | %x = %x)\n", + val, GPIO_X_GDBCLK_MASK, MODULEMODE_MASK, + GPIO_X_GDBCLK_MASK | MODULEMODE_MASK); + + if (enable) { + val = val & MODULEMODE_MASK; + val |= GPIOX_GDBCLK_ENABLE; + } else { + val = val & MODULEMODE_MASK; + val |= GPIOX_GDBCLK_DISABLE; + } + + DPRINTF(sc->dev, "val %x\n", val); + WRITE4(clk, sc->register_offset, val); + + /* Wait */ + while (timeout) { + READ4(clk, sc->register_offset, &val); + gpio_x_gdbclk = val & GPIO_X_GDBCLK_MASK; + if (enable && (gpio_x_gdbclk == GPIOX_GDBCLK_ENABLE)) + break; + else if (!enable && (gpio_x_gdbclk == GPIOX_GDBCLK_DISABLE)) + break; + DELAY(10); + timeout--; + } + if (timeout == 0) { + device_printf(sc->dev, "ti_clkctrl_set_gdbclk_gate: Timeout\n"); + return (1); + } + + return (0); +} + +static int +ti_clkctrl_set_gate(struct clknode *clk, bool enable) +{ + struct ti_clkctrl_clknode_sc *sc; + uint32_t val, idlest, module; + uint32_t timeout=100; + int err; + + sc = clknode_get_softc(clk); + + if (sc->gdbclk) { + err = ti_clkctrl_set_gdbclk_gate(clk, enable); + return (err); + } + + READ4(clk, sc->register_offset, &val); + + if (enable) + WRITE4(clk, sc->register_offset, MODULEMODE_ENABLE); + else + WRITE4(clk, sc->register_offset, MODULEMODE_DISABLE); + + while (timeout) { + READ4(clk, sc->register_offset, &val); + idlest = val & IDLEST_MASK; + module = val & MODULEMODE_MASK; + if (enable && + (idlest == IDLEST_FUNC || idlest == IDLEST_TRANS) && + module == MODULEMODE_ENABLE) + break; + else if (!enable && + idlest == IDLEST_DISABLE && + module == MODULEMODE_DISABLE) + break; + DELAY(10); + timeout--; + } + + if (timeout == 0) { + device_printf(sc->dev, "ti_clkctrl_set_gate: Timeout\n"); + return (1); + } + + return (0); +} + +static clknode_method_t ti_clkctrl_clknode_methods[] = { + /* Device interface */ + CLKNODEMETHOD(clknode_init, ti_clkctrl_init), + CLKNODEMETHOD(clknode_set_gate, ti_clkctrl_set_gate), + CLKNODEMETHOD_END +}; + +DEFINE_CLASS_1(ti_clkctrl_clknode, ti_clkctrl_clknode_class, + ti_clkctrl_clknode_methods, sizeof(struct ti_clkctrl_clknode_sc), + clknode_class); + +int +ti_clknode_clkctrl_register(struct clkdom *clkdom, + struct ti_clk_clkctrl_def *clkdef) +{ + struct clknode *clk; + struct ti_clkctrl_clknode_sc *sc; + + clk = clknode_create(clkdom, &ti_clkctrl_clknode_class, + &clkdef->clkdef); + + if (clk == NULL) { + return (1); + } + + sc = clknode_get_softc(clk); + sc->register_offset = clkdef->register_offset; + sc->gdbclk = clkdef->gdbclk; + + if (clknode_register(clkdom, clk) == NULL) { + return (2); + } + return (0); +} diff --git a/sys/arm/ti/clk/ti_clk_clkctrl.h b/sys/arm/ti/clk/ti_clk_clkctrl.h new file mode 100644 index 000000000000..d78736244815 --- /dev/null +++ b/sys/arm/ti/clk/ti_clk_clkctrl.h @@ -0,0 +1,43 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _TI_CLK_CLKCTRL_H_ +#define _TI_CLK_CLKCTRL_H_ + +#include <dev/extres/clk/clk.h> + +struct ti_clk_clkctrl_def { + struct clknode_init_def clkdef; + bool gdbclk; + uint32_t register_offset; +}; + +int ti_clknode_clkctrl_register(struct clkdom *clkdom, struct ti_clk_clkctrl_def *clkdef); + +#endif /* _TI_CLK_CLKCTRL_H_ */ diff --git a/sys/arm/ti/clk/ti_clk_dpll.c b/sys/arm/ti/clk/ti_clk_dpll.c new file mode 100644 index 000000000000..14e48dc95026 --- /dev/null +++ b/sys/arm/ti/clk/ti_clk_dpll.c @@ -0,0 +1,341 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2019 Emmanuel Vadot <manu@freebsd.org> + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * based on sys/arm/allwinner/clkng/aw_clk_np.c + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <dev/extres/clk/clk.h> + +#include <arm/ti/clk/ti_clk_dpll.h> + +#include "clkdev_if.h" + +/* + * clknode for clocks matching the formula : + * + * clk = clkin * n / p + * + */ + +struct ti_dpll_clknode_sc { + uint32_t ti_clkmode_offset; /* control */ + uint8_t ti_clkmode_flags; + + uint32_t ti_idlest_offset; + + uint32_t ti_clksel_offset; /* mult-div1 */ + struct ti_clk_factor n; /* ti_clksel_mult */ + struct ti_clk_factor p; /* ti_clksel_div */ + + uint32_t ti_autoidle_offset; +}; + +#define WRITE4(_clk, off, val) \ + CLKDEV_WRITE_4(clknode_get_device(_clk), off, val) +#define READ4(_clk, off, val) \ + CLKDEV_READ_4(clknode_get_device(_clk), off, val) +#define DEVICE_LOCK(_clk) \ + CLKDEV_DEVICE_LOCK(clknode_get_device(_clk)) +#define DEVICE_UNLOCK(_clk) \ + CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk)) + +static int +ti_dpll_clk_init(struct clknode *clk, device_t dev) +{ + struct ti_dpll_clknode_sc *sc; + + sc = clknode_get_softc(clk); + + clknode_init_parent_idx(clk, 0); + return (0); +} + +/* helper to keep aw_clk_np_find_best "intact" */ +static inline uint32_t +ti_clk_factor_get_max(struct ti_clk_factor *factor) +{ + uint32_t max; + + if (factor->flags & TI_CLK_FACTOR_FIXED) + max = factor->value; + else { + max = (1 << factor->width); + } + + return (max); +} + +static inline uint32_t +ti_clk_factor_get_min(struct ti_clk_factor *factor) +{ + uint32_t min; + + if (factor->flags & TI_CLK_FACTOR_FIXED) + min = factor->value; + else if (factor->flags & TI_CLK_FACTOR_ZERO_BASED) + min = 0; + else if (factor->flags & TI_CLK_FACTOR_MIN_VALUE) + min = factor->min_value; + else + min = 1; + + return (min); +} + +static uint64_t +ti_dpll_clk_find_best(struct ti_dpll_clknode_sc *sc, uint64_t fparent, + uint64_t *fout, uint32_t *factor_n, uint32_t *factor_p) +{ + uint64_t cur, best; + uint32_t n, p, max_n, max_p, min_n, min_p; + + *factor_n = *factor_p = 0; + + max_n = ti_clk_factor_get_max(&sc->n); + max_p = ti_clk_factor_get_max(&sc->p); + min_n = ti_clk_factor_get_min(&sc->n); + min_p = ti_clk_factor_get_min(&sc->p); + + for (p = min_p; p <= max_p; ) { + for (n = min_n; n <= max_n; ) { + cur = fparent * n / p; + if (abs(*fout - cur) < abs(*fout - best)) { + best = cur; + *factor_n = n; + *factor_p = p; + } + + n++; + } + p++; + } + + return (best); +} + +static inline uint32_t +ti_clk_get_factor(uint32_t val, struct ti_clk_factor *factor) +{ + uint32_t factor_val; + + if (factor->flags & TI_CLK_FACTOR_FIXED) + return (factor->value); + + factor_val = (val & factor->mask) >> factor->shift; + if (!(factor->flags & TI_CLK_FACTOR_ZERO_BASED)) + factor_val += 1; + + return (factor_val); +} + +static inline uint32_t +ti_clk_factor_get_value(struct ti_clk_factor *factor, uint32_t raw) +{ + uint32_t val; + + if (factor->flags & TI_CLK_FACTOR_FIXED) + return (factor->value); + + if (factor->flags & TI_CLK_FACTOR_ZERO_BASED) + val = raw; + else if (factor->flags & TI_CLK_FACTOR_MAX_VALUE && + raw > factor->max_value) + val = factor->max_value; + else + val = raw - 1; + + return (val); +} + + +static int +ti_dpll_clk_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout, + int flags, int *stop) +{ + struct ti_dpll_clknode_sc *sc; + uint64_t cur, best; + uint32_t val, n, p, best_n, best_p, timeout; + + sc = clknode_get_softc(clk); + + best = cur = 0; + + best = ti_dpll_clk_find_best(sc, fparent, fout, + &best_n, &best_p); + + if ((flags & CLK_SET_DRYRUN) != 0) { + *fout = best; + *stop = 1; + return (0); + } + + if ((best < *fout) && + (flags == CLK_SET_ROUND_DOWN)) { + *stop = 1; + return (ERANGE); + } + if ((best > *fout) && + (flags == CLK_SET_ROUND_UP)) { + *stop = 1; + return (ERANGE); + } + + DEVICE_LOCK(clk); + /* 1 switch PLL to bypass mode */ + WRITE4(clk, sc->ti_clkmode_offset, DPLL_EN_MN_BYPASS_MODE); + + /* 2 Ensure PLL is in bypass */ + timeout = 10000; + do { + DELAY(10); + READ4(clk, sc->ti_idlest_offset, &val); + } while (!(val & ST_MN_BYPASS_MASK) && timeout--); + + if (timeout == 0) { + DEVICE_UNLOCK(clk); + return (ERANGE); // FIXME: Better return value? + } + + /* 3 Set DPLL_MULT & DPLL_DIV bits */ + READ4(clk, sc->ti_clksel_offset, &val); + + n = ti_clk_factor_get_value(&sc->n, best_n); + p = ti_clk_factor_get_value(&sc->p, best_p); + val &= ~sc->n.mask; + val &= ~sc->p.mask; + val |= n << sc->n.shift; + val |= p << sc->p.shift; + + WRITE4(clk, sc->ti_clksel_offset, val); + + /* 4. configure M2, M4, M5 and M6 */ + /* + * FIXME: According to documentation M2/M4/M5/M6 can be set "later" + * See note in TRM 8.1.6.7.1 + */ + + /* 5 Switch over to lock mode */ + WRITE4(clk, sc->ti_clkmode_offset, DPLL_EN_LOCK_MODE); + + /* 6 Ensure PLL is locked */ + timeout = 10000; + do { + DELAY(10); + READ4(clk, sc->ti_idlest_offset, &val); + } while (!(val & ST_DPLL_CLK_MASK) && timeout--); + + DEVICE_UNLOCK(clk); + if (timeout == 0) { + return (ERANGE); // FIXME: Better return value? + } + + *fout = best; + *stop = 1; + + return (0); +} + +static int +ti_dpll_clk_recalc(struct clknode *clk, uint64_t *freq) +{ + struct ti_dpll_clknode_sc *sc; + uint32_t val, n, p; + + sc = clknode_get_softc(clk); + + DEVICE_LOCK(clk); + READ4(clk, sc->ti_clksel_offset, &val); + DEVICE_UNLOCK(clk); + + n = ti_clk_get_factor(val, &sc->n); + p = ti_clk_get_factor(val, &sc->p); + + *freq = *freq * n / p; + + return (0); +} + +static clknode_method_t ti_dpll_clknode_methods[] = { + /* Device interface */ + CLKNODEMETHOD(clknode_init, ti_dpll_clk_init), + CLKNODEMETHOD(clknode_recalc_freq, ti_dpll_clk_recalc), + CLKNODEMETHOD(clknode_set_freq, ti_dpll_clk_set_freq), + CLKNODEMETHOD_END +}; + +DEFINE_CLASS_1(ti_dpll_clknode, ti_dpll_clknode_class, ti_dpll_clknode_methods, + sizeof(struct ti_dpll_clknode_sc), clknode_class); + +int +ti_clknode_dpll_register(struct clkdom *clkdom, struct ti_clk_dpll_def *clkdef) +{ + struct clknode *clk; + struct ti_dpll_clknode_sc *sc; + + clk = clknode_create(clkdom, &ti_dpll_clknode_class, &clkdef->clkdef); + if (clk == NULL) + return (1); + + sc = clknode_get_softc(clk); + + sc->ti_clkmode_offset = clkdef->ti_clkmode_offset; + sc->ti_clkmode_flags = clkdef->ti_clkmode_flags; + sc->ti_idlest_offset = clkdef->ti_idlest_offset; + sc->ti_clksel_offset = clkdef->ti_clksel_offset; + + sc->n.shift = clkdef->ti_clksel_mult.shift; + sc->n.mask = clkdef->ti_clksel_mult.mask; + sc->n.width = clkdef->ti_clksel_mult.width; + sc->n.value = clkdef->ti_clksel_mult.value; + sc->n.min_value = clkdef->ti_clksel_mult.min_value; + sc->n.max_value = clkdef->ti_clksel_mult.max_value; + sc->n.flags = clkdef->ti_clksel_mult.flags; + + sc->p.shift = clkdef->ti_clksel_div.shift; + sc->p.mask = clkdef->ti_clksel_div.mask; + sc->p.width = clkdef->ti_clksel_div.width; + sc->p.value = clkdef->ti_clksel_div.value; + sc->p.min_value = clkdef->ti_clksel_div.min_value; + sc->p.max_value = clkdef->ti_clksel_div.max_value; + sc->p.flags = clkdef->ti_clksel_div.flags; + + sc->ti_autoidle_offset = clkdef->ti_autoidle_offset; + + clknode_register(clkdom, clk); + + return (0); +} diff --git a/sys/arm/ti/clk/ti_clk_dpll.h b/sys/arm/ti/clk/ti_clk_dpll.h new file mode 100644 index 000000000000..54bc0b988d6e --- /dev/null +++ b/sys/arm/ti/clk/ti_clk_dpll.h @@ -0,0 +1,97 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org> + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _TI_DPLL_CLOCK_H_ +#define _TI_DPLL_CLOCK_H_ + +#include <dev/extres/clk/clk.h> + +/* Registers are described in AM335x TRM chapter 8.1.12.2.* */ + +/* Register offsets */ +#define CM_CLKSEL_DPLL_PERIPH 0x49C + +/* CM_IDLEST_DPLL_xxx */ +#define ST_MN_BYPASS_MASK 0x0100 +#define ST_MN_BYPASS_SHIFT 8 +#define ST_DPLL_CLK_MASK 0x0001 + +/* CM_CLKMODE_DPLL_DPLL_EN feature flag */ +#define LOW_POWER_STOP_MODE_FLAG 0x01 +#define MN_BYPASS_MODE_FLAG 0x02 +#define IDLE_BYPASS_LOW_POWER_MODE_FLAG 0x04 +#define IDLE_BYPASS_FAST_RELOCK_MODE_FLAG 0x08 +#define LOCK_MODE_FLAG 0x10 + +/* CM_CLKMODE_DPLL_xxx */ +#define DPLL_EN_LOW_POWER_STOP_MODE 0x01 +#define DPLL_EN_MN_BYPASS_MODE 0x04 +#define DPLL_EN_IDLE_BYPASS_LOW_POWER_MODE 0x05 +#define DPLL_EN_IDLE_BYPASS_FAST_RELOCK_MODE 0x06 +#define DPLL_EN_LOCK_MODE 0x07 + + +#define TI_CLK_FACTOR_ZERO_BASED 0x0002 +#define TI_CLK_FACTOR_FIXED 0x0008 +#define TI_CLK_FACTOR_MIN_VALUE 0x0020 +#define TI_CLK_FACTOR_MAX_VALUE 0x0040 + +/* Based on aw_clk_factor sys/arm/allwinner/clkng/aw_clk.h */ +struct ti_clk_factor { + uint32_t shift; /* Shift bits for the factor */ + uint32_t mask; /* Mask to get the factor */ + uint32_t width; /* Number of bits for the factor */ + uint32_t value; /* Fixed value */ + + uint32_t min_value; + uint32_t max_value; + + uint32_t flags; /* Flags */ +}; + +struct ti_clk_dpll_def { + struct clknode_init_def clkdef; + + uint32_t ti_clkmode_offset; /* control */ + uint8_t ti_clkmode_flags; + + uint32_t ti_idlest_offset; + + uint32_t ti_clksel_offset; /* mult-div1 */ + struct ti_clk_factor ti_clksel_mult; + struct ti_clk_factor ti_clksel_div; + + uint32_t ti_autoidle_offset; +}; + +int ti_clknode_dpll_register(struct clkdom *clkdom, struct ti_clk_dpll_def *clkdef); + +#endif /* _TI_DPLL_CLOCK_H_ */ diff --git a/sys/arm/ti/clk/ti_clkctrl.c b/sys/arm/ti/clk/ti_clkctrl.c new file mode 100644 index 000000000000..5ba0dbe19b79 --- /dev/null +++ b/sys/arm/ti/clk/ti_clkctrl.c @@ -0,0 +1,353 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright 2016 Michal Meloun <mmel@FreeBSD.org> + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/fbio.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/resource.h> +#include <machine/bus.h> +#include <vm/vm.h> +#include <vm/vm_extern.h> +#include <vm/vm_kern.h> +#include <vm/pmap.h> + +#include <dev/fdt/simplebus.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <arm/ti/clk/ti_clk_clkctrl.h> +#include <arm/ti/ti_omap4_cm.h> +#include <arm/ti/ti_cpuid.h> + +#if 0 +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +#define L4LS_CLKCTRL_38 2 +#define L4_WKUP_CLKCTRL_0 1 +#define NO_SPECIAL_REG 0 + +/* Documentation/devicetree/bindings/clock/ti-clkctrl.txt */ + +#define TI_CLKCTRL_L4_WKUP 5 +#define TI_CLKCTRL_L4_SECURE 4 +#define TI_CLKCTRL_L4_PER 3 +#define TI_CLKCTRL_L4_CFG 2 +#define TI_CLKCTRL 1 +#define TI_CLKCTRL_END 0 + +static struct ofw_compat_data compat_data[] = { + { "ti,clkctrl-l4-wkup", TI_CLKCTRL_L4_WKUP }, + { "ti,clkctrl-l4-secure", TI_CLKCTRL_L4_SECURE }, + { "ti,clkctrl-l4-per", TI_CLKCTRL_L4_PER }, + { "ti,clkctrl-l4-cfg", TI_CLKCTRL_L4_CFG }, + { "ti,clkctrl", TI_CLKCTRL }, + { NULL, TI_CLKCTRL_END } +}; + +struct ti_clkctrl_softc { + device_t dev; + + struct clkdom *clkdom; +}; + +static int ti_clkctrl_probe(device_t dev); +static int ti_clkctrl_attach(device_t dev); +static int ti_clkctrl_detach(device_t dev); +int clkctrl_ofw_map(struct clkdom *clkdom, uint32_t ncells, + phandle_t *cells, struct clknode **clk); +static int +create_clkctrl(struct ti_clkctrl_softc *sc, cell_t *reg, uint32_t index, uint32_t reg_offset, + uint64_t parent_offset, const char *org_name, bool special_gdbclk_reg); + +static int +ti_clkctrl_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "TI clkctrl"); + + return (BUS_PROBE_DEFAULT); +} + +static int +ti_clkctrl_attach(device_t dev) +{ + struct ti_clkctrl_softc *sc; + phandle_t node; + cell_t *reg; + ssize_t numbytes_reg; + int num_reg, err, ti_clock_cells; + uint32_t index, reg_offset, reg_address; + const char *org_name; + uint64_t parent_offset; + uint8_t special_reg = NO_SPECIAL_REG; + + sc = device_get_softc(dev); + sc->dev = dev; + node = ofw_bus_get_node(dev); + + /* Sanity check */ + err = OF_searchencprop(node, "#clock-cells", + &ti_clock_cells, sizeof(ti_clock_cells)); + if (err == -1) { + device_printf(sc->dev, "Failed to get #clock-cells\n"); + return (ENXIO); + } + + if (ti_clock_cells != 2) { + device_printf(sc->dev, "clock cells(%d) != 2\n", + ti_clock_cells); + return (ENXIO); + } + + /* Grab the content of reg properties */ + numbytes_reg = OF_getproplen(node, "reg"); + if (numbytes_reg == 0) { + device_printf(sc->dev, "reg property empty - check your devicetree\n"); + return (ENXIO); + } + num_reg = numbytes_reg / sizeof(cell_t); + + reg = malloc(numbytes_reg, M_DEVBUF, M_WAITOK); + OF_getencprop(node, "reg", reg, numbytes_reg); + + /* Create clock domain */ + sc->clkdom = clkdom_create(sc->dev); + if (sc->clkdom == NULL) { + free(reg, M_DEVBUF); + DPRINTF(sc->dev, "Failed to create clkdom\n"); + return (ENXIO); + } + clkdom_set_ofw_mapper(sc->clkdom, clkctrl_ofw_map); + + /* Create clock nodes */ + /* name */ + clk_parse_ofw_clk_name(sc->dev, node, &org_name); + + /* Get parent range */ + parent_offset = ti_omap4_cm_get_simplebus_base_host(device_get_parent(dev)); + + /* Check if this is a clkctrl with special registers like gpio */ + switch (ti_chip()) { +#ifdef SOC_OMAP4 + case CHIP_OMAP_4: + /* FIXME: Todo */ + break; + +#endif /* SOC_OMAP4 */ +#ifdef SOC_TI_AM335X + /* Checkout TRM 8.1.12.1.29 - 8.1.12.31 and 8.1.12.2.3 + * and the DTS. + */ + case CHIP_AM335X: + if (strcmp(org_name, "l4ls-clkctrl@38") == 0) + special_reg = L4LS_CLKCTRL_38; + else if (strcmp(org_name, "l4-wkup-clkctrl@0") == 0) + special_reg = L4_WKUP_CLKCTRL_0; + break; +#endif /* SOC_TI_AM335X */ + default: + break; + } + + /* reg property has a pair of (base address, length) */ + for (index = 0; index < num_reg; index += 2) { + for (reg_offset = 0; reg_offset < reg[index+1]; reg_offset += sizeof(cell_t)) { + + err = create_clkctrl(sc, reg, index, reg_offset, parent_offset, + org_name, false); + if (err) + goto cleanup; + + /* Create special clkctrl for GDBCLK in GPIO registers */ + switch (special_reg) { + case NO_SPECIAL_REG: + break; + case L4LS_CLKCTRL_38: + reg_address = reg[index] + reg_offset-reg[0]; + if (reg_address == 0x74 || + reg_address == 0x78 || + reg_address == 0x7C) + { + err = create_clkctrl(sc, reg, index, reg_offset, + parent_offset, org_name, true); + if (err) + goto cleanup; + } + break; + case L4_WKUP_CLKCTRL_0: + reg_address = reg[index] + reg_offset - reg[0]; + if (reg_address == 0x8) + { + err = create_clkctrl(sc, reg, index, reg_offset, + parent_offset, org_name, true); + if (err) + goto cleanup; + } + break; + } /* switch (special_reg) */ + } /* inner for */ + } /* for */ + + err = clkdom_finit(sc->clkdom); + if (err) { + DPRINTF(sc->dev, "Clk domain finit fails %x.\n", err); + err = ENXIO; + goto cleanup; + } + +cleanup: + OF_prop_free(__DECONST(char *, org_name)); + + free(reg, M_DEVBUF); + + if (err) + return (err); + + return (bus_generic_attach(dev)); +} + +static int +ti_clkctrl_detach(device_t dev) +{ + return (EBUSY); +} + +/* modified version of default mapper from clk.c */ +int +clkctrl_ofw_map(struct clkdom *clkdom, uint32_t ncells, + phandle_t *cells, struct clknode **clk) { + if (ncells == 0) + *clk = clknode_find_by_id(clkdom, 1); + else if (ncells == 1) + *clk = clknode_find_by_id(clkdom, cells[0]); + else if (ncells == 2) { + /* To avoid collision with other IDs just add one. + * All other registers has an offset of 4 from each other. + */ + if (cells[1]) + *clk = clknode_find_by_id(clkdom, cells[0]+1); + else + *clk = clknode_find_by_id(clkdom, cells[0]); + } + else + return (ERANGE); + + if (*clk == NULL) + return (ENXIO); + + return (0); +} + +static int +create_clkctrl(struct ti_clkctrl_softc *sc, cell_t *reg, uint32_t index, uint32_t reg_offset, + uint64_t parent_offset, const char *org_name, bool special_gdbclk_reg) { + struct ti_clk_clkctrl_def def; + char *name; + size_t name_len; + int err; + + name_len = strlen(org_name) + 1 + 5; /* 5 = _xxxx */ + name = malloc(name_len, M_OFWPROP, M_WAITOK); + + /* + * Check out XX_CLKCTRL-INDEX(offset)-macro dance in + * sys/gnu/dts/dts/include/dt-bindings/clock/am3.h + * sys/gnu/dts/dts/include/dt-bindings/clock/am4.h + * sys/gnu/dts/dts/include/dt-bindings/clock/dra7.h + * reg[0] are in practice the same as the offset described in the dts. + */ + /* special_gdbclk_reg are 0 or 1 */ + def.clkdef.id = reg[index] + reg_offset - reg[0] + special_gdbclk_reg; + def.register_offset = parent_offset + reg[index] + reg_offset; + + /* Indicate this clkctrl is special and dont use IDLEST/MODULEMODE */ + def.gdbclk = special_gdbclk_reg; + + /* Make up an uniq name in the namespace for each clkctrl */ + snprintf(name, name_len, "%s_%x", + org_name, def.clkdef.id); + def.clkdef.name = (const char *) name; + + DPRINTF(sc->dev, "ti_clkctrl_attach: reg[%d]: %s %x\n", + index, def.clkdef.name, def.clkdef.id); + + /* No parent name */ + def.clkdef.parent_cnt = 0; + + /* set flags */ + def.clkdef.flags = 0x0; + + /* Register the clkctrl */ + err = ti_clknode_clkctrl_register(sc->clkdom, &def); + if (err) { + DPRINTF(sc->dev, + "ti_clknode_clkctrl_register[%d:%d] failed %x\n", + index, reg_offset, err); + err = ENXIO; + } + OF_prop_free(name); + return (err); +} + +static device_method_t ti_clkctrl_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ti_clkctrl_probe), + DEVMETHOD(device_attach, ti_clkctrl_attach), + DEVMETHOD(device_detach, ti_clkctrl_detach), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(ti_clkctrl, ti_clkctrl_driver, ti_clkctrl_methods, + sizeof(struct ti_clkctrl_softc)); + +static devclass_t ti_clkctrl_devclass; + +EARLY_DRIVER_MODULE(ti_clkctrl, simplebus, ti_clkctrl_driver, +ti_clkctrl_devclass, 0, 0, BUS_PASS_BUS+BUS_PASS_ORDER_MIDDLE); + +MODULE_VERSION(ti_clkctrl, 1); diff --git a/sys/arm/ti/clk/ti_divider_clock.c b/sys/arm/ti/clk/ti_divider_clock.c new file mode 100644 index 000000000000..753b5f535d29 --- /dev/null +++ b/sys/arm/ti/clk/ti_divider_clock.c @@ -0,0 +1,264 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/systm.h> +#include <sys/libkern.h> + +#include <machine/bus.h> +#include <dev/fdt/simplebus.h> + +#include <dev/extres/clk/clk_div.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include "clock_common.h" + +#if 0 +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +/* + * Devicetree description + * Documentation/devicetree/bindings/clock/ti/divider.txt + */ + +struct ti_divider_softc { + device_t sc_dev; + bool attach_done; + struct clk_div_def div_def; + + struct clock_cell_info clock_cell; + struct clkdom *clkdom; +}; + +static int ti_divider_probe(device_t dev); +static int ti_divider_attach(device_t dev); +static int ti_divider_detach(device_t dev); + +#define TI_DIVIDER_CLOCK 2 +#define TI_COMPOSITE_DIVIDER_CLOCK 1 +#define TI_DIVIDER_END 0 + +static struct ofw_compat_data compat_data[] = { + { "ti,divider-clock", TI_DIVIDER_CLOCK }, + { "ti,composite-divider-clock", TI_COMPOSITE_DIVIDER_CLOCK }, + { NULL, TI_DIVIDER_END } +}; + +static int +register_clk(struct ti_divider_softc *sc) { + int err; + + sc->clkdom = clkdom_create(sc->sc_dev); + if (sc->clkdom == NULL) { + DPRINTF(sc->sc_dev, "Failed to create clkdom\n"); + return (ENXIO); + } + + err = clknode_div_register(sc->clkdom, &sc->div_def); + if (err) { + DPRINTF(sc->sc_dev, "clknode_div_register failed %x\n", err); + return (ENXIO); + } + + err = clkdom_finit(sc->clkdom); + if (err) { + DPRINTF(sc->sc_dev, "Clk domain finit fails %x.\n", err); + return (ENXIO); + } + + return (0); +} + +static int +ti_divider_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "TI Divider Clock"); + + return (BUS_PROBE_DEFAULT); +} + +static int +ti_divider_attach(device_t dev) +{ + struct ti_divider_softc *sc; + phandle_t node; + int err; + cell_t value; + uint32_t ti_max_div; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + node = ofw_bus_get_node(dev); + + /* Grab the content of reg properties */ + OF_getencprop(node, "reg", &value, sizeof(value)); + sc->div_def.offset = value; + + if (OF_hasprop(node, "ti,bit-shift")) { + OF_getencprop(node, "ti,bit-shift", &value, sizeof(value)); + sc->div_def.i_shift = value; + } + + if (OF_hasprop(node, "ti,index-starts-at-one")) { + sc->div_def.div_flags = CLK_DIV_ZERO_BASED; + } + + if (OF_hasprop(node, "ti,index-power-of-two")) { + /* FIXME: later */ + device_printf(sc->sc_dev, "ti,index-power-of-two - Not implemented\n"); + /* remember to update i_width a few lines below */ + } + if (OF_hasprop(node, "ti,max-div")) { + OF_getencprop(node, "ti,max-div", &value, sizeof(value)); + ti_max_div = value; + } + + if (OF_hasprop(node, "clock-output-names")) + device_printf(sc->sc_dev, "clock-output-names\n"); + if (OF_hasprop(node, "ti,dividers")) + device_printf(sc->sc_dev, "ti,dividers\n"); + if (OF_hasprop(node, "ti,min-div")) + device_printf(sc->sc_dev, "ti,min-div - Not implemented\n"); + + if (OF_hasprop(node, "ti,autoidle-shift")) + device_printf(sc->sc_dev, "ti,autoidle-shift - Not implemented\n"); + if (OF_hasprop(node, "ti,set-rate-parent")) + device_printf(sc->sc_dev, "ti,set-rate-parent - Not implemented\n"); + if (OF_hasprop(node, "ti,latch-bit")) + device_printf(sc->sc_dev, "ti,latch-bit - Not implemented\n"); + + /* Figure out the width from ti_max_div */ + if (sc->div_def.div_flags) + sc->div_def.i_width = fls(ti_max_div-1); + else + sc->div_def.i_width = fls(ti_max_div); + + DPRINTF(sc->sc_dev, "div_def.i_width %x\n", sc->div_def.i_width); + + read_clock_cells(sc->sc_dev, &sc->clock_cell); + + create_clkdef(sc->sc_dev, &sc->clock_cell, &sc->div_def.clkdef); + + err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->div_def.clkdef); + + if (err) { + /* free_clkdef will be called in ti_divider_new_pass */ + DPRINTF(sc->sc_dev, "find_parent_clock_names failed\n"); + return (bus_generic_attach(sc->sc_dev)); + } + + err = register_clk(sc); + + if (err) { + /* free_clkdef will be called in ti_divider_new_pass */ + DPRINTF(sc->sc_dev, "register_clk failed\n"); + return (bus_generic_attach(sc->sc_dev)); + } + + sc->attach_done = true; + + free_clkdef(&sc->div_def.clkdef); + + return (bus_generic_attach(sc->sc_dev)); +} + +static int +ti_divider_detach(device_t dev) +{ + return (EBUSY); +} + +static void +ti_divider_new_pass(device_t dev) +{ + struct ti_divider_softc *sc; + int err; + + sc = device_get_softc(dev); + + if (sc->attach_done) { + return; + } + + err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->div_def.clkdef); + if (err) { + /* free_clkdef will be called in a later call to ti_divider_new_pass */ + DPRINTF(sc->sc_dev, "new_pass find_parent_clock_names failed\n"); + return; + } + + err = register_clk(sc); + if (err) { + /* free_clkdef will be called in a later call to ti_divider_new_pass */ + DPRINTF(sc->sc_dev, "new_pass register_clk failed\n"); + return; + } + + sc->attach_done = true; + + free_clkdef(&sc->div_def.clkdef); +} + +static device_method_t ti_divider_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ti_divider_probe), + DEVMETHOD(device_attach, ti_divider_attach), + DEVMETHOD(device_detach, ti_divider_detach), + + /* Bus interface */ + DEVMETHOD(bus_new_pass, ti_divider_new_pass), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(ti_divider, ti_divider_driver, ti_divider_methods, + sizeof(struct ti_divider_softc)); + +static devclass_t ti_divider_devclass; + +EARLY_DRIVER_MODULE(ti_divider, simplebus, ti_divider_driver, + ti_divider_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +MODULE_VERSION(ti_divider, 1); diff --git a/sys/arm/ti/clk/ti_dpll_clock.c b/sys/arm/ti/clk/ti_dpll_clock.c new file mode 100644 index 000000000000..91127c570c4d --- /dev/null +++ b/sys/arm/ti/clk/ti_dpll_clock.c @@ -0,0 +1,375 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/systm.h> +#include <sys/libkern.h> + +#include <machine/bus.h> +#include <dev/fdt/simplebus.h> + +#include <dev/extres/clk/clk_div.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <arm/ti/clk/ti_clk_dpll.h> +#include "clock_common.h" + +#if 0 +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +/* + * Devicetree description + * Documentation/devicetree/bindings/clock/ti/dpll.txt + */ + +struct ti_dpll_softc { + device_t dev; + uint8_t dpll_type; + + bool attach_done; + struct ti_clk_dpll_def dpll_def; + + struct clock_cell_info clock_cell; + struct clkdom *clkdom; +}; + +static int ti_dpll_probe(device_t dev); +static int ti_dpll_attach(device_t dev); +static int ti_dpll_detach(device_t dev); + +#define TI_OMAP3_DPLL_CLOCK 17 +#define TI_OMAP3_DPLL_CORE_CLOCK 16 +#define TI_OMAP3_DPLL_PER_CLOCK 15 +#define TI_OMAP3_DPLL_PER_J_TYPE_CLOCK 14 +#define TI_OMAP4_DPLL_CLOCK 13 +#define TI_OMAP4_DPLL_X2_CLOCK 12 +#define TI_OMAP4_DPLL_CORE_CLOCK 11 +#define TI_OMAP4_DPLL_M4XEN_CLOCK 10 +#define TI_OMAP4_DPLL_J_TYPE_CLOCK 9 +#define TI_OMAP5_MPU_DPLL_CLOCK 8 +#define TI_AM3_DPLL_NO_GATE_CLOCK 7 +#define TI_AM3_DPLL_J_TYPE_CLOCK 6 +#define TI_AM3_DPLL_NO_GATE_J_TYPE_CLOCK 5 +#define TI_AM3_DPLL_CLOCK 4 +#define TI_AM3_DPLL_CORE_CLOCK 3 +#define TI_AM3_DPLL_X2_CLOCK 2 +#define TI_OMAP2_DPLL_CORE_CLOCK 1 +#define TI_DPLL_END 0 + +static struct ofw_compat_data compat_data[] = { + { "ti,omap3-dpll-clock", TI_OMAP3_DPLL_CLOCK }, + { "ti,omap3-dpll-core-clock", TI_OMAP3_DPLL_CORE_CLOCK }, + { "ti,omap3-dpll-per-clock", TI_OMAP3_DPLL_PER_CLOCK }, + { "ti,omap3-dpll-per-j-type-clock",TI_OMAP3_DPLL_PER_J_TYPE_CLOCK }, + { "ti,omap4-dpll-clock", TI_OMAP4_DPLL_CLOCK }, + { "ti,omap4-dpll-x2-clock", TI_OMAP4_DPLL_X2_CLOCK }, + { "ti,omap4-dpll-core-clock", TI_OMAP4_DPLL_CORE_CLOCK }, + { "ti,omap4-dpll-m4xen-clock", TI_OMAP4_DPLL_M4XEN_CLOCK }, + { "ti,omap4-dpll-j-type-clock", TI_OMAP4_DPLL_J_TYPE_CLOCK }, + { "ti,omap5-mpu-dpll-clock", TI_OMAP5_MPU_DPLL_CLOCK }, + { "ti,am3-dpll-no-gate-clock", TI_AM3_DPLL_NO_GATE_CLOCK }, + { "ti,am3-dpll-j-type-clock", TI_AM3_DPLL_J_TYPE_CLOCK }, + { "ti,am3-dpll-no-gate-j-type-clock",TI_AM3_DPLL_NO_GATE_J_TYPE_CLOCK }, + { "ti,am3-dpll-clock", TI_AM3_DPLL_CLOCK }, + { "ti,am3-dpll-core-clock", TI_AM3_DPLL_CORE_CLOCK }, + { "ti,am3-dpll-x2-clock", TI_AM3_DPLL_X2_CLOCK }, + { "ti,omap2-dpll-core-clock", TI_OMAP2_DPLL_CORE_CLOCK }, + { NULL, TI_DPLL_END } +}; + +static int +register_clk(struct ti_dpll_softc *sc) { + int err; + + sc->clkdom = clkdom_create(sc->dev); + if (sc->clkdom == NULL) { + DPRINTF(sc->dev, "Failed to create clkdom\n"); + return (ENXIO); + } + + err = ti_clknode_dpll_register(sc->clkdom, &sc->dpll_def); + if (err) { + DPRINTF(sc->dev, + "ti_clknode_dpll_register failed %x\n", err); + return (ENXIO); + } + + err = clkdom_finit(sc->clkdom); + if (err) { + DPRINTF(sc->dev, "Clk domain finit fails %x.\n", err); + return (ENXIO); + } + + return (0); +} + +static int +ti_dpll_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "TI DPLL Clock"); + + return (BUS_PROBE_DEFAULT); +} + +static int +parse_dpll_reg(struct ti_dpll_softc *sc) { + ssize_t numbytes_regs; + uint32_t num_regs; + phandle_t node; + cell_t reg_cells[4]; + + if (sc->dpll_type == TI_AM3_DPLL_X2_CLOCK || + sc->dpll_type == TI_OMAP4_DPLL_X2_CLOCK) { + sc->dpll_def.ti_clksel_mult.value = 2; + sc->dpll_def.ti_clksel_mult.flags = TI_CLK_FACTOR_FIXED; + + sc->dpll_def.ti_clksel_div.value = 1; + sc->dpll_def.ti_clksel_div.flags = TI_CLK_FACTOR_FIXED; + return (0); + } + + node = ofw_bus_get_node(sc->dev); + + numbytes_regs = OF_getproplen(node, "reg"); + num_regs = numbytes_regs / sizeof(cell_t); + + /* Sanity check */ + if (num_regs > 4) + return (ENXIO); + + OF_getencprop(node, "reg", reg_cells, numbytes_regs); + + switch (sc->dpll_type) { + case TI_AM3_DPLL_NO_GATE_CLOCK: + case TI_AM3_DPLL_J_TYPE_CLOCK: + case TI_AM3_DPLL_NO_GATE_J_TYPE_CLOCK: + case TI_AM3_DPLL_CLOCK: + case TI_AM3_DPLL_CORE_CLOCK: + case TI_AM3_DPLL_X2_CLOCK: + if (num_regs != 3) + return (ENXIO); + sc->dpll_def.ti_clkmode_offset = reg_cells[0]; + sc->dpll_def.ti_idlest_offset = reg_cells[1]; + sc->dpll_def.ti_clksel_offset = reg_cells[2]; + break; + + case TI_OMAP2_DPLL_CORE_CLOCK: + if (num_regs != 2) + return (ENXIO); + sc->dpll_def.ti_clkmode_offset = reg_cells[0]; + sc->dpll_def.ti_clksel_offset = reg_cells[1]; + break; + + default: + sc->dpll_def.ti_clkmode_offset = reg_cells[0]; + sc->dpll_def.ti_idlest_offset = reg_cells[1]; + sc->dpll_def.ti_clksel_offset = reg_cells[2]; + sc->dpll_def.ti_autoidle_offset = reg_cells[3]; + break; + } + + /* AM335x */ + if (sc->dpll_def.ti_clksel_offset == CM_CLKSEL_DPLL_PERIPH) { + sc->dpll_def.ti_clksel_mult.shift = 8; + sc->dpll_def.ti_clksel_mult.mask = 0x000FFF00; + sc->dpll_def.ti_clksel_mult.width = 12; + sc->dpll_def.ti_clksel_mult.value = 0; + sc->dpll_def.ti_clksel_mult.min_value = 2; + sc->dpll_def.ti_clksel_mult.max_value = 4095; + sc->dpll_def.ti_clksel_mult.flags = TI_CLK_FACTOR_ZERO_BASED | + TI_CLK_FACTOR_MIN_VALUE | + TI_CLK_FACTOR_MAX_VALUE; + + sc->dpll_def.ti_clksel_div.shift = 0; + sc->dpll_def.ti_clksel_div.mask = 0x000000FF; + sc->dpll_def.ti_clksel_div.width = 8; + sc->dpll_def.ti_clksel_div.value = 0; + sc->dpll_def.ti_clksel_div.min_value = 0; + sc->dpll_def.ti_clksel_div.max_value = 255; + sc->dpll_def.ti_clksel_div.flags = TI_CLK_FACTOR_MIN_VALUE | + TI_CLK_FACTOR_MAX_VALUE; + } else { + sc->dpll_def.ti_clksel_mult.shift = 8; + sc->dpll_def.ti_clksel_mult.mask = 0x0007FF00; + sc->dpll_def.ti_clksel_mult.width = 11; + sc->dpll_def.ti_clksel_mult.value = 0; + sc->dpll_def.ti_clksel_mult.min_value = 2; + sc->dpll_def.ti_clksel_mult.max_value = 2047; + sc->dpll_def.ti_clksel_mult.flags = TI_CLK_FACTOR_ZERO_BASED | + TI_CLK_FACTOR_MIN_VALUE | + TI_CLK_FACTOR_MAX_VALUE; + + sc->dpll_def.ti_clksel_div.shift = 0; + sc->dpll_def.ti_clksel_div.mask = 0x0000007F; + sc->dpll_def.ti_clksel_div.width = 7; + sc->dpll_def.ti_clksel_div.value = 0; + sc->dpll_def.ti_clksel_div.min_value = 0; + sc->dpll_def.ti_clksel_div.max_value = 127; + sc->dpll_def.ti_clksel_div.flags = TI_CLK_FACTOR_MIN_VALUE | + TI_CLK_FACTOR_MAX_VALUE; + } + DPRINTF(sc->dev, "clkmode %x idlest %x clksel %x autoidle %x\n", + sc->dpll_def.ti_clkmode_offset, sc->dpll_def.ti_idlest_offset, + sc->dpll_def.ti_clksel_offset, + sc->dpll_def.ti_autoidle_offset); + + return (0); +} +static int +ti_dpll_attach(device_t dev) +{ + struct ti_dpll_softc *sc; + phandle_t node; + int err; + + sc = device_get_softc(dev); + sc->dev = dev; + + sc->dpll_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; + node = ofw_bus_get_node(dev); + + /* Grab the content of reg properties */ + parse_dpll_reg(sc); + + /* default flags (OMAP4&AM335x) not present in the dts at moment */ + sc->dpll_def.ti_clkmode_flags = MN_BYPASS_MODE_FLAG | LOCK_MODE_FLAG; + + if (OF_hasprop(node, "ti,low-power-stop")) { + sc->dpll_def.ti_clkmode_flags |= LOW_POWER_STOP_MODE_FLAG; + } + if (OF_hasprop(node, "ti,low-power-bypass")) { + sc->dpll_def.ti_clkmode_flags |= IDLE_BYPASS_LOW_POWER_MODE_FLAG; + } + if (OF_hasprop(node, "ti,lock")) { + sc->dpll_def.ti_clkmode_flags |= LOCK_MODE_FLAG; + } + + read_clock_cells(sc->dev, &sc->clock_cell); + + create_clkdef(sc->dev, &sc->clock_cell, &sc->dpll_def.clkdef); + + err = find_parent_clock_names(sc->dev, &sc->clock_cell, + &sc->dpll_def.clkdef); + + if (err) { + /* free_clkdef will be called in ti_dpll_new_pass */ + DPRINTF(sc->dev, "find_parent_clock_names failed\n"); + return (bus_generic_attach(sc->dev)); + } + + err = register_clk(sc); + + if (err) { + /* free_clkdef will be called in ti_dpll_new_pass */ + DPRINTF(sc->dev, "register_clk failed\n"); + return (bus_generic_attach(sc->dev)); + } + + sc->attach_done = true; + + free_clkdef(&sc->dpll_def.clkdef); + + return (bus_generic_attach(sc->dev)); +} + +static int +ti_dpll_detach(device_t dev) +{ + return (EBUSY); +} + +static void +ti_dpll_new_pass(device_t dev) +{ + struct ti_dpll_softc *sc; + int err; + + sc = device_get_softc(dev); + + if (sc->attach_done) { + return; + } + + err = find_parent_clock_names(sc->dev, &sc->clock_cell, + &sc->dpll_def.clkdef); + if (err) { + /* free_clkdef will be called in a later call to ti_dpll_new_pass */ + DPRINTF(sc->dev, + "new_pass find_parent_clock_names failed\n"); + return; + } + + err = register_clk(sc); + if (err) { + /* free_clkdef will be called in a later call to ti_dpll_new_pass */ + DPRINTF(sc->dev, "new_pass register_clk failed\n"); + return; + } + + sc->attach_done = true; + free_clkdef(&sc->dpll_def.clkdef); +} + +static device_method_t ti_dpll_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ti_dpll_probe), + DEVMETHOD(device_attach, ti_dpll_attach), + DEVMETHOD(device_detach, ti_dpll_detach), + + /* Bus interface */ + DEVMETHOD(bus_new_pass, ti_dpll_new_pass), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(ti_dpll, ti_dpll_driver, ti_dpll_methods, + sizeof(struct ti_dpll_softc)); + +static devclass_t ti_dpll_devclass; + +EARLY_DRIVER_MODULE(ti_dpll, simplebus, ti_dpll_driver, + ti_dpll_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +MODULE_VERSION(ti_dpll, 1); diff --git a/sys/arm/ti/clk/ti_gate_clock.c b/sys/arm/ti/clk/ti_gate_clock.c new file mode 100644 index 000000000000..b4fb65995e74 --- /dev/null +++ b/sys/arm/ti/clk/ti_gate_clock.c @@ -0,0 +1,266 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/systm.h> +#include <sys/libkern.h> + +#include <machine/bus.h> +#include <dev/fdt/simplebus.h> + +#include <dev/extres/clk/clk_gate.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include "clock_common.h" + +#define DEBUG_GATE 0 + +#if DEBUG_GATE +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +/* + * Devicetree description + * Documentation/devicetree/bindings/clock/ti/gate.txt + */ + +struct ti_gate_softc { + device_t sc_dev; + bool attach_done; + uint8_t sc_type; + + struct clk_gate_def gate_def; + struct clock_cell_info clock_cell; + struct clkdom *clkdom; +}; + +static int ti_gate_probe(device_t dev); +static int ti_gate_attach(device_t dev); +static int ti_gate_detach(device_t dev); + +#define TI_GATE_CLOCK 7 +#define TI_WAIT_GATE_CLOCK 6 +#define TI_DSS_GATE_CLOCK 5 +#define TI_AM35XX_GATE_CLOCK 4 +#define TI_CLKDM_GATE_CLOCK 3 +#define TI_HSDIV_GATE_CLOCK 2 +#define TI_COMPOSITE_NO_WAIT_GATE_CLOCK 1 +#define TI_GATE_END 0 + +static struct ofw_compat_data compat_data[] = { + { "ti,gate-clock", TI_GATE_CLOCK }, + { "ti,wait-gate-clock", TI_WAIT_GATE_CLOCK }, + { "ti,dss-gate-clock", TI_DSS_GATE_CLOCK }, + { "ti,am35xx-gate-clock", TI_AM35XX_GATE_CLOCK }, + { "ti,clkdm-gate-clock", TI_CLKDM_GATE_CLOCK }, + { "ti,hsdiv-gate-cloc", TI_HSDIV_GATE_CLOCK }, + { "ti,composite-no-wait-gate-clock", TI_COMPOSITE_NO_WAIT_GATE_CLOCK }, + { NULL, TI_GATE_END } +}; + +static int +ti_gate_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "TI Gate Clock"); + + return (BUS_PROBE_DEFAULT); +} + +static int +register_clk(struct ti_gate_softc *sc) { + int err; + sc->clkdom = clkdom_create(sc->sc_dev); + if (sc->clkdom == NULL) { + DPRINTF(sc->sc_dev, "Failed to create clkdom\n"); + return ENXIO; + } + + err = clknode_gate_register(sc->clkdom, &sc->gate_def); + if (err) { + DPRINTF(sc->sc_dev, "clknode_gate_register failed %x\n", err); + return ENXIO; + } + + err = clkdom_finit(sc->clkdom); + if (err) { + DPRINTF(sc->sc_dev, "Clk domain finit fails %x.\n", err); + return ENXIO; + } + + return (0); +} + +static int +ti_gate_attach(device_t dev) +{ + struct ti_gate_softc *sc; + phandle_t node; + int err; + cell_t value; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + node = ofw_bus_get_node(dev); + + /* Get the compatible type */ + sc->sc_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; + + /* Get the content of reg properties */ + if (sc->sc_type != TI_CLKDM_GATE_CLOCK) { + OF_getencprop(node, "reg", &value, sizeof(value)); + sc->gate_def.offset = value; + } +#if DEBUG_GATE + else { + DPRINTF(sc->sc_dev, "no reg (TI_CLKDM_GATE_CLOCK)\n"); + } +#endif + + if (OF_hasprop(node, "ti,bit-shift")) { + OF_getencprop(node, "ti,bit-shift", &value, sizeof(value)); + sc->gate_def.shift = value; + DPRINTF(sc->sc_dev, "ti,bit-shift => shift %x\n", sc->gate_def.shift); + } + if (OF_hasprop(node, "ti,set-bit-to-disable")) { + sc->gate_def.on_value = 0; + sc->gate_def.off_value = 1; + DPRINTF(sc->sc_dev, + "on_value = 0, off_value = 1 (ti,set-bit-to-disable)\n"); + } else { + sc->gate_def.on_value = 1; + sc->gate_def.off_value = 0; + DPRINTF(sc->sc_dev, "on_value = 1, off_value = 0\n"); + } + + sc->gate_def.gate_flags = 0x0; + + read_clock_cells(sc->sc_dev, &sc->clock_cell); + + create_clkdef(sc->sc_dev, &sc->clock_cell, &sc->gate_def.clkdef); + + /* Calculate mask */ + sc->gate_def.mask = (1 << fls(sc->clock_cell.num_real_clocks)) - 1; + DPRINTF(sc->sc_dev, "num_real_clocks %x gate_def.mask %x\n", + sc->clock_cell.num_real_clocks, sc->gate_def.mask); + + err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->gate_def.clkdef); + + if (err) { + /* free_clkdef will be called in ti_gate_new_pass */ + DPRINTF(sc->sc_dev, "find_parent_clock_names failed\n"); + return (bus_generic_attach(sc->sc_dev)); + } + + err = register_clk(sc); + + if (err) { + /* free_clkdef will be called in ti_gate_new_pass */ + DPRINTF(sc->sc_dev, "register_clk failed\n"); + return (bus_generic_attach(sc->sc_dev)); + } + + sc->attach_done = true; + + free_clkdef(&sc->gate_def.clkdef); + + return (bus_generic_attach(sc->sc_dev)); +} + +static int +ti_gate_detach(device_t dev) +{ + return (EBUSY); +} + +static void +ti_gate_new_pass(device_t dev) { + struct ti_gate_softc *sc; + int err; + + sc = device_get_softc(dev); + + if (sc->attach_done) { + return; + } + + err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->gate_def.clkdef); + if (err) { + /* free_clkdef will be called in later call to ti_gate_new_pass */ + DPRINTF(sc->sc_dev, "new_pass find_parent_clock_names failed\n"); + return; + } + + err = register_clk(sc); + if (err) { + /* free_clkdef will be called in later call to ti_gate_new_pass */ + DPRINTF(sc->sc_dev, "new_pass register_clk failed\n"); + return; + } + + sc->attach_done = true; + + free_clkdef(&sc->gate_def.clkdef); +} + +static device_method_t ti_gate_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ti_gate_probe), + DEVMETHOD(device_attach, ti_gate_attach), + DEVMETHOD(device_detach, ti_gate_detach), + + /* Bus interface */ + DEVMETHOD(bus_new_pass, ti_gate_new_pass), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(ti_gate, ti_gate_driver, ti_gate_methods, + sizeof(struct ti_gate_softc)); + +static devclass_t ti_gate_devclass; + +EARLY_DRIVER_MODULE(ti_gate, simplebus, ti_gate_driver, + ti_gate_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +MODULE_VERSION(ti_gate, 1); diff --git a/sys/arm/ti/clk/ti_mux_clock.c b/sys/arm/ti/clk/ti_mux_clock.c new file mode 100644 index 000000000000..bd232290e6a0 --- /dev/null +++ b/sys/arm/ti/clk/ti_mux_clock.c @@ -0,0 +1,249 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/systm.h> +#include <sys/libkern.h> +#include <sys/types.h> +#include <sys/malloc.h> + +#include <machine/bus.h> +#include <dev/fdt/simplebus.h> + +#include <dev/extres/clk/clk_mux.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include "clock_common.h" + +#if 0 +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +/* + * Devicetree description + * Documentation/devicetree/bindings/clock/ti/mux.txt + */ + +struct ti_mux_softc { + device_t sc_dev; + bool attach_done; + + struct clk_mux_def mux_def; + struct clock_cell_info clock_cell; + struct clkdom *clkdom; +}; + +static int ti_mux_probe(device_t dev); +static int ti_mux_attach(device_t dev); +static int ti_mux_detach(device_t dev); + +#define TI_MUX_CLOCK 2 +#define TI_COMPOSITE_MUX_CLOCK 1 +#define TI_MUX_END 0 + +static struct ofw_compat_data compat_data[] = { + { "ti,mux-clock", TI_MUX_CLOCK }, + { "ti,composite-mux-clock", TI_COMPOSITE_MUX_CLOCK }, + { NULL, TI_MUX_END } +}; + +static int +ti_mux_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "TI Mux Clock"); + + return (BUS_PROBE_DEFAULT); +} + +static int +register_clk(struct ti_mux_softc *sc) { + int err; + + sc->clkdom = clkdom_create(sc->sc_dev); + if (sc->clkdom == NULL) { + DPRINTF(sc->sc_dev, "Failed to create clkdom\n"); + return ENXIO; + } + + err = clknode_mux_register(sc->clkdom, &sc->mux_def); + if (err) { + DPRINTF(sc->sc_dev, "clknode_mux_register failed %x\n", err); + return ENXIO; + } + + err = clkdom_finit(sc->clkdom); + if (err) { + DPRINTF(sc->sc_dev, "Clk domain finit fails %x.\n", err); + return ENXIO; + } + + return 0; +} + +static int +ti_mux_attach(device_t dev) +{ + struct ti_mux_softc *sc; + phandle_t node; + int err; + cell_t value; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + node = ofw_bus_get_node(dev); + + /* Grab the content of reg properties */ + OF_getencprop(node, "reg", &value, sizeof(value)); + sc->mux_def.offset = value; + + if (OF_hasprop(node, "ti,bit-shift")) { + OF_getencprop(node, "ti,bit-shift", &value, sizeof(value)); + sc->mux_def.shift = value; + DPRINTF(sc->sc_dev, "ti,bit-shift => shift %x\n", sc->mux_def.shift); + } + if (OF_hasprop(node, "ti,index-starts-at-one")) { + /* FIXME: Add support in dev/extres/clk */ + /*sc->mux_def.mux_flags = ... */ + device_printf(sc->sc_dev, "ti,index-starts-at-one - Not implemented\n"); + } + + if (OF_hasprop(node, "ti,set-rate-parent")) + device_printf(sc->sc_dev, "ti,set-rate-parent - Not implemented\n"); + if (OF_hasprop(node, "ti,latch-bit")) + device_printf(sc->sc_dev, "ti,latch-bit - Not implemented\n"); + + read_clock_cells(sc->sc_dev, &sc->clock_cell); + + create_clkdef(sc->sc_dev, &sc->clock_cell, &sc->mux_def.clkdef); + + /* Figure out the width from ti_max_div */ + if (sc->mux_def.mux_flags) + sc->mux_def.width = fls(sc->clock_cell.num_real_clocks-1); + else + sc->mux_def.width = fls(sc->clock_cell.num_real_clocks); + + DPRINTF(sc->sc_dev, "sc->clock_cell.num_real_clocks %x def.width %x\n", + sc->clock_cell.num_real_clocks, sc->mux_def.width); + + err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->mux_def.clkdef); + + if (err) { + /* free_clkdef will be called in ti_mux_new_pass */ + DPRINTF(sc->sc_dev, "find_parent_clock_names failed\n"); + return (bus_generic_attach(sc->sc_dev)); + } + + err = register_clk(sc); + + if (err) { + /* free_clkdef will be called in ti_mux_new_pass */ + DPRINTF(sc->sc_dev, "register_clk failed\n"); + return (bus_generic_attach(sc->sc_dev)); + } + + sc->attach_done = true; + + free_clkdef(&sc->mux_def.clkdef); + + return (bus_generic_attach(sc->sc_dev)); +} + +static void +ti_mux_new_pass(device_t dev) +{ + struct ti_mux_softc *sc; + int err; + + sc = device_get_softc(dev); + + if (sc->attach_done) { + return; + } + + err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->mux_def.clkdef); + if (err) { + /* free_clkdef will be called in later call to ti_mux_new_pass */ + DPRINTF(sc->sc_dev, "ti_mux_new_pass find_parent_clock_names failed\n"); + return; + } + + err = register_clk(sc); + if (err) { + /* free_clkdef will be called in later call to ti_mux_new_pass */ + DPRINTF(sc->sc_dev, "ti_mux_new_pass register_clk failed\n"); + return; + } + + sc->attach_done = true; + + free_clkdef(&sc->mux_def.clkdef); +} + +static int +ti_mux_detach(device_t dev) +{ + return (EBUSY); +} + +static device_method_t ti_mux_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ti_mux_probe), + DEVMETHOD(device_attach, ti_mux_attach), + DEVMETHOD(device_detach, ti_mux_detach), + + /* Bus interface */ + DEVMETHOD(bus_new_pass, ti_mux_new_pass), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(ti_mux, ti_mux_driver, ti_mux_methods, + sizeof(struct ti_mux_softc)); + +static devclass_t ti_mux_devclass; + +EARLY_DRIVER_MODULE(ti_mux, simplebus, ti_mux_driver, + ti_mux_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +MODULE_VERSION(ti_mux, 1); diff --git a/sys/arm/ti/cpsw/if_cpsw.c b/sys/arm/ti/cpsw/if_cpsw.c index 4503304e7b5b..9c43419d568b 100644 --- a/sys/arm/ti/cpsw/if_cpsw.c +++ b/sys/arm/ti/cpsw/if_cpsw.c @@ -74,7 +74,8 @@ __FBSDID("$FreeBSD$"); #include <net/if_media.h> #include <net/if_types.h> -#include <arm/ti/ti_scm.h> +#include <dev/extres/syscon/syscon.h> +#include "syscon_if.h" #include <arm/ti/am335x/am335x_scm.h> #include <dev/mii/mii.h> @@ -1004,6 +1005,8 @@ cpswp_attach(device_t dev) struct cpswp_softc *sc; uint32_t reg; uint8_t mac_addr[ETHER_ADDR_LEN]; + phandle_t opp_table; + struct syscon *syscon; sc = device_get_softc(dev); sc->dev = dev; @@ -1047,15 +1050,34 @@ cpswp_attach(device_t dev) IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); IFQ_SET_READY(&ifp->if_snd); + /* FIXME: For now; Go and kidnap syscon from opp-table */ + /* ti,cpsw actually have an optional syscon reference but only for am33xx?? */ + opp_table = OF_finddevice("/opp-table"); + if (opp_table == -1) { + device_printf(dev, "Cant find /opp-table\n"); + cpswp_detach(dev); + return (ENXIO); + } + if (!OF_hasprop(opp_table, "syscon")) { + device_printf(dev, "/opp-table doesnt have required syscon property\n"); + cpswp_detach(dev); + return (ENXIO); + } + if (syscon_get_by_ofw_property(dev, opp_table, "syscon", &syscon) != 0) { + device_printf(dev, "Failed to get syscon\n"); + cpswp_detach(dev); + return (ENXIO); + } + /* Get high part of MAC address from control module (mac_id[0|1]_hi) */ - ti_scm_reg_read_4(SCM_MAC_ID0_HI + sc->unit * 8, ®); + reg = SYSCON_READ_4(syscon, SCM_MAC_ID0_HI + sc->unit * 8); mac_addr[0] = reg & 0xFF; mac_addr[1] = (reg >> 8) & 0xFF; mac_addr[2] = (reg >> 16) & 0xFF; mac_addr[3] = (reg >> 24) & 0xFF; /* Get low part of MAC address from control module (mac_id[0|1]_lo) */ - ti_scm_reg_read_4(SCM_MAC_ID0_LO + sc->unit * 8, ®); + reg = SYSCON_READ_4(syscon, SCM_MAC_ID0_LO + sc->unit * 8); mac_addr[4] = reg & 0xFF; mac_addr[5] = (reg >> 8) & 0xFF; diff --git a/sys/arm/ti/files.ti b/sys/arm/ti/files.ti index 83b3c2ed8d89..87beccd120a0 100644 --- a/sys/arm/ti/files.ti +++ b/sys/arm/ti/files.ti @@ -1,14 +1,16 @@ #$FreeBSD$ arm/ti/ti_cpuid.c standard -arm/ti/ti_hwmods.c standard arm/ti/ti_machdep.c standard arm/ti/ti_prcm.c standard +arm/ti/ti_omap4_cm.c standard arm/ti/ti_scm.c standard +arm/ti/ti_scm_syscon.c standard arm/ti/ti_pinmux.c standard dev/mbox/mbox_if.m optional ti_mbox arm/ti/ti_mbox.c optional ti_mbox arm/ti/ti_pruss.c optional ti_pruss +arm/ti/ti_prm.c optional ti_pruss arm/ti/ti_wdt.c optional ti_wdt arm/ti/ti_adc.c optional ti_adc arm/ti/ti_gpio.c optional gpio @@ -18,6 +20,15 @@ arm/ti/ti_sdhci.c optional sdhci arm/ti/ti_spi.c optional ti_spi arm/ti/ti_sysc.c standard +arm/ti/clk/clock_common.c standard +arm/ti/clk/ti_clk_clkctrl.c standard +arm/ti/clk/ti_clkctrl.c standard +arm/ti/clk/ti_clk_dpll.c standard +arm/ti/clk/ti_dpll_clock.c standard +arm/ti/clk/ti_mux_clock.c standard +arm/ti/clk/ti_divider_clock.c standard +arm/ti/clk/ti_gate_clock.c standard + dev/uart/uart_dev_ti8250.c optional uart dev/uart/uart_dev_ns8250.c optional uart diff --git a/sys/arm/ti/omap4/files.omap4 b/sys/arm/ti/omap4/files.omap4 index ddae056d3fc4..0b2f2d3bf26d 100644 --- a/sys/arm/ti/omap4/files.omap4 +++ b/sys/arm/ti/omap4/files.omap4 @@ -9,7 +9,7 @@ arm/ti/ti_sdma.c optional ti_sdma arm/ti/omap4/omap4_gpio.c optional gpio arm/ti/omap4/omap4_l2cache.c optional pl310 -arm/ti/omap4/omap4_prcm_clks.c standard +#arm/ti/omap4/omap4_prcm_clks.c standard arm/ti/omap4/omap4_scm_padconf.c standard arm/ti/omap4/omap4_mp.c optional smp arm/ti/omap4/omap4_wugen.c standard diff --git a/sys/arm/ti/ti_adc.c b/sys/arm/ti/ti_adc.c index 7d7f1deae580..3c67500f3ebc 100644 --- a/sys/arm/ti/ti_adc.c +++ b/sys/arm/ti/ti_adc.c @@ -58,7 +58,7 @@ __FBSDID("$FreeBSD$"); #include <dev/evdev/evdev.h> #endif -#include <arm/ti/ti_prcm.h> +#include <arm/ti/ti_sysc.h> #include <arm/ti/ti_adcreg.h> #include <arm/ti/ti_adcvar.h> @@ -824,7 +824,7 @@ ti_adc_attach(device_t dev) } /* Activate the ADC_TSC module. */ - err = ti_prcm_clk_enable(TSC_ADC_CLK); + err = ti_sysc_clock_enable(device_get_parent(dev)); if (err) return (err); @@ -846,7 +846,7 @@ ti_adc_attach(device_t dev) } /* Check the ADC revision. */ - rev = ADC_READ4(sc, ADC_REVISION); + rev = ADC_READ4(sc, ti_sysc_get_rev_address_offset_host(device_get_parent(dev))); device_printf(dev, "scheme: %#x func: %#x rtl: %d rev: %d.%d custom rev: %d\n", (rev & ADC_REV_SCHEME_MSK) >> ADC_REV_SCHEME_SHIFT, @@ -964,6 +964,7 @@ static devclass_t ti_adc_devclass; DRIVER_MODULE(ti_adc, simplebus, ti_adc_driver, ti_adc_devclass, 0, 0); MODULE_VERSION(ti_adc, 1); MODULE_DEPEND(ti_adc, simplebus, 1, 1, 1); +MODULE_DEPEND(ti_adc, ti_sysc, 1, 1, 1); #ifdef EVDEV_SUPPORT MODULE_DEPEND(ti_adc, evdev, 1, 1, 1); #endif diff --git a/sys/arm/ti/ti_edma3.c b/sys/arm/ti/ti_edma3.c index f8736e001553..7804ee6b1d8d 100644 --- a/sys/arm/ti/ti_edma3.c +++ b/sys/arm/ti/ti_edma3.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus_subr.h> #include <arm/ti/ti_scm.h> -#include <arm/ti/ti_prcm.h> +#include <arm/ti/ti_sysc.h> #include <arm/ti/ti_edma3.h> @@ -181,8 +181,10 @@ ti_edma3_attach(device_t dev) return (ENXIO); } + /* FIXME: Require DTS from Linux kernel 5.7 */ + /* FIXME: OK to enable clkctrl here? */ /* Enable Channel Controller */ - ti_prcm_clk_enable(EDMA_TPCC_CLK); + ti_sysc_clock_enable(device_get_parent(dev)); reg = ti_edma3_cc_rd_4(TI_EDMA3CC_PID); @@ -218,7 +220,7 @@ static driver_t ti_edma3_driver = { static devclass_t ti_edma3_devclass; DRIVER_MODULE(ti_edma3, simplebus, ti_edma3_driver, ti_edma3_devclass, 0, 0); -MODULE_DEPEND(ti_edma3, ti_prcm, 1, 1, 1); +MODULE_DEPEND(ti_edma3, ti_sysc, 1, 1, 1); static void ti_edma3_intr_comp(void *arg) @@ -244,11 +246,6 @@ ti_edma3_init(unsigned int eqn) uint32_t reg; int i; - /* on AM335x Event queue 0 is always mapped to Transfer Controller 0, - * event queue 1 to TC2, etc. So we are asking PRCM to power on specific - * TC based on what event queue we need to initialize */ - ti_prcm_clk_enable(EDMA_TPTC0_CLK + eqn); - /* Clear Event Missed Regs */ ti_edma3_cc_wr_4(TI_EDMA3CC_EMCR, 0xFFFFFFFF); ti_edma3_cc_wr_4(TI_EDMA3CC_EMCRH, 0xFFFFFFFF); diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c index ccdeeb502be4..8754a4769beb 100644 --- a/sys/arm/ti/ti_gpio.c +++ b/sys/arm/ti/ti_gpio.c @@ -57,8 +57,7 @@ __FBSDID("$FreeBSD$"); #include <arm/ti/ti_cpuid.h> #include <arm/ti/ti_gpio.h> #include <arm/ti/ti_scm.h> -#include <arm/ti/ti_prcm.h> -#include <arm/ti/ti_hwmods.h> +#include <arm/ti/ti_sysc.h> #include <dev/gpio/gpiobusvar.h> #include <dev/ofw/openfirm.h> @@ -117,6 +116,18 @@ __FBSDID("$FreeBSD$"); #define PINS_PER_BANK 32 #define TI_GPIO_MASK(p) (1U << ((p) % PINS_PER_BANK)) +#define OMAP4_GPIO1_REV 0x00000 +#define OMAP4_GPIO2_REV 0x55000 +#define OMAP4_GPIO3_REV 0x57000 +#define OMAP4_GPIO4_REV 0x59000 +#define OMAP4_GPIO5_REV 0x5b000 +#define OMAP4_GPIO6_REV 0x5d000 + +#define AM335X_GPIO0_REV 0x07000 +#define AM335X_GPIO1_REV 0x4C000 +#define AM335X_GPIO2_REV 0xAC000 +#define AM335X_GPIO3_REV 0xAE000 + static int ti_gpio_intr(void *arg); static int ti_gpio_detach(device_t); @@ -434,7 +445,7 @@ ti_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) oe &= ~TI_GPIO_MASK(pin); ti_gpio_write_4(sc, TI_GPIO_OE, oe); TI_GPIO_UNLOCK(sc); - + return (0); } @@ -499,7 +510,7 @@ ti_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value) return (EINVAL); /* - * Return data from output latch when set as output and from the + * Return data from output latch when set as output and from the * input register otherwise. */ TI_GPIO_LOCK(sc); @@ -553,29 +564,72 @@ ti_gpio_pin_toggle(device_t dev, uint32_t pin) static int ti_gpio_bank_init(device_t dev) { - int pin; + int pin, err; struct ti_gpio_softc *sc; uint32_t flags, reg_oe, reg_set, rev; - clk_ident_t clk; + uint64_t rev_address; sc = device_get_softc(dev); /* Enable the interface and functional clocks for the module. */ - clk = ti_hwmods_get_clock(dev); - if (clk == INVALID_CLK_IDENT) { - device_printf(dev, "failed to get device id based on ti,hwmods\n"); + rev_address = ti_sysc_get_rev_address(device_get_parent(dev)); + /* AM335x + * sc->sc_bank used in am335x/am335x_gpio.c and omap4/omap4_gpio.c */ + switch(ti_chip()) { +#ifdef SOC_OMAP4 + case CHIP_OMAP_4: + switch (rev_address) { + case OMAP4_GPIO1_REV: + sc->sc_bank = 0; + break; + case OMAP4_GPIO2_REV: + sc->sc_bank = 1; + break; + case OMAP4_GPIO3_REV: + sc->sc_bank = 2; + break; + case OMAP4_GPIO4_REV: + sc->sc_bank = 3; + break; + case OMAP4_GPIO5_REV: + sc->sc_bank = 4; + break; + case OMAP4_GPIO6_REV: + sc->sc_bank = 5; + break; + } +#endif +#ifdef SOC_TI_AM335X + case CHIP_AM335X: + switch (rev_address) { + case AM335X_GPIO0_REV: + sc->sc_bank = 0; + break; + case AM335X_GPIO1_REV: + sc->sc_bank = 1; + break; + case AM335X_GPIO2_REV: + sc->sc_bank = 2; + break; + case AM335X_GPIO3_REV: + sc->sc_bank = 3; + break; + } +#endif + } + err = ti_sysc_clock_enable(device_get_parent(dev)); + if (err) { + device_printf(dev, "Failed to enable clock\n"); return (EINVAL); } - sc->sc_bank = clk - GPIO1_CLK + ti_first_gpio_bank(); - ti_prcm_clk_enable(clk); - /* * Read the revision number of the module. TI don't publish the * actual revision numbers, so instead the values have been * determined by experimentation. */ - rev = ti_gpio_read_4(sc, TI_GPIO_REVISION); + rev = ti_gpio_read_4(sc, + ti_sysc_get_rev_address_offset_host(device_get_parent(dev))); /* Check the revision. */ if (rev != ti_gpio_rev()) { @@ -669,7 +723,7 @@ ti_gpio_attach(device_t dev) /* We need to go through each block and ensure the clocks are running and * the module is enabled. It might be better to do this only when the * pins are configured which would result in less power used if the GPIO - * pins weren't used ... + * pins weren't used ... */ if (sc->sc_mem_res != NULL) { /* Initialize the GPIO module. */ diff --git a/sys/arm/ti/ti_hwmods.c b/sys/arm/ti/ti_hwmods.c deleted file mode 100644 index 97c8f99c828a..000000000000 --- a/sys/arm/ti/ti_hwmods.c +++ /dev/null @@ -1,214 +0,0 @@ -/*- - * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/kernel.h> - -#include <dev/ofw/openfirm.h> -#include <dev/ofw/ofw_bus.h> -#include <dev/ofw/ofw_bus_subr.h> - -#include <machine/bus.h> -#include <machine/fdt.h> - -#include <arm/ti/ti_prcm.h> -#include <arm/ti/ti_hwmods.h> - -struct hwmod { - const char *name; - int clock_id; -}; - -struct hwmod ti_hwmods[] = { - {"i2c1", I2C1_CLK}, - {"i2c2", I2C2_CLK}, - {"i2c3", I2C3_CLK}, - {"i2c4", I2C4_CLK}, - {"i2c5", I2C5_CLK}, - - {"gpio1", GPIO1_CLK}, - {"gpio2", GPIO2_CLK}, - {"gpio3", GPIO3_CLK}, - {"gpio4", GPIO4_CLK}, - {"gpio5", GPIO5_CLK}, - {"gpio6", GPIO6_CLK}, - {"gpio7", GPIO7_CLK}, - - {"mmc1", MMC1_CLK}, - {"mmc2", MMC2_CLK}, - {"mmc3", MMC3_CLK}, - {"mmc4", MMC4_CLK}, - {"mmc5", MMC5_CLK}, - {"mmc6", MMC6_CLK}, - - {"epwmss0", PWMSS0_CLK}, - {"epwmss1", PWMSS1_CLK}, - {"epwmss2", PWMSS2_CLK}, - - {"spi0", SPI0_CLK}, - {"spi1", SPI1_CLK}, - - {"timer1", TIMER1_CLK}, - {"timer2", TIMER2_CLK}, - {"timer3", TIMER3_CLK}, - {"timer4", TIMER4_CLK}, - {"timer5", TIMER5_CLK}, - {"timer6", TIMER6_CLK}, - {"timer7", TIMER7_CLK}, - - {"uart1", UART1_CLK}, - {"uart2", UART2_CLK}, - {"uart3", UART3_CLK}, - {"uart4", UART4_CLK}, - {"uart5", UART5_CLK}, - {"uart6", UART6_CLK}, - {"uart7", UART7_CLK}, - - {NULL, 0} -}; - -static inline int -ti_get_hwmods_prop(phandle_t node, void **name) -{ - int len; - - if ((len = OF_getprop_alloc(node, "ti,hwmods", name)) > 0) - return (len); - return (OF_getprop_alloc(OF_parent(node), "ti,hwmods", name)); -} - -clk_ident_t -ti_hwmods_get_clock(device_t dev) -{ - phandle_t node; - int len, l; - char *name; - char *buf; - int clk; - struct hwmod *hw; - - if ((node = ofw_bus_get_node(dev)) == 0) - return (INVALID_CLK_IDENT); - - if ((len = ti_get_hwmods_prop(node, (void **)&name)) <= 0) - return (INVALID_CLK_IDENT); - - buf = name; - - clk = INVALID_CLK_IDENT; - while ((len > 0) && (clk == INVALID_CLK_IDENT)) { - for (hw = ti_hwmods; hw->name != NULL; ++hw) { - if (strcmp(hw->name, name) == 0) { - clk = hw->clock_id; - break; - } - } - - /* Slide to the next sub-string. */ - l = strlen(name) + 1; - name += l; - len -= l; - } - - if (len > 0) - device_printf(dev, "WARNING: more than one ti,hwmod \n"); - - OF_prop_free(buf); - return (clk); -} - -int ti_hwmods_contains(device_t dev, const char *hwmod) -{ - phandle_t node; - int len, l; - char *name; - char *buf; - int result; - - if ((node = ofw_bus_get_node(dev)) == 0) - return (0); - - if ((len = ti_get_hwmods_prop(node, (void **)&name)) <= 0) - return (0); - - buf = name; - - result = 0; - while (len > 0) { - if (strcmp(name, hwmod) == 0) { - result = 1; - break; - } - - /* Slide to the next sub-string. */ - l = strlen(name) + 1; - name += l; - len -= l; - } - - OF_prop_free(buf); - - return (result); -} - -int -ti_hwmods_get_unit(device_t dev, const char *hwmod) -{ - phandle_t node; - int l, len, hwmodlen, result; - char *name; - char *buf; - - if ((node = ofw_bus_get_node(dev)) == 0) - return (0); - - if ((len = ti_get_hwmods_prop(node, (void **)&name)) <= 0) - return (0); - - buf = name; - hwmodlen = strlen(hwmod); - result = 0; - while (len > 0) { - if (strncmp(name, hwmod, hwmodlen) == 0) { - result = (int)strtoul(name + hwmodlen, NULL, 10); - break; - } - /* Slide to the next sub-string. */ - l = strlen(name) + 1; - name += l; - len -= l; - } - - OF_prop_free(buf); - return (result); -} diff --git a/sys/arm/ti/ti_hwmods.h b/sys/arm/ti/ti_hwmods.h deleted file mode 100644 index c236cc0d0db0..000000000000 --- a/sys/arm/ti/ti_hwmods.h +++ /dev/null @@ -1,37 +0,0 @@ -/*- - * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ -#ifndef _TI_HWMODS_H_ -#define _TI_HWMODS_H_ - -clk_ident_t ti_hwmods_get_clock(device_t dev); -int ti_hwmods_contains(device_t dev, const char *hwmod); - -/* Returns the N from "hwmodN" in the ti,hwmods property; 0 on failure. */ -int ti_hwmods_get_unit(device_t dev, const char *hwmod); - -#endif /* _TI_HWMODS_H_ */ diff --git a/sys/arm/ti/ti_i2c.c b/sys/arm/ti/ti_i2c.c index 4a9313d6f501..526cb45481f0 100644 --- a/sys/arm/ti/ti_i2c.c +++ b/sys/arm/ti/ti_i2c.c @@ -63,8 +63,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus_subr.h> #include <arm/ti/ti_cpuid.h> -#include <arm/ti/ti_prcm.h> -#include <arm/ti/ti_hwmods.h> +#include <arm/ti/ti_sysc.h> #include <arm/ti/ti_i2c.h> #include <dev/iicbus/iiconf.h> @@ -79,7 +78,6 @@ __FBSDID("$FreeBSD$"); struct ti_i2c_softc { device_t sc_dev; - clk_ident_t clk_id; struct resource* sc_irq_res; struct resource* sc_mem_res; device_t sc_iicbus; @@ -700,7 +698,7 @@ ti_i2c_activate(device_t dev) * 1. Enable the functional and interface clocks (see Section * 23.1.5.1.1.1.1). */ - err = ti_prcm_clk_enable(sc->clk_id); + err = ti_sysc_clock_enable(device_get_parent(dev)); if (err) return (err); @@ -748,7 +746,7 @@ ti_i2c_deactivate(device_t dev) } /* Finally disable the functional and interface clocks. */ - ti_prcm_clk_disable(sc->clk_id); + ti_sysc_clock_disable(device_get_parent(dev)); } static int @@ -818,7 +816,6 @@ static int ti_i2c_attach(device_t dev) { int err, rid; - phandle_t node; struct ti_i2c_softc *sc; struct sysctl_ctx_list *ctx; struct sysctl_oid_list *tree; @@ -827,15 +824,6 @@ ti_i2c_attach(device_t dev) sc = device_get_softc(dev); sc->sc_dev = dev; - /* Get the i2c device id from FDT. */ - node = ofw_bus_get_node(dev); - /* i2c ti,hwmods bindings is special: it start with index 1 */ - sc->clk_id = ti_hwmods_get_clock(dev); - if (sc->clk_id == INVALID_CLK_IDENT) { - device_printf(dev, "failed to get device id using ti,hwmod\n"); - return (ENXIO); - } - /* Get the memory resource for the register mapping. */ rid = 0; sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, @@ -986,5 +974,5 @@ static devclass_t ti_i2c_devclass; DRIVER_MODULE(ti_iic, simplebus, ti_i2c_driver, ti_i2c_devclass, 0, 0); DRIVER_MODULE(iicbus, ti_iic, iicbus_driver, iicbus_devclass, 0, 0); -MODULE_DEPEND(ti_iic, ti_prcm, 1, 1, 1); +MODULE_DEPEND(ti_iic, ti_sysc, 1, 1, 1); MODULE_DEPEND(ti_iic, iicbus, 1, 1, 1); diff --git a/sys/arm/ti/ti_mbox.c b/sys/arm/ti/ti_mbox.c index ea8454f96f7a..f77f2d9eafbf 100644 --- a/sys/arm/ti/ti_mbox.c +++ b/sys/arm/ti/ti_mbox.c @@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <arm/ti/ti_mbox.h> -#include <arm/ti/ti_prcm.h> +#include <arm/ti/ti_sysc.h> #include "mbox_if.h" @@ -102,6 +102,7 @@ static driver_t ti_mbox_driver = { static devclass_t ti_mbox_devclass; DRIVER_MODULE(ti_mbox, simplebus, ti_mbox_driver, ti_mbox_devclass, 0, 0); +MODULE_DEPEND(ti_mbox, ti_sysc, 1, 1, 1); static __inline uint32_t ti_mbox_reg_read(struct ti_mbox_softc *sc, uint16_t reg) @@ -137,10 +138,11 @@ ti_mbox_attach(device_t dev) int rid, delay, chan; uint32_t rev, sysconfig; - if (ti_prcm_clk_enable(MAILBOX0_CLK) != 0) { + if (ti_sysc_clock_enable(device_get_parent(dev)) != 0) { device_printf(dev, "could not enable MBOX clock\n"); return (ENXIO); } + sc = device_get_softc(dev); rid = 0; mtx_init(&sc->sc_mtx, "TI mbox", NULL, MTX_DEF); @@ -188,7 +190,8 @@ ti_mbox_attach(device_t dev) */ ti_mbox_reg_write(sc, TI_MBOX_SYSCONFIG, ti_mbox_reg_read(sc, TI_MBOX_SYSCONFIG) | TI_MBOX_SYSCONFIG_SMARTIDLE); - rev = ti_mbox_reg_read(sc, TI_MBOX_REVISION); + rev = ti_mbox_reg_read(sc, + ti_sysc_get_rev_address_offset_host(device_get_parent(dev))); DPRINTF("rev %d\n", rev); device_printf(dev, "revision %d.%d\n", (rev >> 8) & 0x4, rev & 0x40); /* diff --git a/sys/arm/ti/ti_omap4_cm.c b/sys/arm/ti/ti_omap4_cm.c new file mode 100644 index 000000000000..c9545a612e1f --- /dev/null +++ b/sys/arm/ti/ti_omap4_cm.c @@ -0,0 +1,151 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org> + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Based on sys/arm/ti/ti_sysc.c + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/fbio.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/resource.h> +#include <machine/bus.h> +#include <vm/vm.h> +#include <vm/vm_extern.h> +#include <vm/vm_kern.h> +#include <vm/pmap.h> + +#include <dev/fdt/simplebus.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <arm/ti/ti_omap4_cm.h> + +static struct ofw_compat_data compat_data[] = { + { "ti,omap4-cm", 1 }, + { NULL, 0 } +}; + +struct ti_omap4_cm_softc { + struct simplebus_softc sc; + device_t dev; +}; + +uint64_t +ti_omap4_cm_get_simplebus_base_host(device_t dev) { + struct ti_omap4_cm_softc *sc; + + sc = device_get_softc(dev); + if (sc->sc.nranges == 0) + return (0); + + return (sc->sc.ranges[0].host); +} + +static int ti_omap4_cm_probe(device_t dev); +static int ti_omap4_cm_attach(device_t dev); +static int ti_omap4_cm_detach(device_t dev); + +static int +ti_omap4_cm_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "TI OMAP4-CM"); + if (!bootverbose) + device_quiet(dev); + + return (BUS_PROBE_DEFAULT); +} + +static int +ti_omap4_cm_attach(device_t dev) +{ + struct ti_omap4_cm_softc *sc; + device_t cdev; + phandle_t node, child; + + sc = device_get_softc(dev); + sc->dev = dev; + node = ofw_bus_get_node(dev); + + simplebus_init(dev, node); + if (simplebus_fill_ranges(node, &sc->sc) < 0) { + device_printf(dev, "could not get ranges\n"); + return (ENXIO); + } + + bus_generic_probe(sc->dev); + + for (child = OF_child(node); child > 0; child = OF_peer(child)) { + cdev = simplebus_add_device(dev, child, 0, NULL, -1, NULL); + if (cdev != NULL) + device_probe_and_attach(cdev); + } + + return (bus_generic_attach(dev)); +} + +static int +ti_omap4_cm_detach(device_t dev) +{ + return (EBUSY); +} + +static device_method_t ti_omap4_cm_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ti_omap4_cm_probe), + DEVMETHOD(device_attach, ti_omap4_cm_attach), + DEVMETHOD(device_detach, ti_omap4_cm_detach), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(ti_omap4_cm, ti_omap4_cm_driver, ti_omap4_cm_methods, + sizeof(struct ti_omap4_cm_softc), simplebus_driver); + +static devclass_t ti_omap4_cm_devclass; + +EARLY_DRIVER_MODULE(ti_omap4_cm, simplebus, ti_omap4_cm_driver, +ti_omap4_cm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST); + +EARLY_DRIVER_MODULE(ti_omap4_cm, ofwbus, ti_omap4_cm_driver, +ti_omap4_cm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST); + diff --git a/sys/arm/ti/ti_omap4_cm.h b/sys/arm/ti/ti_omap4_cm.h new file mode 100644 index 000000000000..4da56520cc97 --- /dev/null +++ b/sys/arm/ti/ti_omap4_cm.h @@ -0,0 +1,34 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __TI_OMAP4_CM__ +#define __TI_OMAP4_CM__ + +uint64_t ti_omap4_cm_get_simplebus_base_host(device_t dev); + +#endif /* __TI_OMAP4_CM__ */ diff --git a/sys/arm/ti/ti_pinmux.c b/sys/arm/ti/ti_pinmux.c index b532d9124ce6..da4b8a85526c 100644 --- a/sys/arm/ti/ti_pinmux.c +++ b/sys/arm/ti/ti_pinmux.c @@ -459,3 +459,5 @@ static driver_t ti_pinmux_driver = { static devclass_t ti_pinmux_devclass; DRIVER_MODULE(ti_pinmux, simplebus, ti_pinmux_driver, ti_pinmux_devclass, 0, 0); +MODULE_VERSION(ti_pinmux, 1); +MODULE_DEPEND(ti_pinmux, ti_scm, 1, 1, 1); diff --git a/sys/arm/ti/ti_prcm.c b/sys/arm/ti/ti_prcm.c index 3b6bbabe6910..ff85e724ada4 100644 --- a/sys/arm/ti/ti_prcm.c +++ b/sys/arm/ti/ti_prcm.c @@ -1,10 +1,11 @@ /*- - * SPDX-License-Identifier: BSD-4-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2010 - * Ben Gray <ben.r.gray@gmail.com>. + * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org> * All rights reserved. * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -13,345 +14,332 @@ * 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 Ben Gray. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. * - * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR + * 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 BEN GRAY 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. - */ - -/** - * Power, Reset and Clock Management Module - * - * This is a very simple driver wrapper around the PRCM set of registers in - * the OMAP3 chip. It allows you to turn on and off things like the functional - * and interface clocks to the various on-chip modules. + * 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$ */ + +/* Based on sys/arm/ti/am335x/am335x_prcm.c */ + #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/bus.h> #include <sys/kernel.h> #include <sys/module.h> -#include <sys/bus.h> -#include <sys/resource.h> +#include <sys/malloc.h> #include <sys/rman.h> -#include <sys/lock.h> -#include <sys/mutex.h> - +#include <sys/timeet.h> +#include <sys/timetc.h> +#include <sys/watchdog.h> #include <machine/bus.h> -#include <machine/resource.h> +#include <machine/cpu.h> #include <machine/intr.h> #include <arm/ti/ti_cpuid.h> #include <arm/ti/ti_prcm.h> +#include <arm/ti/tivar.h> -/** - * ti_*_clk_devmap - Array of clock devices, should be defined one per SoC - * - * This array is typically defined in one of the targeted *_prcm_clk.c - * files and is specific to the given SoC platform. Each entry in the array - * corresponds to an individual clock device. - */ -extern struct ti_clock_dev ti_omap4_clk_devmap[]; -extern struct ti_clock_dev ti_am335x_clk_devmap[]; +#include <dev/fdt/simplebus.h> -/** - * ti_prcm_clk_dev - returns a pointer to the clock device with given id - * @clk: the ID of the clock device to get - * - * Simply iterates through the clk_devmap global array and returns a pointer - * to the clock device if found. - * - * LOCKING: - * None - * - * RETURNS: - * The pointer to the clock device on success, on failure NULL is returned. - */ -static struct ti_clock_dev * -ti_prcm_clk_dev(clk_ident_t clk) +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include "clkdev_if.h" + +#if 0 +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +struct ti_prcm_softc { + struct simplebus_softc sc_simplebus; + device_t dev; + struct resource * mem_res; + bus_space_tag_t bst; + bus_space_handle_t bsh; + int attach_done; + struct mtx mtx; +}; + +static struct ti_prcm_softc *ti_prcm_sc = NULL; +static void omap4_prcm_reset(void); +static void am335x_prcm_reset(void); + +#define TI_AM3_PRCM 18 +#define TI_AM4_PRCM 17 +#define TI_OMAP2_PRCM 16 +#define TI_OMAP3_PRM 15 +#define TI_OMAP3_CM 14 +#define TI_OMAP4_CM1 13 +#define TI_OMAP4_PRM 12 +#define TI_OMAP4_CM2 11 +#define TI_OMAP4_SCRM 10 +#define TI_OMAP5_PRM 9 +#define TI_OMAP5_CM_CORE_AON 8 +#define TI_OMAP5_SCRM 7 +#define TI_OMAP5_CM_CORE 6 +#define TI_DRA7_PRM 5 +#define TI_DRA7_CM_CORE_AON 4 +#define TI_DRA7_CM_CORE 3 +#define TI_DM814_PRCM 2 +#define TI_DM816_PRCM 1 +#define TI_PRCM_END 0 + +static struct ofw_compat_data compat_data[] = { + { "ti,am3-prcm", TI_AM3_PRCM }, + { "ti,am4-prcm", TI_AM4_PRCM }, + { "ti,omap2-prcm", TI_OMAP2_PRCM }, + { "ti,omap3-prm", TI_OMAP3_PRM }, + { "ti,omap3-cm", TI_OMAP3_CM }, + { "ti,omap4-cm1", TI_OMAP4_CM1 }, + { "ti,omap4-prm", TI_OMAP4_PRM }, + { "ti,omap4-cm2", TI_OMAP4_CM2 }, + { "ti,omap4-scrm", TI_OMAP4_SCRM }, + { "ti,omap5-prm", TI_OMAP5_PRM }, + { "ti,omap5-cm-core-aon", TI_OMAP5_CM_CORE_AON }, + { "ti,omap5-scrm", TI_OMAP5_SCRM }, + { "ti,omap5-cm-core", TI_OMAP5_CM_CORE }, + { "ti,dra7-prm", TI_DRA7_PRM }, + { "ti,dra7-cm-core-aon", TI_DRA7_CM_CORE_AON }, + { "ti,dra7-cm-core", TI_DRA7_CM_CORE }, + { "ti,dm814-prcm", TI_DM814_PRCM }, + { "ti,dm816-prcm", TI_DM816_PRCM }, + { NULL, TI_PRCM_END} +}; + +static int +ti_prcm_probe(device_t dev) { - struct ti_clock_dev *clk_dev; - - /* Find the clock within the devmap - it's a bit inefficent having a for - * loop for this, but this function should only called when a driver is - * being activated so IMHO not a big issue. + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) { + return (ENXIO); + } + + device_set_desc(dev, "TI Power and Clock Management"); + return(BUS_PROBE_DEFAULT); +} + +static int +ti_prcm_attach(device_t dev) +{ + struct ti_prcm_softc *sc; + phandle_t node, child; + int rid; + + sc = device_get_softc(dev); + sc->dev = dev; + + node = ofw_bus_get_node(sc->dev); + simplebus_init(sc->dev, node); + + if (simplebus_fill_ranges(node, &sc->sc_simplebus) < 0) { + device_printf(sc->dev, "could not get ranges\n"); + return (ENXIO); + } + if (sc->sc_simplebus.nranges == 0) { + device_printf(sc->dev, "nranges == 0\n"); + return (ENXIO); + } + + sc->mem_res = bus_alloc_resource(sc->dev, SYS_RES_MEMORY, &rid, + sc->sc_simplebus.ranges[0].host, + (sc->sc_simplebus.ranges[0].host + + sc->sc_simplebus.ranges[0].size - 1), + sc->sc_simplebus.ranges[0].size, + RF_ACTIVE | RF_SHAREABLE); + + if (sc->mem_res == NULL) { + return (ENXIO); + } + + sc->bst = rman_get_bustag(sc->mem_res); + sc->bsh = rman_get_bushandle(sc->mem_res); + + mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); + + /* Fixme: for xxx_prcm_reset functions. + * Get rid of global variables? */ - clk_dev = NULL; + ti_prcm_sc = sc; + switch(ti_chip()) { #ifdef SOC_OMAP4 case CHIP_OMAP_4: - clk_dev = &(ti_omap4_clk_devmap[0]); + ti_cpu_reset = omap4_prcm_reset; break; #endif #ifdef SOC_TI_AM335X case CHIP_AM335X: - clk_dev = &(ti_am335x_clk_devmap[0]); + ti_cpu_reset = am335x_prcm_reset; break; #endif } - if (clk_dev == NULL) - panic("No clock devmap found"); - while (clk_dev->id != INVALID_CLK_IDENT) { - if (clk_dev->id == clk) { - return (clk_dev); - } - clk_dev++; + + bus_generic_probe(sc->dev); + for (child = OF_child(node); child != 0; child = OF_peer(child)) { + simplebus_add_device(dev, child, 0, NULL, -1, NULL); } - /* Sanity check we managed to find the clock */ - printf("ti_prcm: Failed to find clock device (%d)\n", clk); - return (NULL); + return (bus_generic_attach(sc->dev)); } -/** - * ti_prcm_clk_valid - enables a clock for a particular module - * @clk: identifier for the module to enable, see ti_prcm.h for a list - * of possible modules. - * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK. - * - * This function can enable either a functional or interface clock. - * - * The real work done to enable the clock is really done in the callback - * function associated with the clock, this function is simply a wrapper - * around that. - * - * LOCKING: - * Internally locks the driver context. - * - * RETURNS: - * Returns 0 on success or positive error code on failure. - */ int -ti_prcm_clk_valid(clk_ident_t clk) +ti_prcm_write_4(device_t dev, bus_addr_t addr, uint32_t val) { - int ret = 0; + struct ti_prcm_softc *sc; - if (ti_prcm_clk_dev(clk) == NULL) - ret = EINVAL; - - return (ret); + sc = device_get_softc(dev); + DPRINTF(sc->dev, "offset=%lx write %x\n", addr, val); + bus_space_write_4(sc->bst, sc->bsh, addr, val); + return (0); } +int +ti_prcm_read_4(device_t dev, bus_addr_t addr, uint32_t *val) +{ + struct ti_prcm_softc *sc; + sc = device_get_softc(dev); + + *val = bus_space_read_4(sc->bst, sc->bsh, addr); + DPRINTF(sc->dev, "offset=%lx Read %x\n", addr, *val); + return (0); +} -/** - * ti_prcm_clk_enable - enables a clock for a particular module - * @clk: identifier for the module to enable, see ti_prcm.h for a list - * of possible modules. - * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK. - * - * This function can enable either a functional or interface clock. - * - * The real work done to enable the clock is really done in the callback - * function associated with the clock, this function is simply a wrapper - * around that. - * - * LOCKING: - * Internally locks the driver context. - * - * RETURNS: - * Returns 0 on success or positive error code on failure. - */ int -ti_prcm_clk_enable(clk_ident_t clk) +ti_prcm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set) { - struct ti_clock_dev *clk_dev; - int ret; - - /* Find the clock within the devmap - it's a bit inefficent having a for - * loop for this, but this function should only called when a driver is - * being activated so IMHO not a big issue. - */ - clk_dev = ti_prcm_clk_dev(clk); + struct ti_prcm_softc *sc; + uint32_t reg; - /* Sanity check we managed to find the clock */ - if (clk_dev == NULL) - return (EINVAL); + sc = device_get_softc(dev); - /* Activate the clock */ - if (clk_dev->clk_activate) - ret = clk_dev->clk_activate(clk_dev); - else - ret = EINVAL; + reg = bus_space_read_4(sc->bst, sc->bsh, addr); + reg &= ~clr; + reg |= set; + bus_space_write_4(sc->bst, sc->bsh, addr, reg); + DPRINTF(sc->dev, "offset=%lx reg: %x (clr %x set %x)\n", addr, reg, clr, set); - return (ret); + return (0); } - -/** - * ti_prcm_clk_disable - disables a clock for a particular module - * @clk: identifier for the module to enable, see ti_prcm.h for a list - * of possible modules. - * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK. - * - * This function can enable either a functional or interface clock. - * - * The real work done to enable the clock is really done in the callback - * function associated with the clock, this function is simply a wrapper - * around that. - * - * LOCKING: - * Internally locks the driver context. - * - * RETURNS: - * Returns 0 on success or positive error code on failure. - */ -int -ti_prcm_clk_disable(clk_ident_t clk) +void +ti_prcm_device_lock(device_t dev) { - struct ti_clock_dev *clk_dev; - int ret; + struct ti_prcm_softc *sc; - /* Find the clock within the devmap - it's a bit inefficent having a for - * loop for this, but this function should only called when a driver is - * being activated so IMHO not a big issue. - */ - clk_dev = ti_prcm_clk_dev(clk); - - /* Sanity check we managed to find the clock */ - if (clk_dev == NULL) - return (EINVAL); - - /* Activate the clock */ - if (clk_dev->clk_deactivate) - ret = clk_dev->clk_deactivate(clk_dev); - else - ret = EINVAL; - - return (ret); + sc = device_get_softc(dev); + mtx_lock(&sc->mtx); } -/** - * ti_prcm_clk_set_source - sets the source - * @clk: identifier for the module to enable, see ti_prcm.h for a list - * of possible modules. - * Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK. - * - * This function can enable either a functional or interface clock. - * - * The real work done to enable the clock is really done in the callback - * function associated with the clock, this function is simply a wrapper - * around that. - * - * LOCKING: - * Internally locks the driver context. - * - * RETURNS: - * Returns 0 on success or positive error code on failure. - */ -int -ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc) +void +ti_prcm_device_unlock(device_t dev) { - struct ti_clock_dev *clk_dev; - int ret; + struct ti_prcm_softc *sc; - /* Find the clock within the devmap - it's a bit inefficent having a for - * loop for this, but this function should only called when a driver is - * being activated so IMHO not a big issue. - */ - clk_dev = ti_prcm_clk_dev(clk); + sc = device_get_softc(dev); + mtx_unlock(&sc->mtx); +} - /* Sanity check we managed to find the clock */ - if (clk_dev == NULL) - return (EINVAL); +static device_method_t ti_prcm_methods[] = { + DEVMETHOD(device_probe, ti_prcm_probe), + DEVMETHOD(device_attach, ti_prcm_attach), - /* Activate the clock */ - if (clk_dev->clk_set_source) - ret = clk_dev->clk_set_source(clk_dev, clksrc); - else - ret = EINVAL; + /* clkdev interface */ + DEVMETHOD(clkdev_write_4, ti_prcm_write_4), + DEVMETHOD(clkdev_read_4, ti_prcm_read_4), + DEVMETHOD(clkdev_modify_4, ti_prcm_modify_4), + DEVMETHOD(clkdev_device_lock, ti_prcm_device_lock), + DEVMETHOD(clkdev_device_unlock, ti_prcm_device_unlock), - return (ret); -} + DEVMETHOD_END +}; +DEFINE_CLASS_1(ti_prcm, ti_prcm_driver, ti_prcm_methods, + sizeof(struct ti_prcm_softc), simplebus_driver); -/** - * ti_prcm_clk_get_source_freq - gets the source clock frequency - * @clk: identifier for the module to enable, see ti_prcm.h for a list - * of possible modules. - * @freq: pointer to an integer that upon return will contain the src freq - * - * This function returns the frequency of the source clock. - * - * The real work done to enable the clock is really done in the callback - * function associated with the clock, this function is simply a wrapper - * around that. - * - * LOCKING: - * Internally locks the driver context. - * - * RETURNS: - * Returns 0 on success or positive error code on failure. - */ -int -ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq) -{ - struct ti_clock_dev *clk_dev; - int ret; +static devclass_t ti_prcm_devclass; - /* Find the clock within the devmap - it's a bit inefficent having a for - * loop for this, but this function should only called when a driver is - * being activated so IMHO not a big issue. - */ - clk_dev = ti_prcm_clk_dev(clk); +EARLY_DRIVER_MODULE(ti_prcm, ofwbus, ti_prcm_driver, + ti_prcm_devclass, 0, 0, BUS_PASS_BUS); +EARLY_DRIVER_MODULE(ti_prcm, simplebus, ti_prcm_driver, + ti_prcm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +MODULE_VERSION(ti_prcm, 1); +MODULE_DEPEND(ti_prcm, ti_scm, 1, 1, 1); - /* Sanity check we managed to find the clock */ - if (clk_dev == NULL) - return (EINVAL); - /* Get the source frequency of the clock */ - if (clk_dev->clk_get_source_freq) - ret = clk_dev->clk_get_source_freq(clk_dev, freq); - else - ret = EINVAL; +/* From sys/arm/ti/am335x/am335x_prcm.c + * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org> + */ +#define PRM_DEVICE_OFFSET 0xF00 +#define AM335x_PRM_RSTCTRL (PRM_DEVICE_OFFSET + 0x00) - return (ret); +static void +am335x_prcm_reset(void) +{ + ti_prcm_write_4(ti_prcm_sc->dev, AM335x_PRM_RSTCTRL, (1<<1)); } -/** - * ti_prcm_clk_set_source_freq - sets the source clock frequency as close to freq as possible - * @clk: identifier for the module to enable, see ti_prcm.h for a list - * of possible modules. - * @freq: requested freq +/* FIXME: Is this correct - or should the license part be ontop? */ + +/* From sys/arm/ti/omap4/omap4_prcm_clks.c */ +/*- + * SPDX-License-Identifier: BSD-3-Clause * - * LOCKING: - * Internally locks the driver context. + * Copyright (c) 2011 + * Ben Gray <ben.r.gray@gmail.com>. + * All rights reserved. * - * RETURNS: - * Returns 0 on success or positive error code on failure. + * 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. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``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 BEN GRAY 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. */ -int -ti_prcm_clk_set_source_freq(clk_ident_t clk, unsigned int freq) -{ - struct ti_clock_dev *clk_dev; - int ret; +#define PRM_RSTCTRL 0x1b00 +#define PRM_RSTCTRL_RESET 0x2 - clk_dev = ti_prcm_clk_dev(clk); - - /* Sanity check we managed to find the clock */ - if (clk_dev == NULL) - return (EINVAL); - - /* Get the source frequency of the clock */ - if (clk_dev->clk_set_source_freq) - ret = clk_dev->clk_set_source_freq(clk_dev, freq); - else - ret = EINVAL; +static void +omap4_prcm_reset(void) +{ + uint32_t reg; - return (ret); + ti_prcm_read_4(ti_prcm_sc->dev, PRM_RSTCTRL, ®); + reg = reg | PRM_RSTCTRL_RESET; + ti_prcm_write_4(ti_prcm_sc->dev, PRM_RSTCTRL, reg); + ti_prcm_read_4(ti_prcm_sc->dev, PRM_RSTCTRL, ®); } diff --git a/sys/arm/ti/ti_prcm.h b/sys/arm/ti/ti_prcm.h index 6df39436cb2f..98f8abc15dd7 100644 --- a/sys/arm/ti/ti_prcm.h +++ b/sys/arm/ti/ti_prcm.h @@ -1,9 +1,7 @@ /*- - * SPDX-License-Identifier: BSD-4-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2010 - * Ben Gray <ben.r.gray@gmail.com>. - * All rights reserved. + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -13,197 +11,29 @@ * 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 Ben Gray. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. * - * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR + * 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 BEN GRAY 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. + * 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 __TI_PRCM_H__ +#define __TI_PRCM_H__ -/* - * Texas Instruments - OMAP3xxx series processors - * - * Reference: - * OMAP35x Applications Processor - * Technical Reference Manual - * (omap35xx_techref.pdf) - */ -#ifndef _TI_PRCM_H_ -#define _TI_PRCM_H_ - -typedef enum { - - INVALID_CLK_IDENT = 0, - - /* System clocks, typically you can only call ti_prcm_clk_get_source_freq() - * on these clocks as they are enabled by default. - */ - SYS_CLK = 1, - - /* The MPU (ARM) core clock */ - MPU_CLK = 20, - - /* MMC modules */ - MMC1_CLK = 100, - MMC2_CLK, - MMC3_CLK, - MMC4_CLK, - MMC5_CLK, - MMC6_CLK, - - /* I2C modules */ - I2C1_CLK = 200, - I2C2_CLK, - I2C3_CLK, - I2C4_CLK, - I2C5_CLK, - - /* USB module(s) */ - USBTLL_CLK = 300, - USBHSHOST_CLK, - USBFSHOST_CLK, - USBP1_PHY_CLK, - USBP2_PHY_CLK, - USBP1_UTMI_CLK, - USBP2_UTMI_CLK, - USBP1_HSIC_CLK, - USBP2_HSIC_CLK, - - /* UART modules */ - UART1_CLK = 400, - UART2_CLK, - UART3_CLK, - UART4_CLK, - UART5_CLK, - UART6_CLK, - UART7_CLK, - UART8_CLK, - UART9_CLK, - - /* General purpose timer modules */ - TIMER1_CLK = 500, - TIMER2_CLK, - TIMER3_CLK, - TIMER4_CLK, - TIMER5_CLK, - TIMER6_CLK, - TIMER7_CLK, - TIMER8_CLK, - TIMER9_CLK, - TIMER10_CLK, - TIMER11_CLK, - TIMER12_CLK, - - /* McBSP module(s) */ - MCBSP1_CLK = 600, - MCBSP2_CLK, - MCBSP3_CLK, - MCBSP4_CLK, - MCBSP5_CLK, - - /* General purpose I/O modules */ - GPIO1_CLK = 700, - GPIO2_CLK, - GPIO3_CLK, - GPIO4_CLK, - GPIO5_CLK, - GPIO6_CLK, - GPIO7_CLK, - - /* sDMA module */ - SDMA_CLK = 800, - - /* CPSW modules */ - CPSW_CLK = 1000, - - /* Mentor USB modules */ - MUSB0_CLK = 1100, - - /* EDMA module */ - EDMA_TPCC_CLK = 1200, - EDMA_TPTC0_CLK, - EDMA_TPTC1_CLK, - EDMA_TPTC2_CLK, - - /* LCD controller module */ - LCDC_CLK = 1300, - - /* PWM modules */ - PWMSS0_CLK = 1400, - PWMSS1_CLK, - PWMSS2_CLK, - - /* Mailbox modules */ - MAILBOX0_CLK = 1500, - - /* Spinlock modules */ - SPINLOCK0_CLK = 1600, - - PRUSS_CLK = 1700, - - TSC_ADC_CLK = 1800, - - /* RTC module */ - RTC_CLK = 1900, - - /* McSPI */ - SPI0_CLK = 2000, - SPI1_CLK, -} clk_ident_t; - -/* - * - */ -typedef enum { - SYSCLK_CLK, /* System clock */ - EXT_CLK, - - F32KHZ_CLK, /* 32KHz clock */ - F48MHZ_CLK, /* 48MHz clock */ - F64MHZ_CLK, /* 64MHz clock */ - F96MHZ_CLK, /* 96MHz clock */ - -} clk_src_t; - -struct ti_clock_dev { - /* The profile of the timer */ - clk_ident_t id; - - /* A bunch of callbacks associated with the clock device */ - int (*clk_activate)(struct ti_clock_dev *clkdev); - int (*clk_deactivate)(struct ti_clock_dev *clkdev); - int (*clk_set_source)(struct ti_clock_dev *clkdev, - clk_src_t clksrc); - int (*clk_accessible)(struct ti_clock_dev *clkdev); - int (*clk_set_source_freq)(struct ti_clock_dev *clkdev, - unsigned int freq); - int (*clk_get_source_freq)(struct ti_clock_dev *clkdev, - unsigned int *freq); -}; - -int ti_prcm_clk_valid(clk_ident_t clk); -int ti_prcm_clk_enable(clk_ident_t clk); -int ti_prcm_clk_disable(clk_ident_t clk); -int ti_prcm_clk_accessible(clk_ident_t clk); -int ti_prcm_clk_disable_autoidle(clk_ident_t clk); -int ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc); -int ti_prcm_clk_set_source_freq(clk_ident_t clk, unsigned int freq); -int ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq); -void ti_prcm_reset(void); +int ti_prcm_write_4(device_t dev, bus_addr_t addr, uint32_t val); +int ti_prcm_read_4(device_t dev, bus_addr_t addr, uint32_t *val); +int ti_prcm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set); +void ti_prcm_device_lock(device_t dev); +void ti_prcm_device_unlock(device_t dev); -#endif /* _TI_PRCM_H_ */ +#endif diff --git a/sys/arm/ti/ti_prm.c b/sys/arm/ti/ti_prm.c new file mode 100644 index 000000000000..4a57fbb8b972 --- /dev/null +++ b/sys/arm/ti/ti_prm.c @@ -0,0 +1,210 @@ +/*- + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +/* + * Power management - simple driver to handle reset and give access to + * memory space region for other drivers through prcm driver. + * Documentation/devicetree/binding/arm/omap/prm-inst.txt + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> + +#include <dev/fdt/simplebus.h> + +#include <dev/ofw/ofw_bus_subr.h> + +#include <arm/ti/ti_prcm.h> +#include <arm/ti/ti_prm.h> + +#if 0 +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +/* relative to prcm address range */ +#define TI_PRM_PER_RSTCTRL 0xC00 + +struct ti_prm_softc { + device_t dev; + uint8_t type; + bool has_reset; +}; + +/* Device */ +#define TI_OMAP_PRM_INST 10 + +#define TI_AM3_PRM_INST 5 +#define TI_AM4_PRM_INST 4 +#define TI_OMAP4_PRM_INST 3 +#define TI_OMAP5_PRM_INST 2 +#define TI_DRA7_PRM_INST 1 +#define TI_END 0 + +static struct ofw_compat_data compat_data[] = { + { "ti,am3-prm-inst", TI_AM3_PRM_INST }, + { "ti,am4-prm-inst", TI_AM4_PRM_INST }, + { "ti,omap4-prm-inst", TI_OMAP4_PRM_INST }, + { "ti,omap5-prm-inst", TI_OMAP5_PRM_INST }, + { "ti,dra7-prm-inst", TI_DRA7_PRM_INST }, + { NULL, TI_END } +}; + +static struct ofw_compat_data required_data[] = { + { "ti,omap-prm-inst", TI_OMAP_PRM_INST }, + { NULL, TI_END } +}; + +/* device interface */ +static int +ti_prm_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, required_data)->ocd_data == 0) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "TI OMAP Power Management"); + return(BUS_PROBE_DEFAULT); +} + +static int +ti_prm_attach(device_t dev) +{ + struct ti_prm_softc *sc; + phandle_t node; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; + + node = ofw_bus_get_node(sc->dev); + + if (OF_hasprop(node, "#reset-cells")) { + sc->has_reset = true; + } else + sc->has_reset = false; + + /* Make device visible for other drivers */ + OF_device_register_xref(OF_xref_from_node(node), sc->dev); + + return (0); +} + +static int +ti_prm_detach(device_t dev) { + return (EBUSY); +} + +int +ti_prm_reset(device_t dev) +{ + struct ti_prm_softc *sc; + int err; + + sc = device_get_softc(dev); + if (sc->has_reset == false) + return 1; + + err = ti_prm_modify_4(dev, TI_PRM_PER_RSTCTRL, 0x2, 0x00); + return (err); +} + +int +ti_prm_write_4(device_t dev, bus_addr_t addr, uint32_t val) +{ + struct ti_prm_softc *sc; + device_t parent; + + parent = device_get_parent(dev); + sc = device_get_softc(dev); + DPRINTF(sc->dev, "offset=%lx write %x\n", addr, val); + ti_prcm_device_lock(parent); + ti_prcm_write_4(parent, addr, val); + ti_prcm_device_unlock(parent); + return (0); +} + +int +ti_prm_read_4(device_t dev, bus_addr_t addr, uint32_t *val) +{ + struct ti_prm_softc *sc; + device_t parent; + + parent = device_get_parent(dev); + sc = device_get_softc(dev); + + ti_prcm_device_lock(parent); + ti_prcm_read_4(parent, addr, val); + ti_prcm_device_unlock(parent); + DPRINTF(sc->dev, "offset=%lx Read %x\n", addr, *val); + return (0); +} + +int +ti_prm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set) +{ + struct ti_prm_softc *sc; + device_t parent; + + parent = device_get_parent(dev); + sc = device_get_softc(dev); + + ti_prcm_device_lock(parent); + ti_prcm_modify_4(parent, addr, clr, set); + ti_prcm_device_unlock(parent); + DPRINTF(sc->dev, "offset=%lx (clr %x set %x)\n", addr, clr, set); + + return (0); +} + +static device_method_t ti_prm_methods[] = { + DEVMETHOD(device_probe, ti_prm_probe), + DEVMETHOD(device_attach, ti_prm_attach), + DEVMETHOD(device_detach, ti_prm_detach), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(ti_prm, ti_prm_driver, ti_prm_methods, + sizeof(struct ti_prm_softc), simplebus_driver); + +static devclass_t ti_prm_devclass; + +EARLY_DRIVER_MODULE(ti_prm, simplebus, ti_prm_driver, + ti_prm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +MODULE_VERSION(ti_prm, 1); +MODULE_DEPEND(ti_prm, ti_sysc, 1, 1, 1); diff --git a/sys/arm/ti/ti_prm.h b/sys/arm/ti/ti_prm.h new file mode 100644 index 000000000000..bc3e991088f0 --- /dev/null +++ b/sys/arm/ti/ti_prm.h @@ -0,0 +1,38 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __TI_PRM__ +#define __TI_PRM__ + +int ti_prm_reset(device_t dev); + +int ti_prm_write_4(device_t dev, bus_addr_t addr, uint32_t val); +int ti_prm_read_4(device_t dev, bus_addr_t addr, uint32_t *val); +int ti_prm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set); + +#endif /* __TI_PRM__ */ diff --git a/sys/arm/ti/ti_pruss.c b/sys/arm/ti/ti_pruss.c index 48c6b17f3ac8..a8dc15ab80b0 100644 --- a/sys/arm/ti/ti_pruss.c +++ b/sys/arm/ti/ti_pruss.c @@ -57,8 +57,11 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> -#include <arm/ti/ti_prcm.h> +#include <dev/extres/clk/clk.h> + +#include <arm/ti/ti_sysc.h> #include <arm/ti/ti_pruss.h> +#include <arm/ti/ti_prm.h> #ifdef DEBUG #define DPRINTF(fmt, ...) do { \ @@ -161,7 +164,8 @@ static driver_t ti_pruss_driver = { static devclass_t ti_pruss_devclass; DRIVER_MODULE(ti_pruss, simplebus, ti_pruss_driver, ti_pruss_devclass, 0, 0); -MODULE_DEPEND(ti_pruss, ti_prcm, 1, 1, 1); +MODULE_DEPEND(ti_pruss, ti_sysc, 1, 1, 1); +MODULE_DEPEND(ti_pruss, ti_prm, 1, 1, 1); static struct resource_spec ti_pruss_irq_spec[] = { { SYS_RES_IRQ, 0, RF_ACTIVE }, @@ -515,14 +519,89 @@ static int ti_pruss_attach(device_t dev) { struct ti_pruss_softc *sc; - int rid, i; + int rid, i, err, ncells; + uint32_t reg; + phandle_t node; + clk_t l3_gclk, pruss_ocp_gclk; + phandle_t ti_prm_ref, *cells; + device_t ti_prm_dev; - if (ti_prcm_clk_enable(PRUSS_CLK) != 0) { - device_printf(dev, "could not enable PRUSS clock\n"); + rid = 0; + sc = device_get_softc(dev); + node = ofw_bus_get_node(device_get_parent(dev)); + if (node <= 0) { + device_printf(dev, "Cant get ofw node\n"); return (ENXIO); } - sc = device_get_softc(dev); - rid = 0; + + /* + * Follow activate pattern from sys/arm/ti/am335x/am335x_prcm.c + * by Damjan Marion + */ + + /* Set MODULEMODE to ENABLE(2) */ + /* Wait for MODULEMODE to become ENABLE(2) */ + if (ti_sysc_clock_enable(device_get_parent(dev)) != 0) { + device_printf(dev, "Could not enable PRUSS clock\n"); + return (ENXIO); + } + + /* Set CLKTRCTRL to SW_WKUP(2) */ + /* Wait for the 200 MHz OCP clock to become active */ + /* Wait for the 200 MHz IEP clock to become active */ + /* Wait for the 192 MHz UART clock to become active */ + /* + * At the moment there is no reference to CM_PER_PRU_ICSS_CLKSTCTRL@140 + * in the devicetree. The register reset state are SW_WKUP(2) as default + * so at the moment ignore setting this register. + */ + + /* Select L3F as OCP clock */ + /* Get the clock and set the parent */ + err = clk_get_by_name(dev, "l3_gclk", &l3_gclk); + if (err) { + device_printf(dev, "Cant get l3_gclk err %d\n", err); + return (ENXIO); + } + + err = clk_get_by_name(dev, "pruss_ocp_gclk@530", &pruss_ocp_gclk); + if (err) { + device_printf(dev, "Cant get pruss_ocp_gclk@530 err %d\n", err); + return (ENXIO); + } + + err = clk_set_parent_by_clk(pruss_ocp_gclk, l3_gclk); + if (err) { + device_printf(dev, + "Cant set pruss_ocp_gclk parent to l3_gclk err %d\n", err); + return (ENXIO); + } + + /* Clear the RESET bit */ + /* Find the ti_prm */ + /* #reset-cells should not been used in this way but... */ + err = ofw_bus_parse_xref_list_alloc(node, "resets", "#reset-cells", 0, + &ti_prm_ref, &ncells, &cells); + OF_prop_free(cells); + if (err) { + device_printf(dev, + "Cant fetch \"resets\" reference %x\n", err); + return (ENXIO); + } + + ti_prm_dev = OF_device_from_xref(ti_prm_ref); + if (ti_prm_dev == NULL) { + device_printf(dev, "Cant get device from \"resets\"\n"); + return (ENXIO); + } + + err = ti_prm_reset(ti_prm_dev); + if (err) { + device_printf(dev, "ti_prm_reset failed %d\n", err); + return (ENXIO); + } + /* End of clock activation */ + mtx_init(&sc->sc_mtx, "TI PRUSS", NULL, MTX_DEF); sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); @@ -602,6 +681,9 @@ ti_pruss_attach(device_t dev) } } + reg = ti_pruss_reg_read(sc, + ti_sysc_get_sysc_address_offset_host(device_get_parent(dev))); + if (ti_pruss_reg_read(sc, PRUSS_AM33XX_INTC) == PRUSS_AM33XX_REV) device_printf(dev, "AM33xx PRU-ICSS\n"); diff --git a/sys/arm/ti/ti_scm.c b/sys/arm/ti/ti_scm.c index fbc87eeb4f92..896a8d09cbf3 100644 --- a/sys/arm/ti/ti_scm.c +++ b/sys/arm/ti/ti_scm.c @@ -1,9 +1,7 @@ /*- - * SPDX-License-Identifier: BSD-4-Clause + * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org> * - * Copyright (c) 2010 - * Ben Gray <ben.r.gray@gmail.com>. - * All rights reserved. + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -13,169 +11,152 @@ * 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 Ben Gray. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. * - * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR + * 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 BEN GRAY 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. - */ - -/** - * SCM - System Control Module - * - * Hopefully in the end this module will contain a bunch of utility functions - * for configuring and querying the general system control registers, but for - * now it only does pin(pad) multiplexing. - * - * This is different from the GPIO module in that it is used to configure the - * pins between modules not just GPIO input/output. - * - * This file contains the generic top level driver, however it relies on chip - * specific settings and therefore expects an array of ti_scm_padconf structs - * call ti_padconf_devmap to be located somewhere in the kernel. + * 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$ */ + #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); + +/* Based on sys/arm/ti/ti_sysc.c */ + #include <sys/param.h> #include <sys/systm.h> +#include <sys/bus.h> +#include <sys/fbio.h> #include <sys/kernel.h> #include <sys/module.h> -#include <sys/bus.h> -#include <sys/resource.h> #include <sys/rman.h> -#include <sys/lock.h> -#include <sys/mutex.h> - +#include <sys/resource.h> #include <machine/bus.h> -#include <machine/resource.h> +#include <vm/vm.h> +#include <vm/vm_extern.h> +#include <vm/vm_kern.h> +#include <vm/pmap.h> + +#include <dev/fdt/simplebus.h> -#include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> -#include <dev/fdt/fdt_pinctrl.h> - -#include "ti_scm.h" -#include "ti_cpuid.h" -static struct resource_spec ti_scm_res_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Control memory window */ - { -1, 0 } +#define TI_AM3_SCM 14 +#define TI_AM4_SCM 13 +#define TI_DM814_SCRM 12 +#define TI_DM816_SCRM 11 +#define TI_OMAP2_SCM 10 +#define TI_OMAP3_SCM 9 +#define TI_OMAP4_SCM_CORE 8 +#define TI_OMAP4_SCM_PADCONF_CORE 7 +#define TI_OMAP4_SCM_WKUP 6 +#define TI_OMAP4_SCM_PADCONF_WKUP 5 +#define TI_OMAP5_SCM_CORE 4 +#define TI_OMAP5_SCM_PADCONF_CORE 3 +#define TI_OMAP5_SCM_WKUP_PAD_CONF 2 +#define TI_DRA7_SCM_CORE 1 +#define TI_SCM_END 0 + +static struct ofw_compat_data compat_data[] = { + { "ti,am3-scm", TI_AM3_SCM }, + { "ti,am4-scm", TI_AM4_SCM }, + { "ti,dm814-scrm", TI_DM814_SCRM }, + { "ti,dm816-scrm", TI_DM816_SCRM }, + { "ti,omap2-scm", TI_OMAP2_SCM }, + { "ti,omap3-scm", TI_OMAP3_SCM }, + { "ti,omap4-scm-core", TI_OMAP4_SCM_CORE }, + { "ti,omap4-scm-padconf-core", TI_OMAP4_SCM_PADCONF_CORE }, + { "ti,omap4-scm-wkup", TI_OMAP4_SCM_WKUP }, + { "ti,omap4-scm-padconf-wkup", TI_OMAP4_SCM_PADCONF_WKUP }, + { "ti,omap5-scm-core", TI_OMAP5_SCM_CORE }, + { "ti,omap5-scm-padconf-core", TI_OMAP5_SCM_PADCONF_CORE }, + { "ti,omap5-scm-wkup-pad-conf", TI_OMAP5_SCM_WKUP_PAD_CONF }, + { "ti,dra7-scm-core", TI_DRA7_SCM_CORE }, + { NULL, TI_SCM_END } }; -static struct ti_scm_softc *ti_scm_sc; +struct ti_scm_softc { + struct simplebus_softc sc; + device_t dev; +}; -#define ti_scm_read_4(sc, reg) \ - bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) -#define ti_scm_write_4(sc, reg, val) \ - bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) +static int ti_scm_probe(device_t dev); +static int ti_scm_attach(device_t dev); +static int ti_scm_detach(device_t dev); -/* - * Device part of OMAP SCM driver - */ static int ti_scm_probe(device_t dev) { - - if (!ti_soc_is_supported()) - return (ENXIO); - if (!ofw_bus_status_okay(dev)) return (ENXIO); - if (!ofw_bus_is_compatible(dev, "syscon")) + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); - if (ti_scm_sc) { - return (EEXIST); - } + device_set_desc(dev, "TI OMAP Control Module"); - device_set_desc(dev, "TI Control Module"); return (BUS_PROBE_DEFAULT); } -/** - * ti_scm_attach - attaches the timer to the simplebus - * @dev: new device - * - * Reserves memory and interrupt resources, stores the softc structure - * globally and registers both the timecount and eventtimer objects. - * - * RETURNS - * Zero on success or ENXIO if an error occuried. - */ static int ti_scm_attach(device_t dev) { - struct ti_scm_softc *sc = device_get_softc(dev); + struct ti_scm_softc *sc; + device_t cdev; + phandle_t node, child; - sc->sc_dev = dev; + sc = device_get_softc(dev); + sc->dev = dev; + node = ofw_bus_get_node(dev); - if (bus_alloc_resources(dev, ti_scm_res_spec, sc->sc_res)) { - device_printf(dev, "could not allocate resources\n"); + simplebus_init(dev, node); + if (simplebus_fill_ranges(node, &sc->sc) < 0) { + device_printf(dev, "could not get ranges\n"); return (ENXIO); } - /* Global timer interface */ - sc->sc_bst = rman_get_bustag(sc->sc_res[0]); - sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]); - - ti_scm_sc = sc; - - /* Attach platform extensions, if any. */ - bus_generic_probe(dev); + for (child = OF_child(node); child > 0; child = OF_peer(child)) { + cdev = simplebus_add_device(dev, child, 0, NULL, -1, NULL); + if (cdev != NULL) + device_probe_and_attach(cdev); + } return (bus_generic_attach(dev)); } -int -ti_scm_reg_read_4(uint32_t reg, uint32_t *val) -{ - if (!ti_scm_sc) - return (ENXIO); - - *val = ti_scm_read_4(ti_scm_sc, reg); - return (0); -} - -int -ti_scm_reg_write_4(uint32_t reg, uint32_t val) +static int +ti_scm_detach(device_t dev) { - if (!ti_scm_sc) - return (ENXIO); - - ti_scm_write_4(ti_scm_sc, reg, val); - return (0); + return (EBUSY); } - static device_method_t ti_scm_methods[] = { + /* Device interface */ DEVMETHOD(device_probe, ti_scm_probe), DEVMETHOD(device_attach, ti_scm_attach), + DEVMETHOD(device_detach, ti_scm_detach), - { 0, 0 } + DEVMETHOD_END }; -static driver_t ti_scm_driver = { - "ti_scm", - ti_scm_methods, - sizeof(struct ti_scm_softc), -}; +DEFINE_CLASS_1(ti_scm, ti_scm_driver, ti_scm_methods, + sizeof(struct ti_scm_softc), simplebus_driver); static devclass_t ti_scm_devclass; -EARLY_DRIVER_MODULE(ti_scm, simplebus, ti_scm_driver, ti_scm_devclass, 0, 0, - BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +EARLY_DRIVER_MODULE(ti_scm, simplebus, ti_scm_driver, + ti_scm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST); +MODULE_VERSION(ti_scm, 1); +MODULE_DEPEND(ti_scm, ti_sysc, 1, 1, 1); + diff --git a/sys/arm/ti/ti_scm_syscon.c b/sys/arm/ti/ti_scm_syscon.c new file mode 100644 index 000000000000..2c3fa9345210 --- /dev/null +++ b/sys/arm/ti/ti_scm_syscon.c @@ -0,0 +1,294 @@ +/*- + * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org> + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +/* Based on sys/arm/ti/ti_sysc.c */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/resource.h> +#include <sys/rman.h> +#include <sys/lock.h> +#include <sys/mutex.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#include <dev/fdt/simplebus.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include "syscon_if.h" +#include <dev/extres/syscon/syscon.h> +#include "clkdev_if.h" + +#if 0 +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +MALLOC_DECLARE(M_SYSCON); + +struct ti_scm_syscon_softc { + struct simplebus_softc sc_simplebus; + device_t dev; + struct syscon * syscon; + struct resource * res[1]; + bus_space_tag_t bst; + bus_space_handle_t bsh; + struct mtx mtx; +}; + +static struct resource_spec ti_scm_syscon_res_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE }, + { -1, 0 } +}; + +/* Device */ +static struct ofw_compat_data compat_data[] = { + { "syscon", 1 }, + { NULL, 0 } +}; + +/* --- dev/extres/syscon syscon_method_t interface --- */ +static int +ti_scm_syscon_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val) +{ + struct ti_scm_syscon_softc *sc; + + sc = device_get_softc(syscon->pdev); + DPRINTF(sc->dev, "offset=%lx write %x\n", offset, val); + mtx_lock(&sc->mtx); + bus_space_write_4(sc->bst, sc->bsh, offset, val); + mtx_unlock(&sc->mtx); + return (0); +} + +static uint32_t +ti_scm_syscon_read_4(struct syscon *syscon, bus_size_t offset) +{ + struct ti_scm_syscon_softc *sc; + uint32_t val; + + sc = device_get_softc(syscon->pdev); + + mtx_lock(&sc->mtx); + val = bus_space_read_4(sc->bst, sc->bsh, offset); + mtx_unlock(&sc->mtx); + DPRINTF(sc->dev, "offset=%lx Read %x\n", offset, val); + return (val); +} +static int +ti_scm_syscon_modify_4(struct syscon *syscon, bus_size_t offset, uint32_t clr, uint32_t set) +{ + struct ti_scm_syscon_softc *sc; + uint32_t reg; + + sc = device_get_softc(syscon->pdev); + + mtx_lock(&sc->mtx); + reg = bus_space_read_4(sc->bst, sc->bsh, offset); + reg &= ~clr; + reg |= set; + bus_space_write_4(sc->bst, sc->bsh, offset, reg); + mtx_unlock(&sc->mtx); + DPRINTF(sc->dev, "offset=%lx reg: %x (clr %x set %x)\n", offset, reg, clr, set); + + return (0); +} + +static syscon_method_t ti_scm_syscon_reg_methods[] = { + SYSCONMETHOD(syscon_read_4, ti_scm_syscon_read_4), + SYSCONMETHOD(syscon_write_4, ti_scm_syscon_write_4), + SYSCONMETHOD(syscon_modify_4, ti_scm_syscon_modify_4), + + SYSCONMETHOD_END +}; + +DEFINE_CLASS_1(ti_scm_syscon_reg, ti_scm_syscon_reg_class, ti_scm_syscon_reg_methods, + 0, syscon_class); + +/* device interface */ +static int +ti_scm_syscon_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "TI OMAP Control Module Syscon"); + return(BUS_PROBE_DEFAULT); +} + +static int +ti_scm_syscon_attach(device_t dev) +{ + struct ti_scm_syscon_softc *sc; + phandle_t node, child; + int err; + + sc = device_get_softc(dev); + sc->dev = dev; + + if (bus_alloc_resources(dev, ti_scm_syscon_res_spec, sc->res)) { + device_printf(sc->dev, "Cant allocate resources\n"); + return (ENXIO); + } + + sc->dev = dev; + sc->bst = rman_get_bustag(sc->res[0]); + sc->bsh = rman_get_bushandle(sc->res[0]); + + mtx_init(&sc->mtx, device_get_nameunit(sc->dev), NULL, MTX_DEF); + node = ofw_bus_get_node(sc->dev); + + /* dev/extres/syscon interface */ + sc->syscon = syscon_create_ofw_node(dev, &ti_scm_syscon_reg_class, node); + if (sc->syscon == NULL) { + device_printf(dev, "Failed to create/register syscon\n"); + return (ENXIO); + } + + simplebus_init(sc->dev, node); + + err = bus_generic_probe(sc->dev); + for (child = OF_child(node); child != 0; child = OF_peer(child)) { + simplebus_add_device(sc->dev, child, 0, NULL, -1, NULL); + } + + return (bus_generic_attach(sc->dev)); +} + +/* syscon interface */ +static int +ti_scm_syscon_get_handle(device_t dev, struct syscon **syscon) +{ + struct ti_scm_syscon_softc *sc; + + sc = device_get_softc(dev); + *syscon = sc->syscon; + if (*syscon == NULL) + return (ENODEV); + return (0); +} + +/* clkdev interface */ +static int +ti_scm_syscon_clk_write_4(device_t dev, bus_addr_t addr, uint32_t val) +{ + struct ti_scm_syscon_softc *sc; + + sc = device_get_softc(dev); + DPRINTF(sc->dev, "offset=%lx write %x\n", addr, val); + bus_space_write_4(sc->bst, sc->bsh, addr, val); + return (0); +} + +static int +ti_scm_syscon_clk_read_4(device_t dev, bus_addr_t addr, uint32_t *val) +{ + struct ti_scm_syscon_softc *sc; + + sc = device_get_softc(dev); + + *val = bus_space_read_4(sc->bst, sc->bsh, addr); + DPRINTF(sc->dev, "offset=%lx Read %x\n", addr, *val); + return (0); +} + +static int +ti_scm_syscon_clk_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set) +{ + struct ti_scm_syscon_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + reg = bus_space_read_4(sc->bst, sc->bsh, addr); + reg &= ~clr; + reg |= set; + bus_space_write_4(sc->bst, sc->bsh, addr, reg); + DPRINTF(sc->dev, "offset=%lx reg: %x (clr %x set %x)\n", addr, reg, clr, set); + + return (0); +} + +static void +ti_scm_syscon_clk_device_lock(device_t dev) +{ + struct ti_scm_syscon_softc *sc; + + sc = device_get_softc(dev); + mtx_lock(&sc->mtx); +} + +static void +ti_scm_syscon_clk_device_unlock(device_t dev) +{ + struct ti_scm_syscon_softc *sc; + sc = device_get_softc(dev); + mtx_unlock(&sc->mtx); +} + +static device_method_t ti_scm_syscon_methods[] = { + DEVMETHOD(device_probe, ti_scm_syscon_probe), + DEVMETHOD(device_attach, ti_scm_syscon_attach), + + /* syscon interface */ + DEVMETHOD(syscon_get_handle, ti_scm_syscon_get_handle), + + /* clkdev interface */ + DEVMETHOD(clkdev_write_4, ti_scm_syscon_clk_write_4), + DEVMETHOD(clkdev_read_4, ti_scm_syscon_clk_read_4), + DEVMETHOD(clkdev_modify_4, ti_scm_syscon_clk_modify_4), + DEVMETHOD(clkdev_device_lock, ti_scm_syscon_clk_device_lock), + DEVMETHOD(clkdev_device_unlock, ti_scm_syscon_clk_device_unlock), + + DEVMETHOD_END +}; + + +DEFINE_CLASS_1(ti_scm_syscon, ti_scm_syscon_driver, ti_scm_syscon_methods, + sizeof(struct ti_scm_syscon_softc), simplebus_driver); + +static devclass_t ti_scm_syscon_devclass; + +EARLY_DRIVER_MODULE(ti_scm_syscon, simplebus, ti_scm_syscon_driver, + ti_scm_syscon_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); +MODULE_VERSION(ti_scm_syscon, 1); +MODULE_DEPEND(ti_scm_syscon, ti_scm, 1, 1, 1); diff --git a/sys/arm/ti/ti_sdhci.c b/sys/arm/ti/ti_sdhci.c index a76453d92588..4d19f4663d2f 100644 --- a/sys/arm/ti/ti_sdhci.c +++ b/sys/arm/ti/ti_sdhci.c @@ -44,10 +44,11 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/mutex.h> -#include <machine/bus.h> -#include <machine/resource.h> -#include <machine/intr.h> +#include <arm/ti/ti_cpuid.h> +#include <arm/ti/ti_sysc.h> +#include "gpio_if.h" +#include <dev/extres/clk/clk.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> @@ -59,10 +60,10 @@ __FBSDID("$FreeBSD$"); #include <dev/sdhci/sdhci_fdt_gpio.h> #include "sdhci_if.h" -#include <arm/ti/ti_cpuid.h> -#include <arm/ti/ti_prcm.h> -#include <arm/ti/ti_hwmods.h> -#include "gpio_if.h" +#include <machine/bus.h> +#include <machine/resource.h> +#include <machine/intr.h> + #include "opt_mmccam.h" @@ -73,10 +74,9 @@ struct ti_sdhci_softc { struct resource * irq_res; void * intr_cookie; struct sdhci_slot slot; - clk_ident_t mmchs_clk_id; uint32_t mmchs_reg_off; uint32_t sdhci_reg_off; - uint32_t baseclk_hz; + uint64_t baseclk_hz; uint32_t cmd_and_mode; uint32_t sdhci_clkdiv; boolean_t disable_highspeed; @@ -414,24 +414,32 @@ ti_sdhci_detach(device_t dev) return (EBUSY); } -static void +static int ti_sdhci_hw_init(device_t dev) { struct ti_sdhci_softc *sc = device_get_softc(dev); uint32_t regval; unsigned long timeout; + clk_t mmc_clk; + int err; /* Enable the controller and interface/functional clocks */ - if (ti_prcm_clk_enable(sc->mmchs_clk_id) != 0) { + if (ti_sysc_clock_enable(device_get_parent(dev)) != 0) { device_printf(dev, "Error: failed to enable MMC clock\n"); - return; + return (ENXIO); } - /* Get the frequency of the source clock */ - if (ti_prcm_clk_get_source_freq(sc->mmchs_clk_id, - &sc->baseclk_hz) != 0) { - device_printf(dev, "Error: failed to get source clock freq\n"); - return; + /* FIXME: Devicetree dosent have any reference to mmc_clk */ + err = clk_get_by_name(dev, "mmc_clk", &mmc_clk); + if (err) { + device_printf(dev, "Can not find mmc_clk\n"); + return (ENXIO); + } + err = clk_get_freq(mmc_clk, &sc->baseclk_hz); + if (err) { + device_printf(dev, "Cant get mmc_clk frequency\n"); + /* AM335x TRM 8.1.6.8 table 8-24 96MHz @ OPP100 */ + sc->baseclk_hz = 96000000; } /* Issue a softreset to the controller */ @@ -499,6 +507,8 @@ ti_sdhci_hw_init(device_t dev) /* Set the initial controller configuration. */ ti_mmchs_write_4(sc, MMCHS_CON, MMCHS_CON_DVAL_8_4MS); + + return (0); } static int @@ -512,16 +522,9 @@ ti_sdhci_attach(device_t dev) sc->dev = dev; /* - * Get the MMCHS device id from FDT. If it's not there use the newbus - * unit number (which will work as long as the devices are in order and - * none are skipped in the fdt). Note that this is a property we made - * up and added in freebsd, it doesn't exist in the published bindings. + * Get the MMCHS device id from FDT. Use rev address to identify the unit. */ node = ofw_bus_get_node(dev); - sc->mmchs_clk_id = ti_hwmods_get_clock(dev); - if (sc->mmchs_clk_id == INVALID_CLK_IDENT) { - device_printf(dev, "failed to get clock based on hwmods property\n"); - } /* * The hardware can inherently do dual-voltage (1p8v, 3p0v) on the first @@ -531,7 +534,8 @@ ti_sdhci_attach(device_t dev) * that it can set the right values in the CAPA register. */ sc->slot.host.caps |= MMC_OCR_LOW_VOLTAGE; - if (sc->mmchs_clk_id == MMC1_CLK || OF_hasprop(node, "ti,dual-volt")) { + + if (OF_hasprop(node, "ti,dual-volt")) { sc->slot.host.caps |= MMC_OCR_290_300 | MMC_OCR_300_310; } @@ -603,7 +607,11 @@ ti_sdhci_attach(device_t dev) sc->disable_readonly = true; /* Initialise the MMCHS hardware. */ - ti_sdhci_hw_init(dev); + err = ti_sdhci_hw_init(dev); + if (err != 0) { + /* err should already contain ENXIO from ti_sdhci_hw_init() */ + goto fail; + } /* * The capabilities register can only express base clock frequencies in @@ -754,6 +762,7 @@ static driver_t ti_sdhci_driver = { DRIVER_MODULE(sdhci_ti, simplebus, ti_sdhci_driver, ti_sdhci_devclass, NULL, NULL); +MODULE_DEPEND(sdhci_ti, ti_sysc, 1, 1, 1); SDHCI_DEPEND(sdhci_ti); #ifndef MMCCAM diff --git a/sys/arm/ti/ti_sdma.c b/sys/arm/ti/ti_sdma.c index b5c47a109b6f..3df674a33dcd 100644 --- a/sys/arm/ti/ti_sdma.c +++ b/sys/arm/ti/ti_sdma.c @@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus_subr.h> #include <arm/ti/ti_cpuid.h> -#include <arm/ti/ti_prcm.h> +#include <arm/ti/ti_sysc.h> #include <arm/ti/ti_sdma.h> #include <arm/ti/ti_sdmareg.h> @@ -79,7 +79,7 @@ __FBSDID("$FreeBSD$"); */ struct ti_sdma_channel { - /* + /* * The configuration registers for the given channel, these are modified * by the set functions and only written to the actual registers when a * transaction is started. @@ -109,7 +109,7 @@ struct ti_sdma_softc { struct resource* sc_irq_res; struct resource* sc_mem_res; - /* + /* * I guess in theory we should have a mutex per DMA channel for register * modifications. But since we know we are never going to be run on a SMP * system, we can use just the single lock for all channels. @@ -119,7 +119,7 @@ struct ti_sdma_softc { /* Stores the H/W revision read from the registers */ uint32_t sc_hw_rev; - /* + /* * Bits in the sc_active_channels data field indicate if the channel has * been activated. */ @@ -266,7 +266,7 @@ ti_sdma_intr(void *arg) if (csr & DMA4_CSR_TRANS_ERR) { device_printf(sc->sc_dev, "Transaction error event on " "channel %u\n", ch); - /* + /* * Apparently according to linux code, there is an errata * that says the channel is not disabled upon this error. * They explicitly disable the channel here .. since I @@ -1175,10 +1175,11 @@ ti_sdma_attach(device_t dev) panic("%s: Cannot map registers", device_get_name(dev)); /* Enable the interface and functional clocks */ - ti_prcm_clk_enable(SDMA_CLK); + ti_sysc_clock_enable(device_get_parent(dev)); /* Read the sDMA revision register and sanity check it's known */ - sc->sc_hw_rev = ti_sdma_read_4(sc, DMA4_REVISION); + sc->sc_hw_rev = ti_sdma_read_4(sc, + ti_sysc_get_rev_address_offset_host(device_get_parent(dev))); device_printf(dev, "sDMA revision %08x\n", sc->sc_hw_rev); if (!ti_sdma_is_omap4_rev(sc) && !ti_sdma_is_omap3_rev(sc)) { @@ -1213,7 +1214,7 @@ ti_sdma_attach(device_t dev) } } - /* + /* * Install interrupt handlers for the for possible interrupts. Any channel * can trip one of the four IRQs */ @@ -1248,4 +1249,4 @@ static driver_t ti_sdma_driver = { static devclass_t ti_sdma_devclass; DRIVER_MODULE(ti_sdma, simplebus, ti_sdma_driver, ti_sdma_devclass, 0, 0); -MODULE_DEPEND(ti_sdma, ti_prcm, 1, 1, 1); +MODULE_DEPEND(ti_sdma, ti_sysc, 1, 1, 1); diff --git a/sys/arm/ti/ti_spi.c b/sys/arm/ti/ti_spi.c index a424f36b8683..19b80605b9b6 100644 --- a/sys/arm/ti/ti_spi.c +++ b/sys/arm/ti/ti_spi.c @@ -48,8 +48,7 @@ __FBSDID("$FreeBSD$"); #include <dev/spibus/spi.h> #include <dev/spibus/spibusvar.h> -#include <arm/ti/ti_prcm.h> -#include <arm/ti/ti_hwmods.h> +#include <arm/ti/ti_sysc.h> #include <arm/ti/ti_spireg.h> #include <arm/ti/ti_spivar.h> @@ -166,28 +165,15 @@ ti_spi_probe(device_t dev) static int ti_spi_attach(device_t dev) { - int clk_id, err, i, rid, timeout; + int err, i, rid, timeout; struct ti_spi_softc *sc; uint32_t rev; sc = device_get_softc(dev); sc->sc_dev = dev; - /* - * Get the MMCHS device id from FDT. If it's not there use the newbus - * unit number (which will work as long as the devices are in order and - * none are skipped in the fdt). Note that this is a property we made - * up and added in freebsd, it doesn't exist in the published bindings. - */ - clk_id = ti_hwmods_get_clock(dev); - if (clk_id == INVALID_CLK_IDENT) { - device_printf(dev, - "failed to get clock based on hwmods property\n"); - return (EINVAL); - } - /* Activate the McSPI module. */ - err = ti_prcm_clk_enable(clk_id); + err = ti_sysc_clock_enable(device_get_parent(dev)); if (err) { device_printf(dev, "Error: failed to activate source clock\n"); return (err); @@ -245,7 +231,8 @@ ti_spi_attach(device_t dev) } /* Print the McSPI module revision. */ - rev = TI_SPI_READ(sc, MCSPI_REVISION); + rev = TI_SPI_READ(sc, + ti_sysc_get_rev_address_offset_host(device_get_parent(dev))); device_printf(dev, "scheme: %#x func: %#x rtl: %d rev: %d.%d custom rev: %d\n", (rev >> MCSPI_REVISION_SCHEME_SHIFT) & MCSPI_REVISION_SCHEME_MSK, @@ -592,3 +579,4 @@ static driver_t ti_spi_driver = { }; DRIVER_MODULE(ti_spi, simplebus, ti_spi_driver, ti_spi_devclass, 0, 0); +MODULE_DEPEND(ti_spi, ti_sysc, 1, 1, 1); diff --git a/sys/arm/ti/ti_sysc.c b/sys/arm/ti/ti_sysc.c index d428dd44a1ab..171520643c13 100644 --- a/sys/arm/ti/ti_sysc.c +++ b/sys/arm/ti/ti_sysc.c @@ -1,6 +1,8 @@ /*- * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.org> * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -34,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include <sys/fbio.h> #include <sys/kernel.h> #include <sys/module.h> +#include <sys/queue.h> #include <sys/rman.h> #include <sys/resource.h> #include <machine/bus.h> @@ -47,21 +50,402 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> +#include <dev/extres/clk/clk.h> + +#include <arm/ti/ti_sysc.h> +#include <arm/ti/clk/clock_common.h> + +#define DEBUG_SYSC 0 + +#if DEBUG_SYSC +#define DPRINTF(dev, msg...) device_printf(dev, msg) +#else +#define DPRINTF(dev, msg...) +#endif + +/* Documentation/devicetree/bindings/bus/ti-sysc.txt + * + * Documentation/devicetree/clock/clock-bindings.txt + * Defines phandle + optional pair + * Documentation/devicetree/clock/ti-clkctl.txt + */ + +static int ti_sysc_probe(device_t dev); +static int ti_sysc_attach(device_t dev); +static int ti_sysc_detach(device_t dev); + +#define TI_SYSC_DRA7_MCAN 15 +#define TI_SYSC_USB_HOST_FS 14 +#define TI_SYSC_DRA7_MCASP 13 +#define TI_SYSC_MCASP 12 +#define TI_SYSC_OMAP_AES 11 +#define TI_SYSC_OMAP3_SHAM 10 +#define TI_SYSC_OMAP4_SR 9 +#define TI_SYSC_OMAP3630_SR 8 +#define TI_SYSC_OMAP3430_SR 7 +#define TI_SYSC_OMAP4_TIMER 6 +#define TI_SYSC_OMAP2_TIMER 5 +/* Above needs special workarounds */ +#define TI_SYSC_OMAP4_SIMPLE 4 +#define TI_SYSC_OMAP4 3 +#define TI_SYSC_OMAP2 2 +#define TI_SYSC 1 +#define TI_SYSC_END 0 + static struct ofw_compat_data compat_data[] = { - { "ti,sysc", 1 }, - { NULL, 0 } + { "ti,sysc-dra7-mcan", TI_SYSC_DRA7_MCAN }, + { "ti,sysc-usb-host-fs", TI_SYSC_USB_HOST_FS }, + { "ti,sysc-dra7-mcasp", TI_SYSC_DRA7_MCASP }, + { "ti,sysc-mcasp", TI_SYSC_MCASP }, + { "ti,sysc-omap-aes", TI_SYSC_OMAP_AES }, + { "ti,sysc-omap3-sham", TI_SYSC_OMAP3_SHAM }, + { "ti,sysc-omap4-sr", TI_SYSC_OMAP4_SR }, + { "ti,sysc-omap3630-sr", TI_SYSC_OMAP3630_SR }, + { "ti,sysc-omap3430-sr", TI_SYSC_OMAP3430_SR }, + { "ti,sysc-omap4-timer", TI_SYSC_OMAP4_TIMER }, + { "ti,sysc-omap2-timer", TI_SYSC_OMAP2_TIMER }, + /* Above needs special workarounds */ + { "ti,sysc-omap4-simple", TI_SYSC_OMAP4_SIMPLE }, + { "ti,sysc-omap4", TI_SYSC_OMAP4 }, + { "ti,sysc-omap2", TI_SYSC_OMAP2 }, + { "ti,sysc", TI_SYSC }, + { NULL, TI_SYSC_END } +}; + +/* reg-names can be "rev", "sysc" and "syss" */ +static const char * reg_names[] = { "rev", "sysc", "syss" }; +#define REG_REV 0 +#define REG_SYSC 1 +#define REG_SYSS 2 +#define REG_MAX 3 + +/* master idle / slave idle mode defined in 8.1.3.2.1 / 8.1.3.2.2 */ +#include <gnu/dts/include/dt-bindings/bus/ti-sysc.h> +#define SYSC_IDLE_MAX 4 + +struct sysc_reg { + uint64_t address; + uint64_t size; +}; + +struct clk_list { + TAILQ_ENTRY(clk_list) next; + clk_t clk; }; struct ti_sysc_softc { struct simplebus_softc sc; + bool attach_done; + device_t dev; + int device_type; + + struct sysc_reg reg[REG_MAX]; + /* Offset from host base address */ + uint64_t offset_reg[REG_MAX]; + + uint32_t ti_sysc_mask; + int32_t ti_sysc_midle[SYSC_IDLE_MAX]; + int32_t ti_sysc_sidle[SYSC_IDLE_MAX]; + uint32_t ti_sysc_delay_us; + uint32_t ti_syss_mask; + + int num_clocks; + TAILQ_HEAD(, clk_list) clk_list; + + /* deprecated ti_hwmods */ + bool ti_no_reset_on_init; + bool ti_no_idle_on_init; + bool ti_no_idle; }; -static int ti_sysc_probe(device_t dev); -static int ti_sysc_attach(device_t dev); -static int ti_sysc_detach(device_t dev); +/* + * All sysc seems to have a reg["rev"] register. + * Lets use that for identification of which module the driver are connected to. + */ +uint64_t +ti_sysc_get_rev_address(device_t dev) { + struct ti_sysc_softc *sc = device_get_softc(dev); + + return (sc->reg[REG_REV].address); +} + +uint64_t +ti_sysc_get_rev_address_offset_host(device_t dev) { + struct ti_sysc_softc *sc = device_get_softc(dev); + + return (sc->offset_reg[REG_REV]); +} + +uint64_t +ti_sysc_get_sysc_address(device_t dev) { + struct ti_sysc_softc *sc = device_get_softc(dev); + + return (sc->reg[REG_SYSC].address); +} + +uint64_t +ti_sysc_get_sysc_address_offset_host(device_t dev) { + struct ti_sysc_softc *sc = device_get_softc(dev); + + return (sc->offset_reg[REG_SYSC]); +} + +uint64_t +ti_sysc_get_syss_address(device_t dev) { + struct ti_sysc_softc *sc = device_get_softc(dev); + + return (sc->reg[REG_SYSS].address); +} + +uint64_t +ti_sysc_get_syss_address_offset_host(device_t dev) { + struct ti_sysc_softc *sc = device_get_softc(dev); + + return (sc->offset_reg[REG_SYSS]); +} + +/* + * Due no memory region is assigned the sysc driver the children needs to + * handle the practical read/writes to the registers. + * Check if sysc has reset bit. + */ +uint32_t +ti_sysc_get_soft_reset_bit(device_t dev) { + struct ti_sysc_softc *sc = device_get_softc(dev); + switch (sc->device_type) { + case TI_SYSC_OMAP4_TIMER: + case TI_SYSC_OMAP4_SIMPLE: + case TI_SYSC_OMAP4: + if (sc->ti_sysc_mask & SYSC_OMAP4_SOFTRESET) { + return (SYSC_OMAP4_SOFTRESET); + } + break; + + case TI_SYSC_OMAP2_TIMER: + case TI_SYSC_OMAP2: + case TI_SYSC: + if (sc->ti_sysc_mask & SYSC_OMAP2_SOFTRESET) { + return (SYSC_OMAP2_SOFTRESET); + } + break; + default: + break; + } + + return (0); +} + +int +ti_sysc_clock_enable(device_t dev) { + struct clk_list *clkp, *clkp_tmp; + struct ti_sysc_softc *sc = device_get_softc(dev); + int err; + + TAILQ_FOREACH_SAFE(clkp, &sc->clk_list, next, clkp_tmp) { + err = clk_enable(clkp->clk); + + if (err) { + DPRINTF(sc->dev, "clk_enable %s failed %d\n", + clk_get_name(clkp->clk), err); + break; + } + } + return (err); +} + +int +ti_sysc_clock_disable(device_t dev) { + struct clk_list *clkp, *clkp_tmp; + struct ti_sysc_softc *sc = device_get_softc(dev); + int err = 0; + + TAILQ_FOREACH_SAFE(clkp, &sc->clk_list, next, clkp_tmp) { + err = clk_disable(clkp->clk); + + if (err) { + DPRINTF(sc->dev, "clk_enable %s failed %d\n", + clk_get_name(clkp->clk), err); + break; + } + } + return (err); +} static int +parse_regfields(struct ti_sysc_softc *sc) { + phandle_t node; + uint32_t parent_address_cells; + uint32_t parent_size_cells; + cell_t *reg; + ssize_t nreg; + int err, k, reg_i, prop_idx; + uint32_t idx; + + node = ofw_bus_get_node(sc->dev); + + /* Get parents address and size properties */ + err = OF_searchencprop(OF_parent(node), "#address-cells", + &parent_address_cells, sizeof(parent_address_cells)); + if (err == -1) + return (ENXIO); + if (!(parent_address_cells == 1 || parent_address_cells == 2)) { + DPRINTF(sc->dev, "Expect parent #address-cells=[1||2]\n"); + return (ENXIO); + } + + err = OF_searchencprop(OF_parent(node), "#size-cells", + &parent_size_cells, sizeof(parent_size_cells)); + if (err == -1) + return (ENXIO); + + if (!(parent_size_cells == 1 || parent_size_cells == 2)) { + DPRINTF(sc->dev, "Expect parent #size-cells = [1||2]\n"); + return (ENXIO); + } + + /* Grab the content of reg properties */ + nreg = OF_getproplen(node, "reg"); + reg = malloc(nreg, M_DEVBUF, M_WAITOK); + OF_getencprop(node, "reg", reg, nreg); + + /* Make sure address & size are 0 */ + for (idx = 0; idx < REG_MAX; idx++) { + sc->reg[idx].address = 0; + sc->reg[idx].size = 0; + } + + /* Loop through reg-names and figure out which reg-name corresponds to + * index populate the values into the reg array. + */ + for (idx = 0, reg_i = 0; idx < REG_MAX && reg_i < nreg; idx++) { + err = ofw_bus_find_string_index(node, "reg-names", + reg_names[idx], &prop_idx); + if (err != 0) + continue; + + for (k = 0; k < parent_address_cells; k++) { + sc->reg[prop_idx].address <<= 32; + sc->reg[prop_idx].address |= reg[reg_i++]; + } + + for (k = 0; k < parent_size_cells; k++) { + sc->reg[prop_idx].size <<= 32; + sc->reg[prop_idx].size |= reg[reg_i++]; + } + + if (sc->sc.nranges == 0) + sc->offset_reg[prop_idx] = sc->reg[prop_idx].address; + else + sc->offset_reg[prop_idx] = sc->reg[prop_idx].address - + sc->sc.ranges[REG_REV].host; + + DPRINTF(sc->dev, "reg[%s] adress %#jx size %#jx\n", + reg_names[idx], + sc->reg[prop_idx].address, + sc->reg[prop_idx].size); + } + free(reg, M_DEVBUF); + return (0); +} + +static void +parse_idle(struct ti_sysc_softc *sc, const char *name, uint32_t *idle) { + phandle_t node; + cell_t value[SYSC_IDLE_MAX]; + int len, no, i; + + node = ofw_bus_get_node(sc->dev); + + if (!OF_hasprop(node, name)) { + return; + } + + len = OF_getproplen(node, name); + no = len / sizeof(cell_t); + if (no >= SYSC_IDLE_MAX) { + DPRINTF(sc->dev, "Limit %s\n", name); + no = SYSC_IDLE_MAX-1; + len = no * sizeof(cell_t); + } + + OF_getencprop(node, name, value, len); + for (i = 0; i < no; i++) { + idle[i] = value[i]; +#if DEBUG_SYSC + DPRINTF(sc->dev, "%s[%d] = %d ", + name, i, value[i]); + switch(value[i]) { + case SYSC_IDLE_FORCE: + DPRINTF(sc->dev, "SYSC_IDLE_FORCE\n"); + break; + case SYSC_IDLE_NO: + DPRINTF(sc->dev, "SYSC_IDLE_NO\n"); + break; + case SYSC_IDLE_SMART: + DPRINTF(sc->dev, "SYSC_IDLE_SMART\n"); + break; + case SYSC_IDLE_SMART_WKUP: + DPRINTF(sc->dev, "SYSC_IDLE_SMART_WKUP\n"); + break; + } +#endif + } + for ( ; i < SYSC_IDLE_MAX; i++) + idle[i] = -1; +} + +static int +ti_sysc_attach_clocks(struct ti_sysc_softc *sc) { + clk_t *clk; + struct clk_list *clkp; + int index, err; + phandle_t cnode; + + clk = malloc(sc->num_clocks*sizeof(clk_t), M_DEVBUF, M_WAITOK | M_ZERO); + + cnode = ofw_bus_get_node(sc->dev); + + /* Check if all clocks can be found */ + for (index = 0; index < sc->num_clocks; index++) { + err = clk_get_by_ofw_index(sc->dev, 0, index, &clk[index]); + + if (err != 0) { + free(clk, M_DEVBUF); + return (1); + } + } + + /* All clocks are found, add to list */ + for (index = 0; index < sc->num_clocks; index++) { + clkp = malloc(sizeof(*clkp), M_DEVBUF, M_WAITOK | M_ZERO); + clkp->clk = clk[index]; + TAILQ_INSERT_TAIL(&sc->clk_list, clkp, next); + } + + /* Release the clk array */ + free(clk, M_DEVBUF); + return (0); +} + +static int +ti_sysc_simplebus_attach_child(device_t dev) { + device_t cdev; + phandle_t node, child; + struct ti_sysc_softc *sc = device_get_softc(dev); + + node = ofw_bus_get_node(sc->dev); + + for (child = OF_child(node); child > 0; child = OF_peer(child)) { + cdev = simplebus_add_device(sc->dev, child, 0, NULL, -1, NULL); + if (cdev != NULL) + device_probe_and_attach(cdev); + } + return (0); +} + +/* Device interface */ +static int ti_sysc_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) @@ -71,8 +455,6 @@ ti_sysc_probe(device_t dev) return (ENXIO); device_set_desc(dev, "TI SYSC Interconnect"); - if (!bootverbose) - device_quiet(dev); return (BUS_PROBE_DEFAULT); } @@ -81,48 +463,160 @@ static int ti_sysc_attach(device_t dev) { struct ti_sysc_softc *sc; - device_t cdev; - phandle_t node, child; + phandle_t node; + int err; + cell_t value; sc = device_get_softc(dev); sc->dev = dev; - node = ofw_bus_get_node(dev); + sc->device_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; - simplebus_init(dev, node); + node = ofw_bus_get_node(sc->dev); + /* ranges - use simplebus */ + simplebus_init(sc->dev, node); if (simplebus_fill_ranges(node, &sc->sc) < 0) { - device_printf(dev, "could not get ranges\n"); + DPRINTF(sc->dev, "could not get ranges\n"); return (ENXIO); } - for (child = OF_child(node); child > 0; child = OF_peer(child)) { - cdev = simplebus_add_device(dev, child, 0, NULL, -1, NULL); - if (cdev != NULL) - device_probe_and_attach(cdev); + if (sc->sc.nranges == 0) { + DPRINTF(sc->dev, "nranges == 0\n"); + return (ENXIO); + } + + /* Required field reg & reg-names - assume at least "rev" exists */ + err = parse_regfields(sc); + if (err) { + DPRINTF(sc->dev, "parse_regfields failed %d\n", err); + return (ENXIO); + } + + /* Optional */ + if (OF_hasprop(node, "ti,sysc-mask")) { + OF_getencprop(node, "ti,sysc-mask", &value, sizeof(cell_t)); + sc->ti_sysc_mask = value; + } + if (OF_hasprop(node, "ti,syss-mask")) { + OF_getencprop(node, "ti,syss-mask", &value, sizeof(cell_t)); + sc->ti_syss_mask = value; + } + if (OF_hasprop(node, "ti,sysc-delay-us")) { + OF_getencprop(node, "ti,sysc-delay-us", &value, sizeof(cell_t)); + sc->ti_sysc_delay_us = value; + } + + DPRINTF(sc->dev, "sysc_mask %x syss_mask %x delay_us %x\n", + sc->ti_sysc_mask, sc->ti_syss_mask, sc->ti_sysc_delay_us); + + parse_idle(sc, "ti,sysc-midle", sc->ti_sysc_midle); + parse_idle(sc, "ti,sysc-sidle", sc->ti_sysc_sidle); + + if (OF_hasprop(node, "ti,no-reset-on-init")) + sc->ti_no_reset_on_init = true; + else + sc->ti_no_reset_on_init = false; + + if (OF_hasprop(node, "ti,no-idle-on-init")) + sc->ti_no_idle_on_init = true; + else + sc->ti_no_idle_on_init = false; + + if (OF_hasprop(node, "ti,no-idle")) + sc->ti_no_idle = true; + else + sc->ti_no_idle = false; + + DPRINTF(sc->dev, + "no-reset-on-init %d, no-idle-on-init %d, no-idle %d\n", + sc->ti_no_reset_on_init, + sc->ti_no_idle_on_init, + sc->ti_no_idle); + + if (OF_hasprop(node, "clocks")) { + struct clock_cell_info cell_info; + read_clock_cells(sc->dev, &cell_info); + free(cell_info.clock_cells, M_DEVBUF); + free(cell_info.clock_cells_ncells, M_DEVBUF); + + sc->num_clocks = cell_info.num_real_clocks; + TAILQ_INIT(&sc->clk_list); + + err = ti_sysc_attach_clocks(sc); + if (err) { + DPRINTF(sc->dev, "Failed to attach clocks\n"); + return (bus_generic_attach(sc->dev)); + } + } + + err = ti_sysc_simplebus_attach_child(sc->dev); + if (err) { + DPRINTF(sc->dev, "ti_sysc_simplebus_attach_child %d\n", + err); + return (err); } - return (bus_generic_attach(dev)); + sc->attach_done = true; + + return (bus_generic_attach(sc->dev)); } static int ti_sysc_detach(device_t dev) { - return (EBUSY); } +/* Bus interface */ +static void +ti_sysc_new_pass(device_t dev) +{ + struct ti_sysc_softc *sc; + int err; + phandle_t node; + + sc = device_get_softc(dev); + + if (sc->attach_done) { + bus_generic_new_pass(sc->dev); + return; + } + + node = ofw_bus_get_node(sc->dev); + if (OF_hasprop(node, "clocks")) { + err = ti_sysc_attach_clocks(sc); + if (err) { + DPRINTF(sc->dev, "Failed to attach clocks\n"); + return; + } + } + + err = ti_sysc_simplebus_attach_child(sc->dev); + if (err) { + DPRINTF(sc->dev, + "ti_sysc_simplebus_attach_child failed %d\n", err); + return; + } + sc->attach_done = true; + + bus_generic_attach(sc->dev); +} + static device_method_t ti_sysc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ti_sysc_probe), DEVMETHOD(device_attach, ti_sysc_attach), DEVMETHOD(device_detach, ti_sysc_detach), + /* Bus interface */ + DEVMETHOD(bus_new_pass, ti_sysc_new_pass), + DEVMETHOD_END }; DEFINE_CLASS_1(ti_sysc, ti_sysc_driver, ti_sysc_methods, - sizeof(struct ti_sysc_softc), simplebus_driver); + sizeof(struct ti_sysc_softc), simplebus_driver); static devclass_t ti_sysc_devclass; EARLY_DRIVER_MODULE(ti_sysc, simplebus, ti_sysc_driver, -ti_sysc_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST); + ti_sysc_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST); diff --git a/sys/arm/ti/ti_sysc.h b/sys/arm/ti/ti_sysc.h new file mode 100644 index 000000000000..b74222f05772 --- /dev/null +++ b/sys/arm/ti/ti_sysc.h @@ -0,0 +1,43 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __TI_SYSC__ +#define __TI_SYSC__ + +uint64_t ti_sysc_get_rev_address(device_t dev); +uint64_t ti_sysc_get_rev_address_offset_host(device_t dev); +uint64_t ti_sysc_get_sysc_address(device_t dev); +uint64_t ti_sysc_get_sysc_address_offset_host(device_t dev); +uint64_t ti_sysc_get_syss_address(device_t dev); +uint64_t ti_sysc_get_syss_address_offset_host(device_t dev); +int ti_sysc_clock_enable(device_t dev); +int ti_sysc_clock_disable(device_t dev); + +uint32_t ti_sysc_get_soft_reset_bit(device_t dev); + +#endif /* __TI_SYSC__ */ diff --git a/sys/arm/ti/ti_wdt.c b/sys/arm/ti/ti_wdt.c index 539e4d93950f..29ae41eac531 100644 --- a/sys/arm/ti/ti_wdt.c +++ b/sys/arm/ti/ti_wdt.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> -#include <arm/ti/ti_prcm.h> #include <arm/ti/ti_wdt.h> #ifdef DEBUG @@ -93,6 +92,7 @@ static driver_t ti_wdt_driver = { static devclass_t ti_wdt_devclass; DRIVER_MODULE(ti_wdt, simplebus, ti_wdt_driver, ti_wdt_devclass, 0, 0); +MODULE_DEPEND(ti_wdt, ti_sysc, 1, 1, 1); static __inline uint32_t ti_wdt_reg_read(struct ti_wdt_softc *sc, uint32_t reg) diff --git a/sys/arm/ti/usb/omap_ehci.c b/sys/arm/ti/usb/omap_ehci.c index c14a483b7175..adc2c122f054 100644 --- a/sys/arm/ti/usb/omap_ehci.c +++ b/sys/arm/ti/usb/omap_ehci.c @@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> -#include <arm/ti/ti_prcm.h> #include <arm/ti/usb/omap_usb.h> #include <arm/ti/omap4/pandaboard/pandaboard.h> diff --git a/sys/arm/ti/usb/omap_host.c b/sys/arm/ti/usb/omap_host.c index 304e80d33df8..736ccf17262e 100644 --- a/sys/arm/ti/usb/omap_host.c +++ b/sys/arm/ti/usb/omap_host.c @@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> -#include <arm/ti/ti_prcm.h> +#include <arm/ti/ti_sysc.h> #include <arm/ti/usb/omap_usb.h> /* @@ -139,12 +139,14 @@ omap_uhh_init(struct omap_uhh_softc *isc) int i; /* Enable Clocks for high speed USBHOST */ - ti_prcm_clk_enable(USBHSHOST_CLK); + ti_sysc_clock_enable(device_get_parent(isc->sc_dev)); /* Read the UHH revision */ isc->uhh_rev = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_REVISION); device_printf(isc->sc_dev, "UHH revision 0x%08x\n", isc->uhh_rev); + /* FIXME */ +#if 0 if (isc->uhh_rev == OMAP_UHH_REV2) { /* For OMAP44xx devices you have to enable the per-port clocks: * PHY_MODE - External ULPI clock @@ -200,6 +202,7 @@ omap_uhh_init(struct omap_uhh_softc *isc) device_printf(isc->sc_dev, "unknown port mode %d for port 1\n", isc->port_mode[1]); } } +#endif /* Put UHH in SmartIdle/SmartStandby mode */ reg = omap_uhh_read_4(isc, OMAP_USBHOST_UHH_SYSCONFIG); @@ -327,7 +330,7 @@ omap_uhh_fini(struct omap_uhh_softc *isc) } /* Disable functional and interface clocks for the TLL and HOST modules */ - ti_prcm_clk_disable(USBHSHOST_CLK); + ti_sysc_clock_disable(device_get_parent(isc->sc_dev)); device_printf(isc->sc_dev, "Clock to USB host has been disabled\n"); } diff --git a/sys/arm/ti/usb/omap_tll.c b/sys/arm/ti/usb/omap_tll.c index eb3e246a61d6..c5383e3d52d3 100644 --- a/sys/arm/ti/usb/omap_tll.c +++ b/sys/arm/ti/usb/omap_tll.c @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> -#include <arm/ti/ti_prcm.h> +#include <arm/ti/ti_sysc.h> #include <arm/ti/usb/omap_usb.h> /* @@ -212,7 +212,7 @@ omap_tll_init(struct omap_tll_softc *sc) int ret = 0; /* Enable the USB TLL */ - ti_prcm_clk_enable(USBTLL_CLK); + ti_sysc_clock_enable(device_get_parent(sc->sc_dev)); /* Perform TLL soft reset, and wait until reset is complete */ omap_tll_write_4(sc, OMAP_USBTLL_SYSCONFIG, TLL_SYSCONFIG_SOFTRESET); @@ -248,7 +248,7 @@ omap_tll_init(struct omap_tll_softc *sc) err_sys_status: /* Disable the TLL clocks */ - ti_prcm_clk_disable(USBTLL_CLK); + ti_sysc_clock_disable(device_get_parent(sc->sc_dev)); return(ret); } @@ -273,7 +273,7 @@ omap_tll_disable(struct omap_tll_softc *sc) } /* Disable functional and interface clocks for the TLL and HOST modules */ - ti_prcm_clk_disable(USBTLL_CLK); + ti_sysc_clock_disable(device_get_parent(sc->sc_dev)); } static int diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index 1667d5993998..423adac08208 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -132,6 +132,8 @@ void pagezero_cache(void *); /* pagezero_simple is default pagezero */ void (*pagezero)(void *p) = pagezero_simple; +int (*apei_nmi)(void); + static void pan_setup(void) { diff --git a/sys/arm64/include/acpica_machdep.h b/sys/arm64/include/acpica_machdep.h index 282c79f5eaec..7f8139f9134b 100644 --- a/sys/arm64/include/acpica_machdep.h +++ b/sys/arm64/include/acpica_machdep.h @@ -57,6 +57,8 @@ struct acpi_generic_address; int acpi_map_addr(struct acpi_generic_address *, bus_space_tag_t *, bus_space_handle_t *, bus_size_t); +extern int (*apei_nmi)(void); + #endif /* _KERNEL */ #endif /* __ACPICA_MACHDEP_H__ */ diff --git a/sys/conf/files b/sys/conf/files index 8ed21c37d214..cbb29fa45663 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -754,6 +754,7 @@ dev/acpica/Osd/OsdSynch.c optional acpi dev/acpica/Osd/OsdTable.c optional acpi dev/acpica/acpi.c optional acpi dev/acpica/acpi_acad.c optional acpi +dev/acpica/acpi_apei.c optional acpi dev/acpica/acpi_battery.c optional acpi dev/acpica/acpi_button.c optional acpi dev/acpica/acpi_cmbat.c optional acpi @@ -1540,9 +1541,6 @@ t6fw.fw optional cxgbe \ clean "t6fw.fw" dev/cxgbe/crypto/t4_crypto.c optional ccr \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" -dev/cy/cy.c optional cy -dev/cy/cy_isa.c optional cy isa -dev/cy/cy_pci.c optional cy pci dev/cyapa/cyapa.c optional cyapa iicbus dev/dc/if_dc.c optional dc pci dev/dc/dcphy.c optional dc pci @@ -1640,6 +1638,10 @@ dev/e1000/e1000_osdep.c optional em \ dev/et/if_et.c optional et dev/ena/ena.c optional ena \ compile-with "${NORMAL_C} -I$S/contrib" +dev/ena/ena_datapath.c optional ena \ + compile-with "${NORMAL_C} -I$S/contrib" +dev/ena/ena_netmap.c optional ena \ + compile-with "${NORMAL_C} -I$S/contrib" dev/ena/ena_sysctl.c optional ena \ compile-with "${NORMAL_C} -I$S/contrib" contrib/ena-com/ena_com.c optional ena @@ -2770,14 +2772,10 @@ dev/random/random_harvestq.c standard dev/random/randomdev.c optional !random_loadable dev/random/fortuna.c optional !random_loadable dev/random/hash.c optional !random_loadable -dev/rc/rc.c optional rc dev/rccgpio/rccgpio.c optional rccgpio gpio dev/re/if_re.c optional re dev/rl/if_rl.c optional rl pci dev/rndtest/rndtest.c optional rndtest -dev/rp/rp.c optional rp -dev/rp/rp_isa.c optional rp isa -dev/rp/rp_pci.c optional rp pci # dev/rtwn/if_rtwn.c optional rtwn dev/rtwn/if_rtwn_beacon.c optional rtwn @@ -3028,6 +3026,7 @@ dev/smbus/smbconf.c optional smbus dev/smbus/smbus.c optional smbus dev/smbus/smbus_if.m optional smbus dev/smc/if_smc.c optional smc +dev/smc/if_smc_acpi.c optional smc acpi dev/smc/if_smc_fdt.c optional smc fdt dev/snp/snp.c optional snp dev/sound/clone.c optional sound diff --git a/sys/contrib/pcg-c/include/pcg_variants.h b/sys/contrib/pcg-c/include/pcg_variants.h new file mode 100644 index 000000000000..768fb75ae93b --- /dev/null +++ b/sys/contrib/pcg-c/include/pcg_variants.h @@ -0,0 +1,2544 @@ +/* + * PCG Random Number Generation for C. + * + * Copyright 2014-2019 Melissa O'Neill <oneill@pcg-random.org>, + * and the PCG Project contributors. + * + * SPDX-License-Identifier: (Apache-2.0 OR MIT) + * + * Licensed under the Apache License, Version 2.0 (provided in + * LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0) + * or under the MIT license (provided in LICENSE-MIT.txt and at + * http://opensource.org/licenses/MIT), at your option. This file may not + * be copied, modified, or distributed except according to those terms. + * + * Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See your chosen license for details. + * + * For additional information about the PCG random number generation scheme, + * visit http://www.pcg-random.org/. + */ + +/* + * This code is derived from the canonical C++ PCG implementation, which + * has many additional features and is preferable if you can use C++ in + * your project. + * + * Much of the derivation was performed mechanically. In particular, the + * output functions were generated by compiling the C++ output functions + * into LLVM bitcode and then transforming that using the LLVM C backend + * (from https://github.com/draperlaboratory/llvm-cbe), and then + * postprocessing and hand editing the output. + * + * Much of the remaining code was generated by C-preprocessor metaprogramming. + */ + +#ifndef PCG_VARIANTS_H_INCLUDED +#define PCG_VARIANTS_H_INCLUDED 1 + +#include <inttypes.h> + +#if __SIZEOF_INT128__ + typedef __uint128_t pcg128_t; + #define PCG_128BIT_CONSTANT(high,low) \ + ((((pcg128_t)high) << 64) + low) + #define PCG_HAS_128BIT_OPS 1 +#endif + +#if __GNUC_GNU_INLINE__ && !defined(__cplusplus) + #error Nonstandard GNU inlining semantics. Compile with -std=c99 or better. + /* We could instead use macros PCG_INLINE and PCG_EXTERN_INLINE + but better to just reject ancient C code. */ +#endif + +#if __cplusplus +extern "C" { +#endif + +/* + * Rotate helper functions. + */ + +inline uint8_t pcg_rotr_8(uint8_t value, unsigned int rot) +{ +/* Unfortunately, clang is kinda pathetic when it comes to properly + * recognizing idiomatic rotate code, so for clang we actually provide + * assembler directives (enabled with PCG_USE_INLINE_ASM). Boo, hiss. + */ +#if PCG_USE_INLINE_ASM && __clang__ && (__x86_64__ || __i386__) + asm ("rorb %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); + return value; +#else + return (value >> rot) | (value << ((- rot) & 7)); +#endif +} + +inline uint16_t pcg_rotr_16(uint16_t value, unsigned int rot) +{ +#if PCG_USE_INLINE_ASM && __clang__ && (__x86_64__ || __i386__) + asm ("rorw %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); + return value; +#else + return (value >> rot) | (value << ((- rot) & 15)); +#endif +} + +inline uint32_t pcg_rotr_32(uint32_t value, unsigned int rot) +{ +#if PCG_USE_INLINE_ASM && __clang__ && (__x86_64__ || __i386__) + asm ("rorl %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); + return value; +#else + return (value >> rot) | (value << ((- rot) & 31)); +#endif +} + +inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) +{ +#if 0 && PCG_USE_INLINE_ASM && __clang__ && __x86_64__ + /* For whatever reason, clang actually *does* generate rotq by + itself, so we don't need this code. */ + asm ("rorq %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); + return value; +#else + return (value >> rot) | (value << ((- rot) & 63)); +#endif +} + +#if PCG_HAS_128BIT_OPS +inline pcg128_t pcg_rotr_128(pcg128_t value, unsigned int rot) +{ + return (value >> rot) | (value << ((- rot) & 127)); +} +#endif + +/* + * Output functions. These are the core of the PCG generation scheme. + */ + +/* XSH RS */ + +inline uint8_t pcg_output_xsh_rs_16_8(uint16_t state) +{ + return (uint8_t)(((state >> 7u) ^ state) >> ((state >> 14u) + 3u)); +} + +inline uint16_t pcg_output_xsh_rs_32_16(uint32_t state) +{ + return (uint16_t)(((state >> 11u) ^ state) >> ((state >> 30u) + 11u)); +} + +inline uint32_t pcg_output_xsh_rs_64_32(uint64_t state) +{ + + return (uint32_t)(((state >> 22u) ^ state) >> ((state >> 61u) + 22u)); +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_output_xsh_rs_128_64(pcg128_t state) +{ + return (uint64_t)(((state >> 43u) ^ state) >> ((state >> 124u) + 45u)); +} +#endif + +/* XSH RR */ + +inline uint8_t pcg_output_xsh_rr_16_8(uint16_t state) +{ + return pcg_rotr_8(((state >> 5u) ^ state) >> 5u, state >> 13u); +} + +inline uint16_t pcg_output_xsh_rr_32_16(uint32_t state) +{ + return pcg_rotr_16(((state >> 10u) ^ state) >> 12u, state >> 28u); +} + +inline uint32_t pcg_output_xsh_rr_64_32(uint64_t state) +{ + return pcg_rotr_32(((state >> 18u) ^ state) >> 27u, state >> 59u); +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_output_xsh_rr_128_64(pcg128_t state) +{ + return pcg_rotr_64(((state >> 35u) ^ state) >> 58u, state >> 122u); +} +#endif + +/* RXS M XS */ + +inline uint8_t pcg_output_rxs_m_xs_8_8(uint8_t state) +{ + uint8_t word = ((state >> ((state >> 6u) + 2u)) ^ state) * 217u; + return (word >> 6u) ^ word; +} + +inline uint16_t pcg_output_rxs_m_xs_16_16(uint16_t state) +{ + uint16_t word = ((state >> ((state >> 13u) + 3u)) ^ state) * 62169u; + return (word >> 11u) ^ word; +} + +inline uint32_t pcg_output_rxs_m_xs_32_32(uint32_t state) +{ + uint32_t word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; + return (word >> 22u) ^ word; +} + +inline uint64_t pcg_output_rxs_m_xs_64_64(uint64_t state) +{ + uint64_t word = ((state >> ((state >> 59u) + 5u)) ^ state) + * 12605985483714917081ull; + return (word >> 43u) ^ word; +} + +#if PCG_HAS_128BIT_OPS +inline pcg128_t pcg_output_rxs_m_xs_128_128(pcg128_t state) +{ + pcg128_t word = ((state >> ((state >> 122u) + 6u)) ^ state) + * (PCG_128BIT_CONSTANT(17766728186571221404ULL, + 12605985483714917081ULL)); + /* 327738287884841127335028083622016905945 */ + return (word >> 86u) ^ word; +} +#endif + +/* RXS M */ + +inline uint8_t pcg_output_rxs_m_16_8(uint16_t state) +{ + return (((state >> ((state >> 13u) + 3u)) ^ state) * 62169u) >> 8u; +} + +inline uint16_t pcg_output_rxs_m_32_16(uint32_t state) +{ + return (((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u) >> 16u; +} + +inline uint32_t pcg_output_rxs_m_64_32(uint64_t state) +{ + return (((state >> ((state >> 59u) + 5u)) ^ state) + * 12605985483714917081ull) >> 32u; +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_output_rxs_m_128_64(pcg128_t state) +{ + return (((state >> ((state >> 122u) + 6u)) ^ state) + * (PCG_128BIT_CONSTANT(17766728186571221404ULL, + 12605985483714917081ULL))) >> 64u; + /* 327738287884841127335028083622016905945 */ +} +#endif + +/* XSL RR (only defined for >= 64 bits) */ + +inline uint32_t pcg_output_xsl_rr_64_32(uint64_t state) +{ + return pcg_rotr_32(((uint32_t)(state >> 32u)) ^ (uint32_t)state, + state >> 59u); +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_output_xsl_rr_128_64(pcg128_t state) +{ + return pcg_rotr_64(((uint64_t)(state >> 64u)) ^ (uint64_t)state, + state >> 122u); +} +#endif + +/* XSL RR RR (only defined for >= 64 bits) */ + +inline uint64_t pcg_output_xsl_rr_rr_64_64(uint64_t state) +{ + uint32_t rot1 = (uint32_t)(state >> 59u); + uint32_t high = (uint32_t)(state >> 32u); + uint32_t low = (uint32_t)state; + uint32_t xored = high ^ low; + uint32_t newlow = pcg_rotr_32(xored, rot1); + uint32_t newhigh = pcg_rotr_32(high, newlow & 31u); + return (((uint64_t)newhigh) << 32u) | newlow; +} + +#if PCG_HAS_128BIT_OPS +inline pcg128_t pcg_output_xsl_rr_rr_128_128(pcg128_t state) +{ + uint32_t rot1 = (uint32_t)(state >> 122u); + uint64_t high = (uint64_t)(state >> 64u); + uint64_t low = (uint64_t)state; + uint64_t xored = high ^ low; + uint64_t newlow = pcg_rotr_64(xored, rot1); + uint64_t newhigh = pcg_rotr_64(high, newlow & 63u); + return (((pcg128_t)newhigh) << 64u) | newlow; +} +#endif + +#define PCG_DEFAULT_MULTIPLIER_8 141U +#define PCG_DEFAULT_MULTIPLIER_16 12829U +#define PCG_DEFAULT_MULTIPLIER_32 747796405U +#define PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL + +#define PCG_DEFAULT_INCREMENT_8 77U +#define PCG_DEFAULT_INCREMENT_16 47989U +#define PCG_DEFAULT_INCREMENT_32 2891336453U +#define PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL + +#if PCG_HAS_128BIT_OPS +#define PCG_DEFAULT_MULTIPLIER_128 \ + PCG_128BIT_CONSTANT(2549297995355413924ULL,4865540595714422341ULL) +#define PCG_DEFAULT_INCREMENT_128 \ + PCG_128BIT_CONSTANT(6364136223846793005ULL,1442695040888963407ULL) +#endif + +/* + * Static initialization constants (if you can't call srandom for some + * bizarre reason). + */ + +#define PCG_STATE_ONESEQ_8_INITIALIZER { 0xd7U } +#define PCG_STATE_ONESEQ_16_INITIALIZER { 0x20dfU } +#define PCG_STATE_ONESEQ_32_INITIALIZER { 0x46b56677U } +#define PCG_STATE_ONESEQ_64_INITIALIZER { 0x4d595df4d0f33173ULL } +#if PCG_HAS_128BIT_OPS +#define PCG_STATE_ONESEQ_128_INITIALIZER \ + { PCG_128BIT_CONSTANT(0xb8dc10e158a92392ULL, 0x98046df007ec0a53ULL) } +#endif + +#define PCG_STATE_UNIQUE_8_INITIALIZER PCG_STATE_ONESEQ_8_INITIALIZER +#define PCG_STATE_UNIQUE_16_INITIALIZER PCG_STATE_ONESEQ_16_INITIALIZER +#define PCG_STATE_UNIQUE_32_INITIALIZER PCG_STATE_ONESEQ_32_INITIALIZER +#define PCG_STATE_UNIQUE_64_INITIALIZER PCG_STATE_ONESEQ_64_INITIALIZER +#if PCG_HAS_128BIT_OPS +#define PCG_STATE_UNIQUE_128_INITIALIZER PCG_STATE_ONESEQ_128_INITIALIZER +#endif + +#define PCG_STATE_MCG_8_INITIALIZER { 0xe5U } +#define PCG_STATE_MCG_16_INITIALIZER { 0xa5e5U } +#define PCG_STATE_MCG_32_INITIALIZER { 0xd15ea5e5U } +#define PCG_STATE_MCG_64_INITIALIZER { 0xcafef00dd15ea5e5ULL } +#if PCG_HAS_128BIT_OPS +#define PCG_STATE_MCG_128_INITIALIZER \ + { PCG_128BIT_CONSTANT(0x0000000000000000ULL, 0xcafef00dd15ea5e5ULL) } +#endif + +#define PCG_STATE_SETSEQ_8_INITIALIZER { 0x9bU, 0xdbU } +#define PCG_STATE_SETSEQ_16_INITIALIZER { 0xe39bU, 0x5bdbU } +#define PCG_STATE_SETSEQ_32_INITIALIZER { 0xec02d89bU, 0x94b95bdbU } +#define PCG_STATE_SETSEQ_64_INITIALIZER \ + { 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL } +#if PCG_HAS_128BIT_OPS +#define PCG_STATE_SETSEQ_128_INITIALIZER \ + { PCG_128BIT_CONSTANT(0x979c9a98d8462005ULL, 0x7d3e9cb6cfe0549bULL), \ + PCG_128BIT_CONSTANT(0x0000000000000001ULL, 0xda3e39cb94b95bdbULL) } +#endif + +/* Representations for the oneseq, mcg, and unique variants */ + +struct pcg_state_8 { + uint8_t state; +}; + +struct pcg_state_16 { + uint16_t state; +}; + +struct pcg_state_32 { + uint32_t state; +}; + +struct pcg_state_64 { + uint64_t state; +}; + +#if PCG_HAS_128BIT_OPS +struct pcg_state_128 { + pcg128_t state; +}; +#endif + +/* Representations setseq variants */ + +struct pcg_state_setseq_8 { + uint8_t state; + uint8_t inc; +}; + +struct pcg_state_setseq_16 { + uint16_t state; + uint16_t inc; +}; + +struct pcg_state_setseq_32 { + uint32_t state; + uint32_t inc; +}; + +struct pcg_state_setseq_64 { + uint64_t state; + uint64_t inc; +}; + +#if PCG_HAS_128BIT_OPS +struct pcg_state_setseq_128 { + pcg128_t state; + pcg128_t inc; +}; +#endif + +/* Multi-step advance functions (jump-ahead, jump-back) */ + +extern uint8_t pcg_advance_lcg_8(uint8_t state, uint8_t delta, uint8_t cur_mult, + uint8_t cur_plus); +extern uint16_t pcg_advance_lcg_16(uint16_t state, uint16_t delta, + uint16_t cur_mult, uint16_t cur_plus); +extern uint32_t pcg_advance_lcg_32(uint32_t state, uint32_t delta, + uint32_t cur_mult, uint32_t cur_plus); +extern uint64_t pcg_advance_lcg_64(uint64_t state, uint64_t delta, + uint64_t cur_mult, uint64_t cur_plus); + +#if PCG_HAS_128BIT_OPS +extern pcg128_t pcg_advance_lcg_128(pcg128_t state, pcg128_t delta, + pcg128_t cur_mult, pcg128_t cur_plus); +#endif + +/* Functions to advance the underlying LCG, one version for each size and + * each style. These functions are considered semi-private. There is rarely + * a good reason to call them directly. + */ + +inline void pcg_oneseq_8_step_r(struct pcg_state_8* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_8 + + PCG_DEFAULT_INCREMENT_8; +} + +inline void pcg_oneseq_8_advance_r(struct pcg_state_8* rng, uint8_t delta) +{ + rng->state = pcg_advance_lcg_8(rng->state, delta, PCG_DEFAULT_MULTIPLIER_8, + PCG_DEFAULT_INCREMENT_8); +} + +inline void pcg_mcg_8_step_r(struct pcg_state_8* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_8; +} + +inline void pcg_mcg_8_advance_r(struct pcg_state_8* rng, uint8_t delta) +{ + rng->state + = pcg_advance_lcg_8(rng->state, delta, PCG_DEFAULT_MULTIPLIER_8, 0u); +} + +inline void pcg_unique_8_step_r(struct pcg_state_8* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_8 + + (uint8_t)(((intptr_t)rng) | 1u); +} + +inline void pcg_unique_8_advance_r(struct pcg_state_8* rng, uint8_t delta) +{ + rng->state = pcg_advance_lcg_8(rng->state, delta, PCG_DEFAULT_MULTIPLIER_8, + (uint8_t)(((intptr_t)rng) | 1u)); +} + +inline void pcg_setseq_8_step_r(struct pcg_state_setseq_8* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_8 + rng->inc; +} + +inline void pcg_setseq_8_advance_r(struct pcg_state_setseq_8* rng, + uint8_t delta) +{ + rng->state = pcg_advance_lcg_8(rng->state, delta, PCG_DEFAULT_MULTIPLIER_8, + rng->inc); +} + +inline void pcg_oneseq_16_step_r(struct pcg_state_16* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_16 + + PCG_DEFAULT_INCREMENT_16; +} + +inline void pcg_oneseq_16_advance_r(struct pcg_state_16* rng, uint16_t delta) +{ + rng->state = pcg_advance_lcg_16( + rng->state, delta, PCG_DEFAULT_MULTIPLIER_16, PCG_DEFAULT_INCREMENT_16); +} + +inline void pcg_mcg_16_step_r(struct pcg_state_16* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_16; +} + +inline void pcg_mcg_16_advance_r(struct pcg_state_16* rng, uint16_t delta) +{ + rng->state + = pcg_advance_lcg_16(rng->state, delta, PCG_DEFAULT_MULTIPLIER_16, 0u); +} + +inline void pcg_unique_16_step_r(struct pcg_state_16* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_16 + + (uint16_t)(((intptr_t)rng) | 1u); +} + +inline void pcg_unique_16_advance_r(struct pcg_state_16* rng, uint16_t delta) +{ + rng->state + = pcg_advance_lcg_16(rng->state, delta, PCG_DEFAULT_MULTIPLIER_16, + (uint16_t)(((intptr_t)rng) | 1u)); +} + +inline void pcg_setseq_16_step_r(struct pcg_state_setseq_16* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_16 + rng->inc; +} + +inline void pcg_setseq_16_advance_r(struct pcg_state_setseq_16* rng, + uint16_t delta) +{ + rng->state = pcg_advance_lcg_16(rng->state, delta, + PCG_DEFAULT_MULTIPLIER_16, rng->inc); +} + +inline void pcg_oneseq_32_step_r(struct pcg_state_32* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_32 + + PCG_DEFAULT_INCREMENT_32; +} + +inline void pcg_oneseq_32_advance_r(struct pcg_state_32* rng, uint32_t delta) +{ + rng->state = pcg_advance_lcg_32( + rng->state, delta, PCG_DEFAULT_MULTIPLIER_32, PCG_DEFAULT_INCREMENT_32); +} + +inline void pcg_mcg_32_step_r(struct pcg_state_32* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_32; +} + +inline void pcg_mcg_32_advance_r(struct pcg_state_32* rng, uint32_t delta) +{ + rng->state + = pcg_advance_lcg_32(rng->state, delta, PCG_DEFAULT_MULTIPLIER_32, 0u); +} + +inline void pcg_unique_32_step_r(struct pcg_state_32* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_32 + + (uint32_t)(((intptr_t)rng) | 1u); +} + +inline void pcg_unique_32_advance_r(struct pcg_state_32* rng, uint32_t delta) +{ + rng->state + = pcg_advance_lcg_32(rng->state, delta, PCG_DEFAULT_MULTIPLIER_32, + (uint32_t)(((intptr_t)rng) | 1u)); +} + +inline void pcg_setseq_32_step_r(struct pcg_state_setseq_32* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_32 + rng->inc; +} + +inline void pcg_setseq_32_advance_r(struct pcg_state_setseq_32* rng, + uint32_t delta) +{ + rng->state = pcg_advance_lcg_32(rng->state, delta, + PCG_DEFAULT_MULTIPLIER_32, rng->inc); +} + +inline void pcg_oneseq_64_step_r(struct pcg_state_64* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_64 + + PCG_DEFAULT_INCREMENT_64; +} + +inline void pcg_oneseq_64_advance_r(struct pcg_state_64* rng, uint64_t delta) +{ + rng->state = pcg_advance_lcg_64( + rng->state, delta, PCG_DEFAULT_MULTIPLIER_64, PCG_DEFAULT_INCREMENT_64); +} + +inline void pcg_mcg_64_step_r(struct pcg_state_64* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_64; +} + +inline void pcg_mcg_64_advance_r(struct pcg_state_64* rng, uint64_t delta) +{ + rng->state + = pcg_advance_lcg_64(rng->state, delta, PCG_DEFAULT_MULTIPLIER_64, 0u); +} + +inline void pcg_unique_64_step_r(struct pcg_state_64* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_64 + + (uint64_t)(((intptr_t)rng) | 1u); +} + +inline void pcg_unique_64_advance_r(struct pcg_state_64* rng, uint64_t delta) +{ + rng->state + = pcg_advance_lcg_64(rng->state, delta, PCG_DEFAULT_MULTIPLIER_64, + (uint64_t)(((intptr_t)rng) | 1u)); +} + +inline void pcg_setseq_64_step_r(struct pcg_state_setseq_64* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_64 + rng->inc; +} + +inline void pcg_setseq_64_advance_r(struct pcg_state_setseq_64* rng, + uint64_t delta) +{ + rng->state = pcg_advance_lcg_64(rng->state, delta, + PCG_DEFAULT_MULTIPLIER_64, rng->inc); +} + +#if PCG_HAS_128BIT_OPS +inline void pcg_oneseq_128_step_r(struct pcg_state_128* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + + PCG_DEFAULT_INCREMENT_128; +} +#endif + +#if PCG_HAS_128BIT_OPS +inline void pcg_oneseq_128_advance_r(struct pcg_state_128* rng, pcg128_t delta) +{ + rng->state + = pcg_advance_lcg_128(rng->state, delta, PCG_DEFAULT_MULTIPLIER_128, + PCG_DEFAULT_INCREMENT_128); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline void pcg_mcg_128_step_r(struct pcg_state_128* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128; +} +#endif + +#if PCG_HAS_128BIT_OPS +inline void pcg_mcg_128_advance_r(struct pcg_state_128* rng, pcg128_t delta) +{ + rng->state = pcg_advance_lcg_128(rng->state, delta, + PCG_DEFAULT_MULTIPLIER_128, 0u); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline void pcg_unique_128_step_r(struct pcg_state_128* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + + (pcg128_t)(((intptr_t)rng) | 1u); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline void pcg_unique_128_advance_r(struct pcg_state_128* rng, pcg128_t delta) +{ + rng->state + = pcg_advance_lcg_128(rng->state, delta, PCG_DEFAULT_MULTIPLIER_128, + (pcg128_t)(((intptr_t)rng) | 1u)); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline void pcg_setseq_128_step_r(struct pcg_state_setseq_128* rng) +{ + rng->state = rng->state * PCG_DEFAULT_MULTIPLIER_128 + rng->inc; +} +#endif + +#if PCG_HAS_128BIT_OPS +inline void pcg_setseq_128_advance_r(struct pcg_state_setseq_128* rng, + pcg128_t delta) +{ + rng->state = pcg_advance_lcg_128(rng->state, delta, + PCG_DEFAULT_MULTIPLIER_128, rng->inc); +} +#endif + +/* Functions to seed the RNG state, one version for each size and each + * style. Unlike the step functions, regular users can and should call + * these functions. + */ + +inline void pcg_oneseq_8_srandom_r(struct pcg_state_8* rng, uint8_t initstate) +{ + rng->state = 0U; + pcg_oneseq_8_step_r(rng); + rng->state += initstate; + pcg_oneseq_8_step_r(rng); +} + +inline void pcg_mcg_8_srandom_r(struct pcg_state_8* rng, uint8_t initstate) +{ + rng->state = initstate | 1u; +} + +inline void pcg_unique_8_srandom_r(struct pcg_state_8* rng, uint8_t initstate) +{ + rng->state = 0U; + pcg_unique_8_step_r(rng); + rng->state += initstate; + pcg_unique_8_step_r(rng); +} + +inline void pcg_setseq_8_srandom_r(struct pcg_state_setseq_8* rng, + uint8_t initstate, uint8_t initseq) +{ + rng->state = 0U; + rng->inc = (initseq << 1u) | 1u; + pcg_setseq_8_step_r(rng); + rng->state += initstate; + pcg_setseq_8_step_r(rng); +} + +inline void pcg_oneseq_16_srandom_r(struct pcg_state_16* rng, + uint16_t initstate) +{ + rng->state = 0U; + pcg_oneseq_16_step_r(rng); + rng->state += initstate; + pcg_oneseq_16_step_r(rng); +} + +inline void pcg_mcg_16_srandom_r(struct pcg_state_16* rng, uint16_t initstate) +{ + rng->state = initstate | 1u; +} + +inline void pcg_unique_16_srandom_r(struct pcg_state_16* rng, + uint16_t initstate) +{ + rng->state = 0U; + pcg_unique_16_step_r(rng); + rng->state += initstate; + pcg_unique_16_step_r(rng); +} + +inline void pcg_setseq_16_srandom_r(struct pcg_state_setseq_16* rng, + uint16_t initstate, uint16_t initseq) +{ + rng->state = 0U; + rng->inc = (initseq << 1u) | 1u; + pcg_setseq_16_step_r(rng); + rng->state += initstate; + pcg_setseq_16_step_r(rng); +} + +inline void pcg_oneseq_32_srandom_r(struct pcg_state_32* rng, + uint32_t initstate) +{ + rng->state = 0U; + pcg_oneseq_32_step_r(rng); + rng->state += initstate; + pcg_oneseq_32_step_r(rng); +} + +inline void pcg_mcg_32_srandom_r(struct pcg_state_32* rng, uint32_t initstate) +{ + rng->state = initstate | 1u; +} + +inline void pcg_unique_32_srandom_r(struct pcg_state_32* rng, + uint32_t initstate) +{ + rng->state = 0U; + pcg_unique_32_step_r(rng); + rng->state += initstate; + pcg_unique_32_step_r(rng); +} + +inline void pcg_setseq_32_srandom_r(struct pcg_state_setseq_32* rng, + uint32_t initstate, uint32_t initseq) +{ + rng->state = 0U; + rng->inc = (initseq << 1u) | 1u; + pcg_setseq_32_step_r(rng); + rng->state += initstate; + pcg_setseq_32_step_r(rng); +} + +inline void pcg_oneseq_64_srandom_r(struct pcg_state_64* rng, + uint64_t initstate) +{ + rng->state = 0U; + pcg_oneseq_64_step_r(rng); + rng->state += initstate; + pcg_oneseq_64_step_r(rng); +} + +inline void pcg_mcg_64_srandom_r(struct pcg_state_64* rng, uint64_t initstate) +{ + rng->state = initstate | 1u; +} + +inline void pcg_unique_64_srandom_r(struct pcg_state_64* rng, + uint64_t initstate) +{ + rng->state = 0U; + pcg_unique_64_step_r(rng); + rng->state += initstate; + pcg_unique_64_step_r(rng); +} + +inline void pcg_setseq_64_srandom_r(struct pcg_state_setseq_64* rng, + uint64_t initstate, uint64_t initseq) +{ + rng->state = 0U; + rng->inc = (initseq << 1u) | 1u; + pcg_setseq_64_step_r(rng); + rng->state += initstate; + pcg_setseq_64_step_r(rng); +} + +#if PCG_HAS_128BIT_OPS +inline void pcg_oneseq_128_srandom_r(struct pcg_state_128* rng, + pcg128_t initstate) +{ + rng->state = 0U; + pcg_oneseq_128_step_r(rng); + rng->state += initstate; + pcg_oneseq_128_step_r(rng); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline void pcg_mcg_128_srandom_r(struct pcg_state_128* rng, pcg128_t initstate) +{ + rng->state = initstate | 1u; +} +#endif + +#if PCG_HAS_128BIT_OPS +inline void pcg_unique_128_srandom_r(struct pcg_state_128* rng, + pcg128_t initstate) +{ + rng->state = 0U; + pcg_unique_128_step_r(rng); + rng->state += initstate; + pcg_unique_128_step_r(rng); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline void pcg_setseq_128_srandom_r(struct pcg_state_setseq_128* rng, + pcg128_t initstate, pcg128_t initseq) +{ + rng->state = 0U; + rng->inc = (initseq << 1u) | 1u; + pcg_setseq_128_step_r(rng); + rng->state += initstate; + pcg_setseq_128_step_r(rng); +} +#endif + +/* Now, finally we create each of the individual generators. We provide + * a random_r function that provides a random number of the appropriate + * type (using the full range of the type) and a boundedrand_r version + * that provides + * + * Implementation notes for boundedrand_r: + * + * To avoid bias, we need to make the range of the RNG a multiple of + * bound, which we do by dropping output less than a threshold. + * Let's consider a 32-bit case... A naive scheme to calculate the + * threshold would be to do + * + * uint32_t threshold = 0x100000000ull % bound; + * + * but 64-bit div/mod is slower than 32-bit div/mod (especially on + * 32-bit platforms). In essence, we do + * + * uint32_t threshold = (0x100000000ull-bound) % bound; + * + * because this version will calculate the same modulus, but the LHS + * value is less than 2^32. + * + * (Note that using modulo is only wise for good RNGs, poorer RNGs + * such as raw LCGs do better using a technique based on division.) + * Empricical tests show that division is preferable to modulus for + * reducting the range of an RNG. It's faster, and sometimes it can + * even be statistically prefereable. + */ + +/* Generation functions for XSH RS */ + +inline uint8_t pcg_oneseq_16_xsh_rs_8_random_r(struct pcg_state_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_oneseq_16_step_r(rng); + return pcg_output_xsh_rs_16_8(oldstate); +} + +inline uint8_t pcg_oneseq_16_xsh_rs_8_boundedrand_r(struct pcg_state_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_oneseq_16_xsh_rs_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t pcg_oneseq_32_xsh_rs_16_random_r(struct pcg_state_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_oneseq_32_step_r(rng); + return pcg_output_xsh_rs_32_16(oldstate); +} + +inline uint16_t pcg_oneseq_32_xsh_rs_16_boundedrand_r(struct pcg_state_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_oneseq_32_xsh_rs_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_oneseq_64_xsh_rs_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_oneseq_64_step_r(rng); + return pcg_output_xsh_rs_64_32(oldstate); +} + +inline uint32_t pcg_oneseq_64_xsh_rs_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_oneseq_64_xsh_rs_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_oneseq_128_xsh_rs_64_random_r(struct pcg_state_128* rng) +{ + pcg_oneseq_128_step_r(rng); + return pcg_output_xsh_rs_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_oneseq_128_xsh_rs_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_oneseq_128_xsh_rs_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint8_t pcg_unique_16_xsh_rs_8_random_r(struct pcg_state_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_unique_16_step_r(rng); + return pcg_output_xsh_rs_16_8(oldstate); +} + +inline uint8_t pcg_unique_16_xsh_rs_8_boundedrand_r(struct pcg_state_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_unique_16_xsh_rs_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t pcg_unique_32_xsh_rs_16_random_r(struct pcg_state_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_unique_32_step_r(rng); + return pcg_output_xsh_rs_32_16(oldstate); +} + +inline uint16_t pcg_unique_32_xsh_rs_16_boundedrand_r(struct pcg_state_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_unique_32_xsh_rs_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_unique_64_xsh_rs_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_unique_64_step_r(rng); + return pcg_output_xsh_rs_64_32(oldstate); +} + +inline uint32_t pcg_unique_64_xsh_rs_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_unique_64_xsh_rs_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_unique_128_xsh_rs_64_random_r(struct pcg_state_128* rng) +{ + pcg_unique_128_step_r(rng); + return pcg_output_xsh_rs_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_unique_128_xsh_rs_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_unique_128_xsh_rs_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint8_t pcg_setseq_16_xsh_rs_8_random_r(struct pcg_state_setseq_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_setseq_16_step_r(rng); + return pcg_output_xsh_rs_16_8(oldstate); +} + +inline uint8_t +pcg_setseq_16_xsh_rs_8_boundedrand_r(struct pcg_state_setseq_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_setseq_16_xsh_rs_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t +pcg_setseq_32_xsh_rs_16_random_r(struct pcg_state_setseq_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_setseq_32_step_r(rng); + return pcg_output_xsh_rs_32_16(oldstate); +} + +inline uint16_t +pcg_setseq_32_xsh_rs_16_boundedrand_r(struct pcg_state_setseq_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_setseq_32_xsh_rs_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t +pcg_setseq_64_xsh_rs_32_random_r(struct pcg_state_setseq_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_setseq_64_step_r(rng); + return pcg_output_xsh_rs_64_32(oldstate); +} + +inline uint32_t +pcg_setseq_64_xsh_rs_32_boundedrand_r(struct pcg_state_setseq_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_setseq_64_xsh_rs_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_setseq_128_xsh_rs_64_random_r(struct pcg_state_setseq_128* rng) +{ + pcg_setseq_128_step_r(rng); + return pcg_output_xsh_rs_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_setseq_128_xsh_rs_64_boundedrand_r(struct pcg_state_setseq_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_setseq_128_xsh_rs_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint8_t pcg_mcg_16_xsh_rs_8_random_r(struct pcg_state_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_mcg_16_step_r(rng); + return pcg_output_xsh_rs_16_8(oldstate); +} + +inline uint8_t pcg_mcg_16_xsh_rs_8_boundedrand_r(struct pcg_state_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_mcg_16_xsh_rs_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t pcg_mcg_32_xsh_rs_16_random_r(struct pcg_state_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_mcg_32_step_r(rng); + return pcg_output_xsh_rs_32_16(oldstate); +} + +inline uint16_t pcg_mcg_32_xsh_rs_16_boundedrand_r(struct pcg_state_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_mcg_32_xsh_rs_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_mcg_64_xsh_rs_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_mcg_64_step_r(rng); + return pcg_output_xsh_rs_64_32(oldstate); +} + +inline uint32_t pcg_mcg_64_xsh_rs_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_mcg_64_xsh_rs_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_mcg_128_xsh_rs_64_random_r(struct pcg_state_128* rng) +{ + pcg_mcg_128_step_r(rng); + return pcg_output_xsh_rs_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_mcg_128_xsh_rs_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_mcg_128_xsh_rs_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +/* Generation functions for XSH RR */ + +inline uint8_t pcg_oneseq_16_xsh_rr_8_random_r(struct pcg_state_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_oneseq_16_step_r(rng); + return pcg_output_xsh_rr_16_8(oldstate); +} + +inline uint8_t pcg_oneseq_16_xsh_rr_8_boundedrand_r(struct pcg_state_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_oneseq_16_xsh_rr_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t pcg_oneseq_32_xsh_rr_16_random_r(struct pcg_state_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_oneseq_32_step_r(rng); + return pcg_output_xsh_rr_32_16(oldstate); +} + +inline uint16_t pcg_oneseq_32_xsh_rr_16_boundedrand_r(struct pcg_state_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_oneseq_32_xsh_rr_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_oneseq_64_xsh_rr_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_oneseq_64_step_r(rng); + return pcg_output_xsh_rr_64_32(oldstate); +} + +inline uint32_t pcg_oneseq_64_xsh_rr_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_oneseq_64_xsh_rr_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_oneseq_128_xsh_rr_64_random_r(struct pcg_state_128* rng) +{ + pcg_oneseq_128_step_r(rng); + return pcg_output_xsh_rr_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_oneseq_128_xsh_rr_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_oneseq_128_xsh_rr_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint8_t pcg_unique_16_xsh_rr_8_random_r(struct pcg_state_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_unique_16_step_r(rng); + return pcg_output_xsh_rr_16_8(oldstate); +} + +inline uint8_t pcg_unique_16_xsh_rr_8_boundedrand_r(struct pcg_state_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_unique_16_xsh_rr_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t pcg_unique_32_xsh_rr_16_random_r(struct pcg_state_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_unique_32_step_r(rng); + return pcg_output_xsh_rr_32_16(oldstate); +} + +inline uint16_t pcg_unique_32_xsh_rr_16_boundedrand_r(struct pcg_state_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_unique_32_xsh_rr_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_unique_64_xsh_rr_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_unique_64_step_r(rng); + return pcg_output_xsh_rr_64_32(oldstate); +} + +inline uint32_t pcg_unique_64_xsh_rr_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_unique_64_xsh_rr_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_unique_128_xsh_rr_64_random_r(struct pcg_state_128* rng) +{ + pcg_unique_128_step_r(rng); + return pcg_output_xsh_rr_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_unique_128_xsh_rr_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_unique_128_xsh_rr_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint8_t pcg_setseq_16_xsh_rr_8_random_r(struct pcg_state_setseq_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_setseq_16_step_r(rng); + return pcg_output_xsh_rr_16_8(oldstate); +} + +inline uint8_t +pcg_setseq_16_xsh_rr_8_boundedrand_r(struct pcg_state_setseq_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_setseq_16_xsh_rr_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t +pcg_setseq_32_xsh_rr_16_random_r(struct pcg_state_setseq_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_setseq_32_step_r(rng); + return pcg_output_xsh_rr_32_16(oldstate); +} + +inline uint16_t +pcg_setseq_32_xsh_rr_16_boundedrand_r(struct pcg_state_setseq_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_setseq_32_xsh_rr_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t +pcg_setseq_64_xsh_rr_32_random_r(struct pcg_state_setseq_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_setseq_64_step_r(rng); + return pcg_output_xsh_rr_64_32(oldstate); +} + +inline uint32_t +pcg_setseq_64_xsh_rr_32_boundedrand_r(struct pcg_state_setseq_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_setseq_64_xsh_rr_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_setseq_128_xsh_rr_64_random_r(struct pcg_state_setseq_128* rng) +{ + pcg_setseq_128_step_r(rng); + return pcg_output_xsh_rr_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_setseq_128_xsh_rr_64_boundedrand_r(struct pcg_state_setseq_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_setseq_128_xsh_rr_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint8_t pcg_mcg_16_xsh_rr_8_random_r(struct pcg_state_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_mcg_16_step_r(rng); + return pcg_output_xsh_rr_16_8(oldstate); +} + +inline uint8_t pcg_mcg_16_xsh_rr_8_boundedrand_r(struct pcg_state_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_mcg_16_xsh_rr_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t pcg_mcg_32_xsh_rr_16_random_r(struct pcg_state_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_mcg_32_step_r(rng); + return pcg_output_xsh_rr_32_16(oldstate); +} + +inline uint16_t pcg_mcg_32_xsh_rr_16_boundedrand_r(struct pcg_state_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_mcg_32_xsh_rr_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_mcg_64_xsh_rr_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_mcg_64_step_r(rng); + return pcg_output_xsh_rr_64_32(oldstate); +} + +inline uint32_t pcg_mcg_64_xsh_rr_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_mcg_64_xsh_rr_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_mcg_128_xsh_rr_64_random_r(struct pcg_state_128* rng) +{ + pcg_mcg_128_step_r(rng); + return pcg_output_xsh_rr_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_mcg_128_xsh_rr_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_mcg_128_xsh_rr_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +/* Generation functions for RXS M XS (no MCG versions because they + * don't make sense when you want to use the entire state) + */ + +inline uint8_t pcg_oneseq_8_rxs_m_xs_8_random_r(struct pcg_state_8* rng) +{ + uint8_t oldstate = rng->state; + pcg_oneseq_8_step_r(rng); + return pcg_output_rxs_m_xs_8_8(oldstate); +} + +inline uint8_t pcg_oneseq_8_rxs_m_xs_8_boundedrand_r(struct pcg_state_8* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_oneseq_8_rxs_m_xs_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t pcg_oneseq_16_rxs_m_xs_16_random_r(struct pcg_state_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_oneseq_16_step_r(rng); + return pcg_output_rxs_m_xs_16_16(oldstate); +} + +inline uint16_t +pcg_oneseq_16_rxs_m_xs_16_boundedrand_r(struct pcg_state_16* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_oneseq_16_rxs_m_xs_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_oneseq_32_rxs_m_xs_32_random_r(struct pcg_state_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_oneseq_32_step_r(rng); + return pcg_output_rxs_m_xs_32_32(oldstate); +} + +inline uint32_t +pcg_oneseq_32_rxs_m_xs_32_boundedrand_r(struct pcg_state_32* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_oneseq_32_rxs_m_xs_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint64_t pcg_oneseq_64_rxs_m_xs_64_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_oneseq_64_step_r(rng); + return pcg_output_rxs_m_xs_64_64(oldstate); +} + +inline uint64_t +pcg_oneseq_64_rxs_m_xs_64_boundedrand_r(struct pcg_state_64* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_oneseq_64_rxs_m_xs_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline pcg128_t pcg_oneseq_128_rxs_m_xs_128_random_r(struct pcg_state_128* rng) +{ + pcg_oneseq_128_step_r(rng); + return pcg_output_rxs_m_xs_128_128(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline pcg128_t +pcg_oneseq_128_rxs_m_xs_128_boundedrand_r(struct pcg_state_128* rng, + pcg128_t bound) +{ + pcg128_t threshold = -bound % bound; + for (;;) { + pcg128_t r = pcg_oneseq_128_rxs_m_xs_128_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint16_t pcg_unique_16_rxs_m_xs_16_random_r(struct pcg_state_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_unique_16_step_r(rng); + return pcg_output_rxs_m_xs_16_16(oldstate); +} + +inline uint16_t +pcg_unique_16_rxs_m_xs_16_boundedrand_r(struct pcg_state_16* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_unique_16_rxs_m_xs_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_unique_32_rxs_m_xs_32_random_r(struct pcg_state_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_unique_32_step_r(rng); + return pcg_output_rxs_m_xs_32_32(oldstate); +} + +inline uint32_t +pcg_unique_32_rxs_m_xs_32_boundedrand_r(struct pcg_state_32* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_unique_32_rxs_m_xs_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint64_t pcg_unique_64_rxs_m_xs_64_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_unique_64_step_r(rng); + return pcg_output_rxs_m_xs_64_64(oldstate); +} + +inline uint64_t +pcg_unique_64_rxs_m_xs_64_boundedrand_r(struct pcg_state_64* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_unique_64_rxs_m_xs_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline pcg128_t pcg_unique_128_rxs_m_xs_128_random_r(struct pcg_state_128* rng) +{ + pcg_unique_128_step_r(rng); + return pcg_output_rxs_m_xs_128_128(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline pcg128_t +pcg_unique_128_rxs_m_xs_128_boundedrand_r(struct pcg_state_128* rng, + pcg128_t bound) +{ + pcg128_t threshold = -bound % bound; + for (;;) { + pcg128_t r = pcg_unique_128_rxs_m_xs_128_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint8_t pcg_setseq_8_rxs_m_xs_8_random_r(struct pcg_state_setseq_8* rng) +{ + uint8_t oldstate = rng->state; + pcg_setseq_8_step_r(rng); + return pcg_output_rxs_m_xs_8_8(oldstate); +} + +inline uint8_t +pcg_setseq_8_rxs_m_xs_8_boundedrand_r(struct pcg_state_setseq_8* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_setseq_8_rxs_m_xs_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t +pcg_setseq_16_rxs_m_xs_16_random_r(struct pcg_state_setseq_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_setseq_16_step_r(rng); + return pcg_output_rxs_m_xs_16_16(oldstate); +} + +inline uint16_t +pcg_setseq_16_rxs_m_xs_16_boundedrand_r(struct pcg_state_setseq_16* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_setseq_16_rxs_m_xs_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t +pcg_setseq_32_rxs_m_xs_32_random_r(struct pcg_state_setseq_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_setseq_32_step_r(rng); + return pcg_output_rxs_m_xs_32_32(oldstate); +} + +inline uint32_t +pcg_setseq_32_rxs_m_xs_32_boundedrand_r(struct pcg_state_setseq_32* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_setseq_32_rxs_m_xs_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint64_t +pcg_setseq_64_rxs_m_xs_64_random_r(struct pcg_state_setseq_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_setseq_64_step_r(rng); + return pcg_output_rxs_m_xs_64_64(oldstate); +} + +inline uint64_t +pcg_setseq_64_rxs_m_xs_64_boundedrand_r(struct pcg_state_setseq_64* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_setseq_64_rxs_m_xs_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline pcg128_t +pcg_setseq_128_rxs_m_xs_128_random_r(struct pcg_state_setseq_128* rng) +{ + pcg_setseq_128_step_r(rng); + return pcg_output_rxs_m_xs_128_128(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline pcg128_t +pcg_setseq_128_rxs_m_xs_128_boundedrand_r(struct pcg_state_setseq_128* rng, + pcg128_t bound) +{ + pcg128_t threshold = -bound % bound; + for (;;) { + pcg128_t r = pcg_setseq_128_rxs_m_xs_128_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +/* Generation functions for RXS M */ + +inline uint8_t pcg_oneseq_16_rxs_m_8_random_r(struct pcg_state_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_oneseq_16_step_r(rng); + return pcg_output_rxs_m_16_8(oldstate); +} + +inline uint8_t pcg_oneseq_16_rxs_m_8_boundedrand_r(struct pcg_state_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_oneseq_16_rxs_m_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t pcg_oneseq_32_rxs_m_16_random_r(struct pcg_state_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_oneseq_32_step_r(rng); + return pcg_output_rxs_m_32_16(oldstate); +} + +inline uint16_t pcg_oneseq_32_rxs_m_16_boundedrand_r(struct pcg_state_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_oneseq_32_rxs_m_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_oneseq_64_rxs_m_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_oneseq_64_step_r(rng); + return pcg_output_rxs_m_64_32(oldstate); +} + +inline uint32_t pcg_oneseq_64_rxs_m_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_oneseq_64_rxs_m_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_oneseq_128_rxs_m_64_random_r(struct pcg_state_128* rng) +{ + pcg_oneseq_128_step_r(rng); + return pcg_output_rxs_m_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_oneseq_128_rxs_m_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_oneseq_128_rxs_m_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint8_t pcg_unique_16_rxs_m_8_random_r(struct pcg_state_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_unique_16_step_r(rng); + return pcg_output_rxs_m_16_8(oldstate); +} + +inline uint8_t pcg_unique_16_rxs_m_8_boundedrand_r(struct pcg_state_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_unique_16_rxs_m_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t pcg_unique_32_rxs_m_16_random_r(struct pcg_state_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_unique_32_step_r(rng); + return pcg_output_rxs_m_32_16(oldstate); +} + +inline uint16_t pcg_unique_32_rxs_m_16_boundedrand_r(struct pcg_state_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_unique_32_rxs_m_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_unique_64_rxs_m_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_unique_64_step_r(rng); + return pcg_output_rxs_m_64_32(oldstate); +} + +inline uint32_t pcg_unique_64_rxs_m_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_unique_64_rxs_m_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_unique_128_rxs_m_64_random_r(struct pcg_state_128* rng) +{ + pcg_unique_128_step_r(rng); + return pcg_output_rxs_m_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_unique_128_rxs_m_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_unique_128_rxs_m_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint8_t pcg_setseq_16_rxs_m_8_random_r(struct pcg_state_setseq_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_setseq_16_step_r(rng); + return pcg_output_rxs_m_16_8(oldstate); +} + +inline uint8_t +pcg_setseq_16_rxs_m_8_boundedrand_r(struct pcg_state_setseq_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_setseq_16_rxs_m_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t pcg_setseq_32_rxs_m_16_random_r(struct pcg_state_setseq_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_setseq_32_step_r(rng); + return pcg_output_rxs_m_32_16(oldstate); +} + +inline uint16_t +pcg_setseq_32_rxs_m_16_boundedrand_r(struct pcg_state_setseq_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_setseq_32_rxs_m_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_setseq_64_rxs_m_32_random_r(struct pcg_state_setseq_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_setseq_64_step_r(rng); + return pcg_output_rxs_m_64_32(oldstate); +} + +inline uint32_t +pcg_setseq_64_rxs_m_32_boundedrand_r(struct pcg_state_setseq_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_setseq_64_rxs_m_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_setseq_128_rxs_m_64_random_r(struct pcg_state_setseq_128* rng) +{ + pcg_setseq_128_step_r(rng); + return pcg_output_rxs_m_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_setseq_128_rxs_m_64_boundedrand_r(struct pcg_state_setseq_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_setseq_128_rxs_m_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint8_t pcg_mcg_16_rxs_m_8_random_r(struct pcg_state_16* rng) +{ + uint16_t oldstate = rng->state; + pcg_mcg_16_step_r(rng); + return pcg_output_rxs_m_16_8(oldstate); +} + +inline uint8_t pcg_mcg_16_rxs_m_8_boundedrand_r(struct pcg_state_16* rng, + uint8_t bound) +{ + uint8_t threshold = ((uint8_t)(-bound)) % bound; + for (;;) { + uint8_t r = pcg_mcg_16_rxs_m_8_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint16_t pcg_mcg_32_rxs_m_16_random_r(struct pcg_state_32* rng) +{ + uint32_t oldstate = rng->state; + pcg_mcg_32_step_r(rng); + return pcg_output_rxs_m_32_16(oldstate); +} + +inline uint16_t pcg_mcg_32_rxs_m_16_boundedrand_r(struct pcg_state_32* rng, + uint16_t bound) +{ + uint16_t threshold = ((uint16_t)(-bound)) % bound; + for (;;) { + uint16_t r = pcg_mcg_32_rxs_m_16_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +inline uint32_t pcg_mcg_64_rxs_m_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_mcg_64_step_r(rng); + return pcg_output_rxs_m_64_32(oldstate); +} + +inline uint32_t pcg_mcg_64_rxs_m_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_mcg_64_rxs_m_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_mcg_128_rxs_m_64_random_r(struct pcg_state_128* rng) +{ + pcg_mcg_128_step_r(rng); + return pcg_output_rxs_m_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_mcg_128_rxs_m_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_mcg_128_rxs_m_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +/* Generation functions for XSL RR (only defined for "large" types) */ + +inline uint32_t pcg_oneseq_64_xsl_rr_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_oneseq_64_step_r(rng); + return pcg_output_xsl_rr_64_32(oldstate); +} + +inline uint32_t pcg_oneseq_64_xsl_rr_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_oneseq_64_xsl_rr_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_oneseq_128_xsl_rr_64_random_r(struct pcg_state_128* rng) +{ + pcg_oneseq_128_step_r(rng); + return pcg_output_xsl_rr_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_oneseq_128_xsl_rr_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_oneseq_128_xsl_rr_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint32_t pcg_unique_64_xsl_rr_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_unique_64_step_r(rng); + return pcg_output_xsl_rr_64_32(oldstate); +} + +inline uint32_t pcg_unique_64_xsl_rr_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_unique_64_xsl_rr_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_unique_128_xsl_rr_64_random_r(struct pcg_state_128* rng) +{ + pcg_unique_128_step_r(rng); + return pcg_output_xsl_rr_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_unique_128_xsl_rr_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_unique_128_xsl_rr_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint32_t +pcg_setseq_64_xsl_rr_32_random_r(struct pcg_state_setseq_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_setseq_64_step_r(rng); + return pcg_output_xsl_rr_64_32(oldstate); +} + +inline uint32_t +pcg_setseq_64_xsl_rr_32_boundedrand_r(struct pcg_state_setseq_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_setseq_64_xsl_rr_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_setseq_128_xsl_rr_64_random_r(struct pcg_state_setseq_128* rng) +{ + pcg_setseq_128_step_r(rng); + return pcg_output_xsl_rr_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t +pcg_setseq_128_xsl_rr_64_boundedrand_r(struct pcg_state_setseq_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_setseq_128_xsl_rr_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint32_t pcg_mcg_64_xsl_rr_32_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_mcg_64_step_r(rng); + return pcg_output_xsl_rr_64_32(oldstate); +} + +inline uint32_t pcg_mcg_64_xsl_rr_32_boundedrand_r(struct pcg_state_64* rng, + uint32_t bound) +{ + uint32_t threshold = -bound % bound; + for (;;) { + uint32_t r = pcg_mcg_64_xsl_rr_32_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_mcg_128_xsl_rr_64_random_r(struct pcg_state_128* rng) +{ + pcg_mcg_128_step_r(rng); + return pcg_output_xsl_rr_128_64(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline uint64_t pcg_mcg_128_xsl_rr_64_boundedrand_r(struct pcg_state_128* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_mcg_128_xsl_rr_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +/* Generation functions for XSL RR RR (only defined for "large" types) */ + +inline uint64_t pcg_oneseq_64_xsl_rr_rr_64_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_oneseq_64_step_r(rng); + return pcg_output_xsl_rr_rr_64_64(oldstate); +} + +inline uint64_t +pcg_oneseq_64_xsl_rr_rr_64_boundedrand_r(struct pcg_state_64* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_oneseq_64_xsl_rr_rr_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline pcg128_t pcg_oneseq_128_xsl_rr_rr_128_random_r(struct pcg_state_128* rng) +{ + pcg_oneseq_128_step_r(rng); + return pcg_output_xsl_rr_rr_128_128(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline pcg128_t +pcg_oneseq_128_xsl_rr_rr_128_boundedrand_r(struct pcg_state_128* rng, + pcg128_t bound) +{ + pcg128_t threshold = -bound % bound; + for (;;) { + pcg128_t r = pcg_oneseq_128_xsl_rr_rr_128_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint64_t pcg_unique_64_xsl_rr_rr_64_random_r(struct pcg_state_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_unique_64_step_r(rng); + return pcg_output_xsl_rr_rr_64_64(oldstate); +} + +inline uint64_t +pcg_unique_64_xsl_rr_rr_64_boundedrand_r(struct pcg_state_64* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_unique_64_xsl_rr_rr_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline pcg128_t pcg_unique_128_xsl_rr_rr_128_random_r(struct pcg_state_128* rng) +{ + pcg_unique_128_step_r(rng); + return pcg_output_xsl_rr_rr_128_128(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline pcg128_t +pcg_unique_128_xsl_rr_rr_128_boundedrand_r(struct pcg_state_128* rng, + pcg128_t bound) +{ + pcg128_t threshold = -bound % bound; + for (;;) { + pcg128_t r = pcg_unique_128_xsl_rr_rr_128_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +inline uint64_t +pcg_setseq_64_xsl_rr_rr_64_random_r(struct pcg_state_setseq_64* rng) +{ + uint64_t oldstate = rng->state; + pcg_setseq_64_step_r(rng); + return pcg_output_xsl_rr_rr_64_64(oldstate); +} + +inline uint64_t +pcg_setseq_64_xsl_rr_rr_64_boundedrand_r(struct pcg_state_setseq_64* rng, + uint64_t bound) +{ + uint64_t threshold = -bound % bound; + for (;;) { + uint64_t r = pcg_setseq_64_xsl_rr_rr_64_random_r(rng); + if (r >= threshold) + return r % bound; + } +} + +#if PCG_HAS_128BIT_OPS +inline pcg128_t +pcg_setseq_128_xsl_rr_rr_128_random_r(struct pcg_state_setseq_128* rng) +{ + pcg_setseq_128_step_r(rng); + return pcg_output_xsl_rr_rr_128_128(rng->state); +} +#endif + +#if PCG_HAS_128BIT_OPS +inline pcg128_t +pcg_setseq_128_xsl_rr_rr_128_boundedrand_r(struct pcg_state_setseq_128* rng, + pcg128_t bound) +{ + pcg128_t threshold = -bound % bound; + for (;;) { + pcg128_t r = pcg_setseq_128_xsl_rr_rr_128_random_r(rng); + if (r >= threshold) + return r % bound; + } +} +#endif + +/*** Typedefs */ +typedef struct pcg_state_setseq_64 pcg32_random_t; +typedef struct pcg_state_64 pcg32s_random_t; +typedef struct pcg_state_64 pcg32u_random_t; +typedef struct pcg_state_64 pcg32f_random_t; +/*** random_r */ +#define pcg32_random_r pcg_setseq_64_xsh_rr_32_random_r +#define pcg32s_random_r pcg_oneseq_64_xsh_rr_32_random_r +#define pcg32u_random_r pcg_unique_64_xsh_rr_32_random_r +#define pcg32f_random_r pcg_mcg_64_xsh_rs_32_random_r +/*** boundedrand_r */ +#define pcg32_boundedrand_r pcg_setseq_64_xsh_rr_32_boundedrand_r +#define pcg32s_boundedrand_r pcg_oneseq_64_xsh_rr_32_boundedrand_r +#define pcg32u_boundedrand_r pcg_unique_64_xsh_rr_32_boundedrand_r +#define pcg32f_boundedrand_r pcg_mcg_64_xsh_rs_32_boundedrand_r +/*** srandom_r */ +#define pcg32_srandom_r pcg_setseq_64_srandom_r +#define pcg32s_srandom_r pcg_oneseq_64_srandom_r +#define pcg32u_srandom_r pcg_unique_64_srandom_r +#define pcg32f_srandom_r pcg_mcg_64_srandom_r +/*** advance_r */ +#define pcg32_advance_r pcg_setseq_64_advance_r +#define pcg32s_advance_r pcg_oneseq_64_advance_r +#define pcg32u_advance_r pcg_unique_64_advance_r +#define pcg32f_advance_r pcg_mcg_64_advance_r + +#if PCG_HAS_128BIT_OPS +/*** Typedefs */ +typedef struct pcg_state_setseq_128 pcg64_random_t; +typedef struct pcg_state_128 pcg64s_random_t; +typedef struct pcg_state_128 pcg64u_random_t; +typedef struct pcg_state_128 pcg64f_random_t; +/*** random_r */ +#define pcg64_random_r pcg_setseq_128_xsl_rr_64_random_r +#define pcg64s_random_r pcg_oneseq_128_xsl_rr_64_random_r +#define pcg64u_random_r pcg_unique_128_xsl_rr_64_random_r +#define pcg64f_random_r pcg_mcg_128_xsl_rr_64_random_r +/*** boundedrand_r */ +#define pcg64_boundedrand_r pcg_setseq_128_xsl_rr_64_boundedrand_r +#define pcg64s_boundedrand_r pcg_oneseq_128_xsl_rr_64_boundedrand_r +#define pcg64u_boundedrand_r pcg_unique_128_xsl_rr_64_boundedrand_r +#define pcg64f_boundedrand_r pcg_mcg_128_xsl_rr_64_boundedrand_r +/*** srandom_r */ +#define pcg64_srandom_r pcg_setseq_128_srandom_r +#define pcg64s_srandom_r pcg_oneseq_128_srandom_r +#define pcg64u_srandom_r pcg_unique_128_srandom_r +#define pcg64f_srandom_r pcg_mcg_128_srandom_r +/*** advance_r */ +#define pcg64_advance_r pcg_setseq_128_advance_r +#define pcg64s_advance_r pcg_oneseq_128_advance_r +#define pcg64u_advance_r pcg_unique_128_advance_r +#define pcg64f_advance_r pcg_mcg_128_advance_r +#endif + +/*** Typedefs */ +typedef struct pcg_state_8 pcg8si_random_t; +typedef struct pcg_state_16 pcg16si_random_t; +typedef struct pcg_state_32 pcg32si_random_t; +typedef struct pcg_state_64 pcg64si_random_t; +/*** random_r */ +#define pcg8si_random_r pcg_oneseq_8_rxs_m_xs_8_random_r +#define pcg16si_random_r pcg_oneseq_16_rxs_m_xs_16_random_r +#define pcg32si_random_r pcg_oneseq_32_rxs_m_xs_32_random_r +#define pcg64si_random_r pcg_oneseq_64_rxs_m_xs_64_random_r +/*** boundedrand_r */ +#define pcg8si_boundedrand_r pcg_oneseq_8_rxs_m_xs_8_boundedrand_r +#define pcg16si_boundedrand_r pcg_oneseq_16_rxs_m_xs_16_boundedrand_r +#define pcg32si_boundedrand_r pcg_oneseq_32_rxs_m_xs_32_boundedrand_r +#define pcg64si_boundedrand_r pcg_oneseq_64_rxs_m_xs_64_boundedrand_r +/*** srandom_r */ +#define pcg8si_srandom_r pcg_oneseq_8_srandom_r +#define pcg16si_srandom_r pcg_oneseq_16_srandom_r +#define pcg32si_srandom_r pcg_oneseq_32_srandom_r +#define pcg64si_srandom_r pcg_oneseq_64_srandom_r +/*** advance_r */ +#define pcg8si_advance_r pcg_oneseq_8_advance_r +#define pcg16si_advance_r pcg_oneseq_16_advance_r +#define pcg32si_advance_r pcg_oneseq_32_advance_r +#define pcg64si_advance_r pcg_oneseq_64_advance_r + +#if PCG_HAS_128BIT_OPS +typedef struct pcg_state_128 pcg128si_random_t; +#define pcg128si_random_r pcg_oneseq_128_rxs_m_xs_128_random_r +#define pcg128si_boundedrand_r pcg_oneseq_128_rxs_m_xs_128_boundedrand_r +#define pcg128si_srandom_r pcg_oneseq_128_srandom_r +#define pcg128si_advance_r pcg_oneseq_128_advance_r +#endif + +/*** Typedefs */ +typedef struct pcg_state_setseq_8 pcg8i_random_t; +typedef struct pcg_state_setseq_16 pcg16i_random_t; +typedef struct pcg_state_setseq_32 pcg32i_random_t; +typedef struct pcg_state_setseq_64 pcg64i_random_t; +/*** random_r */ +#define pcg8i_random_r pcg_setseq_8_rxs_m_xs_8_random_r +#define pcg16i_random_r pcg_setseq_16_rxs_m_xs_16_random_r +#define pcg32i_random_r pcg_setseq_32_rxs_m_xs_32_random_r +#define pcg64i_random_r pcg_setseq_64_rxs_m_xs_64_random_r +/*** boundedrand_r */ +#define pcg8i_boundedrand_r pcg_setseq_8_rxs_m_xs_8_boundedrand_r +#define pcg16i_boundedrand_r pcg_setseq_16_rxs_m_xs_16_boundedrand_r +#define pcg32i_boundedrand_r pcg_setseq_32_rxs_m_xs_32_boundedrand_r +#define pcg64i_boundedrand_r pcg_setseq_64_rxs_m_xs_64_boundedrand_r +/*** srandom_r */ +#define pcg8i_srandom_r pcg_setseq_8_srandom_r +#define pcg16i_srandom_r pcg_setseq_16_srandom_r +#define pcg32i_srandom_r pcg_setseq_32_srandom_r +#define pcg64i_srandom_r pcg_setseq_64_srandom_r +/*** advance_r */ +#define pcg8i_advance_r pcg_setseq_8_advance_r +#define pcg16i_advance_r pcg_setseq_16_advance_r +#define pcg32i_advance_r pcg_setseq_32_advance_r +#define pcg64i_advance_r pcg_setseq_64_advance_r + +#if PCG_HAS_128BIT_OPS +typedef struct pcg_state_setseq_128 pcg128i_random_t; +#define pcg128i_random_r pcg_setseq_128_rxs_m_xs_128_random_r +#define pcg128i_boundedrand_r pcg_setseq_128_rxs_m_xs_128_boundedrand_r +#define pcg128i_srandom_r pcg_setseq_128_srandom_r +#define pcg128i_advance_r pcg_setseq_128_advance_r +#endif + +extern uint32_t pcg32_random(void); +extern uint32_t pcg32_boundedrand(uint32_t bound); +extern void pcg32_srandom(uint64_t seed, uint64_t seq); +extern void pcg32_advance(uint64_t delta); + +#if PCG_HAS_128BIT_OPS +extern uint64_t pcg64_random(void); +extern uint64_t pcg64_boundedrand(uint64_t bound); +extern void pcg64_srandom(pcg128_t seed, pcg128_t seq); +extern void pcg64_advance(pcg128_t delta); +#endif + +/* + * Static initialization constants (if you can't call srandom for some + * bizarre reason). + */ + +#define PCG32_INITIALIZER PCG_STATE_SETSEQ_64_INITIALIZER +#define PCG32U_INITIALIZER PCG_STATE_UNIQUE_64_INITIALIZER +#define PCG32S_INITIALIZER PCG_STATE_ONESEQ_64_INITIALIZER +#define PCG32F_INITIALIZER PCG_STATE_MCG_64_INITIALIZER + +#if PCG_HAS_128BIT_OPS +#define PCG64_INITIALIZER PCG_STATE_SETSEQ_128_INITIALIZER +#define PCG64U_INITIALIZER PCG_STATE_UNIQUE_128_INITIALIZER +#define PCG64S_INITIALIZER PCG_STATE_ONESEQ_128_INITIALIZER +#define PCG64F_INITIALIZER PCG_STATE_MCG_128_INITIALIZER +#endif + +#define PCG8SI_INITIALIZER PCG_STATE_ONESEQ_8_INITIALIZER +#define PCG16SI_INITIALIZER PCG_STATE_ONESEQ_16_INITIALIZER +#define PCG32SI_INITIALIZER PCG_STATE_ONESEQ_32_INITIALIZER +#define PCG64SI_INITIALIZER PCG_STATE_ONESEQ_64_INITIALIZER +#if PCG_HAS_128BIT_OPS +#define PCG128SI_INITIALIZER PCG_STATE_ONESEQ_128_INITIALIZER +#endif + +#define PCG8I_INITIALIZER PCG_STATE_SETSEQ_8_INITIALIZER +#define PCG16I_INITIALIZER PCG_STATE_SETSEQ_16_INITIALIZER +#define PCG32I_INITIALIZER PCG_STATE_SETSEQ_32_INITIALIZER +#define PCG64I_INITIALIZER PCG_STATE_SETSEQ_64_INITIALIZER +#if PCG_HAS_128BIT_OPS +#define PCG128I_INITIALIZER PCG_STATE_SETSEQ_128_INITIALIZER +#endif + +#if __cplusplus +} +#endif + +#endif /* PCG_VARIANTS_H_INCLUDED */ + diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index c3da5eb4cbbe..abe517263706 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -152,6 +152,7 @@ static ACPI_STATUS acpi_device_scan_children(device_t bus, device_t dev, int max_depth, acpi_scan_cb_t user_fn, void *arg); static int acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids); +static void acpi_platform_osc(device_t dev); static void acpi_probe_children(device_t bus); static void acpi_probe_order(ACPI_HANDLE handle, int *order); static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level, @@ -683,6 +684,8 @@ acpi_attach(device_t dev) /* Register ACPI again to pass the correct argument of pm_func. */ power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, sc); + acpi_platform_osc(dev); + if (!acpi_disabled("bus")) { EVENTHANDLER_REGISTER(dev_lookup, acpi_lookup, NULL, 1000); acpi_probe_children(dev); @@ -1943,6 +1946,34 @@ acpi_enable_pcie(void) #endif } +static void +acpi_platform_osc(device_t dev) +{ + ACPI_HANDLE sb_handle; + ACPI_STATUS status; + uint32_t cap_set[2]; + + /* 0811B06E-4A27-44F9-8D60-3CBBC22E7B48 */ + static uint8_t acpi_platform_uuid[ACPI_UUID_LENGTH] = { + 0x6e, 0xb0, 0x11, 0x08, 0x27, 0x4a, 0xf9, 0x44, + 0x8d, 0x60, 0x3c, 0xbb, 0xc2, 0x2e, 0x7b, 0x48 + }; + + if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &sb_handle))) + return; + + cap_set[1] = 0x10; /* APEI Support */ + status = acpi_EvaluateOSC(sb_handle, acpi_platform_uuid, 1, + nitems(cap_set), cap_set, cap_set, false); + if (ACPI_FAILURE(status)) { + if (status == AE_NOT_FOUND) + return; + device_printf(dev, "_OSC failed: %s\n", + AcpiFormatException(status)); + return; + } +} + /* * Scan all of the ACPI namespace and attach child devices. * diff --git a/sys/dev/acpica/acpi_apei.c b/sys/dev/acpica/acpi_apei.c new file mode 100644 index 000000000000..8cdf09ee150c --- /dev/null +++ b/sys/dev/acpica/acpi_apei.c @@ -0,0 +1,684 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2020 Alexander Motin <mav@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_acpi.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/callout.h> +#include <sys/interrupt.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/queue.h> +#include <sys/rman.h> +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> +#include <contrib/dev/acpica/include/aclocal.h> +#include <contrib/dev/acpica/include/actables.h> + +#include <dev/acpica/acpivar.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +struct apei_ge { + union { + ACPI_HEST_GENERIC v1; + ACPI_HEST_GENERIC_V2 v2; + }; + int res_type; + int res_rid; + struct resource *res; + int res2_type; + int res2_rid; + struct resource *res2; + uint8_t *buf, *copybuf; + TAILQ_ENTRY(apei_ge) link; + struct callout poll; + void *swi_ih; +} *apei_nmi_ge; + +struct apei_softc { + ACPI_TABLE_HEST *hest; + TAILQ_HEAD(, apei_ge) ges; +}; + +struct apei_mem_error { + uint64_t ValidationBits; + uint64_t ErrorStatus; + uint64_t PhysicalAddress; + uint64_t PhysicalAddressMask; + uint16_t Node; + uint16_t Card; + uint16_t Module; + uint16_t Bank; + uint16_t Device; + uint16_t Row; + uint16_t Column; + uint16_t BitPosition; + uint64_t RequesterID; + uint64_t ResponderID; + uint64_t TargetID; + uint8_t MemoryErrorType; + uint8_t Extended; + uint16_t RankNumber; + uint16_t CardHandle; + uint16_t ModuleHandle; +}; + +struct apei_pcie_error { + uint64_t ValidationBits; + uint32_t PortType; + uint32_t Version; + uint32_t CommandStatus; + uint32_t Reserved; + uint8_t DeviceID[16]; + uint8_t DeviceSerialNumber[8]; + uint8_t BridgeControlStatus[4]; + uint8_t CapabilityStructure[60]; + uint8_t AERInfo[96]; +}; + +#ifdef __i386__ +static __inline uint64_t +apei_bus_read_8(struct resource *res, bus_size_t offset) +{ + return (bus_read_4(res, offset) | + ((uint64_t)bus_read_4(res, offset + 4)) << 32); +} +static __inline void +apei_bus_write_8(struct resource *res, bus_size_t offset, uint64_t val) +{ + bus_write_4(res, offset, val); + bus_write_4(res, offset + 4, val >> 32); +} +#define READ8(r, o) apei_bus_read_8((r), (o)) +#define WRITE8(r, o, v) apei_bus_write_8((r), (o), (v)) +#else +#define READ8(r, o) bus_read_8((r), (o)) +#define WRITE8(r, o, v) bus_write_8((r), (o), (v)) +#endif + +int apei_nmi_handler(void); + +static const char * +apei_severity(uint32_t s) +{ + switch (s) { + case ACPI_HEST_GEN_ERROR_RECOVERABLE: + return ("Recoverable"); + case ACPI_HEST_GEN_ERROR_FATAL: + return ("Fatal"); + case ACPI_HEST_GEN_ERROR_CORRECTED: + return ("Corrected"); + case ACPI_HEST_GEN_ERROR_NONE: + return ("Informational"); + } + return ("???"); +} + +static int +apei_mem_handler(ACPI_HEST_GENERIC_DATA *ged) +{ + struct apei_mem_error *p = (struct apei_mem_error *)(ged + 1); + + printf("APEI %s Memory Error:\n", apei_severity(ged->ErrorSeverity)); + if (p->ValidationBits & 0x01) + printf(" Error Status: 0x%jx\n", p->ErrorStatus); + if (p->ValidationBits & 0x02) + printf(" Physical Address: 0x%jx\n", p->PhysicalAddress); + if (p->ValidationBits & 0x04) + printf(" Physical Address Mask: 0x%jx\n", p->PhysicalAddressMask); + if (p->ValidationBits & 0x08) + printf(" Node: %u\n", p->Node); + if (p->ValidationBits & 0x10) + printf(" Card: %u\n", p->Card); + if (p->ValidationBits & 0x20) + printf(" Module: %u\n", p->Module); + if (p->ValidationBits & 0x40) + printf(" Bank: %u\n", p->Bank); + if (p->ValidationBits & 0x80) + printf(" Device: %u\n", p->Device); + if (p->ValidationBits & 0x100) + printf(" Row: %u\n", p->Row); + if (p->ValidationBits & 0x200) + printf(" Column: %u\n", p->Column); + if (p->ValidationBits & 0x400) + printf(" Bit Position: %u\n", p->BitPosition); + if (p->ValidationBits & 0x800) + printf(" Requester ID: 0x%jx\n", p->RequesterID); + if (p->ValidationBits & 0x1000) + printf(" Responder ID: 0x%jx\n", p->ResponderID); + if (p->ValidationBits & 0x2000) + printf(" Target ID: 0x%jx\n", p->TargetID); + if (p->ValidationBits & 0x4000) + printf(" Memory Error Type: %u\n", p->MemoryErrorType); + if (p->ValidationBits & 0x8000) + printf(" Rank Number: %u\n", p->RankNumber); + if (p->ValidationBits & 0x10000) + printf(" Card Handle: 0x%x\n", p->CardHandle); + if (p->ValidationBits & 0x20000) + printf(" Module Handle: 0x%x\n", p->ModuleHandle); + if (p->ValidationBits & 0x40000) + printf(" Extended Row: %u\n", + (uint32_t)(p->Extended & 0x3) << 16 | p->Row); + if (p->ValidationBits & 0x80000) + printf(" Bank Group: %u\n", p->Bank >> 8); + if (p->ValidationBits & 0x100000) + printf(" Bank Address: %u\n", p->Bank & 0xff); + if (p->ValidationBits & 0x200000) + printf(" Chip Identification: %u\n", (p->Extended >> 5) & 0x7); + + return (0); +} + +static int +apei_pcie_handler(ACPI_HEST_GENERIC_DATA *ged) +{ + struct apei_pcie_error *p = (struct apei_pcie_error *)(ged + 1); + device_t dev; + int h = 0, off, sev; + + if ((p->ValidationBits & 0x8) == 0x8) { + mtx_lock(&Giant); + dev = pci_find_dbsf((uint32_t)p->DeviceID[10] << 8 | + p->DeviceID[9], p->DeviceID[11], p->DeviceID[8], + p->DeviceID[7]); + if (dev != NULL) { + switch (ged->ErrorSeverity) { + case ACPI_HEST_GEN_ERROR_FATAL: + sev = PCIEM_STA_FATAL_ERROR; + break; + case ACPI_HEST_GEN_ERROR_RECOVERABLE: + sev = PCIEM_STA_NON_FATAL_ERROR; + break; + default: + sev = PCIEM_STA_CORRECTABLE_ERROR; + break; + } + pcie_apei_error(dev, sev, + (p->ValidationBits & 0x80) ? p->AERInfo : NULL); + h = 1; + } + mtx_unlock(&Giant); + } + if (h) + return (h); + + printf("APEI %s PCIe Error:\n", apei_severity(ged->ErrorSeverity)); + if (p->ValidationBits & 0x01) + printf(" Port Type: %u\n", p->PortType); + if (p->ValidationBits & 0x02) + printf(" Version: %x\n", p->Version); + if (p->ValidationBits & 0x04) + printf(" Command Status: 0x%08x\n", p->CommandStatus); + if (p->ValidationBits & 0x08) { + printf(" DeviceID:"); + for (off = 0; off < sizeof(p->DeviceID); off++) + printf(" %02x", p->DeviceID[off]); + printf("\n"); + } + if (p->ValidationBits & 0x10) { + printf(" Device Serial Number:"); + for (off = 0; off < sizeof(p->DeviceSerialNumber); off++) + printf(" %02x", p->DeviceSerialNumber[off]); + printf("\n"); + } + if (p->ValidationBits & 0x20) { + printf(" Bridge Control Status:"); + for (off = 0; off < sizeof(p->BridgeControlStatus); off++) + printf(" %02x", p->BridgeControlStatus[off]); + printf("\n"); + } + if (p->ValidationBits & 0x40) { + printf(" Capability Structure:\n"); + for (off = 0; off < sizeof(p->CapabilityStructure); off++) { + printf(" %02x", p->CapabilityStructure[off]); + if ((off % 16) == 15 || + off + 1 == sizeof(p->CapabilityStructure)) + printf("\n"); + } + } + if (p->ValidationBits & 0x80) { + printf(" AER Info:\n"); + for (off = 0; off < sizeof(p->AERInfo); off++) { + printf(" %02x", p->AERInfo[off]); + if ((off % 16) == 15 || off + 1 == sizeof(p->AERInfo)) + printf("\n"); + } + } + return (h); +} + +static void +apei_ged_handler(ACPI_HEST_GENERIC_DATA *ged) +{ + ACPI_HEST_GENERIC_DATA_V300 *ged3 = (ACPI_HEST_GENERIC_DATA_V300 *)ged; + /* A5BC1114-6F64-4EDE-B863-3E83ED7C83B1 */ + static uint8_t mem_uuid[ACPI_UUID_LENGTH] = { + 0x14, 0x11, 0xBC, 0xA5, 0x64, 0x6F, 0xDE, 0x4E, + 0xB8, 0x63, 0x3E, 0x83, 0xED, 0x7C, 0x83, 0xB1 + }; + /* D995E954-BBC1-430F-AD91-B44DCB3C6F35 */ + static uint8_t pcie_uuid[ACPI_UUID_LENGTH] = { + 0x54, 0xE9, 0x95, 0xD9, 0xC1, 0xBB, 0x0F, 0x43, + 0xAD, 0x91, 0xB4, 0x4D, 0xCB, 0x3C, 0x6F, 0x35 + }; + uint8_t *t; + int h = 0, off; + + if (memcmp(mem_uuid, ged->SectionType, ACPI_UUID_LENGTH) == 0) { + h = apei_mem_handler(ged); + } else if (memcmp(pcie_uuid, ged->SectionType, ACPI_UUID_LENGTH) == 0) { + h = apei_pcie_handler(ged); + } else { + t = ged->SectionType; + printf("APEI %s Error %02x%02x%02x%02x-%02x%02x-" + "%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x:\n", + apei_severity(ged->ErrorSeverity), + t[3], t[2], t[1], t[0], t[5], t[4], t[7], t[6], + t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15]); + printf(" Error Data:\n"); + t = (uint8_t *)(ged + 1); + for (off = 0; off < ged->ErrorDataLength; off++) { + printf(" %02x", t[off]); + if ((off % 16) == 15 || off + 1 == ged->ErrorDataLength) + printf("\n"); + } + } + if (h) + return; + + printf(" Flags: 0x%x\n", ged->Flags); + if (ged->ValidationBits & ACPI_HEST_GEN_VALID_FRU_ID) { + t = ged->FruId; + printf(" FRU Id: %02x%02x%02x%02x-%02x%02x-%02x%02x-" + "%02x%02x-%02x%02x%02x%02x%02x%02x\n", + t[3], t[2], t[1], t[0], t[5], t[4], t[7], t[6], + t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15]); + } + if (ged->ValidationBits & ACPI_HEST_GEN_VALID_FRU_STRING) + printf(" FRU Text: %.20s", ged->FruText); + if (ged->Revision == 0x300 && + ged->ValidationBits & ACPI_HEST_GEN_VALID_TIMESTAMP) + printf(" Timestamp: %016jx", ged3->TimeStamp); +} + +static int +apei_ge_handler(struct apei_ge *ge, bool copy) +{ + uint8_t *buf = copy ? ge->copybuf : ge->buf; + ACPI_HEST_GENERIC_STATUS *ges = (ACPI_HEST_GENERIC_STATUS *)buf; + ACPI_HEST_GENERIC_DATA *ged; + uint32_t sev; + int i, c, off; + + if (ges->BlockStatus == 0) + return (0); + + c = (ges->BlockStatus >> 4) & 0x3ff; + sev = ges->ErrorSeverity; + + /* Process error entries. */ + for (off = i = 0; i < c && off + sizeof(*ged) <= ges->DataLength; i++) { + ged = (ACPI_HEST_GENERIC_DATA *)&buf[sizeof(*ges) + off]; + apei_ged_handler(ged); + off += sizeof(*ged) + ged->ErrorDataLength; + } + + /* Acknowledge the error has been processed. */ + ges->BlockStatus = 0; + if (!copy && ge->v1.Header.Type == ACPI_HEST_TYPE_GENERIC_ERROR_V2) { + uint64_t val = READ8(ge->res2, 0); + val &= ge->v2.ReadAckPreserve; + val |= ge->v2.ReadAckWrite; + WRITE8(ge->res2, 0, val); + } + + /* If ACPI told the error is fatal -- make it so. */ + if (sev == ACPI_HEST_GEN_ERROR_FATAL) + panic("APEI Fatal Hardware Error!"); + + return (1); +} + +static void +apei_nmi_swi(void *arg) +{ + struct apei_ge *ge = arg; + + apei_ge_handler(ge, true); +} + +int +apei_nmi_handler(void) +{ + struct apei_ge *ge = apei_nmi_ge; + ACPI_HEST_GENERIC_STATUS *ges, *gesc; + + if (ge == NULL) + return (0); + + ges = (ACPI_HEST_GENERIC_STATUS *)ge->buf; + if (ges->BlockStatus == 0) + return (0); + + /* If ACPI told the error is fatal -- make it so. */ + if (ges->ErrorSeverity == ACPI_HEST_GEN_ERROR_FATAL) + panic("APEI Fatal Hardware Error!"); + + /* Copy the buffer for later processing. */ + gesc = (ACPI_HEST_GENERIC_STATUS *)ge->copybuf; + if (gesc->BlockStatus == 0) + memcpy(ge->copybuf, ge->buf, ge->v1.ErrorBlockLength); + + /* Acknowledge the error has been processed. */ + ges->BlockStatus = 0; + if (ge->v1.Header.Type == ACPI_HEST_TYPE_GENERIC_ERROR_V2) { + uint64_t val = READ8(ge->res2, 0); + val &= ge->v2.ReadAckPreserve; + val |= ge->v2.ReadAckWrite; + WRITE8(ge->res2, 0, val); + } + + /* Schedule SWI for real handling. */ + swi_sched(ge->swi_ih, SWI_FROMNMI); + + return (1); +} + +static void +apei_callout_handler(void *context) +{ + struct apei_ge *ge = context; + + apei_ge_handler(ge, false); + callout_schedule(&ge->poll, ge->v1.Notify.PollInterval * hz / 1000); +} + +static void +apei_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) +{ + device_t dev = context; + struct apei_softc *sc = device_get_softc(dev); + struct apei_ge *ge; + + TAILQ_FOREACH(ge, &sc->ges, link) { + if (ge->v1.Notify.Type == ACPI_HEST_NOTIFY_SCI || + ge->v1.Notify.Type == ACPI_HEST_NOTIFY_GPIO || + ge->v1.Notify.Type == ACPI_HEST_NOTIFY_GSIV) + apei_ge_handler(ge, false); + } +} + +static int +hest_parse_structure(struct apei_softc *sc, void *addr, int remaining) +{ + ACPI_HEST_HEADER *hdr = addr; + struct apei_ge *ge; + + if (remaining < (int)sizeof(ACPI_HEST_HEADER)) + return (-1); + + switch (hdr->Type) { + case ACPI_HEST_TYPE_IA32_CHECK: { + ACPI_HEST_IA_MACHINE_CHECK *s = addr; + return (sizeof(*s) + s->NumHardwareBanks * + sizeof(ACPI_HEST_IA_ERROR_BANK)); + } + case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: { + ACPI_HEST_IA_CORRECTED *s = addr; + return (sizeof(*s) + s->NumHardwareBanks * + sizeof(ACPI_HEST_IA_ERROR_BANK)); + } + case ACPI_HEST_TYPE_IA32_NMI: { + ACPI_HEST_IA_NMI *s = addr; + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_AER_ROOT_PORT: { + ACPI_HEST_AER_ROOT *s = addr; + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_AER_ENDPOINT: { + ACPI_HEST_AER *s = addr; + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_AER_BRIDGE: { + ACPI_HEST_AER_BRIDGE *s = addr; + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_GENERIC_ERROR: { + ACPI_HEST_GENERIC *s = addr; + ge = malloc(sizeof(*ge), M_DEVBUF, M_WAITOK | M_ZERO); + ge->v1 = *s; + TAILQ_INSERT_TAIL(&sc->ges, ge, link); + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_GENERIC_ERROR_V2: { + ACPI_HEST_GENERIC_V2 *s = addr; + ge = malloc(sizeof(*ge), M_DEVBUF, M_WAITOK | M_ZERO); + ge->v2 = *s; + TAILQ_INSERT_TAIL(&sc->ges, ge, link); + return (sizeof(*s)); + } + case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: { + ACPI_HEST_IA_DEFERRED_CHECK *s = addr; + return (sizeof(*s) + s->NumHardwareBanks * + sizeof(ACPI_HEST_IA_ERROR_BANK)); + } + default: + return (-1); + } +} + +static void +hest_parse_table(struct apei_softc *sc) +{ + ACPI_TABLE_HEST *hest = sc->hest; + char *cp; + int remaining, consumed; + + remaining = hest->Header.Length - sizeof(ACPI_TABLE_HEST); + while (remaining > 0) { + cp = (char *)hest + hest->Header.Length - remaining; + consumed = hest_parse_structure(sc, cp, remaining); + if (consumed <= 0) + break; + else + remaining -= consumed; + } +} + +static char *apei_ids[] = { "PNP0C33", NULL }; +static devclass_t apei_devclass; + +static ACPI_STATUS +apei_find(ACPI_HANDLE handle, UINT32 level, void *context, + void **status) +{ + int *found = (int *)status; + char **ids; + + for (ids = apei_ids; *ids != NULL; ids++) { + if (acpi_MatchHid(handle, *ids)) { + *found = 1; + break; + } + } + return (AE_OK); +} + +static void +apei_identify(driver_t *driver, device_t parent) +{ + device_t child; + int found; + + if (acpi_disabled("apei")) + return; + if (acpi_find_table(ACPI_SIG_HEST) == 0) + return; + /* Only one APEI device can exist. */ + if (devclass_get_device(apei_devclass, 0)) + return; + /* Search for ACPI error device to be used. */ + found = 0; + AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + 100, apei_find, NULL, NULL, (void *)&found); + if (found) + return; + /* If not found - create a fake one. */ + child = BUS_ADD_CHILD(parent, 2, "apei", 0); + if (child == NULL) + printf("%s: can't add child\n", __func__); +} + +static int +apei_probe(device_t dev) +{ + int rv; + + if (acpi_disabled("apei")) + return (ENXIO); + if (acpi_find_table(ACPI_SIG_HEST) == 0) + return (ENXIO); + if (acpi_get_handle(dev) != NULL) + rv = ACPI_ID_PROBE(device_get_parent(dev), dev, apei_ids, NULL); + else + rv = 0; + if (rv <= 0) + device_set_desc(dev, "Platform Error Interface"); + return (rv); +} + +static int +apei_attach(device_t dev) +{ + struct apei_softc *sc = device_get_softc(dev); + struct apei_ge *ge; + ACPI_STATUS status; + int rid; + + TAILQ_INIT(&sc->ges); + + /* Search and parse HEST table. */ + status = AcpiGetTable(ACPI_SIG_HEST, 0, (ACPI_TABLE_HEADER **)&sc->hest); + if (ACPI_FAILURE(status)) + return (ENXIO); + hest_parse_table(sc); + AcpiPutTable((ACPI_TABLE_HEADER *)sc->hest); + + rid = 0; + TAILQ_FOREACH(ge, &sc->ges, link) { + ge->res_rid = rid++; + acpi_bus_alloc_gas(dev, &ge->res_type, &ge->res_rid, + &ge->v1.ErrorStatusAddress, &ge->res, 0); + if (ge->v1.Header.Type == ACPI_HEST_TYPE_GENERIC_ERROR_V2) { + ge->res2_rid = rid++; + acpi_bus_alloc_gas(dev, &ge->res2_type, &ge->res2_rid, + &ge->v2.ReadAckRegister, &ge->res2, 0); + } + ge->buf = pmap_mapdev_attr(READ8(ge->res, 0), + ge->v1.ErrorBlockLength, VM_MEMATTR_WRITE_COMBINING); + if (ge->v1.Notify.Type == ACPI_HEST_NOTIFY_POLLED) { + callout_init(&ge->poll, 1); + callout_reset(&ge->poll, + ge->v1.Notify.PollInterval * hz / 1000, + apei_callout_handler, ge); + } else if (ge->v1.Notify.Type == ACPI_HEST_NOTIFY_NMI) { + ge->copybuf = malloc(ge->v1.ErrorBlockLength, + M_DEVBUF, M_WAITOK | M_ZERO); + swi_add(&clk_intr_event, "apei", apei_nmi_swi, ge, + SWI_CLOCK, INTR_MPSAFE, &ge->swi_ih); + apei_nmi_ge = ge; + apei_nmi = apei_nmi_handler; + } + } + + if (acpi_get_handle(dev) != NULL) { + AcpiInstallNotifyHandler(acpi_get_handle(dev), + ACPI_DEVICE_NOTIFY, apei_notify_handler, dev); + } + return (0); +} + +static int +apei_detach(device_t dev) +{ + struct apei_softc *sc = device_get_softc(dev); + struct apei_ge *ge; + + apei_nmi = NULL; + apei_nmi_ge = NULL; + if (acpi_get_handle(dev) != NULL) { + AcpiRemoveNotifyHandler(acpi_get_handle(dev), + ACPI_DEVICE_NOTIFY, apei_notify_handler); + } + + while ((ge = TAILQ_FIRST(&sc->ges)) != NULL) { + TAILQ_REMOVE(&sc->ges, ge, link); + bus_release_resource(dev, ge->res_type, ge->res_rid, ge->res); + if (ge->res2) { + bus_release_resource(dev, ge->res2_type, + ge->res2_rid, ge->res2); + } + if (ge->v1.Notify.Type == ACPI_HEST_NOTIFY_POLLED) { + callout_drain(&ge->poll); + } else if (ge->v1.Notify.Type == ACPI_HEST_NOTIFY_NMI) { + swi_remove(&ge->swi_ih); + free(ge->copybuf, M_DEVBUF); + } + pmap_unmapdev((vm_offset_t)ge->buf, ge->v1.ErrorBlockLength); + free(ge, M_DEVBUF); + } + return (0); +} + +static device_method_t apei_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, apei_identify), + DEVMETHOD(device_probe, apei_probe), + DEVMETHOD(device_attach, apei_attach), + DEVMETHOD(device_detach, apei_detach), + DEVMETHOD_END +}; + +static driver_t apei_driver = { + "apei", + apei_methods, + sizeof(struct apei_softc), +}; + +DRIVER_MODULE(apei, acpi, apei_driver, apei_devclass, 0, 0); +MODULE_DEPEND(apei, acpi, 1, 1, 1); diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 938d042c66b4..b088b5899dc0 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -10003,10 +10003,6 @@ load_fw(struct adapter *sc, struct t4_data *fw) } fw_data = malloc(fw->len, M_CXGBE, M_WAITOK); - if (fw_data == NULL) { - rc = ENOMEM; - goto done; - } rc = copyin(fw->data, fw_data, fw->len); if (rc == 0) @@ -10035,10 +10031,6 @@ load_cfg(struct adapter *sc, struct t4_data *cfg) } cfg_data = malloc(cfg->len, M_CXGBE, M_WAITOK); - if (cfg_data == NULL) { - rc = ENOMEM; - goto done; - } rc = copyin(cfg->data, cfg_data, cfg->len); if (rc == 0) @@ -10084,10 +10076,6 @@ load_boot(struct adapter *sc, struct t4_bootrom *br) } br_data = malloc(br->len, M_CXGBE, M_WAITOK); - if (br_data == NULL) { - rc = ENOMEM; - goto done; - } rc = copyin(br->data, br_data, br->len); if (rc == 0) @@ -10116,10 +10104,6 @@ load_bootcfg(struct adapter *sc, struct t4_data *bc) } bc_data = malloc(bc->len, M_CXGBE, M_WAITOK); - if (bc_data == NULL) { - rc = ENOMEM; - goto done; - } rc = copyin(bc->data, bc_data, bc->len); if (rc == 0) diff --git a/sys/dev/cy/cy.c b/sys/dev/cy/cy.c deleted file mode 100644 index 3d397ae775cc..000000000000 --- a/sys/dev/cy/cy.c +++ /dev/null @@ -1,2242 +0,0 @@ -/*- - * cyclades cyclom-y serial driver - * Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993 - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1993 Andrew Herbert. - * 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. The name Andrew Herbert may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * 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. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * TODO: - * Atomic COR change. - * Consoles. - */ - -/* - * Temporary compile-time configuration options. - */ -#define RxFifoThreshold (CD1400_RX_FIFO_SIZE / 2) - /* Number of chars in the receiver FIFO before an - * an interrupt is generated. Should depend on - * line speed. Needs to be about 6 on a 486DX33 - * for 4 active ports at 115200 bps. Why doesn't - * 10 work? - */ -#define PollMode /* Use polling-based irq service routine, not the - * hardware svcack lines. Must be defined for - * Cyclom-16Y boards. Less efficient for Cyclom-8Ys, - * and stops 4 * 115200 bps from working. - */ -#undef Smarts /* Enable slightly more CD1400 intelligence. Mainly - * the output CR/LF processing, plus we can avoid a - * few checks usually done in ttyinput(). - * - * XXX not fully implemented, and not particularly - * worthwhile. - */ -#undef CyDebug /* Include debugging code (not very expensive). */ - -/* These will go away. */ -#undef SOFT_CTS_OFLOW -#define SOFT_HOTCHAR - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/fcntl.h> -#include <sys/interrupt.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/serial.h> -#include <sys/syslog.h> -#include <sys/tty.h> - -#include <machine/psl.h> - -#include <dev/ic/cd1400.h> - -#include <dev/cy/cyreg.h> -#include <dev/cy/cyvar.h> - -#define NCY 10 /* KLUDGE */ - -#define NPORTS (NCY * CY_MAX_PORTS) - -#define CY_MAX_PORTS (CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s) - -/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ -#define CD1400_xIVR_CHAN_SHIFT 3 -#define CD1400_xIVR_CHAN 0x1F - -/* - * ETC states. com->etc may also contain a hardware ETC command value, - * meaning that execution of that command is pending. - */ -#define ETC_NONE 0 /* we depend on bzero() setting this */ -#define ETC_BREAK_STARTING 1 -#define ETC_BREAK_STARTED 2 -#define ETC_BREAK_ENDING 3 -#define ETC_BREAK_ENDED 4 - -#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ - -/* - * com state bits. - * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher - * than the other bits so that they can be tested as a group without masking - * off the low bits. - * - * The following com and tty flags correspond closely: - * CS_BUSY = TS_BUSY (maintained by cystart(), cypoll() and - * comstop()) - * CS_TTGO = ~TS_TTSTOP (maintained by cyparam() and cystart()) - * CS_CTS_OFLOW = CCTS_OFLOW (maintained by cyparam()) - * CS_RTS_IFLOW = CRTS_IFLOW (maintained by cyparam()) - * TS_FLUSH is not used. - * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. - * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). - */ -#define CS_BUSY 0x80 /* output in progress */ -#define CS_TTGO 0x40 /* output not stopped by XOFF */ -#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ -#define CS_CHECKMSR 1 /* check of MSR scheduled */ -#define CS_CTS_OFLOW 2 /* use CTS output flow control */ -#define CS_ODONE 4 /* output completed */ -#define CS_RTS_IFLOW 8 /* use RTS input flow control */ -#define CSE_ODONE 1 /* output transmitted */ - -static char const * const error_desc[] = { -#define CE_OVERRUN 0 - "silo overflow", -#define CE_INTERRUPT_BUF_OVERFLOW 1 - "interrupt-level buffer overflow", -#define CE_TTY_BUF_OVERFLOW 2 - "tty-level buffer overflow", -}; - -#define CE_NTYPES 3 -#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) - -#ifdef SMP -#define COM_LOCK() mtx_lock_spin(&cy_lock) -#define COM_UNLOCK() mtx_unlock_spin(&cy_lock) -#else -#define COM_LOCK() -#define COM_UNLOCK() -#endif - -/* types. XXX - should be elsewhere */ -typedef u_char bool_t; /* boolean */ - -/* queue of linear buffers */ -struct lbq { - u_char *l_head; /* next char to process */ - u_char *l_tail; /* one past the last char to process */ - struct lbq *l_next; /* next in queue */ - bool_t l_queued; /* nonzero if queued */ -}; - -/* com device structure */ -struct com_s { - u_char state; /* miscellaneous flag bits */ - u_char etc; /* pending Embedded Transmit Command */ - u_char extra_state; /* more flag bits, separate for order trick */ - u_char gfrcr_image; /* copy of value read from GFRCR */ - u_char mcr_dtr; /* MCR bit that is wired to DTR */ - u_char mcr_image; /* copy of value written to MCR */ - u_char mcr_rts; /* MCR bit that is wired to RTS */ - int unit; /* unit number */ - - /* - * The high level of the driver never reads status registers directly - * because there would be too many side effects to handle conveniently. - * Instead, it reads copies of the registers stored here by the - * interrupt handler. - */ - u_char last_modem_status; /* last MSR read by intr handler */ - u_char prev_modem_status; /* last MSR handled by high level */ - - u_char *ibuf; /* start of input buffer */ - u_char *ibufend; /* end of input buffer */ - u_char *ibufold; /* old input buffer, to be freed */ - u_char *ihighwater; /* threshold in input buffer */ - u_char *iptr; /* next free spot in input buffer */ - int ibufsize; /* size of ibuf (not include error bytes) */ - int ierroff; /* offset of error bytes in ibuf */ - - struct lbq obufq; /* head of queue of output buffers */ - struct lbq obufs[2]; /* output buffers */ - - int cy_align; /* index for register alignment */ - cy_addr cy_iobase; /* base address of this port's cyclom */ - cy_addr iobase; /* base address of this port's cd1400 */ - int mcr_rts_reg; /* cd1400 reg number of reg holding mcr_rts */ - - struct tty *tp; /* cross reference */ - - u_long bytes_in; /* statistics */ - u_long bytes_out; - u_int delta_error_counts[CE_NTYPES]; - u_long error_counts[CE_NTYPES]; - - u_int recv_exception; /* exception chars received */ - u_int mdm; /* modem signal changes */ -#ifdef CyDebug - u_int start_count; /* no. of calls to cystart() */ - u_int start_real; /* no. of calls that did something */ -#endif - u_char car; /* CD1400 CAR shadow (if first unit in cd) */ - u_char channel_control;/* CD1400 CCR control command shadow */ - u_char cor[3]; /* CD1400 COR1-3 shadows */ - u_char intr_enable; /* CD1400 SRER shadow */ - - /* - * Data area for output buffers. Someday we should build the output - * buffer queue without copying data. - */ - u_char obuf1[256]; - u_char obuf2[256]; -}; - -devclass_t cy_devclass; -char cy_driver_name[] = "cy"; - -static void cd1400_channel_cmd(struct com_s *com, int cmd); -static void cd1400_channel_cmd_wait(struct com_s *com); -static void cd_etc(struct com_s *com, int etc); -static int cd_getreg(struct com_s *com, int reg); -static void cd_setreg(struct com_s *com, int reg, int val); -static void cyinput(struct com_s *com); -static int cyparam(struct tty *tp, struct termios *t); -static void cypoll(void *arg); -static void cysettimeout(void); -static int cysetwater(struct com_s *com, speed_t speed); -static int cyspeed(speed_t speed, u_long cy_clock, int *prescaler_io); -static void cystart(struct tty *tp); -static void comstop(struct tty *tp, int rw); -static timeout_t cywakeup; -static void disc_optim(struct tty *tp, struct termios *t, - struct com_s *com); - -static t_break_t cybreak; -static t_modem_t cymodem; -static t_open_t cyopen; -static t_close_t cyclose; - -#ifdef CyDebug -void cystatus(int unit); -#endif - -static struct mtx cy_lock; -static int cy_inited; - -/* table and macro for fast conversion from a unit number to its com struct */ -static struct com_s *p_cy_addr[NPORTS]; -#define cy_addr(unit) (p_cy_addr[unit]) - -static u_int cy_events; /* input chars + weighted output completions */ -static void *cy_fast_ih; -static void *cy_slow_ih; -static int cy_timeout; -static int cy_timeouts_until_log; -static struct callout_handle cy_timeout_handle - = CALLOUT_HANDLE_INITIALIZER(&cy_timeout_handle); - -#ifdef CyDebug -static u_int cd_inbs; -static u_int cy_inbs; -static u_int cd_outbs; -static u_int cy_outbs; -static u_int cy_svrr_probes; -static u_int cy_timeouts; -#endif - -static int cy_chip_offset[] = { - 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00, -}; -static int cy_nr_cd1400s[NCY]; -static int cy_total_devices; -#undef RxFifoThreshold -static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); - -int -cy_units(cy_addr cy_iobase, int cy_align) -{ - int cyu; - u_char firmware_version; - int i; - cy_addr iobase; - - for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { - iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align); - - /* wait for chip to become ready for new command */ - for (i = 0; i < 10; i++) { - DELAY(50); - if (!cd_inb(iobase, CD1400_CCR, cy_align)) - break; - } - - /* clear the GFRCR register */ - cd_outb(iobase, CD1400_GFRCR, cy_align, 0); - - /* issue a reset command */ - cd_outb(iobase, CD1400_CCR, cy_align, - CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); - - /* XXX bogus initialization to avoid a gcc bug/warning. */ - firmware_version = 0; - - /* wait for the CD1400 to initialize itself */ - for (i = 0; i < 200; i++) { - DELAY(50); - - /* retrieve firmware version */ - firmware_version = cd_inb(iobase, CD1400_GFRCR, - cy_align); - if ((firmware_version & 0xf0) == 0x40) - break; - } - - /* - * Anything in the 0x40-0x4F range is fine. - * If one CD1400 is bad then we don't support higher - * numbered good ones on this board. - */ - if ((firmware_version & 0xf0) != 0x40) - break; - } - return (cyu); -} - -void * -cyattach_common(cy_addr cy_iobase, int cy_align) -{ - int adapter; - int cyu; - u_char firmware_version; - cy_addr iobase; - int ncyu; - int unit; - struct tty *tp; - - while (cy_inited != 2) - if (atomic_cmpset_int(&cy_inited, 0, 1)) { - mtx_init(&cy_lock, cy_driver_name, NULL, MTX_SPIN); - atomic_store_rel_int(&cy_inited, 2); - } - - adapter = cy_total_devices; - if ((u_int)adapter >= NCY) { - printf( - "cy%d: can't attach adapter: insufficient cy devices configured\n", - adapter); - return (NULL); - } - ncyu = cy_units(cy_iobase, cy_align); - if (ncyu == 0) - return (NULL); - cy_nr_cd1400s[adapter] = ncyu; - cy_total_devices++; - - unit = adapter * CY_MAX_PORTS; - for (cyu = 0; cyu < ncyu; ++cyu) { - int cdu; - - iobase = (cy_addr) (cy_iobase - + (cy_chip_offset[cyu] << cy_align)); - firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); - - /* Set up a receive timeout period of than 1+ ms. */ - cd_outb(iobase, CD1400_PPR, cy_align, - howmany(CY_CLOCK(firmware_version) - / CD1400_PPR_PRESCALER, 1000)); - - for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { - struct com_s *com; - int s; - - com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT | M_ZERO); - if (com == NULL) - break; - com->unit = unit; - com->gfrcr_image = firmware_version; - if (CY_RTS_DTR_SWAPPED(firmware_version)) { - com->mcr_dtr = CD1400_MSVR1_RTS; - com->mcr_rts = CD1400_MSVR2_DTR; - com->mcr_rts_reg = CD1400_MSVR2; - } else { - com->mcr_dtr = CD1400_MSVR2_DTR; - com->mcr_rts = CD1400_MSVR1_RTS; - com->mcr_rts_reg = CD1400_MSVR1; - } - com->obufs[0].l_head = com->obuf1; - com->obufs[1].l_head = com->obuf2; - - com->cy_align = cy_align; - com->cy_iobase = cy_iobase; - com->iobase = iobase; - com->car = ~CD1400_CAR_CHAN; - - tp = com->tp = ttyalloc(); - tp->t_open = cyopen; - tp->t_close = cyclose; - tp->t_oproc = cystart; - tp->t_stop = comstop; - tp->t_param = cyparam; - tp->t_break = cybreak; - tp->t_modem = cymodem; - tp->t_sc = com; - - if (cysetwater(com, tp->t_init_in.c_ispeed) != 0) { - free(com, M_DEVBUF); - return (NULL); - } - - s = spltty(); - cy_addr(unit) = com; - splx(s); - - if (cy_fast_ih == NULL) { - swi_add(&tty_intr_event, "cy", cypoll, NULL, SWI_TTY, 0, - &cy_fast_ih); - swi_add(&clk_intr_event, "cy", cypoll, NULL, SWI_CLOCK, 0, - &cy_slow_ih); - } - ttycreate(tp, TS_CALLOUT, "c%r%r", - adapter, unit % CY_MAX_PORTS); - } - } - - /* ensure an edge for the next interrupt */ - cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); - - return (cy_addr(adapter * CY_MAX_PORTS)); -} - -static int -cyopen(struct tty *tp, struct cdev *dev) -{ - struct com_s *com; - int s; - - com = tp->t_sc; - s = spltty(); - /* - * We jump to this label after all non-interrupted sleeps to pick - * up any changes of the device state. - */ - - /* Encode per-board unit in LIVR for access in intr routines. */ - cd_setreg(com, CD1400_LIVR, - (com->unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); - - /* - * Flush fifos. This requires a full channel reset which - * also disables the transmitter and receiver. Recover - * from this. - */ - cd1400_channel_cmd(com, - CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); - cd1400_channel_cmd(com, com->channel_control); - - critical_enter(); - COM_LOCK(); - com->prev_modem_status = com->last_modem_status - = cd_getreg(com, CD1400_MSVR2); - cd_setreg(com, CD1400_SRER, - com->intr_enable - = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); - COM_UNLOCK(); - critical_exit(); - cysettimeout(); - return (0); -} - - -static void -cyclose(struct tty *tp) -{ - cy_addr iobase; - struct com_s *com; - int s; - int unit; - - com = tp->t_sc; - unit = com->unit; - iobase = com->iobase; - s = spltty(); - /* XXX */ - critical_enter(); - COM_LOCK(); - com->etc = ETC_NONE; - cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); - COM_UNLOCK(); - critical_exit(); - cd_etc(com, CD1400_ETC_STOPBREAK); - cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); - - { - critical_enter(); - COM_LOCK(); - cd_setreg(com, CD1400_SRER, com->intr_enable = 0); - COM_UNLOCK(); - critical_exit(); - tp = com->tp; - if ((tp->t_cflag & HUPCL) - /* - * XXX we will miss any carrier drop between here and the - * next open. Perhaps we should watch DCD even when the - * port is closed; it is not sufficient to check it at - * the next open because it might go up and down while - * we're not watching. - */ - || (!tp->t_actout - && !(com->prev_modem_status & CD1400_MSVR2_CD) - && !(tp->t_init_in.c_cflag & CLOCAL)) - || !(tp->t_state & TS_ISOPEN)) { - (void)cymodem(tp, 0, SER_DTR); - - /* Disable receiver (leave transmitter enabled). */ - com->channel_control = CD1400_CCR_CMDCHANCTL - | CD1400_CCR_XMTEN - | CD1400_CCR_RCVDIS; - cd1400_channel_cmd(com, com->channel_control); - - ttydtrwaitstart(tp); - } - } - tp->t_actout = FALSE; - wakeup(&tp->t_actout); - wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ - splx(s); -} - -/* - * This function: - * a) needs to be called with COM_LOCK() held, and - * b) needs to return with COM_LOCK() held. - */ -static void -cyinput(struct com_s *com) -{ - u_char *buf; - int incc; - u_char line_status; - int recv_data; - struct tty *tp; - - buf = com->ibuf; - tp = com->tp; - if (!(tp->t_state & TS_ISOPEN)) { - cy_events -= (com->iptr - com->ibuf); - com->iptr = com->ibuf; - return; - } - if (tp->t_state & TS_CAN_BYPASS_L_RINT) { - /* - * Avoid the grotesquely inefficient lineswitch routine - * (ttyinput) in "raw" mode. It usually takes about 450 - * instructions (that's without canonical processing or echo!). - * slinput is reasonably fast (usually 40 instructions plus - * call overhead). - */ - - do { - /* - * This may look odd, but it is using save-and-enable - * semantics instead of the save-and-disable semantics - * that are used everywhere else. - */ - COM_UNLOCK(); - critical_exit(); - incc = com->iptr - buf; - if (tp->t_rawq.c_cc + incc > tp->t_ihiwat - && (com->state & CS_RTS_IFLOW - || tp->t_iflag & IXOFF) - && !(tp->t_state & TS_TBLOCK)) - ttyblock(tp); - com->delta_error_counts[CE_TTY_BUF_OVERFLOW] - += b_to_q((char *)buf, incc, &tp->t_rawq); - buf += incc; - tk_nin += incc; - tk_rawcc += incc; - tp->t_rawcc += incc; - ttwakeup(tp); - if (tp->t_state & TS_TTSTOP - && (tp->t_iflag & IXANY - || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { - tp->t_state &= ~TS_TTSTOP; - tp->t_lflag &= ~FLUSHO; - cystart(tp); - } - critical_enter(); - COM_LOCK(); - } while (buf < com->iptr); - } else { - do { - /* - * This may look odd, but it is using save-and-enable - * semantics instead of the save-and-disable semantics - * that are used everywhere else. - */ - COM_UNLOCK(); - critical_exit(); - line_status = buf[com->ierroff]; - recv_data = *buf++; - if (line_status - & (CD1400_RDSR_BREAK | CD1400_RDSR_FE | CD1400_RDSR_OE | CD1400_RDSR_PE)) { - if (line_status & CD1400_RDSR_BREAK) - recv_data |= TTY_BI; - if (line_status & CD1400_RDSR_FE) - recv_data |= TTY_FE; - if (line_status & CD1400_RDSR_OE) - recv_data |= TTY_OE; - if (line_status & CD1400_RDSR_PE) - recv_data |= TTY_PE; - } - ttyld_rint(tp, recv_data); - critical_enter(); - COM_LOCK(); - } while (buf < com->iptr); - } - cy_events -= (com->iptr - com->ibuf); - com->iptr = com->ibuf; - - /* - * There is now room for another low-level buffer full of input, - * so enable RTS if it is now disabled and there is room in the - * high-level buffer. - */ - if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) && - !(tp->t_state & TS_TBLOCK)) - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); -} - -int -cyintr(void *vcom) -{ - struct com_s *basecom; - int baseu; - int cy_align; - cy_addr cy_iobase; - int cyu; - cy_addr iobase; - u_char status; - int unit; - - COM_LOCK(); /* XXX could this be placed down lower in the loop? */ - - basecom = (struct com_s *)vcom; - baseu = basecom->unit; - cy_align = basecom->cy_align; - cy_iobase = basecom->cy_iobase; - unit = baseu / CY_MAX_PORTS; - - /* check each CD1400 in turn */ - for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { - iobase = (cy_addr) (cy_iobase - + (cy_chip_offset[cyu] << cy_align)); - /* poll to see if it has any work */ - status = cd_inb(iobase, CD1400_SVRR, cy_align); - if (status == 0) - continue; // XXX - FILTER_STRAY? -#ifdef CyDebug - ++cy_svrr_probes; -#endif - /* service requests as appropriate, giving priority to RX */ - if (status & CD1400_SVRR_RXRDY) { - struct com_s *com; - u_int count; - u_char *ioptr; - u_char line_status; - u_char recv_data; - u_char serv_type; -#ifdef PollMode - u_char save_rir; -#endif - -#ifdef PollMode - save_rir = cd_inb(iobase, CD1400_RIR, cy_align); - - /* enter rx service */ - cd_outb(iobase, CD1400_CAR, cy_align, save_rir); - cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_rir & CD1400_CAR_CHAN; - - serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); - com = cy_addr(baseu - + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) - & CD1400_xIVR_CHAN)); -#else - /* ack receive service */ - serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); - - com = cy_addr(baseu + - + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) - & CD1400_xIVR_CHAN)); -#endif - - if (serv_type & CD1400_RIVR_EXCEPTION) { - ++com->recv_exception; - line_status = cd_inb(iobase, CD1400_RDSR, cy_align); - /* break/unnattached error bits or real input? */ - recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); -#ifndef SOFT_HOTCHAR - if (line_status & CD1400_RDSR_SPECIAL - && com->tp->t_hotchar != 0) - swi_sched(cy_fast_ih, 0); - -#endif -#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ - if (line_status & (CD1400_RDSR_PE|CD1400_RDSR_FE|CD1400_RDSR_BREAK)) { - /* - Don't store PE if IGNPAR and BI if IGNBRK, - this hack allows "raw" tty optimization - works even if IGN* is set. - */ - if ( com->tp == NULL - || !(com->tp->t_state & TS_ISOPEN) - || ((line_status & (CD1400_RDSR_PE|CD1400_RDSR_FE)) - && (com->tp->t_iflag & IGNPAR)) - || ((line_status & CD1400_RDSR_BREAK) - && (com->tp->t_iflag & IGNBRK))) - goto cont; - if ( (line_status & (CD1400_RDSR_PE|CD1400_RDSR_FE)) - && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) - && ((line_status & CD1400_RDSR_FE) - || ((line_status & CD1400_RDSR_PE) - && (com->tp->t_iflag & INPCK)))) - recv_data = 0; - } -#endif /* 1 */ - ++com->bytes_in; -#ifdef SOFT_HOTCHAR - if (com->tp->t_hotchar != 0 && recv_data == com->tp->t_hotchar) - swi_sched(cy_fast_ih, 0); -#endif - ioptr = com->iptr; - if (ioptr >= com->ibufend) - CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); - else { - if (com->tp != NULL && com->tp->t_do_timestamp) - microtime(&com->tp->t_timestamp); - ++cy_events; - ioptr[0] = recv_data; - ioptr[com->ierroff] = line_status; - com->iptr = ++ioptr; - if (ioptr == com->ihighwater - && com->state & CS_RTS_IFLOW) - cd_outb(iobase, com->mcr_rts_reg, - cy_align, - com->mcr_image &= - ~com->mcr_rts); - if (line_status & CD1400_RDSR_OE) - CE_RECORD(com, CE_OVERRUN); - } - goto cont; - } else { - int ifree; - - count = cd_inb(iobase, CD1400_RDCR, cy_align); - if (!count) - goto cont; - com->bytes_in += count; - ioptr = com->iptr; - ifree = com->ibufend - ioptr; - if (count > ifree) { - count -= ifree; - cy_events += ifree; - if (ifree != 0) { - if (com->tp != NULL && com->tp->t_do_timestamp) - microtime(&com->tp->t_timestamp); - do { - recv_data = cd_inb(iobase, - CD1400_RDSR, - cy_align); -#ifdef SOFT_HOTCHAR - if (com->tp->t_hotchar != 0 - && recv_data - == com->tp->t_hotchar) - swi_sched(cy_fast_ih, - 0); -#endif - ioptr[0] = recv_data; - ioptr[com->ierroff] = 0; - ++ioptr; - } while (--ifree != 0); - } - com->delta_error_counts - [CE_INTERRUPT_BUF_OVERFLOW] += count; - do { - recv_data = cd_inb(iobase, CD1400_RDSR, - cy_align); -#ifdef SOFT_HOTCHAR - if (com->tp->t_hotchar != 0 - && recv_data == com->tp->t_hotchar) - swi_sched(cy_fast_ih, 0); -#endif - } while (--count != 0); - } else { - if (com->tp != NULL && com->tp->t_do_timestamp) - microtime(&com->tp->t_timestamp); - if (ioptr <= com->ihighwater - && ioptr + count > com->ihighwater - && com->state & CS_RTS_IFLOW) - cd_outb(iobase, com->mcr_rts_reg, - cy_align, - com->mcr_image - &= ~com->mcr_rts); - cy_events += count; - do { - recv_data = cd_inb(iobase, CD1400_RDSR, - cy_align); -#ifdef SOFT_HOTCHAR - if (com->tp->t_hotchar != 0 - && recv_data == com->tp->t_hotchar) - swi_sched(cy_fast_ih, 0); -#endif - ioptr[0] = recv_data; - ioptr[com->ierroff] = 0; - ++ioptr; - } while (--count != 0); - } - com->iptr = ioptr; - } -cont: - - /* terminate service context */ -#ifdef PollMode - cd_outb(iobase, CD1400_RIR, cy_align, - save_rir - & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); -#else - cd_outb(iobase, CD1400_EOSRR, cy_align, 0); -#endif - } - if (status & CD1400_SVRR_MDMCH) { - struct com_s *com; - u_char modem_status; -#ifdef PollMode - u_char save_mir; -#else - u_char vector; -#endif - -#ifdef PollMode - save_mir = cd_inb(iobase, CD1400_MIR, cy_align); - - /* enter modem service */ - cd_outb(iobase, CD1400_CAR, cy_align, save_mir); - cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_mir & CD1400_CAR_CHAN; - - com = cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS - + (save_mir & CD1400_MIR_CHAN)); -#else - /* ack modem service */ - vector = cy_inb(iobase, CY8_SVCACKM, cy_align); - - com = cy_addr(baseu - + ((vector >> CD1400_xIVR_CHAN_SHIFT) - & CD1400_xIVR_CHAN)); -#endif - ++com->mdm; - modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align); - if (modem_status != com->last_modem_status) { - /* - * Schedule high level to handle DCD changes. Note - * that we don't use the delta bits anywhere. Some - * UARTs mess them up, and it's easy to remember the - * previous bits and calculate the delta. - */ - com->last_modem_status = modem_status; - if (!(com->state & CS_CHECKMSR)) { - cy_events += LOTS_OF_EVENTS; - com->state |= CS_CHECKMSR; - swi_sched(cy_fast_ih, 0); - } - -#ifdef SOFT_CTS_OFLOW - /* handle CTS change immediately for crisp flow ctl */ - if (com->state & CS_CTS_OFLOW) { - if (modem_status & CD1400_MSVR2_CTS) { - com->state |= CS_ODEVREADY; - if (com->state >= (CS_BUSY | CS_TTGO - | CS_ODEVREADY) - && !(com->intr_enable - & CD1400_SRER_TXRDY)) - cd_outb(iobase, CD1400_SRER, - cy_align, - com->intr_enable - = com->intr_enable - & ~CD1400_SRER_TXMPTY - | CD1400_SRER_TXRDY); - } else { - com->state &= ~CS_ODEVREADY; - if (com->intr_enable - & CD1400_SRER_TXRDY) - cd_outb(iobase, CD1400_SRER, - cy_align, - com->intr_enable - = com->intr_enable - & ~CD1400_SRER_TXRDY - | CD1400_SRER_TXMPTY); - } - } -#endif - } - - /* terminate service context */ -#ifdef PollMode - cd_outb(iobase, CD1400_MIR, cy_align, - save_mir - & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); -#else - cd_outb(iobase, CD1400_EOSRR, cy_align, 0); -#endif - } - if (status & CD1400_SVRR_TXRDY) { - struct com_s *com; -#ifdef PollMode - u_char save_tir; -#else - u_char vector; -#endif - -#ifdef PollMode - save_tir = cd_inb(iobase, CD1400_TIR, cy_align); - - /* enter tx service */ - cd_outb(iobase, CD1400_CAR, cy_align, save_tir); - cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_tir & CD1400_CAR_CHAN; - - com = cy_addr(baseu - + cyu * CD1400_NO_OF_CHANNELS - + (save_tir & CD1400_TIR_CHAN)); -#else - /* ack transmit service */ - vector = cy_inb(iobase, CY8_SVCACKT, cy_align); - - com = cy_addr(baseu - + ((vector >> CD1400_xIVR_CHAN_SHIFT) - & CD1400_xIVR_CHAN)); -#endif - - if (com->etc != ETC_NONE) { - if (com->intr_enable & CD1400_SRER_TXRDY) { - /* - * Here due to sloppy SRER_TXRDY - * enabling. Ignore. Come back when - * tx is empty. - */ - cd_outb(iobase, CD1400_SRER, cy_align, - com->intr_enable - = (com->intr_enable - & ~CD1400_SRER_TXRDY) - | CD1400_SRER_TXMPTY); - goto terminate_tx_service; - } - switch (com->etc) { - case CD1400_ETC_SENDBREAK: - case CD1400_ETC_STOPBREAK: - /* - * Start the command. Come back on - * next tx empty interrupt, hopefully - * after command has been executed. - */ - cd_outb(iobase, CD1400_COR2, cy_align, - com->cor[1] |= CD1400_COR2_ETC); - cd_outb(iobase, CD1400_TDR, cy_align, - CD1400_ETC_CMD); - cd_outb(iobase, CD1400_TDR, cy_align, - com->etc); - if (com->etc == CD1400_ETC_SENDBREAK) - com->etc = ETC_BREAK_STARTING; - else - com->etc = ETC_BREAK_ENDING; - goto terminate_tx_service; - case ETC_BREAK_STARTING: - /* - * BREAK is now on. Continue with - * SRER_TXMPTY processing, hopefully - * don't come back. - */ - com->etc = ETC_BREAK_STARTED; - break; - case ETC_BREAK_STARTED: - /* - * Came back due to sloppy SRER_TXMPTY - * enabling. Hope again. - */ - break; - case ETC_BREAK_ENDING: - /* - * BREAK is now off. Continue with - * SRER_TXMPTY processing and don't - * come back. The SWI handler will - * restart tx interrupts if necessary. - */ - cd_outb(iobase, CD1400_COR2, cy_align, - com->cor[1] - &= ~CD1400_COR2_ETC); - com->etc = ETC_BREAK_ENDED; - if (!(com->state & CS_ODONE)) { - cy_events += LOTS_OF_EVENTS; - com->state |= CS_ODONE; - swi_sched(cy_fast_ih, 0); - } - break; - case ETC_BREAK_ENDED: - /* - * Shouldn't get here. Hope again. - */ - break; - } - } - if (com->intr_enable & CD1400_SRER_TXMPTY) { - if (!(com->extra_state & CSE_ODONE)) { - cy_events += LOTS_OF_EVENTS; - com->extra_state |= CSE_ODONE; - swi_sched(cy_fast_ih, 0); - } - cd_outb(iobase, CD1400_SRER, cy_align, - com->intr_enable - &= ~CD1400_SRER_TXMPTY); - goto terminate_tx_service; - } - if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { - u_char *ioptr; - u_int ocount; - - ioptr = com->obufq.l_head; - ocount = com->obufq.l_tail - ioptr; - if (ocount > CD1400_TX_FIFO_SIZE) - ocount = CD1400_TX_FIFO_SIZE; - com->bytes_out += ocount; - do - cd_outb(iobase, CD1400_TDR, cy_align, - *ioptr++); - while (--ocount != 0); - com->obufq.l_head = ioptr; - if (ioptr >= com->obufq.l_tail) { - struct lbq *qp; - - qp = com->obufq.l_next; - qp->l_queued = FALSE; - qp = qp->l_next; - if (qp != NULL) { - com->obufq.l_head = qp->l_head; - com->obufq.l_tail = qp->l_tail; - com->obufq.l_next = qp; - } else { - /* output just completed */ - com->state &= ~CS_BUSY; - - /* - * The setting of CSE_ODONE may be - * stale here. We currently only - * use it when CS_BUSY is set, and - * fixing it when we clear CS_BUSY - * is easiest. - */ - if (com->extra_state & CSE_ODONE) { - cy_events -= LOTS_OF_EVENTS; - com->extra_state &= ~CSE_ODONE; - } - - cd_outb(iobase, CD1400_SRER, cy_align, - com->intr_enable - = (com->intr_enable - & ~CD1400_SRER_TXRDY) - | CD1400_SRER_TXMPTY); - } - if (!(com->state & CS_ODONE)) { - cy_events += LOTS_OF_EVENTS; - com->state |= CS_ODONE; - - /* handle at high level ASAP */ - swi_sched(cy_fast_ih, 0); - } - } - } - - /* terminate service context */ -terminate_tx_service: -#ifdef PollMode - cd_outb(iobase, CD1400_TIR, cy_align, - save_tir - & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); -#else - cd_outb(iobase, CD1400_EOSRR, cy_align, 0); -#endif - } - } - - /* ensure an edge for the next interrupt */ - cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); - - swi_sched(cy_slow_ih, SWI_DELAY); - - COM_UNLOCK(); - return (FILTER_HANDLED); -} - -static void -cybreak(struct tty *tp, int sig) -{ - struct com_s *com; - - com = tp->t_sc; - if (sig) - cd_etc(com, CD1400_ETC_SENDBREAK); - else - cd_etc(com, CD1400_ETC_STOPBREAK); -} - -static void -cypoll(void *arg) -{ - int unit; - -#ifdef CyDebug - ++cy_timeouts; -#endif - if (cy_events == 0) - return; -repeat: - for (unit = 0; unit < NPORTS; ++unit) { - struct com_s *com; - int incc; - struct tty *tp; - - com = cy_addr(unit); - if (com == NULL) - continue; - tp = com->tp; - if (tp == NULL) { - /* - * XXX forget any events related to closed devices - * (actually never opened devices) so that we don't - * loop. - */ - critical_enter(); - COM_LOCK(); - incc = com->iptr - com->ibuf; - com->iptr = com->ibuf; - if (com->state & CS_CHECKMSR) { - incc += LOTS_OF_EVENTS; - com->state &= ~CS_CHECKMSR; - } - cy_events -= incc; - COM_UNLOCK(); - critical_exit(); - if (incc != 0) - log(LOG_DEBUG, - "cy%d: %d events for device with no tp\n", - unit, incc); - continue; - } - if (com->iptr != com->ibuf) { - critical_enter(); - COM_LOCK(); - cyinput(com); - COM_UNLOCK(); - critical_exit(); - } - if (com->state & CS_CHECKMSR) { - u_char delta_modem_status; - - critical_enter(); - COM_LOCK(); - cyinput(com); - delta_modem_status = com->last_modem_status - ^ com->prev_modem_status; - com->prev_modem_status = com->last_modem_status; - cy_events -= LOTS_OF_EVENTS; - com->state &= ~CS_CHECKMSR; - COM_UNLOCK(); - critical_exit(); - if (delta_modem_status & CD1400_MSVR2_CD) - ttyld_modem(tp, - com->prev_modem_status & CD1400_MSVR2_CD); - } - if (com->extra_state & CSE_ODONE) { - critical_enter(); - COM_LOCK(); - cy_events -= LOTS_OF_EVENTS; - com->extra_state &= ~CSE_ODONE; - COM_UNLOCK(); - critical_exit(); - if (!(com->state & CS_BUSY)) { - tp->t_state &= ~TS_BUSY; - ttwwakeup(com->tp); - } - if (com->etc != ETC_NONE) { - if (com->etc == ETC_BREAK_ENDED) - com->etc = ETC_NONE; - wakeup(&com->etc); - } - } - if (com->state & CS_ODONE) { - critical_enter(); - COM_LOCK(); - cy_events -= LOTS_OF_EVENTS; - com->state &= ~CS_ODONE; - COM_UNLOCK(); - critical_exit(); - ttyld_start(tp); - } - if (cy_events == 0) - break; - } - if (cy_events >= LOTS_OF_EVENTS) - goto repeat; -} - -static int -cyparam(struct tty *tp, struct termios *t) -{ - int bits; - int cflag; - struct com_s *com; - u_char cor_change; - u_long cy_clock; - int idivisor; - int iflag; - int iprescaler; - int itimeout; - int odivisor; - int oprescaler; - u_char opt; - int s; - - com = tp->t_sc; - - /* check requested parameters */ - cy_clock = CY_CLOCK(com->gfrcr_image); - idivisor = cyspeed(t->c_ispeed, cy_clock, &iprescaler); - if (idivisor <= 0) - return (EINVAL); - odivisor = cyspeed(t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed, - cy_clock, &oprescaler); - if (odivisor <= 0) - return (EINVAL); - - /* parameters are OK, convert them to the com struct and the device */ - s = spltty(); - if (t->c_ospeed == 0) - (void)cymodem(tp, 0, SER_DTR); - else - (void)cymodem(tp, SER_DTR, 0); - - (void) cysetwater(com, t->c_ispeed); - - /* XXX we don't actually change the speed atomically. */ - - cd_setreg(com, CD1400_RBPR, idivisor); - cd_setreg(com, CD1400_RCOR, iprescaler); - cd_setreg(com, CD1400_TBPR, odivisor); - cd_setreg(com, CD1400_TCOR, oprescaler); - - /* - * channel control - * receiver enable - * transmitter enable (always set) - */ - cflag = t->c_cflag; - opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN - | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); - if (opt != com->channel_control) { - com->channel_control = opt; - cd1400_channel_cmd(com, opt); - } - -#ifdef Smarts - /* set special chars */ - /* XXX if one is _POSIX_VDISABLE, can't use some others */ - if (t->c_cc[VSTOP] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); - if (t->c_cc[VSTART] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); - if (t->c_cc[VINTR] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); - if (t->c_cc[VSUSP] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); -#endif - - /* - * set channel option register 1 - - * parity mode - * stop bits - * char length - */ - opt = 0; - /* parity */ - if (cflag & PARENB) { - if (cflag & PARODD) - opt |= CD1400_COR1_PARODD; - opt |= CD1400_COR1_PARNORMAL; - } - iflag = t->c_iflag; - if (!(iflag & INPCK)) - opt |= CD1400_COR1_NOINPCK; - bits = 1 + 1; - /* stop bits */ - if (cflag & CSTOPB) { - ++bits; - opt |= CD1400_COR1_STOP2; - } - /* char length */ - switch (cflag & CSIZE) { - case CS5: - bits += 5; - opt |= CD1400_COR1_CS5; - break; - case CS6: - bits += 6; - opt |= CD1400_COR1_CS6; - break; - case CS7: - bits += 7; - opt |= CD1400_COR1_CS7; - break; - default: - bits += 8; - opt |= CD1400_COR1_CS8; - break; - } - cor_change = 0; - if (opt != com->cor[0]) { - cor_change |= CD1400_CCR_COR1; - cd_setreg(com, CD1400_COR1, com->cor[0] = opt); - } - - /* - * Set receive time-out period, normally to max(one char time, 5 ms). - */ - itimeout = howmany(1000 * bits, t->c_ispeed); -#ifdef SOFT_HOTCHAR -#define MIN_RTP 1 -#else -#define MIN_RTP 5 -#endif - if (itimeout < MIN_RTP) - itimeout = MIN_RTP; - if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 - && t->c_cc[VTIME] * 10 > itimeout) - itimeout = t->c_cc[VTIME] * 10; - if (itimeout > 255) - itimeout = 255; - cd_setreg(com, CD1400_RTPR, itimeout); - - /* - * set channel option register 2 - - * flow control - */ - opt = 0; -#ifdef Smarts - if (iflag & IXANY) - opt |= CD1400_COR2_IXANY; - if (iflag & IXOFF) - opt |= CD1400_COR2_IXOFF; -#endif -#ifndef SOFT_CTS_OFLOW - if (cflag & CCTS_OFLOW) - opt |= CD1400_COR2_CCTS_OFLOW; -#endif - critical_enter(); - COM_LOCK(); - if (opt != com->cor[1]) { - cor_change |= CD1400_CCR_COR2; - cd_setreg(com, CD1400_COR2, com->cor[1] = opt); - } - COM_UNLOCK(); - critical_exit(); - - /* - * set channel option register 3 - - * receiver FIFO interrupt threshold - * flow control - */ - opt = RxFifoThreshold; -#ifdef Smarts - if (t->c_lflag & ICANON) - opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ - if (iflag & IXOFF) - /* detect and transparently handle START and STOP chars */ - opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; -#endif - if (opt != com->cor[2]) { - cor_change |= CD1400_CCR_COR3; - cd_setreg(com, CD1400_COR3, com->cor[2] = opt); - } - - /* notify the CD1400 if COR1-3 have changed */ - if (cor_change) - cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); - - /* - * set channel option register 4 - - * CR/NL processing - * break processing - * received exception processing - */ - opt = 0; - if (iflag & IGNCR) - opt |= CD1400_COR4_IGNCR; -#ifdef Smarts - /* - * we need a new ttyinput() for this, as we don't want to - * have ICRNL && INLCR being done in both layers, or to have - * synchronisation problems - */ - if (iflag & ICRNL) - opt |= CD1400_COR4_ICRNL; - if (iflag & INLCR) - opt |= CD1400_COR4_INLCR; -#endif - if (iflag & IGNBRK) - opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; - /* - * The `-ignbrk -brkint parmrk' case is not handled by the hardware, - * so only tell the hardware about -brkint if -parmrk. - */ - if (!(iflag & (BRKINT | PARMRK))) - opt |= CD1400_COR4_NOBRKINT; -#if 0 - /* XXX using this "intelligence" breaks reporting of overruns. */ - if (iflag & IGNPAR) - opt |= CD1400_COR4_PFO_DISCARD; - else { - if (iflag & PARMRK) - opt |= CD1400_COR4_PFO_ESC; - else - opt |= CD1400_COR4_PFO_NUL; - } -#else - opt |= CD1400_COR4_PFO_EXCEPTION; -#endif - cd_setreg(com, CD1400_COR4, opt); - - /* - * set channel option register 5 - - */ - opt = 0; - if (iflag & ISTRIP) - opt |= CD1400_COR5_ISTRIP; - if (t->c_iflag & IEXTEN) - /* enable LNEXT (e.g. ctrl-v quoting) handling */ - opt |= CD1400_COR5_LNEXT; -#ifdef Smarts - if (t->c_oflag & ONLCR) - opt |= CD1400_COR5_ONLCR; - if (t->c_oflag & OCRNL) - opt |= CD1400_COR5_OCRNL; -#endif - cd_setreg(com, CD1400_COR5, opt); - - /* - * We always generate modem status change interrupts for CD changes. - * Among other things, this is necessary to track TS_CARR_ON for - * pstat to print even when the driver doesn't care. CD changes - * should be rare so interrupts for them are not worth extra code to - * avoid. We avoid interrupts for other modem status changes (except - * for CTS changes when SOFT_CTS_OFLOW is configured) since this is - * simplest and best. - */ - - /* - * set modem change option register 1 - * generate modem interrupts on which 1 -> 0 input transitions - * also controls auto-DTR output flow-control, which we don't use - */ - opt = CD1400_MCOR1_CDzd; -#ifdef SOFT_CTS_OFLOW - if (cflag & CCTS_OFLOW) - opt |= CD1400_MCOR1_CTSzd; -#endif - cd_setreg(com, CD1400_MCOR1, opt); - - /* - * set modem change option register 2 - * generate modem interrupts on specific 0 -> 1 input transitions - */ - opt = CD1400_MCOR2_CDod; -#ifdef SOFT_CTS_OFLOW - if (cflag & CCTS_OFLOW) - opt |= CD1400_MCOR2_CTSod; -#endif - cd_setreg(com, CD1400_MCOR2, opt); - - /* - * XXX should have done this long ago, but there is too much state - * to change all atomically. - */ - critical_enter(); - COM_LOCK(); - - com->state &= ~CS_TTGO; - if (!(tp->t_state & TS_TTSTOP)) - com->state |= CS_TTGO; - if (cflag & CRTS_IFLOW) { - com->state |= CS_RTS_IFLOW; - /* - * If CS_RTS_IFLOW just changed from off to on, the change - * needs to be propagated to CD1400_MSVR1_RTS. This isn't urgent, - * so do it later by calling cystart() instead of repeating - * a lot of code from cystart() here. - */ - } else if (com->state & CS_RTS_IFLOW) { - com->state &= ~CS_RTS_IFLOW; - /* - * CS_RTS_IFLOW just changed from on to off. Force CD1400_MSVR1_RTS - * on here, since cystart() won't do it later. - */ - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); - } - - /* - * Set up state to handle output flow control. - * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? - * Now has 10+ msec latency, while CTS flow has 50- usec latency. - */ - com->state |= CS_ODEVREADY; -#ifdef SOFT_CTS_OFLOW - com->state &= ~CS_CTS_OFLOW; - if (cflag & CCTS_OFLOW) { - com->state |= CS_CTS_OFLOW; - if (!(com->last_modem_status & CD1400_MSVR2_CTS)) - com->state &= ~CS_ODEVREADY; - } -#endif - /* XXX shouldn't call functions while intrs are disabled. */ - disc_optim(tp, t, com); -#if 0 - /* - * Recover from fiddling with CS_TTGO. We used to call cyintr1() - * unconditionally, but that defeated the careful discarding of - * stale input in cyopen(). - */ - if (com->state >= (CS_BUSY | CS_TTGO)) - cyintr1(com); -#endif - if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { - if (!(com->intr_enable & CD1400_SRER_TXRDY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable & ~CD1400_SRER_TXMPTY) - | CD1400_SRER_TXRDY); - } else { - if (com->intr_enable & CD1400_SRER_TXRDY) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable & ~CD1400_SRER_TXRDY) - | CD1400_SRER_TXMPTY); - } - - COM_UNLOCK(); - critical_exit(); - splx(s); - cystart(tp); - if (com->ibufold != NULL) { - free(com->ibufold, M_DEVBUF); - com->ibufold = NULL; - } - return (0); -} - -static int -cysetwater(struct com_s *com, speed_t speed) -{ - int cp4ticks; - u_char *ibuf; - int ibufsize; - struct tty *tp; - - /* - * Make the buffer size large enough to handle a softtty interrupt - * latency of about 2 ticks without loss of throughput or data - * (about 3 ticks if input flow control is not used or not honoured, - * but a bit less for CS5-CS7 modes). - */ - cp4ticks = speed / 10 / hz * 4; - for (ibufsize = 128; ibufsize < cp4ticks;) - ibufsize <<= 1; - if (ibufsize == com->ibufsize) { - return (0); - } - - /* - * Allocate input buffer. The extra factor of 2 in the size is - * to allow for an error byte for each input byte. - */ - ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); - if (ibuf == NULL) { - return (ENOMEM); - } - - /* Initialize non-critical variables. */ - com->ibufold = com->ibuf; - com->ibufsize = ibufsize; - tp = com->tp; - if (tp != NULL) { - tp->t_ififosize = 2 * ibufsize; - tp->t_ispeedwat = (speed_t)-1; - tp->t_ospeedwat = (speed_t)-1; - } - - /* - * Read current input buffer, if any. Continue with interrupts - * disabled. - */ - critical_enter(); - COM_LOCK(); - if (com->iptr != com->ibuf) - cyinput(com); - - /*- - * Initialize critical variables, including input buffer watermarks. - * The external device is asked to stop sending when the buffer - * exactly reaches high water, or when the high level requests it. - * The high level is notified immediately (rather than at a later - * clock tick) when this watermark is reached. - * The buffer size is chosen so the watermark should almost never - * be reached. - * The low watermark is invisibly 0 since the buffer is always - * emptied all at once. - */ - com->iptr = com->ibuf = ibuf; - com->ibufend = ibuf + ibufsize; - com->ierroff = ibufsize; - com->ihighwater = ibuf + 3 * ibufsize / 4; - - COM_UNLOCK(); - critical_exit(); - return (0); -} - -static void -cystart(struct tty *tp) -{ - struct com_s *com; - int s; -#ifdef CyDebug - bool_t started; -#endif - - com = tp->t_sc; - s = spltty(); - -#ifdef CyDebug - ++com->start_count; - started = FALSE; -#endif - - critical_enter(); - COM_LOCK(); - if (tp->t_state & TS_TTSTOP) { - com->state &= ~CS_TTGO; - if (com->intr_enable & CD1400_SRER_TXRDY) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable & ~CD1400_SRER_TXRDY) - | CD1400_SRER_TXMPTY); - } else { - com->state |= CS_TTGO; - if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) - && !(com->intr_enable & CD1400_SRER_TXRDY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable & ~CD1400_SRER_TXMPTY) - | CD1400_SRER_TXRDY); - } - if (tp->t_state & TS_TBLOCK) { - if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) -#if 0 - outb(com->modem_ctl_port, com->mcr_image &= ~CD1400_MSVR1_RTS); -#else - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image &= ~com->mcr_rts); -#endif - } else { - if (!(com->mcr_image & com->mcr_rts) - && com->iptr < com->ihighwater - && com->state & CS_RTS_IFLOW) -#if 0 - outb(com->modem_ctl_port, com->mcr_image |= CD1400_MSVR1_RTS); -#else - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); -#endif - } - COM_UNLOCK(); - critical_exit(); - if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { - ttwwakeup(tp); - splx(s); - return; - } - if (tp->t_outq.c_cc != 0) { - struct lbq *qp; - struct lbq *next; - - if (!com->obufs[0].l_queued) { -#ifdef CyDebug - started = TRUE; -#endif - com->obufs[0].l_tail - = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, - sizeof com->obuf1); - com->obufs[0].l_next = NULL; - com->obufs[0].l_queued = TRUE; - critical_enter(); - COM_LOCK(); - if (com->state & CS_BUSY) { - qp = com->obufq.l_next; - while ((next = qp->l_next) != NULL) - qp = next; - qp->l_next = &com->obufs[0]; - } else { - com->obufq.l_head = com->obufs[0].l_head; - com->obufq.l_tail = com->obufs[0].l_tail; - com->obufq.l_next = &com->obufs[0]; - com->state |= CS_BUSY; - if (com->state >= (CS_BUSY | CS_TTGO - | CS_ODEVREADY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable - & ~CD1400_SRER_TXMPTY) - | CD1400_SRER_TXRDY); - } - COM_UNLOCK(); - critical_exit(); - } - if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { -#ifdef CyDebug - started = TRUE; -#endif - com->obufs[1].l_tail - = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, - sizeof com->obuf2); - com->obufs[1].l_next = NULL; - com->obufs[1].l_queued = TRUE; - critical_enter(); - COM_LOCK(); - if (com->state & CS_BUSY) { - qp = com->obufq.l_next; - while ((next = qp->l_next) != NULL) - qp = next; - qp->l_next = &com->obufs[1]; - } else { - com->obufq.l_head = com->obufs[1].l_head; - com->obufq.l_tail = com->obufs[1].l_tail; - com->obufq.l_next = &com->obufs[1]; - com->state |= CS_BUSY; - if (com->state >= (CS_BUSY | CS_TTGO - | CS_ODEVREADY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable - & ~CD1400_SRER_TXMPTY) - | CD1400_SRER_TXRDY); - } - COM_UNLOCK(); - critical_exit(); - } - tp->t_state |= TS_BUSY; - } -#ifdef CyDebug - if (started) - ++com->start_real; -#endif -#if 0 - critical_enter(); - COM_LOCK(); - if (com->state >= (CS_BUSY | CS_TTGO)) - cyintr1(com); /* fake interrupt to start output */ - COM_UNLOCK(); - critical_exit(); -#endif - ttwwakeup(tp); - splx(s); -} - -static void -comstop(struct tty *tp, int rw) -{ - struct com_s *com; - bool_t wakeup_etc; - - com = tp->t_sc; - wakeup_etc = FALSE; - critical_enter(); - COM_LOCK(); - if (rw & FWRITE) { - com->obufs[0].l_queued = FALSE; - com->obufs[1].l_queued = FALSE; - if (com->extra_state & CSE_ODONE) { - cy_events -= LOTS_OF_EVENTS; - com->extra_state &= ~CSE_ODONE; - if (com->etc != ETC_NONE) { - if (com->etc == ETC_BREAK_ENDED) - com->etc = ETC_NONE; - wakeup_etc = TRUE; - } - } - com->tp->t_state &= ~TS_BUSY; - if (com->state & CS_ODONE) - cy_events -= LOTS_OF_EVENTS; - com->state &= ~(CS_ODONE | CS_BUSY); - } - if (rw & FREAD) { - /* XXX no way to reset only input fifo. */ - cy_events -= (com->iptr - com->ibuf); - com->iptr = com->ibuf; - } - COM_UNLOCK(); - critical_exit(); - if (wakeup_etc) - wakeup(&com->etc); - if (rw & FWRITE && com->etc == ETC_NONE) - cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); - cystart(tp); -} - -static int -cymodem(struct tty *tp, int sigon, int sigoff) -{ - struct com_s *com; - int mcr; - int msr; - - com = tp->t_sc; - if (sigon == 0 && sigoff == 0) { - sigon = 0; - mcr = com->mcr_image; - if (mcr & com->mcr_dtr) - sigon |= SER_DTR; - if (mcr & com->mcr_rts) - /* XXX wired on for Cyclom-8Ys */ - sigon |= SER_RTS; - - /* - * We must read the modem status from the hardware because - * we don't generate modem status change interrupts for all - * changes, so com->prev_modem_status is not guaranteed to - * be up to date. This is safe, unlike for sio, because - * reading the status register doesn't clear pending modem - * status change interrupts. - */ - msr = cd_getreg(com, CD1400_MSVR2); - - if (msr & CD1400_MSVR2_CTS) - sigon |= SER_CTS; - if (msr & CD1400_MSVR2_CD) - sigon |= SER_DCD; - if (msr & CD1400_MSVR2_DSR) - sigon |= SER_DSR; - if (msr & CD1400_MSVR2_RI) - /* XXX not connected except for Cyclom-16Y? */ - sigon |= SER_RI; - return (sigon); - } - mcr = com->mcr_image; - if (sigon & SER_DTR) - mcr |= com->mcr_dtr; - if (sigoff & SER_DTR) - mcr &= ~com->mcr_dtr; - if (sigon & SER_RTS) - mcr |= com->mcr_rts; - if (sigoff & SER_RTS) - mcr &= ~com->mcr_rts; - critical_enter(); - COM_LOCK(); - com->mcr_image = mcr; - cd_setreg(com, CD1400_MSVR1, mcr); - cd_setreg(com, CD1400_MSVR2, mcr); - COM_UNLOCK(); - critical_exit(); - return (0); -} - -static void -cysettimeout() -{ - struct com_s *com; - bool_t someopen; - int unit; - - /* - * Set our timeout period to 1 second if no polled devices are open. - * Otherwise set it to max(1/200, 1/hz). - * Enable timeouts iff some device is open. - */ - untimeout(cywakeup, (void *)NULL, cy_timeout_handle); - cy_timeout = hz; - someopen = FALSE; - for (unit = 0; unit < NPORTS; ++unit) { - com = cy_addr(unit); - if (com != NULL && com->tp != NULL - && com->tp->t_state & TS_ISOPEN) { - someopen = TRUE; - } - } - if (someopen) { - cy_timeouts_until_log = hz / cy_timeout; - cy_timeout_handle = timeout(cywakeup, (void *)NULL, - cy_timeout); - } else { - /* Flush error messages, if any. */ - cy_timeouts_until_log = 1; - cywakeup((void *)NULL); - untimeout(cywakeup, (void *)NULL, cy_timeout_handle); - } -} - -static void -cywakeup(void *chan) -{ - struct com_s *com; - int unit; - - cy_timeout_handle = timeout(cywakeup, (void *)NULL, cy_timeout); - - /* - * Check for and log errors, but not too often. - */ - if (--cy_timeouts_until_log > 0) - return; - cy_timeouts_until_log = hz / cy_timeout; - for (unit = 0; unit < NPORTS; ++unit) { - int errnum; - - com = cy_addr(unit); - if (com == NULL) - continue; - for (errnum = 0; errnum < CE_NTYPES; ++errnum) { - u_int delta; - u_long total; - - critical_enter(); - COM_LOCK(); - delta = com->delta_error_counts[errnum]; - com->delta_error_counts[errnum] = 0; - COM_UNLOCK(); - critical_exit(); - if (delta == 0) - continue; - total = com->error_counts[errnum] += delta; - log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", - unit, delta, error_desc[errnum], - delta == 1 ? "" : "s", total); - } - } -} - -static void -disc_optim(struct tty *tp, struct termios *t, struct com_s *com) -{ -#ifndef SOFT_HOTCHAR - u_char opt; -#endif - - ttyldoptim(tp); -#ifndef SOFT_HOTCHAR - opt = com->cor[2] & ~CD1400_COR3_SCD34; - if (com->tp->t_hotchar != 0) { - cd_setreg(com, CD1400_SCHR3, com->tp->t_hotchar); - cd_setreg(com, CD1400_SCHR4, com->tp->t_hotchar); - opt |= CD1400_COR3_SCD34; - } - if (opt != com->cor[2]) { - cd_setreg(com, CD1400_COR3, com->cor[2] = opt); - cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); - } -#endif -} - -#ifdef Smarts -/* standard line discipline input routine */ -int -cyinput(int c, struct tty *tp) -{ - /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK - * bits, as they are done by the CD1400. Hardly worth the effort, - * given that high-throughput session are raw anyhow. - */ -} -#endif /* Smarts */ - -static int -cyspeed(speed_t speed, u_long cy_clock, int *prescaler_io) -{ - int actual; - int error; - int divider; - int prescaler; - int prescaler_unit; - - if (speed == 0) - return (0); - if (speed < 0 || speed > 150000) - return (-1); - - /* determine which prescaler to use */ - for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; - prescaler_unit--, prescaler >>= 2) { - if (cy_clock / prescaler / speed > 63) - break; - } - - divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ - if (divider > 255) - divider = 255; - actual = cy_clock/prescaler/divider; - - /* 10 times error in percent: */ - error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; - - /* 3.0% max error tolerance */ - if (error < -30 || error > 30) - return (-1); - - *prescaler_io = prescaler_unit; - return (divider); -} - -static void -cd1400_channel_cmd(struct com_s *com, int cmd) -{ - cd1400_channel_cmd_wait(com); - cd_setreg(com, CD1400_CCR, cmd); - cd1400_channel_cmd_wait(com); -} - -static void -cd1400_channel_cmd_wait(struct com_s *com) -{ - struct timeval start; - struct timeval tv; - long usec; - - if (cd_getreg(com, CD1400_CCR) == 0) - return; - microtime(&start); - for (;;) { - if (cd_getreg(com, CD1400_CCR) == 0) - return; - microtime(&tv); - usec = 1000000 * (tv.tv_sec - start.tv_sec) + - tv.tv_usec - start.tv_usec; - if (usec >= 5000) { - log(LOG_ERR, - "cy%d: channel command timeout (%ld usec)\n", - com->unit, usec); - return; - } - } -} - -static void -cd_etc(struct com_s *com, int etc) -{ - - /* - * We can't change the hardware's ETC state while there are any - * characters in the tx fifo, since those characters would be - * interpreted as commands! Unputting characters from the fifo - * is difficult, so we wait up to 12 character times for the fifo - * to drain. The command will be delayed for up to 2 character - * times for the tx to become empty. Unputting characters from - * the tx holding and shift registers is impossible, so we wait - * for the tx to become empty so that the command is sure to be - * executed soon after we issue it. - */ - critical_enter(); - COM_LOCK(); - if (com->etc == etc) - goto wait; - if ((etc == CD1400_ETC_SENDBREAK - && (com->etc == ETC_BREAK_STARTING - || com->etc == ETC_BREAK_STARTED)) - || (etc == CD1400_ETC_STOPBREAK - && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED - || com->etc == ETC_NONE))) { - COM_UNLOCK(); - critical_exit(); - return; - } - com->etc = etc; - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); -wait: - COM_UNLOCK(); - critical_exit(); - while (com->etc == etc - && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) - continue; -} - -static int -cd_getreg(struct com_s *com, int reg) -{ - struct com_s *basecom; - u_char car; - int cy_align; - cy_addr iobase; -#ifdef SMP - int need_unlock; -#endif - int val; - - basecom = cy_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); - car = com->unit & CD1400_CAR_CHAN; - cy_align = com->cy_align; - iobase = com->iobase; - critical_enter(); -#ifdef SMP - need_unlock = 0; - if (!mtx_owned(&cy_lock)) { - COM_LOCK(); - need_unlock = 1; - } -#endif - if (basecom->car != car) - cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); - val = cd_inb(iobase, reg, cy_align); -#ifdef SMP - if (need_unlock) - COM_UNLOCK(); -#endif - critical_exit(); - return (val); -} - -static void -cd_setreg(struct com_s *com, int reg, int val) -{ - struct com_s *basecom; - u_char car; - int cy_align; - cy_addr iobase; -#ifdef SMP - int need_unlock; -#endif - - basecom = cy_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); - car = com->unit & CD1400_CAR_CHAN; - cy_align = com->cy_align; - iobase = com->iobase; - critical_enter(); -#ifdef SMP - need_unlock = 0; - if (!mtx_owned(&cy_lock)) { - COM_LOCK(); - need_unlock = 1; - } -#endif - if (basecom->car != car) - cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); - cd_outb(iobase, reg, cy_align, val); -#ifdef SMP - if (need_unlock) - COM_UNLOCK(); -#endif - critical_exit(); -} - -#ifdef CyDebug -/* useful in ddb */ -void -cystatus(int unit) -{ - struct com_s *com; - cy_addr iobase; - u_int ocount; - struct tty *tp; - - com = cy_addr(unit); - printf("info for channel %d\n", unit); - printf("------------------\n"); - printf("total cyclom service probes:\t%d\n", cy_svrr_probes); - printf("calls to upper layer:\t\t%d\n", cy_timeouts); - if (com == NULL) - return; - iobase = com->iobase; - printf("\n"); - printf("cd1400 base address:\\tt%p\n", iobase); - printf("saved channel_control:\t\t0x%02x\n", com->channel_control); - printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", - com->cor[0], com->cor[1], com->cor[2]); - printf("service request enable reg:\t0x%02x (0x%02x cached)\n", - cd_getreg(com, CD1400_SRER), com->intr_enable); - printf("service request register:\t0x%02x\n", - cd_inb(iobase, CD1400_SVRR, com->cy_align)); - printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", - cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); - printf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", - cd_inb(iobase, CD1400_RIR, com->cy_align), - cd_inb(iobase, CD1400_TIR, com->cy_align), - cd_inb(iobase, CD1400_MIR, com->cy_align)); - printf("\n"); - printf("com state:\t\t\t0x%02x\n", com->state); - printf("calls to cystart():\t\t%d (%d useful)\n", - com->start_count, com->start_real); - printf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); - ocount = 0; - if (com->obufs[0].l_queued) - ocount += com->obufs[0].l_tail - com->obufs[0].l_head; - if (com->obufs[1].l_queued) - ocount += com->obufs[1].l_tail - com->obufs[1].l_head; - printf("tx buffer chars:\t\t%u\n", ocount); - printf("received chars:\t\t\t%d\n", com->bytes_in); - printf("received exceptions:\t\t%d\n", com->recv_exception); - printf("modem signal deltas:\t\t%d\n", com->mdm); - printf("transmitted chars:\t\t%d\n", com->bytes_out); - printf("\n"); - tp = com->tp; - if (tp != NULL) { - printf("tty state:\t\t\t0x%08x\n", tp->t_state); - printf( - "upper layer queue lengths:\t%d raw, %d canon, %d output\n", - tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); - } else - printf("tty state:\t\t\tclosed\n"); -} -#endif /* CyDebug */ diff --git a/sys/dev/cy/cy_isa.c b/sys/dev/cy/cy_isa.c deleted file mode 100644 index a53da4fc33e6..000000000000 --- a/sys/dev/cy/cy_isa.c +++ /dev/null @@ -1,152 +0,0 @@ -/*- - * cyclades cyclom-y serial driver - * Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993 - * - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1993 Andrew Herbert. - * 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. The name Andrew Herbert may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * 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. - */ - -/* - * Cyclades Y ISA serial interface driver - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/module.h> - -#include <machine/bus.h> -#include <sys/rman.h> -#include <machine/resource.h> - -#include <isa/isavar.h> - -#include <dev/cy/cyreg.h> -#include <dev/cy/cyvar.h> - -static int cy_isa_attach(device_t dev); -static int cy_isa_probe(device_t dev); - -static device_method_t cy_isa_methods[] = { - /* Device interface. */ - DEVMETHOD(device_probe, cy_isa_probe), - DEVMETHOD(device_attach, cy_isa_attach), - - { 0, 0 } -}; - -static driver_t cy_isa_driver = { - cy_driver_name, - cy_isa_methods, - 0, -}; - -DRIVER_MODULE(cy, isa, cy_isa_driver, cy_devclass, 0, 0); - -static int -cy_isa_probe(device_t dev) -{ - struct resource *mem_res; - cy_addr iobase; - int error, mem_rid; - - if (isa_get_logicalid(dev) != 0) /* skip PnP probes */ - return (ENXIO); - - mem_rid = 0; - mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mem_rid, - RF_ACTIVE); - if (mem_res == NULL) { - device_printf(dev, "ioport resource allocation failed\n"); - return (ENXIO); - } - iobase = rman_get_virtual(mem_res); - - /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ - cy_inb(iobase, CY16_RESET, 0); /* XXX? */ - DELAY(500); /* wait for the board to get its act together */ - - /* this is needed to get the board out of reset */ - cy_outb(iobase, CY_CLEAR_INTR, 0, 0); - DELAY(500); - - error = (cy_units(iobase, 0) == 0 ? ENXIO : 0); - bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res); - return (error); -} - -static int -cy_isa_attach(device_t dev) -{ - struct resource *irq_res, *mem_res; - void *irq_cookie, *vaddr, *vsc; - int irq_rid, mem_rid; - - irq_res = NULL; - mem_res = NULL; - - mem_rid = 0; - mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mem_rid, - RF_ACTIVE); - if (mem_res == NULL) { - device_printf(dev, "memory resource allocation failed\n"); - goto fail; - } - vaddr = rman_get_virtual(mem_res); - - vsc = cyattach_common(vaddr, 0); - if (vsc == NULL) { - device_printf(dev, "no ports found!\n"); - goto fail; - } - - irq_rid = 0; - irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irq_rid, - RF_SHAREABLE | RF_ACTIVE); - if (irq_res == NULL) { - device_printf(dev, "interrupt resource allocation failed\n"); - goto fail; - } - if (bus_setup_intr(dev, irq_res, INTR_TYPE_TTY, - cyintr, NULL, vsc, &irq_cookie) != 0) { - device_printf(dev, "interrupt setup failed\n"); - goto fail; - } - - return (0); - -fail: - if (irq_res != NULL) - bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res); - if (mem_res != NULL) - bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res); - return (ENXIO); -} diff --git a/sys/dev/cy/cy_pci.c b/sys/dev/cy/cy_pci.c deleted file mode 100644 index 4bd833e27b19..000000000000 --- a/sys/dev/cy/cy_pci.c +++ /dev/null @@ -1,194 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1996, David Greenman - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Cyclades Y PCI serial interface driver - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "opt_cy_pci_fastintr.h" - -#include <sys/param.h> -#include <sys/bus.h> -#include <sys/kernel.h> -#include <sys/module.h> - -#include <machine/bus.h> -#include <sys/rman.h> -#include <machine/resource.h> - -#include <dev/pci/pcivar.h> - -#include <dev/cy/cyvar.h> - -#define CY_PCI_BASE_ADDR0 0x10 -#define CY_PCI_BASE_ADDR1 0x14 -#define CY_PCI_BASE_ADDR2 0x18 - -#define CY_PLX_9050_ICS 0x4c -#define CY_PLX_9060_ICS 0x68 -#define CY_PLX_9050_ICS_IENABLE 0x040 -#define CY_PLX_9050_ICS_LOCAL_IENABLE 0x001 -#define CY_PLX_9050_ICS_LOCAL_IPOLARITY 0x002 -#define CY_PLX_9060_ICS_IENABLE 0x100 -#define CY_PLX_9060_ICS_LOCAL_IENABLE 0x800 - -/* Cyclom-Y Custom Register for PLX ID. */ -#define PLX_VER 0x3400 -#define PLX_9050 0x0b -#define PLX_9060 0x0c -#define PLX_9080 0x0d - -static int cy_pci_attach(device_t dev); -static int cy_pci_probe(device_t dev); - -static device_method_t cy_pci_methods[] = { - /* Device interface. */ - DEVMETHOD(device_probe, cy_pci_probe), - DEVMETHOD(device_attach, cy_pci_attach), - - { 0, 0 } -}; - -static driver_t cy_pci_driver = { - cy_driver_name, - cy_pci_methods, - 0, -}; - -DRIVER_MODULE(cy, pci, cy_pci_driver, cy_devclass, 0, 0); -MODULE_DEPEND(cy, pci, 1, 1, 1); - -static int -cy_pci_probe(dev) - device_t dev; -{ - u_int32_t device_id; - - device_id = pci_get_devid(dev); - device_id &= ~0x00060000; - if (device_id != 0x0100120e && device_id != 0x0101120e) - return (ENXIO); - device_set_desc(dev, "Cyclades Cyclom-Y Serial Adapter"); - return (BUS_PROBE_DEFAULT); -} - -static int -cy_pci_attach(dev) - device_t dev; -{ - struct resource *ioport_res, *irq_res, *mem_res; - void *irq_cookie, *vaddr, *vsc; - u_int32_t ioport; - int irq_setup, ioport_rid, irq_rid, mem_rid; - u_char plx_ver; - - ioport_res = NULL; - irq_res = NULL; - mem_res = NULL; - - ioport_rid = CY_PCI_BASE_ADDR1; - ioport_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &ioport_rid, - RF_ACTIVE); - if (ioport_res == NULL) { - device_printf(dev, "ioport resource allocation failed\n"); - goto fail; - } - ioport = rman_get_start(ioport_res); - - mem_rid = CY_PCI_BASE_ADDR2; - mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mem_rid, - RF_ACTIVE); - if (mem_res == NULL) { - device_printf(dev, "memory resource allocation failed\n"); - goto fail; - } - vaddr = rman_get_virtual(mem_res); - - vsc = cyattach_common(vaddr, 1); - if (vsc == NULL) { - device_printf(dev, "no ports found!\n"); - goto fail; - } - - irq_rid = 0; - irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irq_rid, - RF_SHAREABLE | RF_ACTIVE); - if (irq_res == NULL) { - device_printf(dev, "interrupt resource allocation failed\n"); - goto fail; - } -#ifdef CY_PCI_FASTINTR - irq_setup = bus_setup_intr(dev, irq_res, INTR_TYPE_TTY, - cyintr, NULL, vsc, &irq_cookie); -#else - irq_setup = ENXIO; -#endif - if (irq_setup != 0) - irq_setup = bus_setup_intr(dev, irq_res, INTR_TYPE_TTY, - NULL, (driver_intr_t *)cyintr, vsc, &irq_cookie); - if (irq_setup != 0) { - device_printf(dev, "interrupt setup failed\n"); - goto fail; - } - - /* - * Enable the "local" interrupt input to generate a - * PCI interrupt. - */ - plx_ver = *((u_char *)vaddr + PLX_VER) & 0x0f; - switch (plx_ver) { - case PLX_9050: - outw(ioport + CY_PLX_9050_ICS, - CY_PLX_9050_ICS_IENABLE | CY_PLX_9050_ICS_LOCAL_IENABLE | - CY_PLX_9050_ICS_LOCAL_IPOLARITY); - break; - case PLX_9060: - case PLX_9080: - default: /* Old board, use PLX_9060 values. */ - outw(ioport + CY_PLX_9060_ICS, - inw(ioport + CY_PLX_9060_ICS) | CY_PLX_9060_ICS_IENABLE | - CY_PLX_9060_ICS_LOCAL_IENABLE); - break; - } - - return (0); - -fail: - if (ioport_res != NULL) - bus_release_resource(dev, SYS_RES_IOPORT, ioport_rid, - ioport_res); - if (irq_res != NULL) - bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res); - if (mem_res != NULL) - bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res); - return (ENXIO); -} diff --git a/sys/dev/cy/cyreg.h b/sys/dev/cy/cyreg.h deleted file mode 100644 index bb29064b471e..000000000000 --- a/sys/dev/cy/cyreg.h +++ /dev/null @@ -1,77 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1995 Bruce Evans. - * 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 author nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY 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 Cyclades Cyclom-Y serial boards. - */ - -/* - * Cyclades register offsets. These are physical offsets for ISA boards - * and physical offsets divided by 2 for PCI boards. - */ -#define CY8_SVCACKR 0x100 /* (r) */ -#define CY8_SVCACKT 0x200 /* (r) */ -#define CY8_SVCACKM 0x300 /* (r) */ -#define CY16_RESET 0x1400 /* (r) */ -#define CY_CLEAR_INTR 0x1800 /* intr ack address (w) */ - -#define CY_MAX_CD1400s 8 /* for Cyclom-32Y */ - -#define CY_CLOCK(version) ((version) >= 0x48 ? 60000000 : 25000000) -#define CY_RTS_DTR_SWAPPED(version) ((version) >= 0x48) - -/* - * The `cd' macros are for access to cd1400 registers. The `cy' macros - * are for access to Cyclades registers. Both sets of macros scale the - * register number to get an offset, but the scales are different for - * mostly historical reasons. - */ -#ifdef CyDebug -#define cd_inb(iobase, reg, cy_align) \ - (++cd_inbs, *((iobase) + (2 * (reg) << (cy_align)))) -#define cy_inb(iobase, reg, cy_align) \ - (++cy_inbs, *((iobase) + ((reg) << (cy_align)))) -#define cd_outb(iobase, reg, cy_align, val) \ - (++cd_outbs, (void)(*((iobase) + (2 * (reg) << (cy_align))) = (val))) -#define cy_outb(iobase, reg, cy_align, val) \ - (++cy_outbs, (void)(*((iobase) + ((reg) << (cy_align))) = (val))) -#else -#define cd_inb(iobase, reg, cy_align) \ - (*((iobase) + (2 * (reg) << (cy_align)))) -#define cy_inb(iobase, reg, cy_align) \ - (*((iobase) + ((reg) << (cy_align)))) -#define cd_outb(iobase, reg, cy_align, val) \ - ((void)(*((iobase) + (2 * (reg) << (cy_align))) = (val))) -#define cy_outb(iobase, reg, cy_align, val) \ - ((void)(*((iobase) + ((reg) << (cy_align))) = (val))) -#endif diff --git a/sys/dev/cy/cyvar.h b/sys/dev/cy/cyvar.h deleted file mode 100644 index 0289ecba4f3e..000000000000 --- a/sys/dev/cy/cyvar.h +++ /dev/null @@ -1,38 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2004 Bruce D. Evans - * 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$ - */ - -typedef u_char volatile *cy_addr; - -extern devclass_t cy_devclass; -extern char cy_driver_name[]; - -void *cyattach_common(cy_addr cy_iobase, int cy_align); -driver_filter_t cyintr; -int cy_units(cy_addr cy_iobase, int cy_align); diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index df7400f73528..d343bdced22d 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -305,7 +305,7 @@ static int pmc_callchaindepth = PMC_CALLCHAIN_DEPTH; SYSCTL_INT(_kern_hwpmc, OID_AUTO, callchaindepth, CTLFLAG_RDTUN, &pmc_callchaindepth, 0, "depth of call chain records"); -char pmc_cpuid[64]; +char pmc_cpuid[PMC_CPUID_LEN]; SYSCTL_STRING(_kern_hwpmc, OID_AUTO, cpuid, CTLFLAG_RD, pmc_cpuid, 0, "cpu version string"); #ifdef HWPMC_DEBUG diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c index 9d4f5e77fa97..38e9cd7b4c26 100644 --- a/sys/dev/hyperv/vmbus/vmbus.c +++ b/sys/dev/hyperv/vmbus/vmbus.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/bus.h> #include <sys/kernel.h> +#include <sys/linker.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/module.h> @@ -46,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/intr_machdep.h> +#include <machine/metadata.h> #include <machine/md_var.h> #include <machine/resource.h> #include <x86/include/apicvar.h> @@ -1332,12 +1334,66 @@ vmbus_get_mmio_res(device_t dev) vmbus_get_mmio_res_pass(dev, parse_32); } +/* + * On Gen2 VMs, Hyper-V provides mmio space for framebuffer. + * This mmio address range is not useable for other PCI devices. + * Currently only efifb driver is using this range without reserving + * it from system. + * Therefore, vmbus driver reserves it before any other PCI device + * drivers start to request mmio addresses. + */ +static struct resource *hv_fb_res; + +static void +vmbus_fb_mmio_res(device_t dev) +{ + struct efi_fb *efifb; + caddr_t kmdp; + + struct vmbus_softc *sc = device_get_softc(dev); + int rid = 0; + + kmdp = preload_search_by_type("elf kernel"); + if (kmdp == NULL) + kmdp = preload_search_by_type("elf64 kernel"); + efifb = (struct efi_fb *)preload_search_info(kmdp, + MODINFO_METADATA | MODINFOMD_EFI_FB); + if (efifb == NULL) { + if (bootverbose) + device_printf(dev, + "fb has no preloaded kernel efi information\n"); + /* We are on Gen1 VM, just return. */ + return; + } else { + if (bootverbose) + device_printf(dev, + "efifb: fb_addr: %#jx, size: %#jx, " + "actual size needed: 0x%x\n", + efifb->fb_addr, efifb->fb_size, + (int) efifb->fb_height * efifb->fb_width); + } + + hv_fb_res = pcib_host_res_alloc(&sc->vmbus_mmio_res, dev, + SYS_RES_MEMORY, &rid, + efifb->fb_addr, efifb->fb_addr + efifb->fb_size, efifb->fb_size, + RF_ACTIVE | rman_make_alignment_flags(PAGE_SIZE)); + + if (hv_fb_res && bootverbose) + device_printf(dev, + "successfully reserved memory for framebuffer " + "starting at %#jx, size %#jx\n", + efifb->fb_addr, efifb->fb_size); +} + static void vmbus_free_mmio_res(device_t dev) { struct vmbus_softc *sc = device_get_softc(dev); pcib_host_res_free(dev, &sc->vmbus_mmio_res); + + if (hv_fb_res) + hv_fb_res = NULL; } #endif /* NEW_PCIB */ @@ -1387,6 +1443,7 @@ vmbus_doattach(struct vmbus_softc *sc) #ifdef NEW_PCIB vmbus_get_mmio_res(sc->vmbus_dev); + vmbus_fb_mmio_res(sc->vmbus_dev); #endif sc->vmbus_flags |= VMBUS_FLAG_ATTACHED; diff --git a/sys/dev/iommu/busdma_iommu.c b/sys/dev/iommu/busdma_iommu.c index a4fe8ee9d063..dd1309fd7dc6 100644 --- a/sys/dev/iommu/busdma_iommu.c +++ b/sys/dev/iommu/busdma_iommu.c @@ -299,7 +299,7 @@ acpi_iommu_get_dma_tag(device_t dev, device_t child) } bool -bus_dma_dmar_set_buswide(device_t dev) +bus_dma_iommu_set_buswide(device_t dev) { struct iommu_unit *unit; device_t parent; @@ -317,15 +317,35 @@ bus_dma_dmar_set_buswide(device_t dev) if (slot != 0 || func != 0) { if (bootverbose) { device_printf(dev, - "dmar%d pci%d:%d:%d requested buswide busdma\n", + "iommu%d pci%d:%d:%d requested buswide busdma\n", unit->unit, busno, slot, func); } return (false); } - dmar_set_buswide_ctx(unit, busno); + iommu_set_buswide_ctx(unit, busno); return (true); } +void +iommu_set_buswide_ctx(struct iommu_unit *unit, u_int busno) +{ + + MPASS(busno <= PCI_BUSMAX); + IOMMU_LOCK(unit); + unit->buswide_ctxs[busno / NBBY / sizeof(uint32_t)] |= + 1 << (busno % (NBBY * sizeof(uint32_t))); + IOMMU_UNLOCK(unit); +} + +bool +iommu_is_buswide_ctx(struct iommu_unit *unit, u_int busno) +{ + + MPASS(busno <= PCI_BUSMAX); + return ((unit->buswide_ctxs[busno / NBBY / sizeof(uint32_t)] & + (1U << (busno % (NBBY * sizeof(uint32_t))))) != 0); +} + static MALLOC_DEFINE(M_IOMMU_DMAMAP, "iommu_dmamap", "IOMMU DMA Map"); static void iommu_bus_schedule_dmamap(struct iommu_unit *unit, @@ -987,7 +1007,7 @@ iommu_fini_busdma(struct iommu_unit *unit) } int -bus_dma_dmar_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map1, +bus_dma_iommu_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map1, vm_paddr_t start, vm_size_t length, int flags) { struct bus_dma_tag_common *tc; diff --git a/sys/dev/iommu/iommu.h b/sys/dev/iommu/iommu.h index c3bc3d26b765..e6ad0569a9ac 100644 --- a/sys/dev/iommu/iommu.h +++ b/sys/dev/iommu/iommu.h @@ -34,12 +34,6 @@ #ifndef _SYS_IOMMU_H_ #define _SYS_IOMMU_H_ -#include <sys/queue.h> -#include <sys/sysctl.h> -#include <sys/taskqueue.h> -#include <sys/tree.h> -#include <sys/types.h> - /* Host or physical memory address, after translation. */ typedef uint64_t iommu_haddr_t; /* Guest or bus address, before translation. */ @@ -96,6 +90,14 @@ struct iommu_unit { struct task dmamap_load_task; TAILQ_HEAD(, bus_dmamap_iommu) delayed_maps; struct taskqueue *delayed_taskqueue; + + /* + * Bitmap of buses for which context must ignore slot:func, + * duplicating the page table pointer into all context table + * entries. This is a client-controlled quirk to support some + * NTBs. + */ + uint32_t buswide_ctxs[(PCI_BUSMAX + 1) / NBBY / sizeof(uint32_t)]; }; /* @@ -211,6 +213,13 @@ int iommu_gas_map_region(struct iommu_domain *domain, int iommu_gas_reserve_region(struct iommu_domain *domain, iommu_gaddr_t start, iommu_gaddr_t end); +void iommu_set_buswide_ctx(struct iommu_unit *unit, u_int busno); +bool iommu_is_buswide_ctx(struct iommu_unit *unit, u_int busno); + +bool bus_dma_iommu_set_buswide(device_t dev); +int bus_dma_iommu_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t start, vm_size_t length, int flags); + SYSCTL_DECL(_hw_iommu); #endif /* !_SYS_IOMMU_H_ */ diff --git a/sys/dev/iommu/iommu_gas.c b/sys/dev/iommu/iommu_gas.c index 5a6e48850b5b..04d7d9667109 100644 --- a/sys/dev/iommu/iommu_gas.c +++ b/sys/dev/iommu/iommu_gas.c @@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include <sys/tree.h> #include <sys/uio.h> #include <sys/vmem.h> -#include <dev/pci/pcivar.h> #include <vm/vm.h> #include <vm/vm_extern.h> #include <vm/vm_kern.h> @@ -60,6 +59,9 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_page.h> #include <vm/vm_map.h> #include <vm/uma.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/iommu/iommu.h> #include <machine/atomic.h> #include <machine/bus.h> #include <machine/md_var.h> @@ -67,11 +69,9 @@ __FBSDID("$FreeBSD$"); #include <machine/specialreg.h> #include <x86/include/busdma_impl.h> #include <x86/iommu/intel_reg.h> -#include <dev/iommu/busdma_iommu.h> -#include <dev/iommu/iommu.h> -#include <dev/pci/pcireg.h> #include <x86/iommu/intel_dmar.h> #endif +#include <dev/iommu/busdma_iommu.h> /* * Guest Address Space management. diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index 863c9a59c27d..b202ea40db45 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -1529,10 +1529,6 @@ mpr_alloc_requests(struct mpr_softc *sc) */ sc->commands = malloc(sizeof(struct mpr_command) * sc->num_reqs, M_MPR, M_WAITOK | M_ZERO); - if (!sc->commands) { - mpr_dprint(sc, MPR_ERROR, "Cannot allocate command memory\n"); - return (ENOMEM); - } for (i = 1; i < sc->num_reqs; i++) { cm = &sc->commands[i]; cm->cm_req = sc->req_frames + i * sc->reqframesz; @@ -2684,11 +2680,6 @@ mpr_register_events(struct mpr_softc *sc, uint8_t *mask, int error = 0; eh = malloc(sizeof(struct mpr_event_handle), M_MPR, M_WAITOK|M_ZERO); - if (!eh) { - mpr_dprint(sc, MPR_EVENT|MPR_ERROR, - "Cannot allocate event memory\n"); - return (ENOMEM); - } eh->callback = cb; eh->data = data; TAILQ_INSERT_TAIL(&sc->event_list, eh, eh_list); diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index 64eed15ea5a6..0e31f0c4d21e 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -736,11 +736,6 @@ mpr_attach_sas(struct mpr_softc *sc) mpr_dprint(sc, MPR_INIT, "%s entered\n", __func__); sassc = malloc(sizeof(struct mprsas_softc), M_MPR, M_WAITOK|M_ZERO); - if (!sassc) { - mpr_dprint(sc, MPR_INIT|MPR_ERROR, - "Cannot allocate SAS subsystem memory\n"); - return (ENOMEM); - } /* * XXX MaxTargets could change during a reinit. Since we don't @@ -751,12 +746,6 @@ mpr_attach_sas(struct mpr_softc *sc) sassc->maxtargets = sc->facts->MaxTargets + sc->facts->MaxVolumes; sassc->targets = malloc(sizeof(struct mprsas_target) * sassc->maxtargets, M_MPR, M_WAITOK|M_ZERO); - if (!sassc->targets) { - mpr_dprint(sc, MPR_INIT|MPR_ERROR, - "Cannot allocate SAS target memory\n"); - free(sassc, M_MPR); - return (ENOMEM); - } sc->sassc = sassc; sassc->sc = sc; @@ -3556,8 +3545,4 @@ mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets) sassc->targets = malloc(sizeof(struct mprsas_target) * maxtargets, M_MPR, M_WAITOK|M_ZERO); - if (!sassc->targets) { - panic("%s failed to alloc targets with error %d\n", - __func__, ENOMEM); - } } diff --git a/sys/dev/mpr/mpr_user.c b/sys/dev/mpr/mpr_user.c index 308b559c7172..751741bcc4f6 100644 --- a/sys/dev/mpr/mpr_user.c +++ b/sys/dev/mpr/mpr_user.c @@ -1528,13 +1528,6 @@ mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register, bzero(sc->fw_diag_buffer, buffer_size); ctx = malloc(sizeof(*ctx), M_MPR, M_WAITOK | M_ZERO); - if (ctx == NULL) { - device_printf(sc->mpr_dev, "%s: context malloc failed\n", - __func__); - *return_code = MPR_FW_DIAG_ERROR_NO_BUFFER; - status = MPR_DIAG_FAILURE; - goto bailout; - } ctx->addr = &sc->fw_diag_busaddr; ctx->buffer_dmat = sc->fw_diag_dmat; ctx->buffer_dmamap = sc->fw_diag_map; diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c index 9802296f06f8..1adbf58c9e17 100644 --- a/sys/dev/mps/mps.c +++ b/sys/dev/mps/mps.c @@ -1520,10 +1520,6 @@ mps_alloc_requests(struct mps_softc *sc) */ sc->commands = malloc(sizeof(struct mps_command) * sc->num_reqs, M_MPT2, M_WAITOK | M_ZERO); - if(!sc->commands) { - mps_dprint(sc, MPS_ERROR, "Cannot allocate command memory\n"); - return (ENOMEM); - } for (i = 1; i < sc->num_reqs; i++) { cm = &sc->commands[i]; cm->cm_req = sc->req_frames + i * sc->reqframesz; @@ -2598,10 +2594,6 @@ mps_register_events(struct mps_softc *sc, u32 *mask, int error = 0; eh = malloc(sizeof(struct mps_event_handle), M_MPT2, M_WAITOK|M_ZERO); - if(!eh) { - mps_dprint(sc, MPS_ERROR, "Cannot allocate event memory\n"); - return (ENOMEM); - } eh->callback = cb; eh->data = data; TAILQ_INSERT_TAIL(&sc->event_list, eh, eh_list); diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c index fd3f47c63697..74fced8abfab 100644 --- a/sys/dev/mps/mps_sas.c +++ b/sys/dev/mps/mps_sas.c @@ -722,11 +722,6 @@ mps_attach_sas(struct mps_softc *sc) mps_dprint(sc, MPS_INIT, "%s entered\n", __func__); sassc = malloc(sizeof(struct mpssas_softc), M_MPT2, M_WAITOK|M_ZERO); - if(!sassc) { - mps_dprint(sc, MPS_INIT|MPS_ERROR, - "Cannot allocate SAS controller memory\n"); - return (ENOMEM); - } /* * XXX MaxTargets could change during a reinit. Since we don't @@ -737,12 +732,6 @@ mps_attach_sas(struct mps_softc *sc) sassc->maxtargets = sc->facts->MaxTargets + sc->facts->MaxVolumes; sassc->targets = malloc(sizeof(struct mpssas_target) * sassc->maxtargets, M_MPT2, M_WAITOK|M_ZERO); - if(!sassc->targets) { - mps_dprint(sc, MPS_INIT|MPS_ERROR, - "Cannot allocate SAS target memory\n"); - free(sassc, M_MPT2); - return (ENOMEM); - } sc->sassc = sassc; sassc->sc = sc; @@ -3421,8 +3410,4 @@ mpssas_realloc_targets(struct mps_softc *sc, int maxtargets) sassc->targets = malloc(sizeof(struct mpssas_target) * maxtargets, M_MPT2, M_WAITOK|M_ZERO); - if (!sassc->targets) { - panic("%s failed to alloc targets with error %d\n", - __func__, ENOMEM); - } } diff --git a/sys/dev/mps/mps_user.c b/sys/dev/mps/mps_user.c index 0a2506070849..15ae463a1ad1 100644 --- a/sys/dev/mps/mps_user.c +++ b/sys/dev/mps/mps_user.c @@ -1436,13 +1436,6 @@ mps_diag_register(struct mps_softc *sc, mps_fw_diag_register_t *diag_register, bzero(sc->fw_diag_buffer, buffer_size); ctx = malloc(sizeof(*ctx), M_MPSUSER, M_WAITOK | M_ZERO); - if (ctx == NULL) { - device_printf(sc->mps_dev, "%s: context malloc failed\n", - __func__); - *return_code = MPS_FW_DIAG_ERROR_NO_BUFFER; - status = MPS_DIAG_FAILURE; - goto bailout; - } ctx->addr = &sc->fw_diag_busaddr; ctx->buffer_dmat = sc->fw_diag_dmat; ctx->buffer_dmamap = sc->fw_diag_map; diff --git a/sys/dev/ntb/ntb_hw/ntb_hw_intel.c b/sys/dev/ntb/ntb_hw/ntb_hw_intel.c index 9182461fe9a5..2dfe49cc1fd9 100644 --- a/sys/dev/ntb/ntb_hw/ntb_hw_intel.c +++ b/sys/dev/ntb/ntb_hw/ntb_hw_intel.c @@ -50,6 +50,8 @@ __FBSDID("$FreeBSD$"); #include <sys/module.h> #include <sys/mutex.h> #include <sys/pciio.h> +#include <sys/taskqueue.h> +#include <sys/tree.h> #include <sys/queue.h> #include <sys/rman.h> #include <sys/sbuf.h> @@ -61,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include <machine/resource.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> +#include <dev/iommu/iommu.h> #include "ntb_hw_intel.h" #include "../ntb.h" @@ -811,7 +814,7 @@ intel_ntb_map_pci_bars(struct ntb_softc *ntb) device_printf(ntb->device, "Unable to create BAR0 map\n"); return (ENOMEM); } - if (bus_dma_dmar_load_ident(ntb->bar0_dma_tag, ntb->bar0_dma_map, + if (bus_dma_iommu_load_ident(ntb->bar0_dma_tag, ntb->bar0_dma_map, bar->pbase, bar->size, 0)) { device_printf(ntb->device, "Unable to load BAR0 map\n"); return (ENOMEM); diff --git a/sys/dev/ntb/ntb_hw/ntb_hw_plx.c b/sys/dev/ntb/ntb_hw/ntb_hw_plx.c index 97df9ce3a4cc..f3d8af4971a4 100644 --- a/sys/dev/ntb/ntb_hw/ntb_hw_plx.c +++ b/sys/dev/ntb/ntb_hw/ntb_hw_plx.c @@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$"); #include <sys/module.h> #include <sys/rman.h> #include <sys/sysctl.h> +#include <sys/taskqueue.h> +#include <sys/tree.h> #include <vm/vm.h> #include <vm/pmap.h> #include <machine/bus.h> @@ -49,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include <machine/resource.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> +#include <dev/iommu/iommu.h> #include "../ntb.h" @@ -343,7 +346,7 @@ ntb_plx_attach(device_t dev) * The device occupies whole bus. In translated TLP slot field * keeps LUT index (original bus/slot), function is passed through. */ - bus_dma_dmar_set_buswide(dev); + bus_dma_iommu_set_buswide(dev); /* Identify chip port we are connected to. */ val = bus_read_4(sc->conf_res, 0x360); diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index e740caa7fc8a..379ad427b6b6 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -6306,6 +6306,67 @@ pcie_get_max_completion_timeout(device_t dev) } } +void +pcie_apei_error(device_t dev, int sev, uint8_t *aerp) +{ + struct pci_devinfo *dinfo = device_get_ivars(dev); + const char *s; + int aer; + uint32_t r, r1; + uint16_t rs; + + if (sev == PCIEM_STA_CORRECTABLE_ERROR) + s = "Correctable"; + else if (sev == PCIEM_STA_NON_FATAL_ERROR) + s = "Uncorrectable (Non-Fatal)"; + else + s = "Uncorrectable (Fatal)"; + device_printf(dev, "%s PCIe error reported by APEI\n", s); + if (aerp) { + if (sev == PCIEM_STA_CORRECTABLE_ERROR) { + r = le32dec(aerp + PCIR_AER_COR_STATUS); + r1 = le32dec(aerp + PCIR_AER_COR_MASK); + } else { + r = le32dec(aerp + PCIR_AER_UC_STATUS); + r1 = le32dec(aerp + PCIR_AER_UC_MASK); + } + device_printf(dev, "status 0x%08x mask 0x%08x", r, r1); + if (sev != PCIEM_STA_CORRECTABLE_ERROR) { + r = le32dec(aerp + PCIR_AER_UC_SEVERITY); + rs = le16dec(aerp + PCIR_AER_CAP_CONTROL); + printf(" severity 0x%08x first %d\n", + r, rs & 0x1f); + } else + printf("\n"); + } + + /* As kind of recovery just report and clear the error statuses. */ + if (pci_find_extcap(dev, PCIZ_AER, &aer) == 0) { + r = pci_read_config(dev, aer + PCIR_AER_UC_STATUS, 4); + if (r != 0) { + pci_write_config(dev, aer + PCIR_AER_UC_STATUS, r, 4); + device_printf(dev, "Clearing UC AER errors 0x%08x\n", r); + } + + r = pci_read_config(dev, aer + PCIR_AER_COR_STATUS, 4); + if (r != 0) { + pci_write_config(dev, aer + PCIR_AER_COR_STATUS, r, 4); + device_printf(dev, "Clearing COR AER errors 0x%08x\n", r); + } + } + if (dinfo->cfg.pcie.pcie_location != 0) { + rs = pci_read_config(dev, dinfo->cfg.pcie.pcie_location + + PCIER_DEVICE_STA, 2); + if ((rs & (PCIEM_STA_CORRECTABLE_ERROR | + PCIEM_STA_NON_FATAL_ERROR | PCIEM_STA_FATAL_ERROR | + PCIEM_STA_UNSUPPORTED_REQ)) != 0) { + pci_write_config(dev, dinfo->cfg.pcie.pcie_location + + PCIER_DEVICE_STA, rs, 2); + device_printf(dev, "Clearing PCIe errors 0x%04x\n", rs); + } + } +} + /* * Perform a Function Level Reset (FLR) on a device. * diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 37ad9242ebe1..29de6dad93f0 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -686,6 +686,7 @@ uint32_t pcie_read_config(device_t dev, int reg, int width); void pcie_write_config(device_t dev, int reg, uint32_t value, int width); uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask, uint32_t value, int width); +void pcie_apei_error(device_t dev, int sev, uint8_t *aer); bool pcie_flr(device_t dev, u_int max_delay, bool force); int pcie_get_max_completion_timeout(device_t dev); bool pcie_wait_for_pending_transactions(device_t dev, u_int max_delay); diff --git a/sys/dev/rc/rc.c b/sys/dev/rc/rc.c deleted file mode 100644 index c4c4370af5fe..000000000000 --- a/sys/dev/rc/rc.c +++ /dev/null @@ -1,1314 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (C) 1995 by Pavel Antonov, Moscow, Russia. - * Copyright (C) 1995 by Andrey A. Chernov, Moscow, Russia. - * All rights reserved. - * Copyright (C) 2002 by John Baldwin <jhb@FreeBSD.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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$ - */ - -/* - * SDL Communications Riscom/8 (based on Cirrus Logic CL-CD180) driver - * - */ - -/*#define RCDEBUG*/ - -#include "opt_tty.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/fcntl.h> -#include <sys/interrupt.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/serial.h> -#include <sys/tty.h> -#include <machine/bus.h> -#include <machine/resource.h> -#include <sys/rman.h> - -#include <dev/ic/cd180.h> -#include <dev/rc/rcreg.h> -#include <isa/isavar.h> - -#define IOBASE_ADDRS 14 - -#define rcin(sc, port) RC_IN(sc, port) -#define rcout(sc, port, v) RC_OUT(sc, port, v) - -#define WAITFORCCR(sc, chan) rc_wait0((sc), (chan), __LINE__) - -#define CCRCMD(sc, chan, cmd) do { \ - WAITFORCCR((sc), (chan)); \ - rcout((sc), CD180_CCR, (cmd)); \ -} while (0) - -#define RC_IBUFSIZE 256 -#define RB_I_HIGH_WATER (TTYHOG - 2 * RC_IBUFSIZE) -#define RC_OBUFSIZE 512 -#define RC_IHIGHWATER (3 * RC_IBUFSIZE / 4) -#define INPUT_FLAGS_SHIFT (2 * RC_IBUFSIZE) -#define LOTS_OF_EVENTS 64 - -#define RC_FAKEID 0x10 - -/* Per-channel structure */ -struct rc_chans { - struct rc_softc *rc_rcb; /* back ptr */ - u_short rc_flags; /* Misc. flags */ - int rc_chan; /* Channel # */ - u_char rc_ier; /* intr. enable reg */ - u_char rc_msvr; /* modem sig. status */ - u_char rc_cor2; /* options reg */ - u_char rc_pendcmd; /* special cmd pending */ - u_int rc_dcdwaits; /* how many waits DCD in open */ - struct tty *rc_tp; /* tty struct */ - u_char *rc_iptr; /* Chars input buffer */ - u_char *rc_hiwat; /* hi-water mark */ - u_char *rc_bufend; /* end of buffer */ - u_char *rc_optr; /* ptr in output buf */ - u_char *rc_obufend; /* end of output buf */ - u_char rc_ibuf[4 * RC_IBUFSIZE]; /* input buffer */ - u_char rc_obuf[RC_OBUFSIZE]; /* output buffer */ - struct callout rc_dtrcallout; -}; - -/* Per-board structure */ -struct rc_softc { - device_t sc_dev; - struct resource *sc_irq; - struct resource *sc_port[IOBASE_ADDRS]; - int sc_irqrid; - void *sc_hwicookie; - bus_space_tag_t sc_bt; - bus_space_handle_t sc_bh; - u_int sc_unit; /* unit # */ - u_char sc_dtr; /* DTR status */ - int sc_scheduled_event; - void *sc_swicookie; - struct rc_chans sc_channels[CD180_NCHAN]; /* channels */ -}; - -/* Static prototypes */ -static t_close_t rc_close; -static void rc_break(struct tty *, int); -static void rc_release_resources(device_t dev); -static void rc_intr(void *); -static void rc_hwreset(struct rc_softc *, unsigned int); -static int rc_test(struct rc_softc *); -static void rc_discard_output(struct rc_chans *); -static int rc_modem(struct tty *, int, int); -static void rc_start(struct tty *); -static void rc_stop(struct tty *, int rw); -static int rc_param(struct tty *, struct termios *); -static void rc_pollcard(void *); -static void rc_reinit(struct rc_softc *); -#ifdef RCDEBUG -static void printrcflags(); -#endif -static void rc_wait0(struct rc_softc *sc, int chan, int line); - -static devclass_t rc_devclass; - -/* Flags */ -#define RC_DTR_OFF 0x0001 /* DTR wait, for close/open */ -#define RC_ACTOUT 0x0002 /* Dial-out port active */ -#define RC_RTSFLOW 0x0004 /* RTS flow ctl enabled */ -#define RC_CTSFLOW 0x0008 /* CTS flow ctl enabled */ -#define RC_DORXFER 0x0010 /* RXFER event planned */ -#define RC_DOXXFER 0x0020 /* XXFER event planned */ -#define RC_MODCHG 0x0040 /* Modem status changed */ -#define RC_OSUSP 0x0080 /* Output suspended */ -#define RC_OSBUSY 0x0100 /* start() routine in progress */ -#define RC_WAS_BUFOVFL 0x0200 /* low-level buffer ovferflow */ -#define RC_WAS_SILOVFL 0x0400 /* silo buffer overflow */ -#define RC_SEND_RDY 0x0800 /* ready to send */ - -/* Table for translation of RCSR status bits to internal form */ -static int rc_rcsrt[16] = { - 0, TTY_OE, TTY_FE, - TTY_FE|TTY_OE, TTY_PE, TTY_PE|TTY_OE, - TTY_PE|TTY_FE, TTY_PE|TTY_FE|TTY_OE, TTY_BI, - TTY_BI|TTY_OE, TTY_BI|TTY_FE, TTY_BI|TTY_FE|TTY_OE, - TTY_BI|TTY_PE, TTY_BI|TTY_PE|TTY_OE, TTY_BI|TTY_PE|TTY_FE, - TTY_BI|TTY_PE|TTY_FE|TTY_OE -}; - -static int rc_ports[] = - { 0x220, 0x240, 0x250, 0x260, 0x2a0, 0x2b0, 0x300, 0x320 }; -static int iobase_addrs[IOBASE_ADDRS] = - { 0, 0x400, 0x800, 0xc00, 0x1400, 0x1800, 0x1c00, 0x2000, - 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x8000 }; - -/**********************************************/ - -static int -rc_probe(device_t dev) -{ - u_int port; - int i, found; - - /* - * We don't know of any PnP ID's for these cards. - */ - if (isa_get_logicalid(dev) != 0) - return (ENXIO); - - /* - * We have to have an IO port hint that is valid. - */ - port = isa_get_port(dev); - if (port == -1) - return (ENXIO); - found = 0; - for (i = 0; i < nitems(rc_ports); i++) - if (rc_ports[i] == port) { - found = 1; - break; - } - if (!found) - return (ENXIO); - - /* - * We have to have an IRQ hint. - */ - if (isa_get_irq(dev) == -1) - return (ENXIO); - - device_set_desc(dev, "SDL Riscom/8"); - return (0); -} - -static int -rc_attach(device_t dev) -{ - struct rc_chans *rc; - struct tty *tp; - struct rc_softc *sc; - u_int port; - int base, chan, error, i, x; - - sc = device_get_softc(dev); - sc->sc_dev = dev; - - /* - * We need to have IO ports. Lots of them. We need - * the following ranges relative to the base port: - * 0x0 - 0x10 - * 0x400 - 0x410 - * 0x800 - 0x810 - * 0xc00 - 0xc10 - * 0x1400 - 0x1410 - * 0x1800 - 0x1810 - * 0x1c00 - 0x1c10 - * 0x2000 - 0x2010 - * 0x3000 - 0x3010 - * 0x3400 - 0x3410 - * 0x3800 - 0x3810 - * 0x3c00 - 0x3c10 - * 0x4000 - 0x4010 - * 0x8000 - 0x8010 - */ - port = isa_get_port(dev); - for (i = 0; i < IOBASE_ADDRS; i++) - if (bus_set_resource(dev, SYS_RES_IOPORT, i, - port + iobase_addrs[i], 0x10) != 0) - return (ENXIO); - error = ENOMEM; - for (i = 0; i < IOBASE_ADDRS; i++) { - x = i; - sc->sc_port[i] = bus_alloc_resource_anywhere(dev, - SYS_RES_IOPORT, &x, 0x10, RF_ACTIVE); - if (x != i) { - device_printf(dev, "ioport %d was rid %d\n", i, x); - goto fail; - } - if (sc->sc_port[i] == NULL) { - device_printf(dev, "failed to alloc ioports %x-%x\n", - port + iobase_addrs[i], - port + iobase_addrs[i] + 0x10); - goto fail; - } - } - sc->sc_bt = rman_get_bustag(sc->sc_port[0]); - sc->sc_bh = rman_get_bushandle(sc->sc_port[0]); - - sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqrid, - RF_ACTIVE); - if (sc->sc_irq == NULL) { - device_printf(dev, "failed to alloc IRQ\n"); - goto fail; - } - - /* - * Now do some actual tests to make sure it works. - */ - error = ENXIO; - rcout(sc, CD180_PPRL, 0x22); /* Random values to Prescale reg. */ - rcout(sc, CD180_PPRH, 0x11); - if (rcin(sc, CD180_PPRL) != 0x22 || rcin(sc, CD180_PPRH) != 0x11) - goto fail; - if (rc_test(sc)) - goto fail; - - /* - * Ok, start actually hooking things up. - */ - sc->sc_unit = device_get_unit(dev); - /*sc->sc_chipid = 0x10 + device_get_unit(dev);*/ - device_printf(dev, "%d chans, firmware rev. %c\n", - CD180_NCHAN, (rcin(sc, CD180_GFRCR) & 0xF) + 'A'); - rc = sc->sc_channels; - base = CD180_NCHAN * sc->sc_unit; - for (chan = 0; chan < CD180_NCHAN; chan++, rc++) { - rc->rc_rcb = sc; - rc->rc_chan = chan; - rc->rc_iptr = rc->rc_ibuf; - rc->rc_bufend = &rc->rc_ibuf[RC_IBUFSIZE]; - rc->rc_hiwat = &rc->rc_ibuf[RC_IHIGHWATER]; - rc->rc_optr = rc->rc_obufend = rc->rc_obuf; - callout_init(&rc->rc_dtrcallout, 0); - tp = rc->rc_tp = ttyalloc(); - tp->t_sc = rc; - tp->t_oproc = rc_start; - tp->t_param = rc_param; - tp->t_modem = rc_modem; - tp->t_break = rc_break; - tp->t_close = rc_close; - tp->t_stop = rc_stop; - ttycreate(tp, TS_CALLOUT, "m%d", chan + base); - } - - error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_TTY, NULL, rc_intr, - sc, &sc->sc_hwicookie); - if (error) { - device_printf(dev, "failed to register interrupt handler\n"); - goto fail; - } - - swi_add(&tty_intr_event, "rc", rc_pollcard, sc, SWI_TTY, 0, - &sc->sc_swicookie); - return (0); - -fail: - rc_release_resources(dev); - return (error); -} - -static int -rc_detach(device_t dev) -{ - struct rc_softc *sc; - struct rc_chans *rc; - int error, i; - - sc = device_get_softc(dev); - - rc = sc->sc_channels; - for (i = 0; i < CD180_NCHAN; i++, rc++) - ttyfree(rc->rc_tp); - - error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_hwicookie); - if (error) - device_printf(dev, "failed to deregister interrupt handler\n"); - swi_remove(sc->sc_swicookie); - rc_release_resources(dev); - - return (0); -} - -static void -rc_release_resources(device_t dev) -{ - struct rc_softc *sc; - int i; - - sc = device_get_softc(dev); - if (sc->sc_irq != NULL) { - bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid, - sc->sc_irq); - sc->sc_irq = NULL; - } - for (i = 0; i < IOBASE_ADDRS; i++) { - if (sc->sc_port[i] == NULL) - break; - bus_release_resource(dev, SYS_RES_IOPORT, i, sc->sc_port[i]); - sc->sc_port[i] = NULL; - } -} - -/* RC interrupt handling */ -static void -rc_intr(void *arg) -{ - struct rc_softc *sc; - struct rc_chans *rc; - int resid, chan; - u_char val, iack, bsr, ucnt, *optr; - int good_data, t_state; - - sc = (struct rc_softc *)arg; - bsr = ~(rcin(sc, RC_BSR)); - if (!(bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT))) { - device_printf(sc->sc_dev, "extra interrupt\n"); - rcout(sc, CD180_EOIR, 0); - return; - } - - while (bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT)) { -#ifdef RCDEBUG_DETAILED - device_printf(sc->sc_dev, "intr (%p) %s%s%s%s\n", arg, bsr, - (bsr & RC_BSR_TOUT)?"TOUT ":"", - (bsr & RC_BSR_RXINT)?"RXINT ":"", - (bsr & RC_BSR_TXINT)?"TXINT ":"", - (bsr & RC_BSR_MOINT)?"MOINT":""); -#endif - if (bsr & RC_BSR_TOUT) { - device_printf(sc->sc_dev, - "hardware failure, reset board\n"); - rcout(sc, RC_CTOUT, 0); - rc_reinit(sc); - return; - } - if (bsr & RC_BSR_RXINT) { - iack = rcin(sc, RC_PILR_RX); - good_data = (iack == (GIVR_IT_RGDI | RC_FAKEID)); - if (!good_data && iack != (GIVR_IT_REI | RC_FAKEID)) { - device_printf(sc->sc_dev, - "fake rxint: %02x\n", iack); - goto more_intrs; - } - chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH); - rc = &sc->sc_channels[chan]; - t_state = rc->rc_tp->t_state; - /* Do RTS flow control stuff */ - if ( (rc->rc_flags & RC_RTSFLOW) - || !(t_state & TS_ISOPEN) - ) { - if ( ( !(t_state & TS_ISOPEN) - || (t_state & TS_TBLOCK) - ) - && (rc->rc_msvr & MSVR_RTS) - ) - rcout(sc, CD180_MSVR, - rc->rc_msvr &= ~MSVR_RTS); - else if (!(rc->rc_msvr & MSVR_RTS)) - rcout(sc, CD180_MSVR, - rc->rc_msvr |= MSVR_RTS); - } - ucnt = rcin(sc, CD180_RDCR) & 0xF; - resid = 0; - - if (t_state & TS_ISOPEN) { - /* check for input buffer overflow */ - if ((rc->rc_iptr + ucnt) >= rc->rc_bufend) { - resid = ucnt; - ucnt = rc->rc_bufend - rc->rc_iptr; - resid -= ucnt; - if (!(rc->rc_flags & RC_WAS_BUFOVFL)) { - rc->rc_flags |= RC_WAS_BUFOVFL; - sc->sc_scheduled_event++; - } - } - optr = rc->rc_iptr; - /* check foor good data */ - if (good_data) { - while (ucnt-- > 0) { - val = rcin(sc, CD180_RDR); - optr[0] = val; - optr[INPUT_FLAGS_SHIFT] = 0; - optr++; - sc->sc_scheduled_event++; - if (val != 0 && val == rc->rc_tp->t_hotchar) - swi_sched(sc->sc_swicookie, 0); - } - } else { - /* Store also status data */ - while (ucnt-- > 0) { - iack = rcin(sc, CD180_RCSR); - if (iack & RCSR_Timeout) - break; - if ( (iack & RCSR_OE) - && !(rc->rc_flags & RC_WAS_SILOVFL)) { - rc->rc_flags |= RC_WAS_SILOVFL; - sc->sc_scheduled_event++; - } - val = rcin(sc, CD180_RDR); - /* - Don't store PE if IGNPAR and BREAK if IGNBRK, - this hack allows "raw" tty optimization - works even if IGN* is set. - */ - if ( !(iack & (RCSR_PE|RCSR_FE|RCSR_Break)) - || ((!(iack & (RCSR_PE|RCSR_FE)) - || !(rc->rc_tp->t_iflag & IGNPAR)) - && (!(iack & RCSR_Break) - || !(rc->rc_tp->t_iflag & IGNBRK)))) { - if ( (iack & (RCSR_PE|RCSR_FE)) - && (t_state & TS_CAN_BYPASS_L_RINT) - && ((iack & RCSR_FE) - || ((iack & RCSR_PE) - && (rc->rc_tp->t_iflag & INPCK)))) - val = 0; - else if (val != 0 && val == rc->rc_tp->t_hotchar) - swi_sched(sc->sc_swicookie, 0); - optr[0] = val; - optr[INPUT_FLAGS_SHIFT] = iack; - optr++; - sc->sc_scheduled_event++; - } - } - } - rc->rc_iptr = optr; - rc->rc_flags |= RC_DORXFER; - } else - resid = ucnt; - /* Clear FIFO if necessary */ - while (resid-- > 0) { - if (!good_data) - iack = rcin(sc, CD180_RCSR); - else - iack = 0; - if (iack & RCSR_Timeout) - break; - (void) rcin(sc, CD180_RDR); - } - goto more_intrs; - } - if (bsr & RC_BSR_MOINT) { - iack = rcin(sc, RC_PILR_MODEM); - if (iack != (GIVR_IT_MSCI | RC_FAKEID)) { - device_printf(sc->sc_dev, "fake moint: %02x\n", - iack); - goto more_intrs; - } - chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH); - rc = &sc->sc_channels[chan]; - iack = rcin(sc, CD180_MCR); - rc->rc_msvr = rcin(sc, CD180_MSVR); - rcout(sc, CD180_MCR, 0); -#ifdef RCDEBUG - printrcflags(rc, "moint"); -#endif - if (rc->rc_flags & RC_CTSFLOW) { - if (rc->rc_msvr & MSVR_CTS) - rc->rc_flags |= RC_SEND_RDY; - else - rc->rc_flags &= ~RC_SEND_RDY; - } else - rc->rc_flags |= RC_SEND_RDY; - if ((iack & MCR_CDchg) && !(rc->rc_flags & RC_MODCHG)) { - sc->sc_scheduled_event += LOTS_OF_EVENTS; - rc->rc_flags |= RC_MODCHG; - swi_sched(sc->sc_swicookie, 0); - } - goto more_intrs; - } - if (bsr & RC_BSR_TXINT) { - iack = rcin(sc, RC_PILR_TX); - if (iack != (GIVR_IT_TDI | RC_FAKEID)) { - device_printf(sc->sc_dev, "fake txint: %02x\n", - iack); - goto more_intrs; - } - chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH); - rc = &sc->sc_channels[chan]; - if ( (rc->rc_flags & RC_OSUSP) - || !(rc->rc_flags & RC_SEND_RDY) - ) - goto more_intrs; - /* Handle breaks and other stuff */ - if (rc->rc_pendcmd) { - rcout(sc, CD180_COR2, rc->rc_cor2 |= COR2_ETC); - rcout(sc, CD180_TDR, CD180_C_ESC); - rcout(sc, CD180_TDR, rc->rc_pendcmd); - rcout(sc, CD180_COR2, rc->rc_cor2 &= ~COR2_ETC); - rc->rc_pendcmd = 0; - goto more_intrs; - } - optr = rc->rc_optr; - resid = rc->rc_obufend - optr; - if (resid > CD180_NFIFO) - resid = CD180_NFIFO; - while (resid-- > 0) - rcout(sc, CD180_TDR, *optr++); - rc->rc_optr = optr; - - /* output completed? */ - if (optr >= rc->rc_obufend) { - rcout(sc, CD180_IER, rc->rc_ier &= ~IER_TxRdy); -#ifdef RCDEBUG - device_printf(sc->sc_dev, - "channel %d: output completed\n", - rc->rc_chan); -#endif - if (!(rc->rc_flags & RC_DOXXFER)) { - sc->sc_scheduled_event += LOTS_OF_EVENTS; - rc->rc_flags |= RC_DOXXFER; - swi_sched(sc->sc_swicookie, 0); - } - } - } - more_intrs: - rcout(sc, CD180_EOIR, 0); /* end of interrupt */ - rcout(sc, RC_CTOUT, 0); - bsr = ~(rcin(sc, RC_BSR)); - } -} - -/* Feed characters to output buffer */ -static void -rc_start(struct tty *tp) -{ - struct rc_softc *sc; - struct rc_chans *rc; - int s; - - rc = tp->t_sc; - if (rc->rc_flags & RC_OSBUSY) - return; - sc = rc->rc_rcb; - s = spltty(); - rc->rc_flags |= RC_OSBUSY; - critical_enter(); - if (tp->t_state & TS_TTSTOP) - rc->rc_flags |= RC_OSUSP; - else - rc->rc_flags &= ~RC_OSUSP; - /* Do RTS flow control stuff */ - if ( (rc->rc_flags & RC_RTSFLOW) - && (tp->t_state & TS_TBLOCK) - && (rc->rc_msvr & MSVR_RTS) - ) { - rcout(sc, CD180_CAR, rc->rc_chan); - rcout(sc, CD180_MSVR, rc->rc_msvr &= ~MSVR_RTS); - } else if (!(rc->rc_msvr & MSVR_RTS)) { - rcout(sc, CD180_CAR, rc->rc_chan); - rcout(sc, CD180_MSVR, rc->rc_msvr |= MSVR_RTS); - } - critical_exit(); - if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) - goto out; -#ifdef RCDEBUG - printrcflags(rc, "rcstart"); -#endif - ttwwakeup(tp); -#ifdef RCDEBUG - printf("rcstart: outq = %d obuf = %d\n", - tp->t_outq.c_cc, rc->rc_obufend - rc->rc_optr); -#endif - if (tp->t_state & TS_BUSY) - goto out; /* output still in progress ... */ - - if (tp->t_outq.c_cc > 0) { - u_int ocnt; - - tp->t_state |= TS_BUSY; - ocnt = q_to_b(&tp->t_outq, rc->rc_obuf, sizeof rc->rc_obuf); - critical_enter(); - rc->rc_optr = rc->rc_obuf; - rc->rc_obufend = rc->rc_optr + ocnt; - critical_exit(); - if (!(rc->rc_ier & IER_TxRdy)) { -#ifdef RCDEBUG - device_printf(sc->sc_dev, - "channel %d: rcstart enable txint\n", rc->rc_chan); -#endif - rcout(sc, CD180_CAR, rc->rc_chan); - rcout(sc, CD180_IER, rc->rc_ier |= IER_TxRdy); - } - } -out: - rc->rc_flags &= ~RC_OSBUSY; - (void) splx(s); -} - -/* Handle delayed events. */ -void -rc_pollcard(void *arg) -{ - struct rc_softc *sc; - struct rc_chans *rc; - struct tty *tp; - u_char *tptr, *eptr; - int chan, icnt; - - sc = (struct rc_softc *)arg; - if (sc->sc_scheduled_event == 0) - return; - do { - rc = sc->sc_channels; - for (chan = 0; chan < CD180_NCHAN; rc++, chan++) { - tp = rc->rc_tp; -#ifdef RCDEBUG - if (rc->rc_flags & (RC_DORXFER|RC_DOXXFER|RC_MODCHG| - RC_WAS_BUFOVFL|RC_WAS_SILOVFL)) - printrcflags(rc, "rcevent"); -#endif - if (rc->rc_flags & RC_WAS_BUFOVFL) { - critical_enter(); - rc->rc_flags &= ~RC_WAS_BUFOVFL; - sc->sc_scheduled_event--; - critical_exit(); - device_printf(sc->sc_dev, - "channel %d: interrupt-level buffer overflow\n", - chan); - } - if (rc->rc_flags & RC_WAS_SILOVFL) { - critical_enter(); - rc->rc_flags &= ~RC_WAS_SILOVFL; - sc->sc_scheduled_event--; - critical_exit(); - device_printf(sc->sc_dev, - "channel %d: silo overflow\n", chan); - } - if (rc->rc_flags & RC_MODCHG) { - critical_enter(); - rc->rc_flags &= ~RC_MODCHG; - sc->sc_scheduled_event -= LOTS_OF_EVENTS; - critical_exit(); - ttyld_modem(tp, !!(rc->rc_msvr & MSVR_CD)); - } - if (rc->rc_flags & RC_DORXFER) { - critical_enter(); - rc->rc_flags &= ~RC_DORXFER; - eptr = rc->rc_iptr; - if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) - tptr = &rc->rc_ibuf[RC_IBUFSIZE]; - else - tptr = rc->rc_ibuf; - icnt = eptr - tptr; - if (icnt > 0) { - if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) { - rc->rc_iptr = rc->rc_ibuf; - rc->rc_bufend = &rc->rc_ibuf[RC_IBUFSIZE]; - rc->rc_hiwat = &rc->rc_ibuf[RC_IHIGHWATER]; - } else { - rc->rc_iptr = &rc->rc_ibuf[RC_IBUFSIZE]; - rc->rc_bufend = &rc->rc_ibuf[2 * RC_IBUFSIZE]; - rc->rc_hiwat = - &rc->rc_ibuf[RC_IBUFSIZE + RC_IHIGHWATER]; - } - if ( (rc->rc_flags & RC_RTSFLOW) - && (tp->t_state & TS_ISOPEN) - && !(tp->t_state & TS_TBLOCK) - && !(rc->rc_msvr & MSVR_RTS) - ) { - rcout(sc, CD180_CAR, chan); - rcout(sc, CD180_MSVR, - rc->rc_msvr |= MSVR_RTS); - } - sc->sc_scheduled_event -= icnt; - } - critical_exit(); - - if (icnt <= 0 || !(tp->t_state & TS_ISOPEN)) - goto done1; - - if ( (tp->t_state & TS_CAN_BYPASS_L_RINT) - && !(tp->t_state & TS_LOCAL)) { - if ((tp->t_rawq.c_cc + icnt) >= RB_I_HIGH_WATER - && ((rc->rc_flags & RC_RTSFLOW) || (tp->t_iflag & IXOFF)) - && !(tp->t_state & TS_TBLOCK)) - ttyblock(tp); - tk_nin += icnt; - tk_rawcc += icnt; - tp->t_rawcc += icnt; - if (b_to_q(tptr, icnt, &tp->t_rawq)) - device_printf(sc->sc_dev, - "channel %d: tty-level buffer overflow\n", - chan); - ttwakeup(tp); - if ((tp->t_state & TS_TTSTOP) && ((tp->t_iflag & IXANY) - || (tp->t_cc[VSTART] == tp->t_cc[VSTOP]))) { - tp->t_state &= ~TS_TTSTOP; - tp->t_lflag &= ~FLUSHO; - rc_start(tp); - } - } else { - for (; tptr < eptr; tptr++) - ttyld_rint(tp, - (tptr[0] | - rc_rcsrt[tptr[INPUT_FLAGS_SHIFT] & 0xF])); - } -done1: ; - } - if (rc->rc_flags & RC_DOXXFER) { - critical_enter(); - sc->sc_scheduled_event -= LOTS_OF_EVENTS; - rc->rc_flags &= ~RC_DOXXFER; - rc->rc_tp->t_state &= ~TS_BUSY; - critical_exit(); - ttyld_start(tp); - } - if (sc->sc_scheduled_event == 0) - break; - } - } while (sc->sc_scheduled_event >= LOTS_OF_EVENTS); -} - -static void -rc_stop(struct tty *tp, int rw) -{ - struct rc_softc *sc; - struct rc_chans *rc; - u_char *tptr, *eptr; - - rc = tp->t_sc; - sc = rc->rc_rcb; -#ifdef RCDEBUG - device_printf(sc->sc_dev, "channel %d: rc_stop %s%s\n", - rc->rc_chan, (rw & FWRITE)?"FWRITE ":"", (rw & FREAD)?"FREAD":""); -#endif - if (rw & FWRITE) - rc_discard_output(rc); - critical_enter(); - if (rw & FREAD) { - rc->rc_flags &= ~RC_DORXFER; - eptr = rc->rc_iptr; - if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) { - tptr = &rc->rc_ibuf[RC_IBUFSIZE]; - rc->rc_iptr = &rc->rc_ibuf[RC_IBUFSIZE]; - } else { - tptr = rc->rc_ibuf; - rc->rc_iptr = rc->rc_ibuf; - } - sc->sc_scheduled_event -= eptr - tptr; - } - if (tp->t_state & TS_TTSTOP) - rc->rc_flags |= RC_OSUSP; - else - rc->rc_flags &= ~RC_OSUSP; - critical_exit(); -} - -static void -rc_close(struct tty *tp) -{ - struct rc_chans *rc; - struct rc_softc *sc; - int s; - - rc = tp->t_sc; - sc = rc->rc_rcb; - s = spltty(); - rcout(sc, CD180_CAR, rc->rc_chan); - - /* Disable rx/tx intrs */ - rcout(sc, CD180_IER, rc->rc_ier = 0); - if ( (tp->t_cflag & HUPCL) - || (!(rc->rc_flags & RC_ACTOUT) - && !(rc->rc_msvr & MSVR_CD) - && !(tp->t_cflag & CLOCAL)) - || !(tp->t_state & TS_ISOPEN) - ) { - CCRCMD(sc, rc->rc_chan, CCR_ResetChan); - WAITFORCCR(sc, rc->rc_chan); - (void) rc_modem(tp, SER_RTS, 0); - ttydtrwaitstart(tp); - } - rc->rc_flags &= ~RC_ACTOUT; - wakeup( &rc->rc_rcb); /* wake bi */ - wakeup(TSA_CARR_ON(tp)); - (void) splx(s); -} - -/* Reset the bastard */ -static void -rc_hwreset(struct rc_softc *sc, u_int chipid) -{ - CCRCMD(sc, -1, CCR_HWRESET); /* Hardware reset */ - DELAY(20000); - WAITFORCCR(sc, -1); - - rcout(sc, RC_CTOUT, 0); /* Clear timeout */ - rcout(sc, CD180_GIVR, chipid); - rcout(sc, CD180_GICR, 0); - - /* Set Prescaler Registers (1 msec) */ - rcout(sc, CD180_PPRL, ((RC_OSCFREQ + 999) / 1000) & 0xFF); - rcout(sc, CD180_PPRH, ((RC_OSCFREQ + 999) / 1000) >> 8); - - /* Initialize Priority Interrupt Level Registers */ - rcout(sc, CD180_PILR1, RC_PILR_MODEM); - rcout(sc, CD180_PILR2, RC_PILR_TX); - rcout(sc, CD180_PILR3, RC_PILR_RX); - - /* Reset DTR */ - rcout(sc, RC_DTREG, ~0); -} - -/* Set channel parameters */ -static int -rc_param(struct tty *tp, struct termios *ts) -{ - struct rc_softc *sc; - struct rc_chans *rc; - int idivs, odivs, s, val, cflag, iflag, lflag, inpflow; - - if ( ts->c_ospeed < 0 || ts->c_ospeed > 76800 - || ts->c_ispeed < 0 || ts->c_ispeed > 76800 - ) - return (EINVAL); - if (ts->c_ispeed == 0) - ts->c_ispeed = ts->c_ospeed; - odivs = RC_BRD(ts->c_ospeed); - idivs = RC_BRD(ts->c_ispeed); - - rc = tp->t_sc; - sc = rc->rc_rcb; - s = spltty(); - - /* Select channel */ - rcout(sc, CD180_CAR, rc->rc_chan); - - /* If speed == 0, hangup line */ - if (ts->c_ospeed == 0) { - CCRCMD(sc, rc->rc_chan, CCR_ResetChan); - WAITFORCCR(sc, rc->rc_chan); - (void) rc_modem(tp, 0, SER_DTR); - } - - tp->t_state &= ~TS_CAN_BYPASS_L_RINT; - cflag = ts->c_cflag; - iflag = ts->c_iflag; - lflag = ts->c_lflag; - - if (idivs > 0) { - rcout(sc, CD180_RBPRL, idivs & 0xFF); - rcout(sc, CD180_RBPRH, idivs >> 8); - } - if (odivs > 0) { - rcout(sc, CD180_TBPRL, odivs & 0xFF); - rcout(sc, CD180_TBPRH, odivs >> 8); - } - - /* set timeout value */ - if (ts->c_ispeed > 0) { - int itm = ts->c_ispeed > 2400 ? 5 : 10000 / ts->c_ispeed + 1; - - if ( !(lflag & ICANON) - && ts->c_cc[VMIN] != 0 && ts->c_cc[VTIME] != 0 - && ts->c_cc[VTIME] * 10 > itm) - itm = ts->c_cc[VTIME] * 10; - - rcout(sc, CD180_RTPR, itm <= 255 ? itm : 255); - } - - switch (cflag & CSIZE) { - case CS5: val = COR1_5BITS; break; - case CS6: val = COR1_6BITS; break; - case CS7: val = COR1_7BITS; break; - default: - case CS8: val = COR1_8BITS; break; - } - if (cflag & PARENB) { - val |= COR1_NORMPAR; - if (cflag & PARODD) - val |= COR1_ODDP; - if (!(cflag & INPCK)) - val |= COR1_Ignore; - } else - val |= COR1_Ignore; - if (cflag & CSTOPB) - val |= COR1_2SB; - rcout(sc, CD180_COR1, val); - - /* Set FIFO threshold */ - val = ts->c_ospeed <= 4800 ? 1 : CD180_NFIFO / 2; - inpflow = 0; - if ( (iflag & IXOFF) - && ( ts->c_cc[VSTOP] != _POSIX_VDISABLE - && ( ts->c_cc[VSTART] != _POSIX_VDISABLE - || (iflag & IXANY) - ) - ) - ) { - inpflow = 1; - val |= COR3_SCDE|COR3_FCT; - } - rcout(sc, CD180_COR3, val); - - /* Initialize on-chip automatic flow control */ - val = 0; - rc->rc_flags &= ~(RC_CTSFLOW|RC_SEND_RDY); - if (cflag & CCTS_OFLOW) { - rc->rc_flags |= RC_CTSFLOW; - val |= COR2_CtsAE; - } else - rc->rc_flags |= RC_SEND_RDY; - if (tp->t_state & TS_TTSTOP) - rc->rc_flags |= RC_OSUSP; - else - rc->rc_flags &= ~RC_OSUSP; - if (cflag & CRTS_IFLOW) - rc->rc_flags |= RC_RTSFLOW; - else - rc->rc_flags &= ~RC_RTSFLOW; - - if (inpflow) { - if (ts->c_cc[VSTART] != _POSIX_VDISABLE) - rcout(sc, CD180_SCHR1, ts->c_cc[VSTART]); - rcout(sc, CD180_SCHR2, ts->c_cc[VSTOP]); - val |= COR2_TxIBE; - if (iflag & IXANY) - val |= COR2_IXM; - } - - rcout(sc, CD180_COR2, rc->rc_cor2 = val); - - CCRCMD(sc, rc->rc_chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); - - ttyldoptim(tp); - - /* modem ctl */ - val = cflag & CLOCAL ? 0 : MCOR1_CDzd; - if (cflag & CCTS_OFLOW) - val |= MCOR1_CTSzd; - rcout(sc, CD180_MCOR1, val); - - val = cflag & CLOCAL ? 0 : MCOR2_CDod; - if (cflag & CCTS_OFLOW) - val |= MCOR2_CTSod; - rcout(sc, CD180_MCOR2, val); - - /* enable i/o and interrupts */ - CCRCMD(sc, rc->rc_chan, - CCR_XMTREN | ((cflag & CREAD) ? CCR_RCVREN : CCR_RCVRDIS)); - WAITFORCCR(sc, rc->rc_chan); - - rc->rc_ier = cflag & CLOCAL ? 0 : IER_CD; - if (cflag & CCTS_OFLOW) - rc->rc_ier |= IER_CTS; - if (cflag & CREAD) - rc->rc_ier |= IER_RxData; - if (tp->t_state & TS_BUSY) - rc->rc_ier |= IER_TxRdy; - if (ts->c_ospeed != 0) - rc_modem(tp, SER_DTR, 0); - if ((cflag & CCTS_OFLOW) && (rc->rc_msvr & MSVR_CTS)) - rc->rc_flags |= RC_SEND_RDY; - rcout(sc, CD180_IER, rc->rc_ier); - (void) splx(s); - return 0; -} - -/* Re-initialize board after bogus interrupts */ -static void -rc_reinit(struct rc_softc *sc) -{ - struct rc_chans *rc; - int i; - - rc_hwreset(sc, RC_FAKEID); - rc = sc->sc_channels; - for (i = 0; i < CD180_NCHAN; i++, rc++) - (void) rc_param(rc->rc_tp, &rc->rc_tp->t_termios); -} - -/* Modem control routines */ - -static int -rc_modem(struct tty *tp, int biton, int bitoff) -{ - struct rc_chans *rc; - struct rc_softc *sc; - u_char *dtr; - u_char msvr; - - rc = tp->t_sc; - sc = rc->rc_rcb; - dtr = &sc->sc_dtr; - rcout(sc, CD180_CAR, rc->rc_chan); - - if (biton == 0 && bitoff == 0) { - msvr = rc->rc_msvr = rcin(sc, CD180_MSVR); - - if (msvr & MSVR_RTS) - biton |= SER_RTS; - if (msvr & MSVR_CTS) - biton |= SER_CTS; - if (msvr & MSVR_DSR) - biton |= SER_DSR; - if (msvr & MSVR_DTR) - biton |= SER_DTR; - if (msvr & MSVR_CD) - biton |= SER_DCD; - if (~rcin(sc, RC_RIREG) & (1 << rc->rc_chan)) - biton |= SER_RI; - return biton; - } - if (biton & SER_DTR) - rcout(sc, RC_DTREG, ~(*dtr |= 1 << rc->rc_chan)); - if (bitoff & SER_DTR) - rcout(sc, RC_DTREG, ~(*dtr &= ~(1 << rc->rc_chan))); - msvr = rcin(sc, CD180_MSVR); - if (biton & SER_DTR) - msvr |= MSVR_DTR; - if (bitoff & SER_DTR) - msvr &= ~MSVR_DTR; - if (biton & SER_RTS) - msvr |= MSVR_RTS; - if (bitoff & SER_RTS) - msvr &= ~MSVR_RTS; - rcout(sc, CD180_MSVR, msvr); - return 0; -} - -static void -rc_break(struct tty *tp, int brk) -{ - struct rc_chans *rc; - - rc = tp->t_sc; - - if (brk) - rc->rc_pendcmd = CD180_C_SBRK; - else - rc->rc_pendcmd = CD180_C_EBRK; -} - -#define ERR(s) do { \ - device_printf(sc->sc_dev, "%s", ""); \ - printf s ; \ - printf("\n"); \ - (void) splx(old_level); \ - return 1; \ -} while (0) - -/* Test the board. */ -int -rc_test(struct rc_softc *sc) -{ - int chan = 0; - int i = 0, rcnt, old_level; - unsigned int iack, chipid; - unsigned short divs; - static u_char ctest[] = "\377\125\252\045\244\0\377"; -#define CTLEN 8 - - struct rtest { - u_char txbuf[CD180_NFIFO]; /* TX buffer */ - u_char rxbuf[CD180_NFIFO]; /* RX buffer */ - int rxptr; /* RX pointer */ - int txptr; /* TX pointer */ - } tchans[CD180_NCHAN]; - - old_level = spltty(); - - chipid = RC_FAKEID; - - /* First, reset board to initial state */ - rc_hwreset(sc, chipid); - - divs = RC_BRD(19200); - - /* Initialize channels */ - for (chan = 0; chan < CD180_NCHAN; chan++) { - - /* Select and reset channel */ - rcout(sc, CD180_CAR, chan); - CCRCMD(sc, chan, CCR_ResetChan); - WAITFORCCR(sc, chan); - - /* Set speed */ - rcout(sc, CD180_RBPRL, divs & 0xFF); - rcout(sc, CD180_RBPRH, divs >> 8); - rcout(sc, CD180_TBPRL, divs & 0xFF); - rcout(sc, CD180_TBPRH, divs >> 8); - - /* set timeout value */ - rcout(sc, CD180_RTPR, 0); - - /* Establish local loopback */ - rcout(sc, CD180_COR1, COR1_NOPAR | COR1_8BITS | COR1_1SB); - rcout(sc, CD180_COR2, COR2_LLM); - rcout(sc, CD180_COR3, CD180_NFIFO); - CCRCMD(sc, chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); - CCRCMD(sc, chan, CCR_RCVREN | CCR_XMTREN); - WAITFORCCR(sc, chan); - rcout(sc, CD180_MSVR, MSVR_RTS); - - /* Fill TXBUF with test data */ - for (i = 0; i < CD180_NFIFO; i++) { - tchans[chan].txbuf[i] = ctest[i]; - tchans[chan].rxbuf[i] = 0; - } - tchans[chan].txptr = tchans[chan].rxptr = 0; - - /* Now, start transmit */ - rcout(sc, CD180_IER, IER_TxMpty|IER_RxData); - } - /* Pseudo-interrupt poll stuff */ - for (rcnt = 10000; rcnt-- > 0; rcnt--) { - i = ~(rcin(sc, RC_BSR)); - if (i & RC_BSR_TOUT) - ERR(("BSR timeout bit set\n")); - else if (i & RC_BSR_TXINT) { - iack = rcin(sc, RC_PILR_TX); - if (iack != (GIVR_IT_TDI | chipid)) - ERR(("Bad TX intr ack (%02x != %02x)\n", - iack, GIVR_IT_TDI | chipid)); - chan = (rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH; - /* If no more data to transmit, disable TX intr */ - if (tchans[chan].txptr >= CD180_NFIFO) { - iack = rcin(sc, CD180_IER); - rcout(sc, CD180_IER, iack & ~IER_TxMpty); - } else { - for (iack = tchans[chan].txptr; - iack < CD180_NFIFO; iack++) - rcout(sc, CD180_TDR, - tchans[chan].txbuf[iack]); - tchans[chan].txptr = iack; - } - rcout(sc, CD180_EOIR, 0); - } else if (i & RC_BSR_RXINT) { - u_char ucnt; - - iack = rcin(sc, RC_PILR_RX); - if (iack != (GIVR_IT_RGDI | chipid) && - iack != (GIVR_IT_REI | chipid)) - ERR(("Bad RX intr ack (%02x != %02x)\n", - iack, GIVR_IT_RGDI | chipid)); - chan = (rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH; - ucnt = rcin(sc, CD180_RDCR) & 0xF; - while (ucnt-- > 0) { - iack = rcin(sc, CD180_RCSR); - if (iack & RCSR_Timeout) - break; - if (iack & 0xF) - ERR(("Bad char chan %d (RCSR = %02X)\n", - chan, iack)); - if (tchans[chan].rxptr > CD180_NFIFO) - ERR(("Got extra chars chan %d\n", - chan)); - tchans[chan].rxbuf[tchans[chan].rxptr++] = - rcin(sc, CD180_RDR); - } - rcout(sc, CD180_EOIR, 0); - } - rcout(sc, RC_CTOUT, 0); - for (iack = chan = 0; chan < CD180_NCHAN; chan++) - if (tchans[chan].rxptr >= CD180_NFIFO) - iack++; - if (iack == CD180_NCHAN) - break; - } - for (chan = 0; chan < CD180_NCHAN; chan++) { - /* Select and reset channel */ - rcout(sc, CD180_CAR, chan); - CCRCMD(sc, chan, CCR_ResetChan); - } - - if (!rcnt) - ERR(("looses characters during local loopback\n")); - /* Now, check data */ - for (chan = 0; chan < CD180_NCHAN; chan++) - for (i = 0; i < CD180_NFIFO; i++) - if (ctest[i] != tchans[chan].rxbuf[i]) - ERR(("data mismatch chan %d ptr %d (%d != %d)\n", - chan, i, ctest[i], tchans[chan].rxbuf[i])); - (void) splx(old_level); - return 0; -} - -#ifdef RCDEBUG -static void -printrcflags(struct rc_chans *rc, char *comment) -{ - struct rc_softc *sc; - u_short f = rc->rc_flags; - - sc = rc->rc_rcb; - printf("rc%d/%d: %s flags: %s%s%s%s%s%s%s%s%s%s%s%s\n", - rc->rc_rcb->rcb_unit, rc->rc_chan, comment, - (f & RC_DTR_OFF)?"DTR_OFF " :"", - (f & RC_ACTOUT) ?"ACTOUT " :"", - (f & RC_RTSFLOW)?"RTSFLOW " :"", - (f & RC_CTSFLOW)?"CTSFLOW " :"", - (f & RC_DORXFER)?"DORXFER " :"", - (f & RC_DOXXFER)?"DOXXFER " :"", - (f & RC_MODCHG) ?"MODCHG " :"", - (f & RC_OSUSP) ?"OSUSP " :"", - (f & RC_OSBUSY) ?"OSBUSY " :"", - (f & RC_WAS_BUFOVFL) ?"BUFOVFL " :"", - (f & RC_WAS_SILOVFL) ?"SILOVFL " :"", - (f & RC_SEND_RDY) ?"SEND_RDY":""); - - rcout(sc, CD180_CAR, rc->rc_chan); - - printf("rc%d/%d: msvr %02x ier %02x ccsr %02x\n", - rc->rc_rcb->rcb_unit, rc->rc_chan, - rcin(sc, CD180_MSVR), - rcin(sc, CD180_IER), - rcin(sc, CD180_CCSR)); -} -#endif /* RCDEBUG */ - -static void -rc_discard_output(struct rc_chans *rc) -{ - critical_enter(); - if (rc->rc_flags & RC_DOXXFER) { - rc->rc_rcb->sc_scheduled_event -= LOTS_OF_EVENTS; - rc->rc_flags &= ~RC_DOXXFER; - } - rc->rc_optr = rc->rc_obufend; - rc->rc_tp->t_state &= ~TS_BUSY; - critical_exit(); - ttwwakeup(rc->rc_tp); -} - -static void -rc_wait0(struct rc_softc *sc, int chan, int line) -{ - int rcnt; - - for (rcnt = 50; rcnt && rcin(sc, CD180_CCR); rcnt--) - DELAY(30); - if (rcnt == 0) - device_printf(sc->sc_dev, - "channel %d command timeout, rc.c line: %d\n", chan, line); -} - -static device_method_t rc_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, rc_probe), - DEVMETHOD(device_attach, rc_attach), - DEVMETHOD(device_detach, rc_detach), - { 0, 0 } -}; - -static driver_t rc_driver = { - "rc", - rc_methods, sizeof(struct rc_softc), -}; - -DRIVER_MODULE(rc, isa, rc_driver, rc_devclass, 0, 0); diff --git a/sys/dev/rc/rcreg.h b/sys/dev/rc/rcreg.h deleted file mode 100644 index 832a1cbe1e54..000000000000 --- a/sys/dev/rc/rcreg.h +++ /dev/null @@ -1,72 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (C) 1995 by Pavel Antonov, Moscow, Russia. - * Copyright (C) 1995 by Andrey A. Chernov, Moscow, Russia. - * All rights reserved. - * Copyright (C) 2002 by John Baldwin <jhb@FreeBSD.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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$ - */ - -/* - * Cirrus Logic CD180 -based RISCom/8 board definitions - */ - -/* Oscillator frequency - 19660.08Mhz / 2 */ -#define RC_OSCFREQ 9830400 - -#define RC_BRD(s) ((s) == 0 ? 0 : \ - (((RC_OSCFREQ + (s) / 2) / (s)) + CD180_CTICKS/2) / CD180_CTICKS) - -/* Riscom/8 board ISA I/O mapping */ -#define RC_IOMAP(r) ((((r) & 07) << 1) | (((r) & ~07) << 7)) - -/* I/O commands */ -#define RC_OUT(sc, addr, value) \ - bus_space_write_1((sc)->sc_bt, (sc)->sc_bh, RC_IOMAP(addr), (value)) -#define RC_IN(sc, addr) \ - bus_space_read_1((sc)->sc_bt, (sc)->sc_bh, RC_IOMAP(addr)) - -/* Riscom on-board registers (mapping assumed) */ -#define RC_RIREG 0x100 /* Ring Indicator Register (read-only) */ -#define RC_DTREG 0x100 /* DTR Register (write-only) */ -#define RC_BSR 0x101 /* Board Status Register (read-only) */ -#define RC_CTOUT 0x101 /* Clear Timeout (write-only) */ - -/* Board Status Register */ -#define RC_BSR_TOUT 0x08 /* Timeout */ -#define RC_BSR_RXINT 0x04 /* Receiver Interrupt */ -#define RC_BSR_TXINT 0x02 /* Transmitter Interrupt */ -#define RC_BSR_MOINT 0x01 /* Modem Control Interrupt */ - -/* Interrupt groups */ -#define RC_MODEMGRP 0x01 /* Modem interrupt group */ -#define RC_RXGRP 0x02 /* Receiver interrupt group */ -#define RC_TXGRP 0x04 /* Transmitter interrupt group */ - -/* Priority Interrupt Level definitions */ -#define RC_PILR_MODEM (0x80 | RC_MODEMGRP) -#define RC_PILR_RX (0x80 | RC_RXGRP ) -#define RC_PILR_TX (0x80 | RC_TXGRP ) diff --git a/sys/dev/rp/rp.c b/sys/dev/rp/rp.c deleted file mode 100644 index 390ab733d2ae..000000000000 --- a/sys/dev/rp/rp.c +++ /dev/null @@ -1,1113 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) Comtrol Corporation <support@comtrol.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 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 prodided 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 Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``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 COMTROL CORPORATION 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * rp.c - for RocketPort FreeBSD - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/endian.h> -#include <sys/fcntl.h> -#include <sys/malloc.h> -#include <sys/serial.h> -#include <sys/tty.h> -#include <sys/conf.h> -#include <sys/kernel.h> -#include <machine/resource.h> -#include <machine/bus.h> -#include <sys/bus.h> -#include <sys/rman.h> - -#define ROCKET_C -#include <dev/rp/rpreg.h> -#include <dev/rp/rpvar.h> - -static const char RocketPortVersion[] = "3.02"; - -static Byte_t RData[RDATASIZE] = -{ - 0x00, 0x09, 0xf6, 0x82, - 0x02, 0x09, 0x86, 0xfb, - 0x04, 0x09, 0x00, 0x0a, - 0x06, 0x09, 0x01, 0x0a, - 0x08, 0x09, 0x8a, 0x13, - 0x0a, 0x09, 0xc5, 0x11, - 0x0c, 0x09, 0x86, 0x85, - 0x0e, 0x09, 0x20, 0x0a, - 0x10, 0x09, 0x21, 0x0a, - 0x12, 0x09, 0x41, 0xff, - 0x14, 0x09, 0x82, 0x00, - 0x16, 0x09, 0x82, 0x7b, - 0x18, 0x09, 0x8a, 0x7d, - 0x1a, 0x09, 0x88, 0x81, - 0x1c, 0x09, 0x86, 0x7a, - 0x1e, 0x09, 0x84, 0x81, - 0x20, 0x09, 0x82, 0x7c, - 0x22, 0x09, 0x0a, 0x0a -}; - -static Byte_t RRegData[RREGDATASIZE]= -{ - 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */ - 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */ - 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */ - 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */ - 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */ - 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */ - 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */ - 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */ - 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */ - 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */ - 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */ - 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */ - 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */ -}; - -#if 0 -/* IRQ number to MUDBAC register 2 mapping */ -Byte_t sIRQMap[16] = -{ - 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80 -}; -#endif - -Byte_t rp_sBitMapClrTbl[8] = -{ - 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f -}; - -Byte_t rp_sBitMapSetTbl[8] = -{ - 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 -}; - -static void rpfree(void *); - -/*************************************************************************** -Function: sReadAiopID -Purpose: Read the AIOP idenfication number directly from an AIOP. -Call: sReadAiopID(CtlP, aiop) - CONTROLLER_T *CtlP; Ptr to controller structure - int aiop: AIOP index -Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X - is replace by an identifying number. - Flag AIOPID_NULL if no valid AIOP is found -Warnings: No context switches are allowed while executing this function. - -*/ -int sReadAiopID(CONTROLLER_T *CtlP, int aiop) -{ - Byte_t AiopID; /* ID byte from AIOP */ - - rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL); /* reset AIOP */ - rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0); - AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07; - if(AiopID == 0x06) - return(1); - else /* AIOP does not exist */ - return(-1); -} - -/*************************************************************************** -Function: sReadAiopNumChan -Purpose: Read the number of channels available in an AIOP directly from - an AIOP. -Call: sReadAiopNumChan(CtlP, aiop) - CONTROLLER_T *CtlP; Ptr to controller structure - int aiop: AIOP index -Return: int: The number of channels available -Comments: The number of channels is determined by write/reads from identical - offsets within the SRAM address spaces for channels 0 and 4. - If the channel 4 space is mirrored to channel 0 it is a 4 channel - AIOP, otherwise it is an 8 channel. -Warnings: No context switches are allowed while executing this function. -*/ -int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop) -{ - Word_t x, y; - - rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */ - rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */ - x = rp_readaiop2(CtlP, aiop, _INDX_DATA); - rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */ - y = rp_readaiop2(CtlP, aiop, _INDX_DATA); - if(x != y) /* if different must be 8 chan */ - return(8); - else - return(4); -} - -/*************************************************************************** -Function: sInitChan -Purpose: Initialization of a channel and channel structure -Call: sInitChan(CtlP,ChP,AiopNum,ChanNum) - CONTROLLER_T *CtlP; Ptr to controller structure - CHANNEL_T *ChP; Ptr to channel structure - int AiopNum; AIOP number within controller - int ChanNum; Channel number within AIOP -Return: int: TRUE if initialization succeeded, FALSE if it fails because channel - number exceeds number of channels available in AIOP. -Comments: This function must be called before a channel can be used. -Warnings: No range checking on any of the parameters is done. - - No context switches are allowed while executing this function. -*/ -int sInitChan( CONTROLLER_T *CtlP, - CHANNEL_T *ChP, - int AiopNum, - int ChanNum) -{ - int i, ChOff; - Byte_t *ChR; - static Byte_t R[4]; - - if(ChanNum >= CtlP->AiopNumChan[AiopNum]) - return(FALSE); /* exceeds num chans in AIOP */ - - /* Channel, AIOP, and controller identifiers */ - ChP->CtlP = CtlP; - ChP->ChanID = CtlP->AiopID[AiopNum]; - ChP->AiopNum = AiopNum; - ChP->ChanNum = ChanNum; - - /* Initialize the channel from the RData array */ - for(i=0; i < RDATASIZE; i+=4) - { - R[0] = RData[i]; - R[1] = RData[i+1] + 0x10 * ChanNum; - R[2] = RData[i+2]; - R[3] = RData[i+3]; - rp_writech4(ChP,_INDX_ADDR,le32dec(R)); - } - - ChR = ChP->R; - for(i=0; i < RREGDATASIZE; i+=4) - { - ChR[i] = RRegData[i]; - ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum; - ChR[i+2] = RRegData[i+2]; - ChR[i+3] = RRegData[i+3]; - } - - /* Indexed registers */ - ChOff = (Word_t)ChanNum * 0x1000; - - ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD); - ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8); - ChP->BaudDiv[2] = (Byte_t)BRD9600; - ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8); - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->BaudDiv)); - - ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL); - ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8); - ChP->TxControl[2] = 0; - ChP->TxControl[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl)); - - ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL); - ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8); - ChP->RxControl[2] = 0; - ChP->RxControl[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl)); - - ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS); - ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8); - ChP->TxEnables[2] = 0; - ChP->TxEnables[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxEnables)); - - ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1); - ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8); - ChP->TxCompare[2] = 0; - ChP->TxCompare[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxCompare)); - - ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1); - ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8); - ChP->TxReplace1[2] = 0; - ChP->TxReplace1[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace1)); - - ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2); - ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8); - ChP->TxReplace2[2] = 0; - ChP->TxReplace2[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace2)); - - ChP->TxFIFOPtrs = ChOff + _TXF_OUTP; - ChP->TxFIFO = ChOff + _TX_FIFO; - - rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */ - rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Tx FIFO count */ - rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ - rp_writech2(ChP,_INDX_DATA,0); - ChP->RxFIFOPtrs = ChOff + _RXF_OUTP; - ChP->RxFIFO = ChOff + _RX_FIFO; - - rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */ - rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Rx FIFO count */ - rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */ - rp_writech2(ChP,_INDX_DATA,0); - rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ - rp_writech2(ChP,_INDX_DATA,0); - ChP->TxPrioCnt = ChOff + _TXP_CNT; - rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); - rp_writech1(ChP,_INDX_DATA,0); - ChP->TxPrioPtr = ChOff + _TXP_PNTR; - rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr); - rp_writech1(ChP,_INDX_DATA,0); - ChP->TxPrioBuf = ChOff + _TXP_BUF; - sEnRxProcessor(ChP); /* start the Rx processor */ - - return(TRUE); -} - -/*************************************************************************** -Function: sStopRxProcessor -Purpose: Stop the receive processor from processing a channel. -Call: sStopRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure - -Comments: The receive processor can be started again with sStartRxProcessor(). - This function causes the receive processor to skip over the - stopped channel. It does not stop it from processing other channels. - -Warnings: No context switches are allowed while executing this function. - - Do not leave the receive processor stopped for more than one - character time. - - After calling this function a delay of 4 uS is required to ensure - that the receive processor is no longer processing this channel. -*/ -void sStopRxProcessor(CHANNEL_T *ChP) -{ - Byte_t R[4]; - - R[0] = ChP->R[0]; - R[1] = ChP->R[1]; - R[2] = 0x0a; - R[3] = ChP->R[3]; - rp_writech4(ChP,_INDX_ADDR,le32dec(R)); -} - -/*************************************************************************** -Function: sFlushRxFIFO -Purpose: Flush the Rx FIFO -Call: sFlushRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: void -Comments: To prevent data from being enqueued or dequeued in the Tx FIFO - while it is being flushed the receive processor is stopped - and the transmitter is disabled. After these operations a - 4 uS delay is done before clearing the pointers to allow - the receive processor to stop. These items are handled inside - this function. -Warnings: No context switches are allowed while executing this function. -*/ -void sFlushRxFIFO(CHANNEL_T *ChP) -{ - int i; - Byte_t Ch; /* channel number within AIOP */ - int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */ - - if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */ - return; /* don't need to flush */ - - RxFIFOEnabled = FALSE; - if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */ - { - RxFIFOEnabled = TRUE; - sDisRxFIFO(ChP); /* disable it */ - for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/ - rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */ - } - sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */ - Ch = (Byte_t)sGetChanNum(ChP); - rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT); /* apply reset Rx FIFO count */ - rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Rx FIFO count */ - rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */ - rp_writech2(ChP,_INDX_DATA,0); - rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ - rp_writech2(ChP,_INDX_DATA,0); - if(RxFIFOEnabled) - sEnRxFIFO(ChP); /* enable Rx FIFO */ -} - -/*************************************************************************** -Function: sFlushTxFIFO -Purpose: Flush the Tx FIFO -Call: sFlushTxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: void -Comments: To prevent data from being enqueued or dequeued in the Tx FIFO - while it is being flushed the receive processor is stopped - and the transmitter is disabled. After these operations a - 4 uS delay is done before clearing the pointers to allow - the receive processor to stop. These items are handled inside - this function. -Warnings: No context switches are allowed while executing this function. -*/ -void sFlushTxFIFO(CHANNEL_T *ChP) -{ - int i; - Byte_t Ch; /* channel number within AIOP */ - int TxEnabled; /* TRUE if transmitter enabled */ - - if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */ - return; /* don't need to flush */ - - TxEnabled = FALSE; - if(ChP->TxControl[3] & TX_ENABLE) - { - TxEnabled = TRUE; - sDisTransmit(ChP); /* disable transmitter */ - } - sStopRxProcessor(ChP); /* stop Rx processor */ - for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */ - rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */ - Ch = (Byte_t)sGetChanNum(ChP); - rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT); /* apply reset Tx FIFO count */ - rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Tx FIFO count */ - rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ - rp_writech2(ChP,_INDX_DATA,0); - if(TxEnabled) - sEnTransmit(ChP); /* enable transmitter */ - sStartRxProcessor(ChP); /* restart Rx processor */ -} - -/*************************************************************************** -Function: sWriteTxPrioByte -Purpose: Write a byte of priority transmit data to a channel -Call: sWriteTxPrioByte(ChP,Data) - CHANNEL_T *ChP; Ptr to channel structure - Byte_t Data; The transmit data byte - -Return: int: 1 if the bytes is successfully written, otherwise 0. - -Comments: The priority byte is transmitted before any data in the Tx FIFO. - -Warnings: No context switches are allowed while executing this function. -*/ -int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data) -{ - Byte_t DWBuf[4]; /* buffer for double word writes */ - - if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */ - { - rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */ - if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */ - return(0); /* nothing sent */ - - le16enc(DWBuf,ChP->TxPrioBuf); /* data byte address */ - - DWBuf[2] = Data; /* data byte value */ - DWBuf[3] = 0; /* priority buffer pointer */ - rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */ - - le16enc(DWBuf,ChP->TxPrioCnt); /* Tx priority count address */ - - DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */ - DWBuf[3] = 0; /* priority buffer pointer */ - rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */ - } - else /* write it to Tx FIFO */ - { - sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data); - } - return(1); /* 1 byte sent */ -} - -/*************************************************************************** -Function: sEnInterrupts -Purpose: Enable one or more interrupts for a channel -Call: sEnInterrupts(ChP,Flags) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Flags: Interrupt enable flags, can be any combination - of the following flags: - TXINT_EN: Interrupt on Tx FIFO empty - RXINT_EN: Interrupt on Rx FIFO at trigger level (see - sSetRxTrigger()) - SRCINT_EN: Interrupt on SRC (Special Rx Condition) - MCINT_EN: Interrupt on modem input change - CHANINT_EN: Allow channel interrupt signal to the AIOP's - Interrupt Channel Register. -Return: void -Comments: If an interrupt enable flag is set in Flags, that interrupt will be - enabled. If an interrupt enable flag is not set in Flags, that - interrupt will not be changed. Interrupts can be disabled with - function sDisInterrupts(). - - This function sets the appropriate bit for the channel in the AIOP's - Interrupt Mask Register if the CHANINT_EN flag is set. This allows - this channel's bit to be set in the AIOP's Interrupt Channel Register. - - Interrupts must also be globally enabled before channel interrupts - will be passed on to the host. This is done with function - sEnGlobalInt(). - - In some cases it may be desirable to disable interrupts globally but - enable channel interrupts. This would allow the global interrupt - status register to be used to determine which AIOPs need service. -*/ -void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags) -{ - Byte_t Mask; /* Interrupt Mask Register */ - - ChP->RxControl[2] |= - ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl)); - - ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN); - - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl)); - - if(Flags & CHANINT_EN) - { - Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum]; - rp_writech1(ChP,_INT_MASK,Mask); - } -} - -/*************************************************************************** -Function: sDisInterrupts -Purpose: Disable one or more interrupts for a channel -Call: sDisInterrupts(ChP,Flags) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Flags: Interrupt flags, can be any combination - of the following flags: - TXINT_EN: Interrupt on Tx FIFO empty - RXINT_EN: Interrupt on Rx FIFO at trigger level (see - sSetRxTrigger()) - SRCINT_EN: Interrupt on SRC (Special Rx Condition) - MCINT_EN: Interrupt on modem input change - CHANINT_EN: Disable channel interrupt signal to the - AIOP's Interrupt Channel Register. -Return: void -Comments: If an interrupt flag is set in Flags, that interrupt will be - disabled. If an interrupt flag is not set in Flags, that - interrupt will not be changed. Interrupts can be enabled with - function sEnInterrupts(). - - This function clears the appropriate bit for the channel in the AIOP's - Interrupt Mask Register if the CHANINT_EN flag is set. This blocks - this channel's bit from being set in the AIOP's Interrupt Channel - Register. -*/ -void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags) -{ - Byte_t Mask; /* Interrupt Mask Register */ - - ChP->RxControl[2] &= - ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl)); - ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN); - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl)); - - if(Flags & CHANINT_EN) - { - Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum]; - rp_writech1(ChP,_INT_MASK,Mask); - } -} - -/********************************************************************* - Begin FreeBsd-specific driver code -**********************************************************************/ - -#define POLL_INTERVAL (hz / 100) - -#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1) -#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff) -#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04) - -/* - * The top-level routines begin here - */ - -static void rpclose(struct tty *tp); -static void rphardclose(struct tty *tp); -static int rpmodem(struct tty *, int, int); -static int rpparam(struct tty *, struct termios *); -static void rpstart(struct tty *); -static int rpioctl(struct tty *, u_long, caddr_t, struct thread *); -static int rpopen(struct tty *); - -static void rp_do_receive(struct rp_port *rp, struct tty *tp, - CHANNEL_t *cp, unsigned int ChanStatus) -{ - unsigned int CharNStat; - int ToRecv, ch, err = 0; - - ToRecv = sGetRxCnt(cp); - if(ToRecv == 0) - return; - -/* If status indicates there are errored characters in the - FIFO, then enter status mode (a word in FIFO holds - characters and status) -*/ - - if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { - if(!(ChanStatus & STATMODE)) { - ChanStatus |= STATMODE; - sEnRxStatusMode(cp); - } - } -/* - if we previously entered status mode then read down the - FIFO one word at a time, pulling apart the character and - the status. Update error counters depending on status. -*/ - tty_lock(tp); - if(ChanStatus & STATMODE) { - while(ToRecv) { - CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp)); - ch = CharNStat & 0xff; - - if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH)) - err |= TRE_FRAMING; - else if (CharNStat & STMPARITYH) - err |= TRE_PARITY; - else if (CharNStat & STMRCVROVRH) { - rp->rp_overflows++; - err |= TRE_OVERRUN; - } - - ttydisc_rint(tp, ch, err); - ToRecv--; - } -/* - After emtying FIFO in status mode, turn off status mode -*/ - - if(sGetRxCnt(cp) == 0) { - sDisRxStatusMode(cp); - } - } else { - ToRecv = sGetRxCnt(cp); - while (ToRecv) { - ch = rp_readch1(cp,sGetTxRxDataIO(cp)); - ttydisc_rint(tp, ch & 0xff, err); - ToRecv--; - } - } - ttydisc_rint_done(tp); - tty_unlock(tp); -} - -static void rp_handle_port(struct rp_port *rp) -{ - CHANNEL_t *cp; - struct tty *tp; - unsigned int IntMask, ChanStatus; - - if(!rp) - return; - - cp = &rp->rp_channel; - tp = rp->rp_tty; - IntMask = sGetChanIntID(cp); - IntMask = IntMask & rp->rp_intmask; - ChanStatus = sGetChanStatus(cp); - if(IntMask & RXF_TRIG) - rp_do_receive(rp, tp, cp, ChanStatus); - if(IntMask & DELTA_CD) { - if(ChanStatus & CD_ACT) { - (void)ttydisc_modem(tp, 1); - } else { - (void)ttydisc_modem(tp, 0); - } - } -/* oldcts = rp->rp_cts; - rp->rp_cts = ((ChanStatus & CTS_ACT) != 0); - if(oldcts != rp->rp_cts) { - printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port); - } -*/ -} - -static void rp_do_poll(void *arg) -{ - CONTROLLER_t *ctl; - struct rp_port *rp; - struct tty *tp; - int count; - unsigned char CtlMask, AiopMask; - - rp = arg; - tp = rp->rp_tty; - tty_assert_locked(tp); - ctl = rp->rp_ctlp; - CtlMask = ctl->ctlmask(ctl); - if (CtlMask & (1 << rp->rp_aiop)) { - AiopMask = sGetAiopIntStatus(ctl, rp->rp_aiop); - if (AiopMask & (1 << rp->rp_chan)) { - rp_handle_port(rp); - } - } - - count = sGetTxCnt(&rp->rp_channel); - if (count >= 0 && (count <= rp->rp_restart)) { - rpstart(tp); - } - callout_schedule(&rp->rp_timer, POLL_INTERVAL); -} - -static struct ttydevsw rp_tty_class = { - .tsw_flags = TF_INITLOCK|TF_CALLOUT, - .tsw_open = rpopen, - .tsw_close = rpclose, - .tsw_outwakeup = rpstart, - .tsw_ioctl = rpioctl, - .tsw_param = rpparam, - .tsw_modem = rpmodem, - .tsw_free = rpfree, -}; - - -static void -rpfree(void *softc) -{ - struct rp_port *rp = softc; - CONTROLLER_t *ctlp = rp->rp_ctlp; - - atomic_subtract_32(&ctlp->free, 1); -} - -int -rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) -{ - int unit; - int num_chan; - int aiop, chan, port; - int ChanStatus; - int retval; - struct rp_port *rp; - struct tty *tp; - - unit = device_get_unit(ctlp->dev); - - printf("RocketPort%d (Version %s) %d ports.\n", unit, - RocketPortVersion, num_ports); - - ctlp->num_ports = num_ports; - ctlp->rp = rp = (struct rp_port *) - malloc(sizeof(struct rp_port) * num_ports, M_DEVBUF, M_NOWAIT | M_ZERO); - if (rp == NULL) { - device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n"); - retval = ENOMEM; - goto nogo; - } - - port = 0; - for(aiop=0; aiop < num_aiops; aiop++) { - num_chan = sGetAiopNumChan(ctlp, aiop); - for(chan=0; chan < num_chan; chan++, port++, rp++) { - rp->rp_tty = tp = tty_alloc(&rp_tty_class, rp); - callout_init_mtx(&rp->rp_timer, tty_getlock(tp), 0); - rp->rp_port = port; - rp->rp_ctlp = ctlp; - rp->rp_unit = unit; - rp->rp_chan = chan; - rp->rp_aiop = aiop; - - rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | - DELTA_CD | DELTA_CTS | DELTA_DSR; -#ifdef notdef - ChanStatus = sGetChanStatus(&rp->rp_channel); -#endif /* notdef */ - if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { - device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n", - unit, aiop, chan); - retval = ENXIO; - goto nogo; - } - ChanStatus = sGetChanStatus(&rp->rp_channel); - rp->rp_cts = (ChanStatus & CTS_ACT) != 0; - tty_makedev(tp, NULL, "R%r%r", unit, port); - } - } - - mtx_init(&ctlp->hwmtx, "rp_hwmtx", NULL, MTX_DEF); - ctlp->hwmtx_init = 1; - return (0); - -nogo: - rp_releaseresource(ctlp); - - return (retval); -} - -void -rp_releaseresource(CONTROLLER_t *ctlp) -{ - struct rp_port *rp; - int i; - - if (ctlp->rp != NULL) { - for (i = 0; i < ctlp->num_ports; i++) { - rp = ctlp->rp + i; - atomic_add_32(&ctlp->free, 1); - tty_lock(rp->rp_tty); - tty_rel_gone(rp->rp_tty); - } - free(ctlp->rp, M_DEVBUF); - ctlp->rp = NULL; - } - - while (ctlp->free != 0) { - pause("rpwt", hz / 10); - } - - if (ctlp->hwmtx_init) - mtx_destroy(&ctlp->hwmtx); -} - -static int -rpopen(struct tty *tp) -{ - struct rp_port *rp; - int flags; - unsigned int IntMask, ChanStatus; - - rp = tty_softc(tp); - - flags = 0; - flags |= SET_RTS; - flags |= SET_DTR; - rp->rp_channel.TxControl[3] = - ((rp->rp_channel.TxControl[3] - & ~(SET_RTS | SET_DTR)) | flags); - rp_writech4(&rp->rp_channel,_INDX_ADDR, - le32dec(rp->rp_channel.TxControl)); - sSetRxTrigger(&rp->rp_channel, TRIG_1); - sDisRxStatusMode(&rp->rp_channel); - sFlushRxFIFO(&rp->rp_channel); - sFlushTxFIFO(&rp->rp_channel); - - sEnInterrupts(&rp->rp_channel, - (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN)); - sSetRxTrigger(&rp->rp_channel, TRIG_1); - - sDisRxStatusMode(&rp->rp_channel); - sClrTxXOFF(&rp->rp_channel); - -/* sDisRTSFlowCtl(&rp->rp_channel); - sDisCTSFlowCtl(&rp->rp_channel); -*/ - sDisTxSoftFlowCtl(&rp->rp_channel); - - sStartRxProcessor(&rp->rp_channel); - - sEnRxFIFO(&rp->rp_channel); - sEnTransmit(&rp->rp_channel); - -/* sSetDTR(&rp->rp_channel); - sSetRTS(&rp->rp_channel); -*/ - - IntMask = sGetChanIntID(&rp->rp_channel); - IntMask = IntMask & rp->rp_intmask; - ChanStatus = sGetChanStatus(&rp->rp_channel); - - callout_reset(&rp->rp_timer, POLL_INTERVAL, rp_do_poll, rp); - - device_busy(rp->rp_ctlp->dev); - return(0); -} - -static void -rpclose(struct tty *tp) -{ - struct rp_port *rp; - - rp = tty_softc(tp); - callout_stop(&rp->rp_timer); - rphardclose(tp); - device_unbusy(rp->rp_ctlp->dev); -} - -static void -rphardclose(struct tty *tp) -{ - struct rp_port *rp; - CHANNEL_t *cp; - - rp = tty_softc(tp); - cp = &rp->rp_channel; - - sFlushRxFIFO(cp); - sFlushTxFIFO(cp); - sDisTransmit(cp); - sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN); - sDisRTSFlowCtl(cp); - sDisCTSFlowCtl(cp); - sDisTxSoftFlowCtl(cp); - sClrTxXOFF(cp); - -#ifdef DJA - if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !tp->t_actout) { - sClrDTR(cp); - } - if(ISCALLOUT(tp->t_dev)) { - sClrDTR(cp); - } - tp->t_actout = FALSE; - wakeup(&tp->t_actout); - wakeup(TSA_CARR_ON(tp)); -#endif /* DJA */ -} - -static int -rpioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) -{ - struct rp_port *rp; - - rp = tty_softc(tp); - switch (cmd) { - case TIOCSBRK: - sSendBreak(&rp->rp_channel); - return (0); - case TIOCCBRK: - sClrBreak(&rp->rp_channel); - return (0); - default: - return ENOIOCTL; - } -} - -static int -rpmodem(struct tty *tp, int sigon, int sigoff) -{ - struct rp_port *rp; - int i, j, k; - - rp = tty_softc(tp); - if (sigon != 0 || sigoff != 0) { - i = j = 0; - if (sigon & SER_DTR) - i = SET_DTR; - if (sigoff & SER_DTR) - j = SET_DTR; - if (sigon & SER_RTS) - i = SET_RTS; - if (sigoff & SER_RTS) - j = SET_RTS; - rp->rp_channel.TxControl[3] &= ~i; - rp->rp_channel.TxControl[3] |= j; - rp_writech4(&rp->rp_channel,_INDX_ADDR, - le32dec(rp->rp_channel.TxControl)); - } else { - i = sGetChanStatusLo(&rp->rp_channel); - j = rp->rp_channel.TxControl[3]; - k = 0; - if (j & SET_DTR) - k |= SER_DTR; - if (j & SET_RTS) - k |= SER_RTS; - if (i & CD_ACT) - k |= SER_DCD; - if (i & DSR_ACT) - k |= SER_DSR; - if (i & CTS_ACT) - k |= SER_CTS; - return(k); - } - return (0); -} - -static struct -{ - int baud; - int conversion; -} baud_table[] = { - {B0, 0}, {B50, BRD50}, {B75, BRD75}, - {B110, BRD110}, {B134, BRD134}, {B150, BRD150}, - {B200, BRD200}, {B300, BRD300}, {B600, BRD600}, - {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400}, - {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200}, - {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400}, - {B57600, BRD57600}, {B76800, BRD76800}, - {B115200, BRD115200}, {B230400, BRD230400}, - {-1, -1} -}; - -static int rp_convert_baud(int baud) { - int i; - - for (i = 0; baud_table[i].baud >= 0; i++) { - if (baud_table[i].baud == baud) - break; - } - - return baud_table[i].conversion; -} - -static int -rpparam(tp, t) - struct tty *tp; - struct termios *t; -{ - struct rp_port *rp; - CHANNEL_t *cp; - int cflag, iflag, oflag, lflag; - int ospeed; -#ifdef RPCLOCAL - int devshift; -#endif - - rp = tty_softc(tp); - cp = &rp->rp_channel; - - cflag = t->c_cflag; -#ifdef RPCLOCAL - devshift = umynor / 32; - devshift = 1 << devshift; - if ( devshift & RPCLOCAL ) { - cflag |= CLOCAL; - } -#endif - iflag = t->c_iflag; - oflag = t->c_oflag; - lflag = t->c_lflag; - - ospeed = rp_convert_baud(t->c_ispeed); - if(ospeed < 0 || t->c_ispeed != t->c_ospeed) - return(EINVAL); - - if(t->c_ospeed == 0) { - sClrDTR(cp); - return(0); - } - rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1; - - /* Set baud rate ----- we only pay attention to ispeed */ - sSetDTR(cp); - sSetRTS(cp); - sSetBaud(cp, ospeed); - - if(cflag & CSTOPB) { - sSetStop2(cp); - } else { - sSetStop1(cp); - } - - if(cflag & PARENB) { - sEnParity(cp); - if(cflag & PARODD) { - sSetOddParity(cp); - } else { - sSetEvenParity(cp); - } - } - else { - sDisParity(cp); - } - if((cflag & CSIZE) == CS8) { - sSetData8(cp); - rp->rp_imask = 0xFF; - } else { - sSetData7(cp); - rp->rp_imask = 0x7F; - } - - if(iflag & ISTRIP) { - rp->rp_imask &= 0x7F; - } - - if(cflag & CLOCAL) { - rp->rp_intmask &= ~DELTA_CD; - } else { - rp->rp_intmask |= DELTA_CD; - } - - /* Put flow control stuff here */ - - if(cflag & CCTS_OFLOW) { - sEnCTSFlowCtl(cp); - } else { - sDisCTSFlowCtl(cp); - } - - if(cflag & CRTS_IFLOW) { - rp->rp_rts_iflow = 1; - } else { - rp->rp_rts_iflow = 0; - } - - if(cflag & CRTS_IFLOW) { - sEnRTSFlowCtl(cp); - } else { - sDisRTSFlowCtl(cp); - } - - return(0); -} - -static void -rpstart(struct tty *tp) -{ - struct rp_port *rp; - CHANNEL_t *cp; - char flags; - int xmit_fifo_room; - int i, count, wcount; - - rp = tty_softc(tp); - cp = &rp->rp_channel; - flags = rp->rp_channel.TxControl[3]; - - if(rp->rp_xmit_stopped) { - sEnTransmit(cp); - rp->rp_xmit_stopped = 0; - } - - xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); - count = ttydisc_getc(tp, &rp->TxBuf, xmit_fifo_room); - if(xmit_fifo_room > 0) { - for( i = 0, wcount = count >> 1; wcount > 0; i += 2, wcount-- ) { - rp_writech2(cp, sGetTxRxDataIO(cp), le16dec(&rp->TxBuf[i])); - } - if ( count & 1 ) { - rp_writech1(cp, sGetTxRxDataIO(cp), rp->TxBuf[(count-1)]); - } - } -} diff --git a/sys/dev/rp/rp_isa.c b/sys/dev/rp/rp_isa.c deleted file mode 100644 index 7a96d54bd607..000000000000 --- a/sys/dev/rp/rp_isa.c +++ /dev/null @@ -1,508 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) Comtrol Corporation <support@comtrol.com> - * All rights reserved. - * - * ISA-specific part separated from: - * sys/i386/isa/rp.c,v 1.33 1999/09/28 11:45:27 phk Exp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 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 prodided 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 Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``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 COMTROL CORPORATION 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/fcntl.h> -#include <sys/malloc.h> -#include <sys/conf.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/module.h> -#include <sys/mutex.h> -#include <machine/resource.h> -#include <machine/bus.h> -#include <sys/bus.h> -#include <sys/rman.h> - -#define ROCKET_C -#include <dev/rp/rpreg.h> -#include <dev/rp/rpvar.h> - -#include <isa/isavar.h> - -/* ISA-specific part of CONTROLLER_t */ -struct ISACONTROLLER_T { - int MBaseIO; /* rid of the Mudbac controller for this controller */ - int MReg0IO; /* offset0 of the Mudbac controller for this controller */ - int MReg1IO; /* offset1 of the Mudbac controller for this controller */ - int MReg2IO; /* offset2 of the Mudbac controller for this controller */ - int MReg3IO; /* offset3 of the Mudbac controller for this controller */ - Byte_t MReg2; - Byte_t MReg3; -}; -typedef struct ISACONTROLLER_T ISACONTROLLER_t; - -#define ISACTL(ctlp) ((ISACONTROLLER_t *)((ctlp)->bus_ctlp)) - -/*************************************************************************** -Function: sControllerEOI -Purpose: Strobe the MUDBAC's End Of Interrupt bit. -Call: sControllerEOI(MudbacCtlP,CtlP) - CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure - CONTROLLER_T *CtlP; Ptr to controller structure -*/ -#define sControllerEOI(MudbacCtlP,CtlP) \ - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg2IO,ISACTL(CtlP)->MReg2 | INT_STROB) - -/*************************************************************************** -Function: sDisAiop -Purpose: Disable I/O access to an AIOP -Call: sDisAiop(MudbacCtlP,CtlP) - CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; Number of AIOP on controller -*/ -#define sDisAiop(MudbacCtlP,CtlP,AIOPNUM) \ -{ \ - ISACTL(CtlP)->MReg3 &= rp_sBitMapClrTbl[AIOPNUM]; \ - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3); \ -} - -/*************************************************************************** -Function: sEnAiop -Purpose: Enable I/O access to an AIOP -Call: sEnAiop(MudbacCtlP,CtlP) - CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; Number of AIOP on controller -*/ -#define sEnAiop(MudbacCtlP,CtlP,AIOPNUM) \ -{ \ - ISACTL(CtlP)->MReg3 |= rp_sBitMapSetTbl[AIOPNUM]; \ - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3); \ -} - -/*************************************************************************** -Function: sGetControllerIntStatus -Purpose: Get the controller interrupt status -Call: sGetControllerIntStatus(MudbacCtlP,CtlP) - CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure - CONTROLLER_T *CtlP; Ptr to controller structure -Return: Byte_t: The controller interrupt status in the lower 4 - bits. Bits 0 through 3 represent AIOP's 0 - through 3 respectively. If a bit is set that - AIOP is interrupting. Bits 4 through 7 will - always be cleared. -*/ -#define sGetControllerIntStatus(MudbacCtlP,CtlP) \ - (rp_readio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg1IO) & 0x0f) - -static devclass_t rp_devclass; -static CONTROLLER_t *rp_controller; -static int rp_nisadevs; - -static int rp_probe(device_t dev); -static int rp_attach(device_t dev); -static void rp_isareleaseresource(CONTROLLER_t *ctlp); -static int sInitController(CONTROLLER_T *CtlP, - CONTROLLER_T *MudbacCtlP, - int AiopNum, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly); -static rp_aiop2rid_t rp_isa_aiop2rid; -static rp_aiop2off_t rp_isa_aiop2off; -static rp_ctlmask_t rp_isa_ctlmask; - -static int -rp_probe(device_t dev) -{ - int unit; - CONTROLLER_t *controller; - int num_aiops; - CONTROLLER_t *ctlp; - int retval; - - /* - * We have no PnP RocketPort cards. - * (At least according to LINT) - */ - if (isa_get_logicalid(dev) != 0) - return (ENXIO); - - /* We need IO port resource to configure an ISA device. */ - if (bus_get_resource_count(dev, SYS_RES_IOPORT, 0) == 0) - return (ENXIO); - - unit = device_get_unit(dev); - if (unit >= 4) { - device_printf(dev, "rpprobe: unit number %d invalid.\n", unit); - return (ENXIO); - } - device_printf(dev, "probing for RocketPort(ISA) unit %d.\n", unit); - - ctlp = device_get_softc(dev); - bzero(ctlp, sizeof(*ctlp)); - ctlp->dev = dev; - ctlp->aiop2rid = rp_isa_aiop2rid; - ctlp->aiop2off = rp_isa_aiop2off; - ctlp->ctlmask = rp_isa_ctlmask; - - /* The IO ports of AIOPs for an ISA controller are discrete. */ - ctlp->io_num = 1; - ctlp->io_rid = malloc(sizeof(*(ctlp->io_rid)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT | M_ZERO); - ctlp->io = malloc(sizeof(*(ctlp->io)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT | M_ZERO); - if (ctlp->io_rid == NULL || ctlp->io == NULL) { - device_printf(dev, "rp_attach: Out of memory.\n"); - retval = ENOMEM; - goto nogo; - } - - ctlp->bus_ctlp = malloc(sizeof(ISACONTROLLER_t) * 1, M_DEVBUF, M_NOWAIT | M_ZERO); - if (ctlp->bus_ctlp == NULL) { - device_printf(dev, "rp_attach: Out of memory.\n"); - retval = ENOMEM; - goto nogo; - } - - ctlp->io_rid[0] = 0; - if (rp_controller != NULL) { - controller = rp_controller; - ctlp->io[0] = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &ctlp->io_rid[0], 0x40, RF_ACTIVE); - } else { - controller = rp_controller = ctlp; - ctlp->io[0] = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &ctlp->io_rid[0], 0x44, RF_ACTIVE); - } - if (ctlp->io[0] == NULL) { - device_printf(dev, "rp_attach: Resource not available.\n"); - retval = ENXIO; - goto nogo; - } - - num_aiops = sInitController(ctlp, - controller, - MAX_AIOPS_PER_BOARD, 0, - FREQ_DIS, 0); - if (num_aiops <= 0) { - device_printf(dev, "board%d init failed.\n", unit); - retval = ENXIO; - goto nogo; - } - - if (rp_controller == NULL) - rp_controller = controller; - rp_nisadevs++; - - device_set_desc(dev, "RocketPort ISA"); - - return (0); - -nogo: - rp_isareleaseresource(ctlp); - - return (retval); -} - -static int -rp_attach(device_t dev) -{ - int unit; - int num_ports, num_aiops; - int aiop; - CONTROLLER_t *ctlp; - int retval; - - unit = device_get_unit(dev); - - ctlp = device_get_softc(dev); - -#ifdef notdef - num_aiops = sInitController(ctlp, - rp_controller, - MAX_AIOPS_PER_BOARD, 0, - FREQ_DIS, 0); -#else - num_aiops = ctlp->NumAiop; -#endif /* notdef */ - - num_ports = 0; - for(aiop=0; aiop < num_aiops; aiop++) { - sResetAiopByNum(ctlp, aiop); - sEnAiop(rp_controller, ctlp, aiop); - num_ports += sGetAiopNumChan(ctlp, aiop); - } - - retval = rp_attachcommon(ctlp, num_aiops, num_ports); - if (retval != 0) - goto nogo; - - return (0); - -nogo: - rp_isareleaseresource(ctlp); - - return (retval); -} - -static void -rp_isareleaseresource(CONTROLLER_t *ctlp) -{ - int i; - - rp_releaseresource(ctlp); - - if (ctlp == rp_controller) - rp_controller = NULL; - if (ctlp->io != NULL) { - for (i = 0 ; i < MAX_AIOPS_PER_BOARD ; i++) - if (ctlp->io[i] != NULL) - bus_release_resource(ctlp->dev, SYS_RES_IOPORT, ctlp->io_rid[i], ctlp->io[i]); - free(ctlp->io, M_DEVBUF); - } - if (ctlp->io_rid != NULL) - free(ctlp->io_rid, M_DEVBUF); - if (rp_controller != NULL && rp_controller->io[ISACTL(ctlp)->MBaseIO] != NULL) { - bus_release_resource(rp_controller->dev, SYS_RES_IOPORT, rp_controller->io_rid[ISACTL(ctlp)->MBaseIO], rp_controller->io[ISACTL(ctlp)->MBaseIO]); - rp_controller->io[ISACTL(ctlp)->MBaseIO] = NULL; - rp_controller->io_rid[ISACTL(ctlp)->MBaseIO] = 0; - } - if (ctlp->bus_ctlp != NULL) - free(ctlp->bus_ctlp, M_DEVBUF); -} - -/*************************************************************************** -Function: sInitController -Purpose: Initialization of controller global registers and controller - structure. -Call: sInitController(CtlP,MudbacCtlP,AiopNum, - IRQNum,Frequency,PeriodicOnly) - CONTROLLER_T *CtlP; Ptr to controller structure - CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure - int AiopNum; Number of Aiops - int IRQNum; Interrupt Request number. Can be any of the following: - 0: Disable global interrupts - 3: IRQ 3 - 4: IRQ 4 - 5: IRQ 5 - 9: IRQ 9 - 10: IRQ 10 - 11: IRQ 11 - 12: IRQ 12 - 15: IRQ 15 - Byte_t Frequency: A flag identifying the frequency - of the periodic interrupt, can be any one of the following: - FREQ_DIS - periodic interrupt disabled - FREQ_137HZ - 137 Hertz - FREQ_69HZ - 69 Hertz - FREQ_34HZ - 34 Hertz - FREQ_17HZ - 17 Hertz - FREQ_9HZ - 9 Hertz - FREQ_4HZ - 4 Hertz - If IRQNum is set to 0 the Frequency parameter is - overidden, it is forced to a value of FREQ_DIS. - int PeriodicOnly: TRUE if all interrupts except the periodic - interrupt are to be blocked. - FALSE is both the periodic interrupt and - other channel interrupts are allowed. - If IRQNum is set to 0 the PeriodicOnly parameter is - overidden, it is forced to a value of FALSE. -Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller - initialization failed. - -Comments: - If periodic interrupts are to be disabled but AIOP interrupts - are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE. - - If interrupts are to be completely disabled set IRQNum to 0. - - Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an - invalid combination. - - This function performs initialization of global interrupt modes, - but it does not actually enable global interrupts. To enable - and disable global interrupts use functions sEnGlobalInt() and - sDisGlobalInt(). Enabling of global interrupts is normally not - done until all other initializations are complete. - - Even if interrupts are globally enabled, they must also be - individually enabled for each channel that is to generate - interrupts. - -Warnings: No range checking on any of the parameters is done. - - No context switches are allowed while executing this function. - - After this function all AIOPs on the controller are disabled, - they can be enabled with sEnAiop(). -*/ -static int -sInitController( CONTROLLER_T *CtlP, - CONTROLLER_T *MudbacCtlP, - int AiopNum, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly) -{ - int i; - int ctl_base, aiop_base, aiop_size; - - CtlP->CtlID = CTLID_0001; /* controller release 1 */ - - ISACTL(CtlP)->MBaseIO = rp_nisadevs; - if (MudbacCtlP->io[ISACTL(CtlP)->MBaseIO] != NULL) { - ISACTL(CtlP)->MReg0IO = 0x40 + 0; - ISACTL(CtlP)->MReg1IO = 0x40 + 1; - ISACTL(CtlP)->MReg2IO = 0x40 + 2; - ISACTL(CtlP)->MReg3IO = 0x40 + 3; - } else { - MudbacCtlP->io_rid[ISACTL(CtlP)->MBaseIO] = ISACTL(CtlP)->MBaseIO; - ctl_base = rman_get_start(MudbacCtlP->io[0]) + 0x40 + 0x400 * rp_nisadevs; - MudbacCtlP->io[ISACTL(CtlP)->MBaseIO] = bus_alloc_resource(MudbacCtlP->dev, SYS_RES_IOPORT, &CtlP->io_rid[ISACTL(CtlP)->MBaseIO], ctl_base, ctl_base + 3, 4, RF_ACTIVE); - ISACTL(CtlP)->MReg0IO = 0; - ISACTL(CtlP)->MReg1IO = 1; - ISACTL(CtlP)->MReg2IO = 2; - ISACTL(CtlP)->MReg3IO = 3; - } -#if 1 - ISACTL(CtlP)->MReg2 = 0; /* interrupt disable */ - ISACTL(CtlP)->MReg3 = 0; /* no periodic interrupts */ -#else - if(sIRQMap[IRQNum] == 0) /* interrupts globally disabled */ - { - ISACTL(CtlP)->MReg2 = 0; /* interrupt disable */ - ISACTL(CtlP)->MReg3 = 0; /* no periodic interrupts */ - } - else - { - ISACTL(CtlP)->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */ - ISACTL(CtlP)->MReg3 = Frequency; /* set frequency */ - if(PeriodicOnly) /* periodic interrupt only */ - { - ISACTL(CtlP)->MReg3 |= PERIODIC_ONLY; - } - } -#endif - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg2IO,ISACTL(CtlP)->MReg2); - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3); - sControllerEOI(MudbacCtlP,CtlP); /* clear EOI if warm init */ - - /* Init AIOPs */ - CtlP->NumAiop = 0; - for(i=0; i < AiopNum; i++) - { - if (CtlP->io[i] == NULL) { - CtlP->io_rid[i] = i; - aiop_base = rman_get_start(CtlP->io[0]) + 0x400 * i; - if (rp_nisadevs == 0) - aiop_size = 0x44; - else - aiop_size = 0x40; - CtlP->io[i] = bus_alloc_resource(CtlP->dev, SYS_RES_IOPORT, &CtlP->io_rid[i], aiop_base, aiop_base + aiop_size - 1, aiop_size, RF_ACTIVE); - } else - aiop_base = rman_get_start(CtlP->io[i]); - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO, - ISACTL(CtlP)->MReg2IO, - ISACTL(CtlP)->MReg2 | (i & 0x03)); /* AIOP index */ - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO, - ISACTL(CtlP)->MReg0IO, - (Byte_t)(aiop_base >> 6)); /* set up AIOP I/O in MUDBAC */ - sEnAiop(MudbacCtlP,CtlP,i); /* enable the AIOP */ - - CtlP->AiopID[i] = sReadAiopID(CtlP, i); /* read AIOP ID */ - if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ - { - sDisAiop(MudbacCtlP,CtlP,i); /* disable AIOP */ - bus_release_resource(CtlP->dev, SYS_RES_IOPORT, CtlP->io_rid[i], CtlP->io[i]); - CtlP->io[i] = NULL; - break; /* done looking for AIOPs */ - } - - CtlP->AiopNumChan[i] = sReadAiopNumChan(CtlP, i); /* num channels in AIOP */ - rp_writeaiop2(CtlP,i,_INDX_ADDR,_CLK_PRE); /* clock prescaler */ - rp_writeaiop1(CtlP,i,_INDX_DATA,CLOCK_PRESC); - CtlP->NumAiop++; /* bump count of AIOPs */ - sDisAiop(MudbacCtlP,CtlP,i); /* disable AIOP */ - } - - if(CtlP->NumAiop == 0) - return(-1); - else - return(CtlP->NumAiop); -} - -/* - * ARGSUSED - * Maps (aiop, offset) to rid. - */ -static int -rp_isa_aiop2rid(int aiop, int offset) -{ - /* rid equals to aiop for an ISA controller. */ - return aiop; -} - -/* - * ARGSUSED - * Maps (aiop, offset) to the offset of resource. - */ -static int -rp_isa_aiop2off(int aiop, int offset) -{ - /* Each aiop has its own resource. */ - return offset; -} - -/* Read the int status for an ISA controller. */ -static unsigned char -rp_isa_ctlmask(CONTROLLER_t *ctlp) -{ - return sGetControllerIntStatus(rp_controller,ctlp); -} - -static device_method_t rp_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, rp_probe), - DEVMETHOD(device_attach, rp_attach), - - { 0, 0 } -}; - -static driver_t rp_driver = { - "rp", - rp_methods, - sizeof(CONTROLLER_t), -}; - -/* - * rp can be attached to an isa bus. - */ -DRIVER_MODULE(rp, isa, rp_driver, rp_devclass, 0, 0); diff --git a/sys/dev/rp/rp_pci.c b/sys/dev/rp/rp_pci.c deleted file mode 100644 index afd378c3c119..000000000000 --- a/sys/dev/rp/rp_pci.c +++ /dev/null @@ -1,368 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) Comtrol Corporation <support@comtrol.com> - * All rights reserved. - * - * PCI-specific part separated from: - * sys/i386/isa/rp.c,v 1.33 1999/09/28 11:45:27 phk Exp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 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 prodided 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 Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``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 COMTROL CORPORATION 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/fcntl.h> -#include <sys/malloc.h> -#include <sys/conf.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/module.h> -#include <sys/mutex.h> -#include <machine/resource.h> -#include <machine/bus.h> -#include <sys/bus.h> -#include <sys/rman.h> - -#define ROCKET_C -#include <dev/rp/rpreg.h> -#include <dev/rp/rpvar.h> - -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> - -/* PCI IDs */ -#define RP_VENDOR_ID 0x11FE -#define RP_DEVICE_ID_32I 0x0001 -#define RP_DEVICE_ID_8I 0x0002 -#define RP_DEVICE_ID_16I 0x0003 -#define RP_DEVICE_ID_4Q 0x0004 -#define RP_DEVICE_ID_8O 0x0005 -#define RP_DEVICE_ID_8J 0x0006 -#define RP_DEVICE_ID_4J 0x0007 -#define RP_DEVICE_ID_6M 0x000C -#define RP_DEVICE_ID_4M 0x000D -#define RP_DEVICE_ID_UPCI_32 0x0801 -#define RP_DEVICE_ID_UPCI_16 0x0803 -#define RP_DEVICE_ID_UPCI_8O 0x0805 - -/************************************************************************** - MUDBAC remapped for PCI -**************************************************************************/ - -#define _CFG_INT_PCI 0x40 -#define _PCI_INT_FUNC 0x3A - -#define PCI_STROB 0x2000 -#define INTR_EN_PCI 0x0010 - -/*************************************************************************** -Function: sPCIControllerEOI -Purpose: Strobe the MUDBAC's End Of Interrupt bit. -Call: sPCIControllerEOI(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -*/ -#define sPCIControllerEOI(CtlP) rp_writeio2(CtlP, 0, _PCI_INT_FUNC, PCI_STROB) - -/*************************************************************************** -Function: sPCIGetControllerIntStatus -Purpose: Get the controller interrupt status -Call: sPCIGetControllerIntStatus(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -Return: Byte_t: The controller interrupt status in the lower 4 - bits. Bits 0 through 3 represent AIOP's 0 - through 3 respectively. If a bit is set that - AIOP is interrupting. Bits 4 through 7 will - always be cleared. -*/ -#define sPCIGetControllerIntStatus(CTLP) ((rp_readio2(CTLP, 0, _PCI_INT_FUNC) >> 8) & 0x1f) - -static devclass_t rp_devclass; - -static int rp_pciprobe(device_t dev); -static int rp_pciattach(device_t dev); -#ifdef notdef -static int rp_pcidetach(device_t dev); -static int rp_pcishutdown(device_t dev); -#endif /* notdef */ -static void rp_pcireleaseresource(CONTROLLER_t *ctlp); -static int sPCIInitController( CONTROLLER_t *CtlP, - int AiopNum, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly, - int VendorDevice); -static rp_aiop2rid_t rp_pci_aiop2rid; -static rp_aiop2off_t rp_pci_aiop2off; -static rp_ctlmask_t rp_pci_ctlmask; - -/* - * The following functions are the pci-specific part - * of rp driver. - */ - -static int -rp_pciprobe(device_t dev) -{ - char *s; - - s = NULL; - if (pci_get_vendor(dev) == RP_VENDOR_ID) - s = "RocketPort PCI"; - - if (s != NULL) { - device_set_desc(dev, s); - return (BUS_PROBE_DEFAULT); - } - - return (ENXIO); -} - -static int -rp_pciattach(device_t dev) -{ - int num_ports, num_aiops; - int aiop; - CONTROLLER_t *ctlp; - int unit; - int retval; - - ctlp = device_get_softc(dev); - bzero(ctlp, sizeof(*ctlp)); - ctlp->dev = dev; - unit = device_get_unit(dev); - ctlp->aiop2rid = rp_pci_aiop2rid; - ctlp->aiop2off = rp_pci_aiop2off; - ctlp->ctlmask = rp_pci_ctlmask; - - /* The IO ports of AIOPs for a PCI controller are continuous. */ - ctlp->io_num = 1; - ctlp->io_rid = malloc(sizeof(*(ctlp->io_rid)) * ctlp->io_num, M_DEVBUF, M_NOWAIT | M_ZERO); - ctlp->io = malloc(sizeof(*(ctlp->io)) * ctlp->io_num, M_DEVBUF, M_NOWAIT | M_ZERO); - if (ctlp->io_rid == NULL || ctlp->io == NULL) { - device_printf(dev, "rp_pciattach: Out of memory.\n"); - retval = ENOMEM; - goto nogo; - } - - ctlp->bus_ctlp = NULL; - - switch (pci_get_device(dev)) { - case RP_DEVICE_ID_UPCI_16: - case RP_DEVICE_ID_UPCI_32: - case RP_DEVICE_ID_UPCI_8O: - ctlp->io_rid[0] = PCIR_BAR(2); - break; - default: - ctlp->io_rid[0] = PCIR_BAR(0); - break; - } - ctlp->io[0] = bus_alloc_resource_any(dev, SYS_RES_IOPORT, - &ctlp->io_rid[0], RF_ACTIVE); - if(ctlp->io[0] == NULL) { - device_printf(dev, "ioaddr mapping failed for RocketPort(PCI).\n"); - retval = ENXIO; - goto nogo; - } - - num_aiops = sPCIInitController(ctlp, - MAX_AIOPS_PER_BOARD, 0, - FREQ_DIS, 0, pci_get_device(dev)); - - num_ports = 0; - for(aiop=0; aiop < num_aiops; aiop++) { - sResetAiopByNum(ctlp, aiop); - num_ports += sGetAiopNumChan(ctlp, aiop); - } - - retval = rp_attachcommon(ctlp, num_aiops, num_ports); - if (retval != 0) - goto nogo; - - return (0); - -nogo: - rp_pcireleaseresource(ctlp); - - return (retval); -} - -static int -rp_pcidetach(device_t dev) -{ - CONTROLLER_t *ctlp; - - ctlp = device_get_softc(dev); - rp_pcireleaseresource(ctlp); - - return (0); -} - -static int -rp_pcishutdown(device_t dev) -{ - CONTROLLER_t *ctlp; - - ctlp = device_get_softc(dev); - rp_pcireleaseresource(ctlp); - - return (0); -} - -static void -rp_pcireleaseresource(CONTROLLER_t *ctlp) -{ - rp_releaseresource(ctlp); - if (ctlp->io != NULL) { - if (ctlp->io[0] != NULL) - bus_release_resource(ctlp->dev, SYS_RES_IOPORT, ctlp->io_rid[0], ctlp->io[0]); - free(ctlp->io, M_DEVBUF); - ctlp->io = NULL; - } - if (ctlp->io_rid != NULL) { - free(ctlp->io_rid, M_DEVBUF); - ctlp->io = NULL; - } -} - -static int -sPCIInitController( CONTROLLER_t *CtlP, - int AiopNum, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly, - int VendorDevice) -{ - int i; - - CtlP->CtlID = CTLID_0001; /* controller release 1 */ - - sPCIControllerEOI(CtlP); - - /* Init AIOPs */ - CtlP->NumAiop = 0; - for(i=0; i < AiopNum; i++) - { - /*device_printf(CtlP->dev, "aiop %d.\n", i);*/ - CtlP->AiopID[i] = sReadAiopID(CtlP, i); /* read AIOP ID */ - /*device_printf(CtlP->dev, "ID = %d.\n", CtlP->AiopID[i]);*/ - if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ - { - break; /* done looking for AIOPs */ - } - - switch( VendorDevice ) { - case RP_DEVICE_ID_4Q: - case RP_DEVICE_ID_4J: - case RP_DEVICE_ID_4M: - CtlP->AiopNumChan[i] = 4; - break; - case RP_DEVICE_ID_6M: - CtlP->AiopNumChan[i] = 6; - break; - case RP_DEVICE_ID_8O: - case RP_DEVICE_ID_8J: - case RP_DEVICE_ID_8I: - case RP_DEVICE_ID_16I: - case RP_DEVICE_ID_32I: - CtlP->AiopNumChan[i] = 8; - break; - default: -#ifdef notdef - CtlP->AiopNumChan[i] = 8; -#else - CtlP->AiopNumChan[i] = sReadAiopNumChan(CtlP, i); -#endif /* notdef */ - break; - } - /*device_printf(CtlP->dev, "%d channels.\n", CtlP->AiopNumChan[i]);*/ - rp_writeaiop2(CtlP, i, _INDX_ADDR,_CLK_PRE); /* clock prescaler */ - /*device_printf(CtlP->dev, "configuring clock prescaler.\n");*/ - rp_writeaiop1(CtlP, i, _INDX_DATA,CLOCK_PRESC); - /*device_printf(CtlP->dev, "configured clock prescaler.\n");*/ - CtlP->NumAiop++; /* bump count of AIOPs */ - } - - if(CtlP->NumAiop == 0) - return(-1); - else - return(CtlP->NumAiop); -} - -/* - * ARGSUSED - * Maps (aiop, offset) to rid. - */ -static int -rp_pci_aiop2rid(int aiop, int offset) -{ - /* Always return zero for a PCI controller. */ - return 0; -} - -/* - * ARGSUSED - * Maps (aiop, offset) to the offset of resource. - */ -static int -rp_pci_aiop2off(int aiop, int offset) -{ - /* Each AIOP reserves 0x40 bytes. */ - return aiop * 0x40 + offset; -} - -/* Read the int status for a PCI controller. */ -static unsigned char -rp_pci_ctlmask(CONTROLLER_t *ctlp) -{ - return sPCIGetControllerIntStatus(ctlp); -} - -static device_method_t rp_pcimethods[] = { - /* Device interface */ - DEVMETHOD(device_probe, rp_pciprobe), - DEVMETHOD(device_attach, rp_pciattach), - DEVMETHOD(device_detach, rp_pcidetach), - DEVMETHOD(device_shutdown, rp_pcishutdown), - - { 0, 0 } -}; - -static driver_t rp_pcidriver = { - "rp", - rp_pcimethods, - sizeof(CONTROLLER_t), -}; - -/* - * rp can be attached to a pci bus. - */ -DRIVER_MODULE(rp, pci, rp_pcidriver, rp_devclass, 0, 0); diff --git a/sys/dev/rp/rpreg.h b/sys/dev/rp/rpreg.h deleted file mode 100644 index bd1de316028d..000000000000 --- a/sys/dev/rp/rpreg.h +++ /dev/null @@ -1,1033 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) Comtrol Corporation <support@comtrol.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 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 prodided 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 Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``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 COMTROL CORPORATION 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, LIFE 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$ - */ - -/* - * Begin OS-specific defines - rpreg.h - for RocketPort FreeBSD - */ - -typedef uint8_t Byte_t; -typedef uint8_t ByteIO_t; - -typedef uint16_t Word_t; -typedef uint16_t WordIO_t; - -typedef uint32_t DWord_t; -typedef uint32_t DWordIO_t; - -#define rp_readio(size, ctlp, rid, offset) \ - (bus_read_##size(ctlp->io[rid], offset)) -#define rp_readmultiio(size, ctlp, rid, offset, addr, count) \ - (bus_read_multi_##size(ctlp->io[rid], offset, addr, count)) -#define rp_writeio(size, ctlp, rid, offset, data) \ - (bus_write_##size(ctlp->io[rid], offset, data)) -#define rp_writemultiio(size, ctlp, rid, offset, addr, count) \ - (bus_write_multi_##size(ctlp->io[rid], offset, addr, count)) - -#define rp_readio1(ctlp, rid, offset) rp_readio(1, ctlp, rid, offset) -#define rp_readio2(ctlp, rid, offset) rp_readio(2, ctlp, rid, offset) -#define rp_readio4(ctlp, rid, offset) rp_readio(4, ctlp, rid, offset) -#define rp_writeio1(ctlp, rid, offset, data) rp_writeio(1, ctlp, rid, offset, data) -#define rp_writeio2(ctlp, rid, offset, data) rp_writeio(2, ctlp, rid, offset, data) -#define rp_writeio4(ctlp, rid, offset, data) rp_writeio(4, ctlp, rid, offset, data) -#define rp_readmultiio1(ctlp, rid, offset, addr, count) rp_readmultiio(1, ctlp, rid, offset, addr, count) -#define rp_readmultiio2(ctlp, rid, offset, addr, count) rp_readmultiio(2, ctlp, rid, offset, addr, count) -#define rp_readmultiio4(ctlp, rid, offset, addr, count) rp_readmultiio(4, ctlp, rid, offset, addr, count) -#define rp_writemultiio1(ctlp, rid, offset, addr, count) rp_writemultiio(1, ctlp, rid, offset, addr, count) -#define rp_writemultiio2(ctlp, rid, offset, addr, count) rp_writemultiio(2, ctlp, rid, offset, addr, count) -#define rp_writemultiio4(ctlp, rid, offset, addr, count) rp_writemultiio(4, ctlp, rid, offset, addr, count) - -#define rp_readaiop1(ctlp, aiop, offset) \ - (rp_readio1((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset))) -#define rp_readaiop2(ctlp, aiop, offset) \ - (rp_readio2((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset))) -#define rp_readaiop4(ctlp, aiop, offset) \ - (rp_readio4((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset))) -#define rp_readmultiaiop1(ctlp, aiop, offset, addr, count) \ - (rp_readmultiio1((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) -#define rp_readmultiaiop2(ctlp, aiop, offset, addr, count) \ - (rp_readmultiio2((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) -#define rp_readmultiaiop4(ctlp, aiop, offset, addr, count) \ - (rp_readmultiio4((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) -#define rp_writeaiop1(ctlp, aiop, offset, data) \ - (rp_writeio1((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), data)) -#define rp_writeaiop2(ctlp, aiop, offset, data) \ - (rp_writeio2((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), data)) -#define rp_writeaiop4(ctlp, aiop, offset, data) \ - (rp_writeio4((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), data)) -#define rp_writemultiaiop1(ctlp, aiop, offset, addr, count) \ - (rp_writemultiio1((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) -#define rp_writemultiaiop2(ctlp, aiop, offset, addr, count) \ - (rp_writemultiio2((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) -#define rp_writemultiaiop4(ctlp, aiop, offset, addr, count) \ - (rp_writemultiio4((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) - -#define rp_readch1(chp, offset) \ - (rp_readaiop1((chp)->CtlP, (chp)->AiopNum, offset)) -#define rp_readch2(chp, offset) \ - (rp_readaiop2((chp)->CtlP, (chp)->AiopNum, offset)) -#define rp_readch4(chp, offset) \ - (rp_readaiop4((chp)->CtlP, (chp)->AiopNum, offset)) -#define rp_readmultich1(chp, offset, addr, count) \ - (rp_readmultiaiop1((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) -#define rp_readmultich2(chp, offset, addr, count) \ - (rp_readmultiaiop2((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) -#define rp_readmultich4(chp, offset, addr, count) \ - (rp_readmultiaiop4((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) -#define rp_writech1(chp, offset, data) \ - (rp_writeaiop1((chp)->CtlP, (chp)->AiopNum, offset, data)) -#define rp_writech2(chp, offset, data) \ - (rp_writeaiop2((chp)->CtlP, (chp)->AiopNum, offset, data)) -#define rp_writech4(chp, offset, data) \ - (rp_writeaiop4((chp)->CtlP, (chp)->AiopNum, offset, data)) -#define rp_writemultich1(chp, offset, addr, count) \ - (rp_writemultiaiop1((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) -#define rp_writemultich2(chp, offset, addr, count) \ - (rp_writemultiaiop2((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) -#define rp_writemultich4(chp, offset, addr, count) \ - (rp_writemultiaiop4((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) - -/* - * End of OS-specific defines - */ - -#define ROCKET_H - -#define CTL_SIZE 4 -#define AIOP_CTL_SIZE 4 -#define CHAN_AIOP_SIZE 8 -#define MAX_PORTS_PER_AIOP 8 -#define MAX_AIOPS_PER_BOARD 4 -#define MAX_PORTS_PER_BOARD 32 - -/* Controller ID numbers */ -#define CTLID_NULL -1 /* no controller exists */ -#define CTLID_0001 0x0001 /* controller release 1 */ - -/* AIOP ID numbers, identifies AIOP type implementing channel */ -#define AIOPID_NULL -1 /* no AIOP or channel exists */ -#define AIOPID_0001 0x0001 /* AIOP release 1 */ - -#define NULLDEV -1 /* identifies non-existant device */ -#define NULLCTL -1 /* identifies non-existant controller */ -#define NULLCTLPTR (CONTROLLER_T *)0 /* identifies non-existant controller */ -#define NULLAIOP -1 /* identifies non-existant AIOP */ -#define NULLCHAN -1 /* identifies non-existant channel */ - -/************************************************************************ - Global Register Offsets - Direct Access - Fixed values -************************************************************************/ - -#define _CMD_REG 0x38 /* Command Register 8 Write */ -#define _INT_CHAN 0x39 /* Interrupt Channel Register 8 Read */ -#define _INT_MASK 0x3A /* Interrupt Mask Register 8 Read / Write */ -#define _UNUSED 0x3B /* Unused 8 */ -#define _INDX_ADDR 0x3C /* Index Register Address 16 Write */ -#define _INDX_DATA 0x3E /* Index Register Data 8/16 Read / Write */ - -/************************************************************************ - Channel Register Offsets for 1st channel in AIOP - Direct Access -************************************************************************/ -#define _TD0 0x00 /* Transmit Data 16 Write */ -#define _RD0 0x00 /* Receive Data 16 Read */ -#define _CHN_STAT0 0x20 /* Channel Status 8/16 Read / Write */ -#define _FIFO_CNT0 0x10 /* Transmit/Receive FIFO Count 16 Read */ -#define _INT_ID0 0x30 /* Interrupt Identification 8 Read */ - -/************************************************************************ - Tx Control Register Offsets - Indexed - External - Fixed -************************************************************************/ -#define _TX_ENBLS 0x980 /* Tx Processor Enables Register 8 Read / Write */ -#define _TXCMP1 0x988 /* Transmit Compare Value #1 8 Read / Write */ -#define _TXCMP2 0x989 /* Transmit Compare Value #2 8 Read / Write */ -#define _TXREP1B1 0x98A /* Tx Replace Value #1 - Byte 1 8 Read / Write */ -#define _TXREP1B2 0x98B /* Tx Replace Value #1 - Byte 2 8 Read / Write */ -#define _TXREP2 0x98C /* Transmit Replace Value #2 8 Read / Write */ - -/************************************************************************ - Receive FIFO -************************************************************************/ -#define RXFIFO_DATA 0x5f -#define RXFIFO_OUT 0x5c -#define RXFIFO_EN 0x08 -#define RXFIFO_DIS 0xa7 - -/************************************************************************ -Memory Controller Register Offsets - Indexed - External - Fixed -************************************************************************/ -#define _RX_FIFO 0x000 /* Rx FIFO */ -#define _TX_FIFO 0x800 /* Tx FIFO */ -#define _RXF_OUTP 0x990 /* Rx FIFO OUT pointer 16 Read / Write */ -#define _RXF_INP 0x992 /* Rx FIFO IN pointer 16 Read / Write */ -#define _TXF_OUTP 0x994 /* Tx FIFO OUT pointer 8 Read / Write */ -#define _TXF_INP 0x995 /* Tx FIFO IN pointer 8 Read / Write */ -#define _TXP_CNT 0x996 /* Tx Priority Count 8 Read / Write */ -#define _TXP_PNTR 0x997 /* Tx Priority Pointer 8 Read / Write */ - -#define PRI_PEND 0x80 /* Priority data pending (bit7, Tx pri cnt) */ -#define TXFIFO_SIZE 255 /* size of Tx FIFO */ -#define RXFIFO_SIZE 1023 /* size of Rx FIFO */ - -/************************************************************************ -Tx Priority Buffer - Indexed - External - Fixed -************************************************************************/ -#define _TXP_BUF 0x9C0 /* Tx Priority Buffer 32 Bytes Read / Write */ -#define TXP_SIZE 0x20 /* 32 bytes */ - -/************************************************************************ -Channel Register Offsets - Indexed - Internal - Fixed -************************************************************************/ - -#define _TX_CTRL 0xFF0 /* Transmit Control 16 Write */ -#define _RX_CTRL 0xFF2 /* Receive Control 8 Write */ -#define _BAUD 0xFF4 /* Baud Rate 16 Write */ -#define _CLK_PRE 0xFF6 /* Clock Prescaler 8 Write */ - -#define CLOCK_PRESC 0x19 /* mod 9 (divide by 10) prescale */ - -#define BRD50 4607 -#define BRD75 3071 -#define BRD110 2094 -#define BRD134 1712 -#define BRD150 1535 -#define BRD200 1151 -#define BRD300 767 -#define BRD600 383 -#define BRD1200 191 -#define BRD1800 127 -#define BRD2000 114 -#define BRD2400 95 -#define BRD3600 64 -#define BRD4800 47 -#define BRD7200 31 -#define BRD9600 23 -#define BRD14400 15 -#define BRD19200 11 -#define BRD38400 5 -#define BRD57600 3 -#define BRD76800 2 -#define BRD115200 1 -#define BRD230400 0 - -#define STMBREAK 0x08 /* BREAK */ -#define STMFRAME 0x04 /* framing error */ -#define STMRCVROVR 0x02 /* receiver over run error */ -#define STMPARITY 0x01 /* parity error */ -#define STMERROR (STMBREAK | STMFRAME | STMPARITY) -#define STMBREAKH 0x800 /* BREAK */ -#define STMFRAMEH 0x400 /* framing error */ -#define STMRCVROVRH 0x200 /* receiver over run error */ -#define STMPARITYH 0x100 /* parity error */ -#define STMERRORH (STMBREAKH | STMFRAMEH | STMPARITYH) - -#define CTS_ACT 0x20 /* CTS input asserted */ -#define DSR_ACT 0x10 /* DSR input asserted */ -#define CD_ACT 0x08 /* CD input asserted */ -#define TXFIFOMT 0x04 /* Tx FIFO is empty */ -#define TXSHRMT 0x02 /* Tx shift register is empty */ -#define RDA 0x01 /* Rx data available */ -#define DRAINED (TXFIFOMT | TXSHRMT) /* indicates Tx is drained */ - -#define STATMODE 0x8000 /* status mode enable bit */ -#define RXFOVERFL 0x2000 /* receive FIFO overflow */ -#define RX2MATCH 0x1000 /* receive compare byte 2 match */ -#define RX1MATCH 0x0800 /* receive compare byte 1 match */ -#define RXBREAK 0x0400 /* received BREAK */ -#define RXFRAME 0x0200 /* received framing error */ -#define RXPARITY 0x0100 /* received parity error */ -#define STATERROR (RXBREAK | RXFRAME | RXPARITY) - -#define CTSFC_EN 0x80 /* CTS flow control enable bit */ -#define RTSTOG_EN 0x40 /* RTS toggle enable bit */ -#define TXINT_EN 0x10 /* transmit interrupt enable */ -#define STOP2 0x08 /* enable 2 stop bits (0 = 1 stop) */ -#define PARITY_EN 0x04 /* enable parity (0 = no parity) */ -#define EVEN_PAR 0x02 /* even parity (0 = odd parity) */ -#define DATA8BIT 0x01 /* 8 bit data (0 = 7 bit data) */ - -#define SETBREAK 0x10 /* send break condition (must clear) */ -#define LOCALLOOP 0x08 /* local loopback set for test */ -#define SET_DTR 0x04 /* assert DTR */ -#define SET_RTS 0x02 /* assert RTS */ -#define TX_ENABLE 0x01 /* enable transmitter */ - -#define RTSFC_EN 0x40 /* RTS flow control enable */ -#define RXPROC_EN 0x20 /* receive processor enable */ -#define TRIG_NO 0x00 /* Rx FIFO trigger level 0 (no trigger) */ -#define TRIG_1 0x08 /* trigger level 1 char */ -#define TRIG_1_2 0x10 /* trigger level 1/2 */ -#define TRIG_7_8 0x18 /* trigger level 7/8 */ -#define TRIG_MASK 0x18 /* trigger level mask */ -#define SRCINT_EN 0x04 /* special Rx condition interrupt enable */ -#define RXINT_EN 0x02 /* Rx interrupt enable */ -#define MCINT_EN 0x01 /* modem change interrupt enable */ - -#define RXF_TRIG 0x20 /* Rx FIFO trigger level interrupt */ -#define TXFIFO_MT 0x10 /* Tx FIFO empty interrupt */ -#define SRC_INT 0x08 /* special receive condition interrupt */ -#define DELTA_CD 0x04 /* CD change interrupt */ -#define DELTA_CTS 0x02 /* CTS change interrupt */ -#define DELTA_DSR 0x01 /* DSR change interrupt */ - -#define REP1W2_EN 0x10 /* replace byte 1 with 2 bytes enable */ -#define IGN2_EN 0x08 /* ignore byte 2 enable */ -#define IGN1_EN 0x04 /* ignore byte 1 enable */ -#define COMP2_EN 0x02 /* compare byte 2 enable */ -#define COMP1_EN 0x01 /* compare byte 1 enable */ - -#define RESET_ALL 0x80 /* reset AIOP (all channels) */ -#define TXOVERIDE 0x40 /* Transmit software off override */ -#define RESETUART 0x20 /* reset channel's UART */ -#define RESTXFCNT 0x10 /* reset channel's Tx FIFO count register */ -#define RESRXFCNT 0x08 /* reset channel's Rx FIFO count register */ - -#define INTSTAT0 0x01 /* AIOP 0 interrupt status */ -#define INTSTAT1 0x02 /* AIOP 1 interrupt status */ -#define INTSTAT2 0x04 /* AIOP 2 interrupt status */ -#define INTSTAT3 0x08 /* AIOP 3 interrupt status */ - -#define INTR_EN 0x08 /* allow interrupts to host */ -#define INT_STROB 0x04 /* strobe and clear interrupt line (EOI) */ - -#define CHAN3_EN 0x08 /* enable AIOP 3 */ -#define CHAN2_EN 0x04 /* enable AIOP 2 */ -#define CHAN1_EN 0x02 /* enable AIOP 1 */ -#define CHAN0_EN 0x01 /* enable AIOP 0 */ -#define FREQ_DIS 0x00 -#define FREQ_274HZ 0x60 -#define FREQ_137HZ 0x50 -#define FREQ_69HZ 0x40 -#define FREQ_34HZ 0x30 -#define FREQ_17HZ 0x20 -#define FREQ_9HZ 0x10 -#define PERIODIC_ONLY 0x80 /* only PERIODIC interrupt */ - -#define CHANINT_EN 0x0100 /* flags to enable/disable channel ints */ - -#define RDATASIZE 72 -#define RREGDATASIZE 52 - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -struct CONTROLLER_str; -struct CHANNEL_str; - -/* The types of bus-specific methods */ -typedef int rp_aiop2rid_t(int, int); -typedef int rp_aiop2off_t(int, int); -typedef unsigned char rp_ctlmask_t(struct CONTROLLER_str *); - -/* Controller level information structure */ -struct CONTROLLER_str -{ - int CtlID; - int NumAiop; - int AiopID[AIOP_CTL_SIZE]; - int AiopNumChan[AIOP_CTL_SIZE]; - - struct mtx hwmtx; /* Spinlock protecting hardware. */ - int hwmtx_init; - int free; - int num_ports; - - /* Device and resource management */ - device_t dev; /* device */ - int io_num; /* Number of IO resources */ - int *io_rid; /* IO resource IDs */ - struct resource **io; /* IO resources */ - - struct rp_port *rp; /* port */ - - /* Device nodes */ - struct cdev **dev_nodes; - - /* Bus-specific properties */ - void *bus_ctlp; - - /* Bus-specific methods */ - rp_aiop2rid_t *aiop2rid; /* (aiop, offset) -> rid */ - rp_aiop2off_t *aiop2off; /* (aiop, offset) -> off */ - rp_ctlmask_t *ctlmask; /* Int status */ -}; -typedef struct CONTROLLER_str CONTROLLER_T; -typedef CONTROLLER_T CONTROLLER_t; - -/* Channel level information structure */ -struct CHANNEL_str -{ - CONTROLLER_t *CtlP; - int AiopNum; - int ChanID; - int ChanNum; - - Word_t TxFIFO; - Word_t TxFIFOPtrs; - Word_t RxFIFO; - Word_t RxFIFOPtrs; - Word_t TxPrioCnt; - Word_t TxPrioPtr; - Word_t TxPrioBuf; - - Byte_t R[RREGDATASIZE]; - - Byte_t BaudDiv[4]; - Byte_t TxControl[4]; - Byte_t RxControl[4]; - Byte_t TxEnables[4]; - Byte_t TxCompare[4]; - Byte_t TxReplace1[4]; - Byte_t TxReplace2[4]; -}; - -typedef struct CHANNEL_str CHANNEL_T; -typedef CHANNEL_T CHANNEL_t; -typedef CHANNEL_T * CHANPTR_T; - -#define CHNOFF_TXRXDATA(chp) ((chp)->ChanNum * 2 + _TD0) -#define CHNOFF_CHANSTAT(chp) ((chp)->ChanNum * 2 + _CHN_STAT0) -#define CHNOFF_TXRXCOUNT(chp) ((chp)->ChanNum * 2 + _FIFO_CNT0) -#define CHNOFF_INTID(chp) ((chp)->ChanNum + _INT_ID0) - -/*************************************************************************** -Function: sClrBreak -Purpose: Stop sending a transmit BREAK signal -Call: sClrBreak(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrBreak(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~SETBREAK; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sClrDTR -Purpose: Clr the DTR output -Call: sClrDTR(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrDTR(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~SET_DTR; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sClrRTS -Purpose: Clr the RTS output -Call: sClrRTS(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrRTS(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~SET_RTS; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sClrTxXOFF -Purpose: Clear any existing transmit software flow control off condition -Call: sClrTxXOFF(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrTxXOFF(ChP) \ -{ \ - rp_writech1(ChP,_CMD_REG,TXOVERIDE | (Byte_t)(ChP)->ChanNum); \ - rp_writech1(ChP,_CMD_REG,(Byte_t)(ChP)->ChanNum); \ -} - -/*************************************************************************** -Function: sDisCTSFlowCtl -Purpose: Disable output flow control using CTS -Call: sDisCTSFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisCTSFlowCtl(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~CTSFC_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: DisParity -Purpose: Disable parity -Call: sDisParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). -*/ -#define sDisParity(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~PARITY_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sDisRxFIFO -Purpose: Disable Rx FIFO -Call: sDisRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisRxFIFO(ChP) \ -{ \ - (ChP)->R[0x32] = 0x0a; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->R + 0x30)); \ -} - -/*************************************************************************** -Function: sDisRxStatusMode -Purpose: Disable the Rx status mode -Call: sDisRxStatusMode(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This takes the channel out of the receive status mode. All - subsequent reads of receive data using sReadRxWord() will return - two data bytes. -*/ -#define sDisRxStatusMode(ChP) rp_writech2(ChP,CHNOFF_CHANSTAT(ChP),0) - -/*************************************************************************** -Function: sDisTransmit -Purpose: Disable transmit -Call: sDisTransmit(ChP) - CHANNEL_T *ChP; Ptr to channel structure - This disables movement of Tx data from the Tx FIFO into the 1 byte - Tx buffer. Therefore there could be up to a 2 byte latency - between the time sDisTransmit() is called and the transmit buffer - and transmit shift register going completely empty. -*/ -#define sDisTransmit(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~TX_ENABLE; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sDisTxSoftFlowCtl -Purpose: Disable Tx Software Flow Control -Call: sDisTxSoftFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisTxSoftFlowCtl(ChP) \ -{ \ - (ChP)->R[0x06] = 0x8a; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->R + 0x04)); \ -} - -/*************************************************************************** -Function: sEnCTSFlowCtl -Purpose: Enable output flow control using CTS -Call: sEnCTSFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnCTSFlowCtl(ChP) \ -{ \ - (ChP)->TxControl[2] |= CTSFC_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: EnParity -Purpose: Enable parity -Call: sEnParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: Before enabling parity odd or even parity should be chosen using - functions sSetOddParity() or sSetEvenParity(). -*/ -#define sEnParity(ChP) \ -{ \ - (ChP)->TxControl[2] |= PARITY_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sEnRTSFlowCtl -Return: void -*/ -#define sEnRTSFlowCtl(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~RTSTOG_EN; \ - (ChP)->TxControl[3] &= ~SET_RTS; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ - (ChP)->RxControl[2] |= RTSFC_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->RxControl)); \ -} - -/*************************************************************************** -Function: sDisRTSFlowCtl -Return: void -*/ -#define sDisRTSFlowCtl(ChP) \ -{ \ - (ChP)->RxControl[2] &= ~RTSFC_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->RxControl)); \ -} - -/*************************************************************************** -Function: sEnRxFIFO -Purpose: Enable Rx FIFO -Call: sEnRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnRxFIFO(ChP) \ -{ \ - (ChP)->R[0x32] = 0x08; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->R + 0x30)); \ -} - -/*************************************************************************** -Function: sEnRxProcessor -Purpose: Enable the receive processor -Call: sEnRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This function is used to start the receive processor. When - the channel is in the reset state the receive processor is not - running. This is done to prevent the receive processor from - executing invalid microcode instructions prior to the - downloading of the microcode. - -Warnings: This function must be called after valid microcode has been - downloaded to the AIOP, and it must not be called before the - microcode has been downloaded. -*/ -#define sEnRxProcessor(ChP) \ -{ \ - (ChP)->RxControl[2] |= RXPROC_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->RxControl)); \ -} - -/*************************************************************************** -Function: sEnRxStatusMode -Purpose: Enable the Rx status mode -Call: sEnRxStatusMode(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This places the channel in the receive status mode. All subsequent - reads of receive data using sReadRxWord() will return a data byte - in the low word and a status byte in the high word. - -*/ -#define sEnRxStatusMode(ChP) rp_writech2(ChP,CHNOFF_CHANSTAT(ChP),STATMODE) - -/*************************************************************************** -Function: sEnTransmit -Purpose: Enable transmit -Call: sEnTransmit(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnTransmit(ChP) \ -{ \ - (ChP)->TxControl[3] |= TX_ENABLE; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sGetAiopIntStatus -Purpose: Get the AIOP interrupt status -Call: sGetAiopIntStatus(CtlP,AiopNum) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; AIOP number -Return: Byte_t: The AIOP interrupt status. Bits 0 through 7 - represent channels 0 through 7 respectively. If a - bit is set that channel is interrupting. -*/ -#define sGetAiopIntStatus(CtlP,AIOPNUM) rp_readaiop1(CtlP,AIOPNUM,_INT_CHAN) - -/*************************************************************************** -Function: sGetAiopNumChan -Purpose: Get the number of channels supported by an AIOP -Call: sGetAiopNumChan(CtlP,AiopNum) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; AIOP number -Return: int: The number of channels supported by the AIOP -*/ -#define sGetAiopNumChan(CtlP,AIOPNUM) CtlP->AiopNumChan[AIOPNUM] - -/*************************************************************************** -Function: sGetChanIntID -Purpose: Get a channel's interrupt identification byte -Call: sGetChanIntID(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The channel interrupt ID. Can be any - combination of the following flags: - RXF_TRIG: Rx FIFO trigger level interrupt - TXFIFO_MT: Tx FIFO empty interrupt - SRC_INT: Special receive condition interrupt - DELTA_CD: CD change interrupt - DELTA_CTS: CTS change interrupt - DELTA_DSR: DSR change interrupt -*/ -#define sGetChanIntID(ChP) (rp_readch1(ChP,(ChP)->ChanNum+_INT_ID0) & (RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR)) - -/*************************************************************************** -Function: sGetChanNum -Purpose: Get the number of a channel within an AIOP -Call: sGetChanNum(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: int: Channel number within AIOP, or NULLCHAN if channel does - not exist. -*/ -#define sGetChanNum(ChP) (ChP)->ChanNum - -/*************************************************************************** -Function: sGetChanStatus -Purpose: Get the channel status -Call: sGetChanStatus(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Word_t: The channel status. Can be any combination of - the following flags: - LOW BYTE FLAGS - CTS_ACT: CTS input asserted - DSR_ACT: DSR input asserted - CD_ACT: CD input asserted - TXFIFOMT: Tx FIFO is empty - TXSHRMT: Tx shift register is empty - RDA: Rx data available - - HIGH BYTE FLAGS - STATMODE: status mode enable bit - RXFOVERFL: receive FIFO overflow - RX2MATCH: receive compare byte 2 match - RX1MATCH: receive compare byte 1 match - RXBREAK: received BREAK - RXFRAME: received framing error - RXPARITY: received parity error -Warnings: This function will clear the high byte flags in the Channel - Status Register. -*/ -#define sGetChanStatus(ChP) rp_readch2(ChP,CHNOFF_CHANSTAT(ChP)) - -/*************************************************************************** -Function: sGetChanStatusLo -Purpose: Get the low byte only of the channel status -Call: sGetChanStatusLo(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The channel status low byte. Can be any combination - of the following flags: - CTS_ACT: CTS input asserted - DSR_ACT: DSR input asserted - CD_ACT: CD input asserted - TXFIFOMT: Tx FIFO is empty - TXSHRMT: Tx shift register is empty - RDA: Rx data available -*/ -#define sGetChanStatusLo(ChP) rp_readch1(ChP,CHNOFF_CHANSTAT(ChP)) - -/*************************************************************************** -Function: sGetRxCnt -Purpose: Get the number of data bytes in the Rx FIFO -Call: sGetRxCnt(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: int: The number of data bytes in the Rx FIFO. -Comments: Byte read of count register is required to obtain Rx count. - -*/ -#define sGetRxCnt(ChP) rp_readch2(ChP,CHNOFF_TXRXCOUNT(ChP)) - -/*************************************************************************** -Function: sGetTxCnt -Purpose: Get the number of data bytes in the Tx FIFO -Call: sGetTxCnt(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The number of data bytes in the Tx FIFO. -Comments: Byte read of count register is required to obtain Tx count. - -*/ -#define sGetTxCnt(ChP) rp_readch1(ChP,CHNOFF_TXRXCOUNT(ChP)) - -/***************************************************************************** -Function: sGetTxRxDataIO -Purpose: Get the offset of a channel's TxRx Data register -Call: sGetTxRxDataIO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: WordIO_t: offset of a channel's TxRx Data register -*/ -#define sGetTxRxDataIO(ChP) CHNOFF_TXRXDATA(ChP) - -/*************************************************************************** -Function: sInitChanDefaults -Purpose: Initialize a channel structure to its default state. -Call: sInitChanDefaults(ChP) - CHANNEL_T *ChP; Ptr to the channel structure -Comments: This function must be called once for every channel structure - that exists before any other SSCI calls can be made. - -*/ -#define sInitChanDefaults(ChP) \ -{ \ - (ChP)->CtlP = NULLCTLPTR; \ - (ChP)->AiopNum = NULLAIOP; \ - (ChP)->ChanID = AIOPID_NULL; \ - (ChP)->ChanNum = NULLCHAN; \ -} - -/*************************************************************************** -Function: sResetAiopByNum -Purpose: Reset the AIOP by number -Call: sResetAiopByNum(CTLP,AIOPNUM) - CONTROLLER_T CTLP; Ptr to controller structure - AIOPNUM; AIOP index -*/ -#define sResetAiopByNum(CTLP,AIOPNUM) \ -{ \ - rp_writeaiop1(CTLP,AIOPNUM,_CMD_REG,RESET_ALL); \ - rp_writeaiop1(CTLP,AIOPNUM,_CMD_REG,0x0); \ -} - -/*************************************************************************** -Function: sSendBreak -Purpose: Send a transmit BREAK signal -Call: sSendBreak(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSendBreak(ChP) \ -{ \ - (ChP)->TxControl[3] |= SETBREAK; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetBaud -Purpose: Set baud rate -Call: sSetBaud(ChP,Divisor) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Divisor; 16 bit baud rate divisor for channel -*/ -#define sSetBaud(ChP,DIVISOR) \ -{ \ - (ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \ - (ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->BaudDiv)); \ -} - -/*************************************************************************** -Function: sSetData7 -Purpose: Set data bits to 7 -Call: sSetData7(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetData7(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~DATA8BIT; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetData8 -Purpose: Set data bits to 8 -Call: sSetData8(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetData8(ChP) \ -{ \ - (ChP)->TxControl[2] |= DATA8BIT; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetDTR -Purpose: Set the DTR output -Call: sSetDTR(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetDTR(ChP) \ -{ \ - (ChP)->TxControl[3] |= SET_DTR; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetEvenParity -Purpose: Set even parity -Call: sSetEvenParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: This function has no effect unless parity is enabled with function - sEnParity(). -*/ -#define sSetEvenParity(ChP) \ -{ \ - (ChP)->TxControl[2] |= EVEN_PAR; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetOddParity -Purpose: Set odd parity -Call: sSetOddParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: This function has no effect unless parity is enabled with function - sEnParity(). -*/ -#define sSetOddParity(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~EVEN_PAR; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetRTS -Purpose: Set the RTS output -Call: sSetRTS(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetRTS(ChP) \ -{ \ - (ChP)->TxControl[3] |= SET_RTS; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetRxTrigger -Purpose: Set the Rx FIFO trigger level -Call: sSetRxProcessor(ChP,Level) - CHANNEL_T *ChP; Ptr to channel structure - Byte_t Level; Number of characters in Rx FIFO at which the - interrupt will be generated. Can be any of the following flags: - - TRIG_NO: no trigger - TRIG_1: 1 character in FIFO - TRIG_1_2: FIFO 1/2 full - TRIG_7_8: FIFO 7/8 full -Comments: An interrupt will be generated when the trigger level is reached - only if function sEnInterrupt() has been called with flag - RXINT_EN set. The RXF_TRIG flag in the Interrupt Idenfification - register will be set whenever the trigger level is reached - regardless of the setting of RXINT_EN. - -*/ -#define sSetRxTrigger(ChP,LEVEL) \ -{ \ - (ChP)->RxControl[2] &= ~TRIG_MASK; \ - (ChP)->RxControl[2] |= LEVEL; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->RxControl)); \ -} - -/*************************************************************************** -Function: sSetStop1 -Purpose: Set stop bits to 1 -Call: sSetStop1(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetStop1(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~STOP2; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetStop2 -Purpose: Set stop bits to 2 -Call: sSetStop2(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetStop2(ChP) \ -{ \ - (ChP)->TxControl[2] |= STOP2; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sStartRxProcessor -Purpose: Start a channel's receive processor -Call: sStartRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This function is used to start a Rx processor after it was - stopped with sStopRxProcessor() or sStopSWInFlowCtl(). It - will restart both the Rx processor and software input flow control. - -*/ -#define sStartRxProcessor(ChP) rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->R)) - -/*************************************************************************** -Function: sWriteTxByte -Purpose: Write a transmit data byte to a channel. - CHANNEL_T *ChP; Ptr to channel structure - ByteIO_t io: Channel transmit register I/O address. This can - be obtained with sGetTxRxDataIO(). - Byte_t Data; The transmit data byte. -Warnings: This function writes the data byte without checking to see if - sMaxTxSize is exceeded in the Tx FIFO. -*/ -#define sWriteTxByte(ChP,IO,DATA) rp_writech1(ChP,IO,DATA) - -int sReadAiopID(CONTROLLER_T *CtlP, int aiop); -int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop); -int sInitChan( CONTROLLER_T *CtlP, - CHANNEL_T *ChP, - int AiopNum, - int ChanNum); -Byte_t sGetRxErrStatus(CHANNEL_T *ChP); -void sStopRxProcessor(CHANNEL_T *ChP); -void sStopSWInFlowCtl(CHANNEL_T *ChP); -void sFlushRxFIFO(CHANNEL_T *ChP); -void sFlushTxFIFO(CHANNEL_T *ChP); -int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data); -void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags); -void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags); -int rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports); -void rp_releaseresource(CONTROLLER_t *ctlp); -static __inline void -rp_lock(CONTROLLER_T *CtlP) -{ - if (CtlP->hwmtx_init != 0) - mtx_lock(&CtlP->hwmtx); -} -static __inline void -rp_unlock(CONTROLLER_T *CtlP) -{ - if (CtlP->hwmtx_init != 0) - mtx_unlock(&CtlP->hwmtx); -} - -#ifndef ROCKET_C -extern Byte_t R[RDATASIZE]; -extern CONTROLLER_T sController[CTL_SIZE]; -extern Byte_t sIRQMap[16]; -#endif -extern Byte_t rp_sBitMapClrTbl[8]; -extern Byte_t rp_sBitMapSetTbl[8]; diff --git a/sys/dev/rp/rpvar.h b/sys/dev/rp/rpvar.h deleted file mode 100644 index a93f48971469..000000000000 --- a/sys/dev/rp/rpvar.h +++ /dev/null @@ -1,76 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) Comtrol Corporation <support@comtrol.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 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 prodided 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 Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``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 COMTROL CORPORATION 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, LIFE 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$ - */ - -/* - * rpvar.h --- RocketPort data structure includes for FreeBSD - */ - -#define RP_UNIT(x) dv_unit(x) -#define RP_PORT(x) (dev2unit(x) & 0x3f) -#define MAX_RP_PORTS 128 - - -struct rp_port { - struct tty * rp_tty; /* cross reference */ - struct callout rp_timer; - - unsigned char state; /* state of dtr */ - - int rp_port; - int rp_flags; - int rp_unit:2; - int rp_aiop:2; - int rp_chan:3; - int rp_intmask; - int rp_imask; /* Input mask */ - int rp_fifo_lw; - int rp_restart; - int rp_overflows; - int rp_rts_iflow:1; - int rp_disable_writes:1; - int rp_cts:1; - int rp_waiting:1; - int rp_xmit_stopped:1; - CONTROLLER_t * rp_ctlp; - CHANNEL_t rp_channel; - unsigned char TxBuf[TXFIFO_SIZE]; - unsigned char RxBuf[RXFIFO_SIZE]; -}; - -/* Actually not used */ -#ifdef notdef -extern struct termios deftermios; -#endif /* notdef */ diff --git a/sys/dev/smc/if_smc.c b/sys/dev/smc/if_smc.c index d3f911d8327c..627787eab641 100644 --- a/sys/dev/smc/if_smc.c +++ b/sys/dev/smc/if_smc.c @@ -80,6 +80,8 @@ __FBSDID("$FreeBSD$"); #include <dev/mii/mii_bitbang.h> #include <dev/mii/miivar.h> +#include "miibus_if.h" + #define SMC_LOCK(sc) mtx_lock(&(sc)->smc_mtx) #define SMC_UNLOCK(sc) mtx_unlock(&(sc)->smc_mtx) #define SMC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->smc_mtx, MA_OWNED) @@ -480,6 +482,27 @@ smc_detach(device_t dev) return (0); } +static device_method_t smc_methods[] = { + /* Device interface */ + DEVMETHOD(device_attach, smc_attach), + DEVMETHOD(device_detach, smc_detach), + + /* MII interface */ + DEVMETHOD(miibus_readreg, smc_miibus_readreg), + DEVMETHOD(miibus_writereg, smc_miibus_writereg), + DEVMETHOD(miibus_statchg, smc_miibus_statchg), + + { 0, 0 } +}; + +driver_t smc_driver = { + "smc", + smc_methods, + sizeof(struct smc_softc), +}; + +DRIVER_MODULE(miibus, smc, miibus_driver, miibus_devclass, 0, 0); + static void smc_start(struct ifnet *ifp) { diff --git a/sys/dev/smc/if_smc_acpi.c b/sys/dev/smc/if_smc_acpi.c new file mode 100644 index 000000000000..74f591493167 --- /dev/null +++ b/sys/dev/smc/if_smc_acpi.c @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 2008 Benno Rice + * All rights reserved. + * Copyright (c) 2020 Andrew Turner + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/socket.h> +#include <sys/systm.h> +#include <sys/taskqueue.h> + +#include <net/if.h> + +#include <dev/smc/if_smcvar.h> + +#include <contrib/dev/acpica/include/acpi.h> +#include <dev/acpica/acpivar.h> + +static int smc_acpi_probe(device_t); + +static int +smc_acpi_probe(device_t dev) +{ + struct smc_softc *sc; + ACPI_HANDLE h; + + if ((h = acpi_get_handle(dev)) == NULL) + return (ENXIO); + + if (!acpi_MatchHid(h, "LNRO0003")) + return (ENXIO); + + sc = device_get_softc(dev); + sc->smc_usemem = 1; + + return (smc_probe(dev)); +} + +static device_method_t smc_acpi_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, smc_acpi_probe), + { 0, 0 } +}; + +DEFINE_CLASS_1(smc, smc_acpi_driver, smc_acpi_methods, + sizeof(struct smc_softc), smc_driver); + +extern devclass_t smc_devclass; + +DRIVER_MODULE(smc, acpi, smc_acpi_driver, smc_devclass, 0, 0); +MODULE_DEPEND(smc, acpi, 1, 1, 1); +MODULE_DEPEND(smc, ether, 1, 1, 1); +MODULE_DEPEND(smc, miibus, 1, 1, 1); diff --git a/sys/dev/smc/if_smc_fdt.c b/sys/dev/smc/if_smc_fdt.c index baca0bd6113e..2c63b9f94d49 100644 --- a/sys/dev/smc/if_smc_fdt.c +++ b/sys/dev/smc/if_smc_fdt.c @@ -35,29 +35,16 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/taskqueue.h> -#include <machine/bus.h> -#include <machine/resource.h> - -#include <net/ethernet.h> #include <net/if.h> -#include <net/if_arp.h> -#include <net/if_media.h> #include <dev/smc/if_smcvar.h> -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> - #include <dev/fdt/fdt_common.h> #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> -#include "miibus_if.h" - static int smc_fdt_probe(device_t); -static int smc_fdt_attach(device_t); -static int smc_fdt_detach(device_t); static int smc_fdt_probe(device_t dev) @@ -81,46 +68,18 @@ smc_fdt_probe(device_t dev) return (ENXIO); } -static int -smc_fdt_attach(device_t dev) -{ - - return smc_attach(dev); -} - -static int -smc_fdt_detach(device_t dev) -{ - - smc_detach(dev); - - return (0); -} - static device_method_t smc_fdt_methods[] = { /* Device interface */ DEVMETHOD(device_probe, smc_fdt_probe), - DEVMETHOD(device_attach, smc_fdt_attach), - DEVMETHOD(device_detach, smc_fdt_detach), - - /* MII interface */ - DEVMETHOD(miibus_readreg, smc_miibus_readreg), - DEVMETHOD(miibus_writereg, smc_miibus_writereg), - DEVMETHOD(miibus_statchg, smc_miibus_statchg), - { 0, 0 } }; -static driver_t smc_fdt_driver = { - "smc", - smc_fdt_methods, - sizeof(struct smc_softc), -}; +DEFINE_CLASS_1(smc, smc_fdt_driver, smc_fdt_methods, + sizeof(struct smc_softc), smc_driver); extern devclass_t smc_devclass; DRIVER_MODULE(smc, simplebus, smc_fdt_driver, smc_devclass, 0, 0); -DRIVER_MODULE(miibus, smc, miibus_driver, miibus_devclass, 0, 0); MODULE_DEPEND(smc, fdt, 1, 1, 1); MODULE_DEPEND(smc, ether, 1, 1, 1); MODULE_DEPEND(smc, miibus, 1, 1, 1); diff --git a/sys/dev/smc/if_smcvar.h b/sys/dev/smc/if_smcvar.h index a58eb0df0374..8de30706a0a5 100644 --- a/sys/dev/smc/if_smcvar.h +++ b/sys/dev/smc/if_smcvar.h @@ -68,6 +68,8 @@ struct smc_softc { void *smc_read_arg; }; +DECLARE_CLASS(smc_driver); + int smc_probe(device_t); int smc_attach(device_t); int smc_detach(device_t); diff --git a/sys/dev/uart/uart_dev_ti8250.c b/sys/dev/uart/uart_dev_ti8250.c index f5a230908da3..ebe777ed7fdb 100644 --- a/sys/dev/uart/uart_dev_ti8250.c +++ b/sys/dev/uart/uart_dev_ti8250.c @@ -39,9 +39,6 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <machine/bus.h> -#include <arm/ti/ti_prcm.h> -#include <arm/ti/ti_hwmods.h> - #include <dev/fdt/fdt_common.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> @@ -52,6 +49,8 @@ __FBSDID("$FreeBSD$"); #include <dev/uart/uart_bus.h> #include <dev/uart/uart_dev_ns8250.h> +#include <arm/ti/ti_sysc.h> + #include "uart_if.h" /* @@ -74,16 +73,8 @@ static int ti8250_bus_probe(struct uart_softc *sc) { int status; - clk_ident_t clkid; - - /* Enable clocks for this device. We can't continue if that fails. */ - clkid = ti_hwmods_get_clock(sc->sc_dev); - if (clkid == INVALID_CLK_IDENT) { - device_printf(sc->sc_dev, - "failed to get clock based on hwmods\n"); - clkid = UART1_CLK + device_get_unit(sc->sc_dev); - } - if ((status = ti_prcm_clk_enable(clkid)) != 0) + + if ((status = ti_sysc_clock_enable(device_get_parent(sc->sc_dev))) != 0) return (status); /* diff --git a/sys/dev/virtio/pci/virtio_pci.c b/sys/dev/virtio/pci/virtio_pci.c index aba35eb38ff5..05a632f526a8 100644 --- a/sys/dev/virtio/pci/virtio_pci.c +++ b/sys/dev/virtio/pci/virtio_pci.c @@ -179,22 +179,24 @@ static void vtpci_config_intr(void *); * I/O port read/write wrappers. */ #define vtpci_read_config_1(sc, o) bus_read_1((sc)->vtpci_res, (o)) -#define vtpci_read_config_2(sc, o) bus_read_2((sc)->vtpci_res, (o)) -#define vtpci_read_config_4(sc, o) bus_read_4((sc)->vtpci_res, (o)) #define vtpci_write_config_1(sc, o, v) bus_write_1((sc)->vtpci_res, (o), (v)) -#define vtpci_write_config_2(sc, o, v) bus_write_2((sc)->vtpci_res, (o), (v)) -#define vtpci_write_config_4(sc, o, v) bus_write_4((sc)->vtpci_res, (o), (v)) /* - * Legacy VirtIO header is always PCI endianness (little), so if we - * are in a BE machine we need to swap bytes from LE to BE when reading - * and from BE to LE when writing. - * If we are in a LE machine, there will be no swaps. + * Virtio-pci specifies that PCI Configuration area is guest endian. However, + * since PCI devices are inherently little-endian, on BE systems the bus layer + * transparently converts it to BE. For virtio-legacy, this conversion is + * undesired, so an extra byte swap is required to fix it. */ -#define vtpci_read_header_2(sc, o) le16toh(vtpci_read_config_2(sc, o)) -#define vtpci_read_header_4(sc, o) le32toh(vtpci_read_config_4(sc, o)) -#define vtpci_write_header_2(sc, o, v) vtpci_write_config_2(sc, o, (htole16(v))) -#define vtpci_write_header_4(sc, o, v) vtpci_write_config_4(sc, o, (htole32(v))) +#define vtpci_read_config_2(sc, o) le16toh(bus_read_2((sc)->vtpci_res, (o))) +#define vtpci_read_config_4(sc, o) le32toh(bus_read_4((sc)->vtpci_res, (o))) +#define vtpci_write_config_2(sc, o, v) bus_write_2((sc)->vtpci_res, (o), (htole16(v))) +#define vtpci_write_config_4(sc, o, v) bus_write_4((sc)->vtpci_res, (o), (htole32(v))) + +/* PCI Header LE. On BE systems the bus layer takes care of byte swapping */ +#define vtpci_read_header_2(sc, o) (bus_read_2((sc)->vtpci_res, (o))) +#define vtpci_read_header_4(sc, o) (bus_read_4((sc)->vtpci_res, (o))) +#define vtpci_write_header_2(sc, o, v) bus_write_2((sc)->vtpci_res, (o), (v)) +#define vtpci_write_header_4(sc, o, v) bus_write_4((sc)->vtpci_res, (o), (v)) /* Tunables. */ static int vtpci_disable_msix = 0; @@ -290,17 +292,6 @@ vtpci_attach(device_t dev) return (ENXIO); } -/* - * For legacy VirtIO, the device-specific configuration is guest - * endian, while the common configuration header is always - * PCI (little) endian and will be handled specifically in - * other parts of this file via functions - * 'vtpci_[read|write]_header_[2|4]' - */ -#if _BYTE_ORDER == _BIG_ENDIAN - rman_set_bustag(sc->vtpci_res, &bs_be_tag); -#endif - if (pci_find_cap(dev, PCIY_MSI, NULL) != 0) sc->vtpci_flags |= VTPCI_FLAG_NO_MSI; diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index 51baee32616e..d9e03cf7b791 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -504,6 +504,7 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap, u_int32_t *tl; struct nfsv2_sattr *sp; nfsattrbit_t attrbits; + struct nfsnode *np; switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) { case ND_NFSV2: @@ -605,8 +606,18 @@ nfscl_fillsattr(struct nfsrv_descript *nd, struct vattr *vap, NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESSSET); if (vap->va_mtime.tv_sec != VNOVAL) NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFYSET); - if (vap->va_birthtime.tv_sec != VNOVAL) - NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMECREATE); + if (vap->va_birthtime.tv_sec != VNOVAL && + strcmp(vp->v_mount->mnt_vfc->vfc_name, "nfs") == 0) { + /* + * We can only test for support of TimeCreate if + * the "vp" argument is for an NFS vnode. + */ + np = VTONFS(vp); + if (NFSISSET_ATTRBIT(&np->n_vattr.na_suppattr, + NFSATTRBIT_TIMECREATE)) + NFSSETBIT_ATTRBIT(&attrbits, + NFSATTRBIT_TIMECREATE); + } (void) nfsv4_fillattr(nd, vp->v_mount, vp, NULL, vap, NULL, 0, &attrbits, NULL, NULL, 0, 0, 0, 0, (uint64_t)0, NULL); break; diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index fbe77fcaf9b6..eb971d73d534 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -144,6 +144,8 @@ static int nfsrv_dsremove(struct vnode *, char *, struct ucred *, NFSPROC_T *); static int nfsrv_dssetacl(struct vnode *, struct acl *, struct ucred *, NFSPROC_T *); static int nfsrv_pnfsstatfs(struct statfs *, struct mount *); +static void nfsm_trimtrailing(struct nfsrv_descript *, struct mbuf *, + char *, int, int); int nfs_pnfsio(task_fn_t *, void *); @@ -459,6 +461,7 @@ nfsvno_setattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred, { u_quad_t savsize = 0; int error, savedit; + time_t savbtime; /* * If this is an exported file system and a pNFS service is running, @@ -490,9 +493,13 @@ nfsvno_setattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred, nvap->na_vattr.va_mode != (mode_t)VNOVAL || nvap->na_vattr.va_atime.tv_sec != VNOVAL || nvap->na_vattr.va_mtime.tv_sec != VNOVAL)) { + /* Never modify birthtime on a DS file. */ + savbtime = nvap->na_vattr.va_birthtime.tv_sec; + nvap->na_vattr.va_birthtime.tv_sec = VNOVAL; /* For a pNFS server, set the attributes on the DS file. */ error = nfsrv_proxyds(vp, 0, 0, cred, p, NFSPROC_SETATTR, NULL, NULL, NULL, nvap, NULL, NULL, 0, NULL); + nvap->na_vattr.va_birthtime.tv_sec = savbtime; if (error == ENOENT) error = 0; } @@ -2038,6 +2045,17 @@ again: vput(vp); /* + * If cnt > MCLBYTES and the reply will not be saved, use + * ext_pgs mbufs for TLS. + * For NFSv4.0, we do not know for sure if the reply will + * be saved, so do not use ext_pgs mbufs for NFSv4.0. + */ + if (cnt > MCLBYTES && siz > MCLBYTES && + (nd->nd_flag & (ND_TLS | ND_EXTPG | ND_SAVEREPLY)) == ND_TLS && + (nd->nd_flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4) + nd->nd_flag |= ND_EXTPG; + + /* * dirlen is the size of the reply, including all XDR and must * not exceed cnt. For NFSv2, RFC1094 didn't clearly indicate * if the XDR should be included in "count", but to be safe, we do. @@ -2141,6 +2159,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram, struct mount *mp, *new_mp; uint64_t mounted_on_fileno; struct thread *p = curthread; + int bextpg0, bextpg1, bextpgsiz0, bextpgsiz1; if (nd->nd_repstat) { nfsrv_postopattr(nd, getret, &at); @@ -2354,11 +2373,27 @@ again: } /* + * If the reply is likely to exceed MCLBYTES and the reply will + * not be saved, use ext_pgs mbufs for TLS. + * It is difficult to predict how large each entry will be and + * how many entries have been read, so just assume the directory + * entries grow by a factor of 4 when attributes are included. + * For NFSv4.0, we do not know for sure if the reply will + * be saved, so do not use ext_pgs mbufs for NFSv4.0. + */ + if (cnt > MCLBYTES && siz > MCLBYTES / 4 && + (nd->nd_flag & (ND_TLS | ND_EXTPG | ND_SAVEREPLY)) == ND_TLS && + (nd->nd_flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4) + nd->nd_flag |= ND_EXTPG; + + /* * Save this position, in case there is an error before one entry * is created. */ mb0 = nd->nd_mb; bpos0 = nd->nd_bpos; + bextpg0 = nd->nd_bextpg; + bextpgsiz0 = nd->nd_bextpgsiz; /* * Fill in the first part of the reply. @@ -2380,6 +2415,8 @@ again: */ mb1 = nd->nd_mb; bpos1 = nd->nd_bpos; + bextpg1 = nd->nd_bextpg; + bextpgsiz1 = nd->nd_bextpgsiz; /* Loop through the records and build reply */ entrycnt = 0; @@ -2396,6 +2433,8 @@ again: */ mb1 = nd->nd_mb; bpos1 = nd->nd_bpos; + bextpg1 = nd->nd_bextpg; + bextpgsiz1 = nd->nd_bextpgsiz; /* * For readdir_and_lookup get the vnode using @@ -2621,11 +2660,11 @@ invalid: if (!nd->nd_repstat && entrycnt == 0) nd->nd_repstat = NFSERR_TOOSMALL; if (nd->nd_repstat) { - newnfs_trimtrailing(nd, mb0, bpos0); + nfsm_trimtrailing(nd, mb0, bpos0, bextpg0, bextpgsiz0); if (nd->nd_flag & ND_NFSV3) nfsrv_postopattr(nd, getret, &at); } else - newnfs_trimtrailing(nd, mb1, bpos1); + nfsm_trimtrailing(nd, mb1, bpos1, bextpg1, bextpgsiz1); eofflag = 0; } else if (cpos < cend) eofflag = 0; @@ -2914,8 +2953,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, struct nfsvattr *nvap, break; case NFSATTRBIT_TIMECREATE: NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME); - if (!nd->nd_repstat) - nd->nd_repstat = NFSERR_ATTRNOTSUPP; + fxdr_nfsv4time(tl, &nvap->na_btime); attrsum += NFSX_V4TIME; break; case NFSATTRBIT_TIMEMODIFYSET: @@ -6414,6 +6452,44 @@ out: return (error); } +/* + * Trim trailing data off the mbuf list being built. + */ +static void +nfsm_trimtrailing(struct nfsrv_descript *nd, struct mbuf *mb, char *bpos, + int bextpg, int bextpgsiz) +{ + vm_page_t pg; + int fullpgsiz, i; + + if (mb->m_next != NULL) { + m_freem(mb->m_next); + mb->m_next = NULL; + } + if ((mb->m_flags & M_EXTPG) != 0) { + /* First, get rid of any pages after this position. */ + for (i = mb->m_epg_npgs - 1; i > bextpg; i--) { + pg = PHYS_TO_VM_PAGE(mb->m_epg_pa[i]); + vm_page_unwire_noq(pg); + vm_page_free(pg); + } + mb->m_epg_npgs = bextpg + 1; + if (bextpg == 0) + fullpgsiz = PAGE_SIZE - mb->m_epg_1st_off; + else + fullpgsiz = PAGE_SIZE; + mb->m_epg_last_len = fullpgsiz - bextpgsiz; + mb->m_len = m_epg_pagelen(mb, 0, mb->m_epg_1st_off); + for (i = 1; i < mb->m_epg_npgs; i++) + mb->m_len += m_epg_pagelen(mb, i, 0); + nd->nd_bextpgsiz = bextpgsiz; + nd->nd_bextpg = bextpg; + } else + mb->m_len = bpos - mtod(mb, char *); + nd->nd_mb = mb; + nd->nd_bpos = bpos; +} + extern int (*nfsd_call_nfsd)(struct thread *, struct nfssvc_args *); /* diff --git a/sys/geom/eli/g_eli_integrity.c b/sys/geom/eli/g_eli_integrity.c index e4f31046c45b..d20b753256dd 100644 --- a/sys/geom/eli/g_eli_integrity.c +++ b/sys/geom/eli/g_eli_integrity.c @@ -543,7 +543,7 @@ g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp) if (g_eli_ivlen(sc->sc_ealgo) != 0) { crp->crp_flags |= CRYPTO_F_IV_SEPARATE; g_eli_crypto_ivgen(sc, dstoff, crp->crp_iv, - sizeof(crp->crp_iv)); + sizeof(crp->crp_iv)); } g_eli_auth_keygen(sc, dstoff, authkey); diff --git a/sys/geom/eli/g_eli_privacy.c b/sys/geom/eli/g_eli_privacy.c index 4a3e91948ebb..7bd8eb29cc28 100644 --- a/sys/geom/eli/g_eli_privacy.c +++ b/sys/geom/eli/g_eli_privacy.c @@ -288,7 +288,7 @@ g_eli_crypto_run(struct g_eli_worker *wr, struct bio *bp) if (g_eli_ivlen(sc->sc_ealgo) != 0) { crp->crp_flags |= CRYPTO_F_IV_SEPARATE; g_eli_crypto_ivgen(sc, dstoff, crp->crp_iv, - sizeof(crp->crp_iv)); + sizeof(crp->crp_iv)); } error = crypto_dispatch(crp); diff --git a/sys/geom/geom.h b/sys/geom/geom.h index 46ec01e6c94a..25cf0131355d 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -434,7 +434,7 @@ void *gctl_get_paraml(struct gctl_req *req, const char *param, int len); void *gctl_get_paraml_opt(struct gctl_req *req, const char *param, int len); int gctl_error(struct gctl_req *req, const char *fmt, ...) __printflike(2, 3); struct g_class *gctl_get_class(struct gctl_req *req, char const *arg); -struct g_geom *gctl_get_geom(struct gctl_req *req, struct g_class *mpr, char const *arg); +struct g_geom *gctl_get_geom(struct gctl_req *req, struct g_class *mp, char const *arg); struct g_provider *gctl_get_provider(struct gctl_req *req, char const *arg); #endif /* _GEOM_GEOM_H_ */ diff --git a/sys/geom/geom_ctl.c b/sys/geom/geom_ctl.c index 8b9af1aa54ab..7dbe012a3320 100644 --- a/sys/geom/geom_ctl.c +++ b/sys/geom/geom_ctl.c @@ -409,25 +409,20 @@ gctl_get_class(struct gctl_req *req, char const *arg) } struct g_geom * -gctl_get_geom(struct gctl_req *req, struct g_class *mpr, char const *arg) +gctl_get_geom(struct gctl_req *req, struct g_class *mp, char const *arg) { char const *p; - struct g_class *mp; struct g_geom *gp; + MPASS(mp != NULL); p = gctl_get_asciiparam(req, arg); if (p == NULL) { gctl_error(req, "Missing %s argument", arg); return (NULL); } - LIST_FOREACH(mp, &g_classes, class) { - if (mpr != NULL && mpr != mp) - continue; - LIST_FOREACH(gp, &mp->geom, geom) { - if (!strcmp(p, gp->name)) - return (gp); - } - } + LIST_FOREACH(gp, &mp->geom, geom) + if (!strcmp(p, gp->name)) + return (gp); gctl_error(req, "Geom not found: \"%s\"", p); return (NULL); } diff --git a/sys/geom/geom_map.c b/sys/geom/geom_map.c index fcdba38c8055..e5f1cb649421 100644 --- a/sys/geom/geom_map.c +++ b/sys/geom/geom_map.c @@ -387,24 +387,11 @@ g_map_taste(struct g_class *mp, struct g_provider *pp, int insist __unused) return (gp); } -static void -g_map_config(struct gctl_req *req, struct g_class *mp, const char *verb) -{ - struct g_geom *gp; - - g_topology_assert(); - gp = gctl_get_geom(req, mp, "geom"); - if (gp == NULL) - return; - gctl_error(req, "Unknown verb"); -} - static struct g_class g_map_class = { .name = MAP_CLASS_NAME, .version = G_VERSION, .taste = g_map_taste, .dumpconf = g_map_dumpconf, - .ctlreq = g_map_config, }; DECLARE_GEOM_CLASS(g_map_class, g_map); MODULE_VERSION(geom_map, 0); diff --git a/sys/geom/geom_redboot.c b/sys/geom/geom_redboot.c index febee5bd8377..ffdb64d16274 100644 --- a/sys/geom/geom_redboot.c +++ b/sys/geom/geom_redboot.c @@ -336,24 +336,11 @@ again: return (gp); } -static void -g_redboot_config(struct gctl_req *req, struct g_class *mp, const char *verb) -{ - struct g_geom *gp; - - g_topology_assert(); - gp = gctl_get_geom(req, mp, "geom"); - if (gp == NULL) - return; - gctl_error(req, "Unknown verb"); -} - static struct g_class g_redboot_class = { .name = REDBOOT_CLASS_NAME, .version = G_VERSION, .taste = g_redboot_taste, .dumpconf = g_redboot_dumpconf, - .ctlreq = g_redboot_config, .ioctl = g_redboot_ioctl, }; DECLARE_GEOM_CLASS(g_redboot_class, g_redboot); diff --git a/sys/kern/kern_dump.c b/sys/kern/kern_dump.c index e5e6a5d1208c..79dc7766a964 100644 --- a/sys/kern/kern_dump.c +++ b/sys/kern/kern_dump.c @@ -54,7 +54,7 @@ static size_t fragsz; struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS]; -#if !defined(__powerpc__) && !defined(__sparc__) +#if !defined(__powerpc__) void dumpsys_gen_pa_init(void) { @@ -97,14 +97,12 @@ dumpsys_gen_unmap_chunk(vm_paddr_t pa __unused, size_t chunk __unused, } -#if !defined(__sparc__) int dumpsys_gen_write_aux_headers(struct dumperinfo *di) { return (0); } -#endif int dumpsys_buf_seek(struct dumperinfo *di, size_t sz) @@ -240,7 +238,6 @@ dumpsys_foreach_chunk(dumpsys_callback_t cb, void *arg) return (seqnr); } -#if !defined(__sparc__) static off_t fileofs; static int @@ -387,4 +384,3 @@ dumpsys_generic(struct dumperinfo *di) printf("\n** DUMP FAILED (ERROR %d) **\n", error); return (error); } -#endif diff --git a/sys/kern/kern_priv.c b/sys/kern/kern_priv.c index a912336cbbca..710e9b90894f 100644 --- a/sys/kern/kern_priv.c +++ b/sys/kern/kern_priv.c @@ -247,8 +247,8 @@ priv_check(struct thread *td, int priv) return (priv_check_cred(td->td_ucred, priv)); } -int -priv_check_cred_vfs_generation(struct ucred *cred) +static int __noinline +priv_check_cred_vfs_generation_slow(struct ucred *cred) { int error; @@ -271,3 +271,18 @@ out: return (priv_check_cred_post(cred, PRIV_VFS_GENERATION, error, true)); } + +int +priv_check_cred_vfs_generation(struct ucred *cred) +{ + int error; + + if (__predict_false(mac_priv_check_fp_flag || + mac_priv_grant_fp_flag || SDT_PROBES_ENABLED())) + return (priv_check_cred_vfs_generation_slow(cred)); + + error = EPERM; + if (!jailed(cred) && cred->cr_uid == 0 && suser_enabled) + error = 0; + return (error); +} diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh index 5a0fcfedfb1a..8cbd00a69fcd 100644 --- a/sys/kern/makesyscalls.sh +++ b/sys/kern/makesyscalls.sh @@ -60,6 +60,9 @@ case $# in ;; esac +1>&2 echo "$0: This script has been replaced by sys/tools/makesyscalls.lua and" +1>&2 echo "$0: will be removed before FreeBSD 13. See also: sys/conf/sysent.mk" + if [ -n "$2" ]; then . "$2" fi diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 15a8b1439463..ac138679c850 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1965,12 +1965,17 @@ restart: } SOCKBUF_LOCK_ASSERT(&so->so_rcv); if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { - if (m == NULL && so->so_rcv.sb_tlsdcc == 0 && + if (m != NULL) + goto dontblock; +#ifdef KERN_TLS + else if (so->so_rcv.sb_tlsdcc == 0 && so->so_rcv.sb_tlscc == 0) { +#else + else { +#endif SOCKBUF_UNLOCK(&so->so_rcv); goto release; - } else - goto dontblock; + } } for (; m != NULL; m = m->m_next) if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) { diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index bd9447d0fb55..efd592f82fe2 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1279,7 +1279,8 @@ uipc_ready_scan(struct socket *so, struct mbuf *m, int count, int *errorp) mb = mb->m_next; if (mb == NULL) { mb = n; - n = mb->m_nextpkt; + if (mb != NULL) + n = mb->m_nextpkt; } } } diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 0deb5ff785c4..524554cdd48f 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -3844,7 +3844,7 @@ getblkx(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size, int slpflag, struct buf *bp; struct bufobj *bo; daddr_t d_blkno; - int bsize, error, maxsize, vmio, lockflags; + int bsize, error, maxsize, vmio; off_t offset; CTR3(KTR_BUF, "getblk(%p, %ld, %d)", vp, (long)blkno, size); @@ -3865,14 +3865,9 @@ getblkx(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size, int slpflag, if (bp == NULL) goto newbuf_unlocked; - lockflags = LK_EXCLUSIVE | LK_SLEEPFAIL | - ((flags & GB_LOCK_NOWAIT) ? LK_NOWAIT : 0); - - error = BUF_TIMELOCK(bp, lockflags, NULL, "getblku", slpflag, - slptimeo); - if (error == EINTR || error == ERESTART) - return (error); - else if (error != 0) + error = BUF_TIMELOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL, "getblku", 0, + 0); + if (error != 0) goto loop; /* Verify buf identify has not changed since lookup. */ @@ -3886,14 +3881,14 @@ loop: BO_RLOCK(bo); bp = gbincore(bo, blkno); if (bp != NULL) { + int lockflags; + /* * Buffer is in-core. If the buffer is not busy nor managed, * it must be on a queue. */ - lockflags = LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK; - - if ((flags & GB_LOCK_NOWAIT) != 0) - lockflags |= LK_NOWAIT; + lockflags = LK_EXCLUSIVE | LK_INTERLOCK | + ((flags & GB_LOCK_NOWAIT) ? LK_NOWAIT : LK_SLEEPFAIL); error = BUF_TIMELOCK(bp, lockflags, BO_LOCKPTR(bo), "getblk", slpflag, slptimeo); diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 16c493a1e39a..6eff71606ac9 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -419,7 +419,6 @@ STATNODE_COUNTER(numcachehv, "Number of namecache entries with vnodes held"); STATNODE_COUNTER(numdrops, "Number of dropped entries due to reaching the limit"); STATNODE_COUNTER(dothits, "Number of '.' hits"); STATNODE_COUNTER(dotdothits, "Number of '..' hits"); -STATNODE_COUNTER(numchecks, "Number of checks in lookup"); STATNODE_COUNTER(nummiss, "Number of cache misses"); STATNODE_COUNTER(nummisszap, "Number of cache misses we do not want to cache"); STATNODE_COUNTER(numposzaps, @@ -807,6 +806,15 @@ cache_negative_remove(struct namecache *ncp) } else { list_locked = true; mtx_lock(&neglist->nl_lock); + /* + * We may be racing against promotion in lockless lookup. + */ + if ((negstate->neg_flag & NEG_HOT) != 0) { + mtx_unlock(&neglist->nl_lock); + hot_locked = true; + mtx_lock(&ncneg_hot.nl_lock); + mtx_lock(&neglist->nl_lock); + } } if ((negstate->neg_flag & NEG_HOT) != 0) { mtx_assert(&ncneg_hot.nl_lock, MA_OWNED); @@ -1306,7 +1314,6 @@ retry: rw_wlock(blp); CK_LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) { - counter_u64_add(numchecks, 1); if (ncp->nc_dvp == dvp && ncp->nc_nlen == cnp->cn_namelen && !bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen)) break; @@ -1451,7 +1458,6 @@ retry_hashed: } CK_LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) { - counter_u64_add(numchecks, 1); if (ncp->nc_dvp == dvp && ncp->nc_nlen == cnp->cn_namelen && !bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen)) break; @@ -3002,7 +3008,8 @@ cache_fpl_handled_impl(struct cache_fpl *fpl, int error, int line) #define cache_fpl_handled(x, e) cache_fpl_handled_impl((x), (e), __LINE__) #define CACHE_FPL_SUPPORTED_CN_FLAGS \ - (LOCKLEAF | FOLLOW | LOCKSHARED | SAVENAME | ISOPEN | AUDITVNODE1) + (LOCKLEAF | LOCKPARENT | WANTPARENT | FOLLOW | LOCKSHARED | SAVENAME | \ + ISOPEN | NOMACCHECK | AUDITVNODE1 | AUDITVNODE2) static bool cache_can_fplookup(struct cache_fpl *fpl) @@ -3060,6 +3067,103 @@ cache_fplookup_vnode_supported(struct vnode *vp) } /* + * Move a negative entry to the hot list. + * + * We have to take locks, but they may be contended and in the worst + * case we may need to go off CPU. We don't want to spin within the + * smr section and we can't block with it. Instead we are going to + * look up the entry again. + */ +static int __noinline +cache_fplookup_negative_promote(struct cache_fpl *fpl, struct namecache *oncp, + uint32_t hash) +{ + struct componentname *cnp; + struct namecache *ncp; + struct neglist *neglist; + struct negstate *negstate; + struct vnode *dvp; + u_char nc_flag; + + cnp = fpl->cnp; + dvp = fpl->dvp; + + if (!vhold_smr(dvp)) + return (cache_fpl_aborted(fpl)); + + neglist = NCP2NEGLIST(oncp); + cache_fpl_smr_exit(fpl); + + mtx_lock(&ncneg_hot.nl_lock); + mtx_lock(&neglist->nl_lock); + /* + * For hash iteration. + */ + cache_fpl_smr_enter(fpl); + + /* + * Avoid all surprises by only succeeding if we got the same entry and + * bailing completely otherwise. + * + * In particular at this point there can be a new ncp which matches the + * search but hashes to a different neglist. + */ + CK_LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) { + if (ncp == oncp) + break; + } + + /* + * No match to begin with. + */ + if (__predict_false(ncp == NULL)) { + goto out_abort; + } + + /* + * The newly found entry may be something different... + */ + if (!(ncp->nc_dvp == dvp && ncp->nc_nlen == cnp->cn_namelen && + !bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen))) { + goto out_abort; + } + + /* + * ... and not even negative. + */ + nc_flag = atomic_load_char(&ncp->nc_flag); + if ((nc_flag & NCF_NEGATIVE) == 0) { + goto out_abort; + } + + if (__predict_false(cache_ncp_invalid(ncp))) { + goto out_abort; + } + + negstate = NCP2NEGSTATE(ncp); + if ((negstate->neg_flag & NEG_HOT) == 0) { + numhotneg++; + TAILQ_REMOVE(&neglist->nl_list, ncp, nc_dst); + TAILQ_INSERT_TAIL(&ncneg_hot.nl_list, ncp, nc_dst); + negstate->neg_flag |= NEG_HOT; + } + + SDT_PROBE2(vfs, namecache, lookup, hit__negative, dvp, ncp->nc_name); + counter_u64_add(numneghits, 1); + cache_fpl_smr_exit(fpl); + mtx_unlock(&neglist->nl_lock); + mtx_unlock(&ncneg_hot.nl_lock); + vdrop(dvp); + return (cache_fpl_handled(fpl, ENOENT)); +out_abort: + cache_fpl_smr_exit(fpl); + mtx_unlock(&neglist->nl_lock); + mtx_unlock(&ncneg_hot.nl_lock); + vdrop(dvp); + return (cache_fpl_aborted(fpl)); +} + +/* * The target vnode is not supported, prepare for the slow path to take over. */ static int @@ -3101,10 +3205,42 @@ cache_fplookup_partial_setup(struct cache_fpl *fpl) } static int -cache_fplookup_final(struct cache_fpl *fpl) +cache_fplookup_final_child(struct cache_fpl *fpl, enum vgetstate tvs) { struct componentname *cnp; - enum vgetstate tvs; + struct vnode *tvp; + seqc_t tvp_seqc; + int error; + + cnp = fpl->cnp; + tvp = fpl->tvp; + tvp_seqc = fpl->tvp_seqc; + + if ((cnp->cn_flags & LOCKLEAF) != 0) { + error = vget_finish(tvp, cnp->cn_lkflags, tvs); + if (error != 0) { + return (cache_fpl_aborted(fpl)); + } + } else { + vget_finish_ref(tvp, tvs); + } + + if (!vn_seqc_consistent(tvp, tvp_seqc)) { + if ((cnp->cn_flags & LOCKLEAF) != 0) + vput(tvp); + else + vrele(tvp); + return (cache_fpl_aborted(fpl)); + } + + return (cache_fpl_handled(fpl, 0)); +} + +static int __noinline +cache_fplookup_final_withparent(struct cache_fpl *fpl) +{ + enum vgetstate dvs, tvs; + struct componentname *cnp; struct vnode *dvp, *tvp; seqc_t dvp_seqc, tvp_seqc; int error; @@ -3115,39 +3251,90 @@ cache_fplookup_final(struct cache_fpl *fpl) tvp = fpl->tvp; tvp_seqc = fpl->tvp_seqc; - VNPASS(cache_fplookup_vnode_supported(dvp), dvp); + MPASS((cnp->cn_flags & (LOCKPARENT|WANTPARENT)) != 0); + /* + * This is less efficient than it can be for simplicity. + */ + dvs = vget_prep_smr(dvp); + if (dvs == VGET_NONE) { + return (cache_fpl_aborted(fpl)); + } tvs = vget_prep_smr(tvp); if (tvs == VGET_NONE) { - return (cache_fpl_partial(fpl)); - } - - if (!vn_seqc_consistent(dvp, dvp_seqc)) { cache_fpl_smr_exit(fpl); - vget_abort(tvp, tvs); + vget_abort(dvp, dvs); return (cache_fpl_aborted(fpl)); } cache_fpl_smr_exit(fpl); - if ((cnp->cn_flags & LOCKLEAF) != 0) { - error = vget_finish(tvp, cnp->cn_lkflags, tvs); + if ((cnp->cn_flags & LOCKPARENT) != 0) { + error = vget_finish(dvp, LK_EXCLUSIVE, dvs); if (error != 0) { + vget_abort(tvp, tvs); return (cache_fpl_aborted(fpl)); } } else { - vget_finish_ref(tvp, tvs); + vget_finish_ref(dvp, dvs); } - if (!vn_seqc_consistent(tvp, tvp_seqc)) { - if ((cnp->cn_flags & LOCKLEAF) != 0) - vput(tvp); + if (!vn_seqc_consistent(dvp, dvp_seqc)) { + vget_abort(tvp, tvs); + if ((cnp->cn_flags & LOCKPARENT) != 0) + vput(dvp); else - vrele(tvp); + vrele(dvp); + cache_fpl_aborted(fpl); + return (error); + } + + error = cache_fplookup_final_child(fpl, tvs); + if (error != 0) { + MPASS(fpl->status == CACHE_FPL_STATUS_ABORTED); + if ((cnp->cn_flags & LOCKPARENT) != 0) + vput(dvp); + else + vrele(dvp); + return (error); + } + + MPASS(fpl->status == CACHE_FPL_STATUS_HANDLED); + return (0); +} + +static int +cache_fplookup_final(struct cache_fpl *fpl) +{ + struct componentname *cnp; + enum vgetstate tvs; + struct vnode *dvp, *tvp; + seqc_t dvp_seqc, tvp_seqc; + + cnp = fpl->cnp; + dvp = fpl->dvp; + dvp_seqc = fpl->dvp_seqc; + tvp = fpl->tvp; + tvp_seqc = fpl->tvp_seqc; + + VNPASS(cache_fplookup_vnode_supported(dvp), dvp); + + if ((cnp->cn_flags & (LOCKPARENT|WANTPARENT)) != 0) + return (cache_fplookup_final_withparent(fpl)); + + tvs = vget_prep_smr(tvp); + if (tvs == VGET_NONE) { + return (cache_fpl_partial(fpl)); + } + + if (!vn_seqc_consistent(dvp, dvp_seqc)) { + cache_fpl_smr_exit(fpl); + vget_abort(tvp, tvs); return (cache_fpl_aborted(fpl)); } - return (cache_fpl_handled(fpl, 0)); + cache_fpl_smr_exit(fpl); + return (cache_fplookup_final_child(fpl, tvs)); } static int @@ -3176,7 +3363,6 @@ cache_fplookup_next(struct cache_fpl *fpl) hash = cache_get_hash(cnp->cn_nameptr, cnp->cn_namelen, dvp); CK_LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) { - counter_u64_add(numchecks, 1); if (ncp->nc_dvp == dvp && ncp->nc_nlen == cnp->cn_namelen && !bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen)) break; @@ -3203,12 +3389,7 @@ cache_fplookup_next(struct cache_fpl *fpl) return (cache_fpl_partial(fpl)); } if (!neg_hot) { - /* - * TODO - * Promoting to hot negative requires locks, thus is - * left not yet supported for simplicity. - */ - return (cache_fpl_partial(fpl)); + return (cache_fplookup_negative_promote(fpl, ncp, hash)); } SDT_PROBE2(vfs, namecache, lookup, hit__negative, dvp, ncp->nc_name); diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index 9dc4e714ed79..f67bc9bf3ef0 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -616,7 +616,9 @@ vop_nopoll(ap) } */ *ap; { - return (poll_no_poll(ap->a_events)); + if (ap->a_events & ~POLLSTANDARD) + return (POLLNVAL); + return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); } /* diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 13e1d6ddce99..7e90d86bb6a1 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -289,11 +289,13 @@ namei_setup(struct nameidata *ndp, struct vnode **dpp, struct pwd **pwdp) struct pwd *pwd; cap_rights_t rights; struct filecaps dirfd_caps; - int error, startdir_used; + int error; + bool startdir_used; cnp = &ndp->ni_cnd; td = cnp->cn_thread; + startdir_used = false; *pwdp = NULL; #ifdef CAPABILITY_MODE @@ -340,7 +342,7 @@ namei_setup(struct nameidata *ndp, struct vnode **dpp, struct pwd **pwdp) } else { if (ndp->ni_startdir != NULL) { *dpp = ndp->ni_startdir; - startdir_used = 1; + startdir_used = true; } else if (ndp->ni_dirfd == AT_FDCWD) { *dpp = pwd->pwd_cdir; vrefact(*dpp); @@ -1388,7 +1390,17 @@ NDINIT_ALL(struct nameidata *ndp, u_long op, u_long flags, enum uio_seg segflg, * Free data allocated by namei(); see namei(9) for details. */ void -NDFREE(struct nameidata *ndp, const u_int flags) +NDFREE_PNBUF(struct nameidata *ndp) +{ + + if ((ndp->ni_cnd.cn_flags & HASBUF) != 0) { + uma_zfree(namei_zone, ndp->ni_cnd.cn_pnbuf); + ndp->ni_cnd.cn_flags &= ~HASBUF; + } +} + +void +(NDFREE)(struct nameidata *ndp, const u_int flags) { int unlock_dvp; int unlock_vp; @@ -1396,10 +1408,8 @@ NDFREE(struct nameidata *ndp, const u_int flags) unlock_dvp = 0; unlock_vp = 0; - if (!(flags & NDF_NO_FREE_PNBUF) && - (ndp->ni_cnd.cn_flags & HASBUF)) { - uma_zfree(namei_zone, ndp->ni_cnd.cn_pnbuf); - ndp->ni_cnd.cn_flags &= ~HASBUF; + if (!(flags & NDF_NO_FREE_PNBUF)) { + NDFREE_PNBUF(ndp); } if (!(flags & NDF_NO_VP_UNLOCK) && (ndp->ni_cnd.cn_flags & LOCKLEAF) && ndp->ni_vp) diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 2eec46774327..d7a69b49d7f0 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -5597,21 +5597,21 @@ vop_rename_pre(void *ap) #ifdef DEBUG_VFS_LOCKS void -vop_fplookup_vexec_pre(void *ap __unused) +vop_fplookup_vexec_debugpre(void *ap __unused) { VFS_SMR_ASSERT_ENTERED(); } void -vop_fplookup_vexec_post(void *ap __unused, int rc __unused) +vop_fplookup_vexec_debugpost(void *ap __unused, int rc __unused) { VFS_SMR_ASSERT_ENTERED(); } void -vop_strategy_pre(void *ap) +vop_strategy_debugpre(void *ap) { struct vop_strategy_args *a; struct buf *bp; @@ -5635,7 +5635,7 @@ vop_strategy_pre(void *ap) } void -vop_lock_pre(void *ap) +vop_lock_debugpre(void *ap) { struct vop_lock1_args *a = ap; @@ -5646,7 +5646,7 @@ vop_lock_pre(void *ap) } void -vop_lock_post(void *ap, int rc) +vop_lock_debugpost(void *ap, int rc) { struct vop_lock1_args *a = ap; @@ -5656,7 +5656,7 @@ vop_lock_post(void *ap, int rc) } void -vop_unlock_pre(void *ap) +vop_unlock_debugpre(void *ap) { struct vop_unlock_args *a = ap; @@ -5664,7 +5664,7 @@ vop_unlock_pre(void *ap) } void -vop_need_inactive_pre(void *ap) +vop_need_inactive_debugpre(void *ap) { struct vop_need_inactive_args *a = ap; @@ -5672,7 +5672,7 @@ vop_need_inactive_pre(void *ap) } void -vop_need_inactive_post(void *ap, int rc) +vop_need_inactive_debugpost(void *ap, int rc) { struct vop_need_inactive_args *a = ap; diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 2caf09f3412c..9e9c53d3327c 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -3541,6 +3541,33 @@ sys_renameat(struct thread *td, struct renameat_args *uap) UIO_USERSPACE)); } +#ifdef MAC +static int +kern_renameat_mac(struct thread *td, int oldfd, const char *old, int newfd, + const char *new, enum uio_seg pathseg, struct nameidata *fromnd) +{ + int error; + + NDINIT_ATRIGHTS(fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | + AUDITVNODE1, pathseg, old, oldfd, &cap_renameat_source_rights, td); + if ((error = namei(fromnd)) != 0) + return (error); + error = mac_vnode_check_rename_from(td->td_ucred, fromnd->ni_dvp, + fromnd->ni_vp, &fromnd->ni_cnd); + VOP_UNLOCK(fromnd->ni_dvp); + if (fromnd->ni_dvp != fromnd->ni_vp) + VOP_UNLOCK(fromnd->ni_vp); + if (error != 0) { + NDFREE(fromnd, NDF_ONLY_PNBUF); + vrele(fromnd->ni_dvp); + vrele(fromnd->ni_vp); + if (fromnd->ni_startdir) + vrele(fromnd->ni_startdir); + } + return (error); +} +#endif + int kern_renameat(struct thread *td, int oldfd, const char *old, int newfd, const char *new, enum uio_seg pathseg) @@ -3553,23 +3580,19 @@ kern_renameat(struct thread *td, int oldfd, const char *old, int newfd, again: bwillwrite(); #ifdef MAC - NDINIT_ATRIGHTS(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | - AUDITVNODE1, pathseg, old, oldfd, - &cap_renameat_source_rights, td); -#else - NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART | AUDITVNODE1, - pathseg, old, oldfd, - &cap_renameat_source_rights, td); + if (mac_vnode_check_rename_from_enabled()) { + error = kern_renameat_mac(td, oldfd, old, newfd, new, pathseg, + &fromnd); + if (error != 0) + return (error); + } else { #endif - + NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART | AUDITVNODE1, + pathseg, old, oldfd, &cap_renameat_source_rights, td); if ((error = namei(&fromnd)) != 0) return (error); #ifdef MAC - error = mac_vnode_check_rename_from(td->td_ucred, fromnd.ni_dvp, - fromnd.ni_vp, &fromnd.ni_cnd); - VOP_UNLOCK(fromnd.ni_dvp); - if (fromnd.ni_dvp != fromnd.ni_vp) - VOP_UNLOCK(fromnd.ni_vp); + } #endif fvp = fromnd.ni_vp; NDINIT_ATRIGHTS(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src index 5c0649fdadaf..e5a7b389fb30 100644 --- a/sys/kern/vnode_if.src +++ b/sys/kern/vnode_if.src @@ -147,8 +147,8 @@ vop_close { %% fplookup_vexec vp - - - -%! fplookup_vexec pre vop_fplookup_vexec_pre -%! fplookup_vexec post vop_fplookup_vexec_post +%! fplookup_vexec debugpre vop_fplookup_vexec_debugpre +%! fplookup_vexec debugpost vop_fplookup_vexec_debugpost vop_fplookup_vexec { IN struct vnode *vp; @@ -379,8 +379,8 @@ vop_inactive { IN struct thread *td; }; -%! need_inactive pre vop_need_inactive_pre -%! need_inactive post vop_need_inactive_post +%! need_inactive debugpre vop_need_inactive_debugpre +%! need_inactive debugpost vop_need_inactive_debugpost vop_need_inactive { IN struct vnode *vp; @@ -395,8 +395,8 @@ vop_reclaim { }; -%! lock1 pre vop_lock_pre -%! lock1 post vop_lock_post +%! lock1 debugpre vop_lock_debugpre +%! lock1 debugpost vop_lock_debugpost vop_lock1 { IN struct vnode *vp; @@ -406,7 +406,7 @@ vop_lock1 { }; -%! unlock pre vop_unlock_pre +%! unlock debugpre vop_unlock_debugpre vop_unlock { IN struct vnode *vp; @@ -426,7 +426,7 @@ vop_bmap { %% strategy vp L L L -%! strategy pre vop_strategy_pre +%! strategy debugpre vop_strategy_debugpre vop_strategy { IN struct vnode *vp; diff --git a/sys/mips/conf/std.MALTA b/sys/mips/conf/std.MALTA index 26940db1b92f..7b951b926824 100644 --- a/sys/mips/conf/std.MALTA +++ b/sys/mips/conf/std.MALTA @@ -55,3 +55,10 @@ device miibus device bpf device md device uart + +# VirtIO support +device virtio # Generic VirtIO bus (required) +device virtio_pci # VirtIO PCI Interface +device vtnet # VirtIO Ethernet device +device virtio_blk # VirtIO Block device +device virtio_random # VirtIO Entropy device diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c index 26f7c1515818..6ada543577c9 100644 --- a/sys/mips/mips/trap.c +++ b/sys/mips/mips/trap.c @@ -824,12 +824,12 @@ dofault: i = SIGTRAP; ucode = TRAP_BRKPT; - addr = trapframe->pc; /* compute address of break instruction */ va = trapframe->pc; if (DELAYBRANCH(trapframe->cause)) va += sizeof(int); + addr = va; if (td->td_md.md_ss_addr != va) break; @@ -1107,7 +1107,7 @@ err: ksi.ksi_signo = i; ksi.ksi_code = ucode; ksi.ksi_addr = (void *)addr; - ksi.ksi_trapno = type; + ksi.ksi_trapno = type & ~T_USER; trapsignal(td, &ksi); out: diff --git a/sys/modules/Makefile b/sys/modules/Makefile index dff871fa7338..dc4e04736670 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -755,7 +755,7 @@ _pst= pst _sbni= sbni .endif -.if ${MACHINE_CPUARCH} == "arm" +.if ${MACHINE_ARCH} == "armv7" _cfi= cfi _cpsw= cpsw .endif diff --git a/sys/modules/esp/Makefile b/sys/modules/esp/Makefile index 1880d385dfb8..8540b4434ae3 100644 --- a/sys/modules/esp/Makefile +++ b/sys/modules/esp/Makefile @@ -3,7 +3,7 @@ .PATH: ${SRCTOP}/sys/dev/esp KMOD= esp -SRCS= device_if.h esp_pci.c ${esp_sbus} bus_if.h ncr53c9x.c ${ofw_bus_if} +SRCS= device_if.h esp_pci.c bus_if.h ncr53c9x.c SRCS+= opt_cam.h pci_if.h .include <bsd.kmod.mk> diff --git a/sys/modules/rc/Makefile b/sys/modules/rc/Makefile deleted file mode 100644 index a30f91d516e3..000000000000 --- a/sys/modules/rc/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/rc - -KMOD= rc -SRCS= rc.c device_if.h bus_if.h isa_if.h - -.include <bsd.kmod.mk> diff --git a/sys/modules/rp/Makefile b/sys/modules/rp/Makefile deleted file mode 100644 index 530fc12898ce..000000000000 --- a/sys/modules/rp/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/rp - -KMOD= rp -SRCS= rp.c rp_pci.c device_if.h bus_if.h pci_if.h - -.include <bsd.kmod.mk> diff --git a/sys/modules/uart/Makefile b/sys/modules/uart/Makefile index b6bba88da9ca..5832f4c1696d 100644 --- a/sys/modules/uart/Makefile +++ b/sys/modules/uart/Makefile @@ -28,7 +28,7 @@ uart_dev_mu=uart_dev_mu.c .endif KMOD= uart -SRCS= ${uart_bus_acpi} ${uart_bus_ebus} uart_bus_isa.c uart_bus_pccard.c \ +SRCS= ${uart_bus_acpi} uart_bus_isa.c uart_bus_pccard.c \ uart_bus_pci.c uart_bus_puc.c uart_bus_scc.c \ uart_core.c ${uart_cpu_acpi} ${uart_cpu_machine} uart_dbg.c \ ${uart_dev_mvebu} uart_dev_ns8250.c ${uart_dev_mu} \ diff --git a/sys/net/iflib.c b/sys/net/iflib.c index f87b31251ffe..9a37f30b43f6 100644 --- a/sys/net/iflib.c +++ b/sys/net/iflib.c @@ -4192,7 +4192,9 @@ iflib_if_ioctl(if_t ifp, u_long command, caddr_t data) if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { if ((if_getflags(ifp) ^ ctx->ifc_if_flags) & (IFF_PROMISC | IFF_ALLMULTI)) { + CTX_UNLOCK(ctx); err = IFDI_PROMISC_SET(ctx, if_getflags(ifp)); + CTX_LOCK(ctx); } } else reinit = 1; diff --git a/sys/netgraph/ng_iface.c b/sys/netgraph/ng_iface.c index 5f4ce3c82f31..a91c202ef832 100644 --- a/sys/netgraph/ng_iface.c +++ b/sys/netgraph/ng_iface.c @@ -111,8 +111,6 @@ typedef const struct iffam *iffam_p; const static struct iffam gFamilies[] = { { AF_INET, NG_IFACE_HOOK_INET }, { AF_INET6, NG_IFACE_HOOK_INET6 }, - { AF_ATM, NG_IFACE_HOOK_ATM }, - { AF_NATM, NG_IFACE_HOOK_NATM }, }; #define NUM_FAMILIES nitems(gFamilies) @@ -732,9 +730,11 @@ ng_iface_rcvdata(hook_p hook, item_p item) } random_harvest_queue(m, sizeof(*m), RANDOM_NET_NG); M_SETFIB(m, ifp->if_fib); + CURVNET_SET(ifp->if_vnet); NET_EPOCH_ENTER(et); netisr_dispatch(isr, m); NET_EPOCH_EXIT(et); + CURVNET_RESTORE(); return (0); } diff --git a/sys/netgraph/ng_iface.h b/sys/netgraph/ng_iface.h index 891422b4b359..49c75832384d 100644 --- a/sys/netgraph/ng_iface.h +++ b/sys/netgraph/ng_iface.h @@ -54,8 +54,6 @@ /* My hook names */ #define NG_IFACE_HOOK_INET "inet" #define NG_IFACE_HOOK_INET6 "inet6" -#define NG_IFACE_HOOK_ATM "atm" -#define NG_IFACE_HOOK_NATM "natm" /* MTU bounds */ #define NG_IFACE_MTU_MIN 72 diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 777fd7200ccd..bf4b413bd4de 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1713,6 +1713,7 @@ tcp_newtcpcb(struct inpcb *inp) if (CC_ALGO(tp)->cb_init(tp->ccv) > 0) { if (tp->t_fb->tfb_tcp_fb_fini) (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); + in_pcbrele_wlocked(inp); refcount_release(&tp->t_fb->tfb_refcnt); uma_zfree(V_tcpcb_zone, tm); return (NULL); @@ -1723,6 +1724,7 @@ tcp_newtcpcb(struct inpcb *inp) if (khelp_init_osd(HELPER_CLASS_TCP, tp->osd)) { if (tp->t_fb->tfb_tcp_fb_fini) (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); + in_pcbrele_wlocked(inp); refcount_release(&tp->t_fb->tfb_refcnt); uma_zfree(V_tcpcb_zone, tm); return (NULL); @@ -1783,7 +1785,12 @@ tcp_newtcpcb(struct inpcb *inp) tcp_log_tcpcbinit(tp); #endif if (tp->t_fb->tfb_tcp_fb_init) { - (*tp->t_fb->tfb_tcp_fb_init)(tp); + if ((*tp->t_fb->tfb_tcp_fb_init)(tp)) { + refcount_release(&tp->t_fb->tfb_refcnt); + in_pcbrele_wlocked(inp); + uma_zfree(V_tcpcb_zone, tm); + return (NULL); + } } #ifdef STATS if (V_tcp_perconn_stats_enable == 1) diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 941af58d367a..975a000f1c81 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -761,6 +761,10 @@ again: IN6_IS_ADDR_MC_NODELOCAL(&dst_sa.sin6_addr)) { if (scopeid > 0) { ifp = in6_getlinkifnet(scopeid); + if (ifp == NULL) { + error = EHOSTUNREACH; + goto bad; + } *dst = dst_sa; /* XXX */ goto nonh6lookup; } diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c index d6579ecfc9cf..743299c09fdb 100644 --- a/sys/powerpc/powerpc/trap.c +++ b/sys/powerpc/powerpc/trap.c @@ -207,7 +207,7 @@ trap(struct trapframe *frame) int sig, type, user; u_int ucode; ksiginfo_t ksi; - register_t fscr; + register_t addr, fscr; VM_CNT_INC(v_trap); @@ -224,6 +224,7 @@ trap(struct trapframe *frame) type = ucode = frame->exc; sig = 0; user = frame->srr1 & PSL_PR; + addr = 0; CTR3(KTR_TRAP, "trap: %s type=%s (%s)", td->td_name, trapname(type), user ? "user" : "kernel"); @@ -248,6 +249,7 @@ trap(struct trapframe *frame) if (user) { td->td_pticks = 0; td->td_frame = frame; + addr = frame->srr0; if (td->td_cowgen != p->p_cowgen) thread_cow_update(td); @@ -261,18 +263,22 @@ trap(struct trapframe *frame) break; #if defined(__powerpc64__) && defined(AIM) - case EXC_ISE: case EXC_DSE: + addr = frame->dar; + /* FALLTHROUGH */ + case EXC_ISE: /* DSE/ISE are automatically fatal with radix pmap. */ if (radix_mmu || handle_user_slb_spill(&p->p_vmspace->vm_pmap, - (type == EXC_ISE) ? frame->srr0 : frame->dar) != 0){ + addr) != 0){ sig = SIGSEGV; ucode = SEGV_MAPERR; } break; #endif case EXC_DSI: + addr = frame->dar; + /* FALLTHROUGH */ case EXC_ISI: if (trap_pfault(frame, true, &sig, &ucode)) sig = 0; @@ -368,6 +374,7 @@ trap(struct trapframe *frame) if (fix_unaligned(td, frame) != 0) { sig = SIGBUS; ucode = BUS_ADRALN; + addr = frame->dar; } else frame->srr0 += 4; @@ -481,7 +488,7 @@ trap(struct trapframe *frame) ksiginfo_init_trap(&ksi); ksi.ksi_signo = sig; ksi.ksi_code = (int) ucode; /* XXX, not POSIX */ - ksi.ksi_addr = (void *)frame->srr0; + ksi.ksi_addr = (void *)addr; ksi.ksi_trapno = type; trapsignal(td, &ksi); } diff --git a/sys/riscv/riscv/intr_machdep.c b/sys/riscv/riscv/intr_machdep.c index 2a45e0905261..3e4afe11989e 100644 --- a/sys/riscv/riscv/intr_machdep.c +++ b/sys/riscv/riscv/intr_machdep.c @@ -163,7 +163,7 @@ riscv_cpu_intr(struct trapframe *frame) KASSERT(frame->tf_scause & EXCP_INTR, ("riscv_cpu_intr: wrong frame passed")); - active_irq = (frame->tf_scause & EXCP_MASK); + active_irq = frame->tf_scause & EXCP_MASK; switch (active_irq) { case IRQ_SOFTWARE_USER: diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c index c9b6a1ea6f47..aa9ec534669d 100644 --- a/sys/riscv/riscv/trap.c +++ b/sys/riscv/riscv/trap.c @@ -80,7 +80,7 @@ void do_trap_supervisor(struct trapframe *); void do_trap_user(struct trapframe *); static __inline void -call_trapsignal(struct thread *td, int sig, int code, void *addr) +call_trapsignal(struct thread *td, int sig, int code, void *addr, int trapno) { ksiginfo_t ksi; @@ -88,6 +88,7 @@ call_trapsignal(struct thread *td, int sig, int code, void *addr) ksi.ksi_signo = sig; ksi.ksi_code = code; ksi.ksi_addr = addr; + ksi.ksi_trapno = trapno; trapsignal(td, &ksi); } @@ -224,7 +225,8 @@ data_abort(struct trapframe *frame, int usermode) error = vm_fault_trap(map, va, ftype, VM_FAULT_NORMAL, &sig, &ucode); if (error != KERN_SUCCESS) { if (usermode) { - call_trapsignal(td, sig, ucode, (void *)stval); + call_trapsignal(td, sig, ucode, (void *)stval, + frame->tf_scause & EXCP_MASK); } else { if (pcb->pcb_onfault != 0) { frame->tf_a[0] = error; @@ -254,7 +256,7 @@ do_trap_supervisor(struct trapframe *frame) KASSERT((csr_read(sstatus) & (SSTATUS_SPP | SSTATUS_SIE)) == SSTATUS_SPP, ("Came from S mode with interrupts enabled")); - exception = (frame->tf_scause & EXCP_MASK); + exception = frame->tf_scause & EXCP_MASK; if (frame->tf_scause & EXCP_INTR) { /* Interrupt */ riscv_cpu_intr(frame); @@ -316,7 +318,7 @@ do_trap_user(struct trapframe *frame) KASSERT((csr_read(sstatus) & (SSTATUS_SPP | SSTATUS_SIE)) == 0, ("Came from U mode with interrupts enabled")); - exception = (frame->tf_scause & EXCP_MASK); + exception = frame->tf_scause & EXCP_MASK; if (frame->tf_scause & EXCP_INTR) { /* Interrupt */ riscv_cpu_intr(frame); @@ -353,11 +355,13 @@ do_trap_user(struct trapframe *frame) break; } #endif - call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)frame->tf_sepc); + call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)frame->tf_sepc, + exception); userret(td, frame); break; case EXCP_BREAKPOINT: - call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_sepc); + call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_sepc, + exception); userret(td, frame); break; default: diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c index aea3789d572f..41c0779fa78e 100644 --- a/sys/security/mac/mac_framework.c +++ b/sys/security/mac/mac_framework.c @@ -139,6 +139,7 @@ FPFLAG(vnode_check_read); FPFLAG(vnode_check_write); FPFLAG(vnode_check_mmap); FPFLAG_RARE(vnode_check_poll); +FPFLAG_RARE(vnode_check_rename_from); #undef FPFLAG #undef FPFLAG_RARE @@ -427,6 +428,8 @@ struct mac_policy_fastpath_elem mac_policy_fastpath_array[] = { .flag = &mac_vnode_check_mmap_fp_flag }, { .offset = FPO(vnode_check_poll), .flag = &mac_vnode_check_poll_fp_flag }, + { .offset = FPO(vnode_check_rename_from), + .flag = &mac_vnode_check_rename_from_fp_flag }, }; static void diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h index e917eeb3c893..6ae634bd2dfe 100644 --- a/sys/security/mac/mac_framework.h +++ b/sys/security/mac/mac_framework.h @@ -259,7 +259,11 @@ void mac_posixshm_destroy(struct shmfd *); void mac_posixshm_init(struct shmfd *); int mac_priv_check_impl(struct ucred *cred, int priv); +#ifdef MAC extern bool mac_priv_check_fp_flag; +#else +#define mac_priv_check_fp_flag 0 +#endif static inline int mac_priv_check(struct ucred *cred, int priv) { @@ -270,7 +274,11 @@ mac_priv_check(struct ucred *cred, int priv) } int mac_priv_grant_impl(struct ucred *cred, int priv); +#ifdef MAC extern bool mac_priv_grant_fp_flag; +#else +#define mac_priv_grant_fp_flag 0 +#endif static inline int mac_priv_grant(struct ucred *cred, int priv) { @@ -482,6 +490,10 @@ mac_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred, #endif int mac_vnode_check_readdir(struct ucred *cred, struct vnode *vp); int mac_vnode_check_readlink(struct ucred *cred, struct vnode *vp); +#define mac_vnode_check_rename_from_enabled() __predict_false(mac_vnode_check_rename_from_fp_flag) +#ifdef MAC +extern bool mac_vnode_check_rename_from_fp_flag; +#endif int mac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, struct vnode *vp, struct componentname *cnp); int mac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, diff --git a/sys/sys/ata.h b/sys/sys/ata.h index a08d5253578f..7ec4526be7df 100644 --- a/sys/sys/ata.h +++ b/sys/sys/ata.h @@ -46,6 +46,7 @@ struct ata_params { #define ATA_ATAPI_TYPE_TAPE 0x0100 /* streaming tape */ #define ATA_ATAPI_TYPE_CDROM 0x0500 /* CD-ROM device */ #define ATA_ATAPI_TYPE_OPTICAL 0x0700 /* optical disk */ +#define ATA_ATAPI_REMOVABLE 0x0080 #define ATA_DRQ_MASK 0x0060 #define ATA_DRQ_SLOW 0x0000 /* cpu 3 ms delay */ #define ATA_DRQ_INTR 0x0020 /* interrupt 10 ms delay */ diff --git a/sys/sys/file.h b/sys/sys/file.h index 65b73158f8d9..10d483764467 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -279,21 +279,22 @@ int fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, int fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp); -static __inline int -_fnoop(void) -{ - - return (0); -} - static __inline __result_use_check bool fhold(struct file *fp) { return (refcount_acquire_checked(&fp->f_count)); } -#define fdrop(fp, td) \ - (refcount_release(&(fp)->f_count) ? _fdrop((fp), (td)) : _fnoop()) +#define fdrop(fp, td) ({ \ + struct file *_fp; \ + int _error; \ + \ + _error = 0; \ + _fp = (fp); \ + if (__predict_false(refcount_release(&_fp->f_count))) \ + _error = _fdrop(_fp, td); \ + _error; \ +}) static __inline fo_rdwr_t fo_read; static __inline fo_rdwr_t fo_write; diff --git a/sys/sys/namei.h b/sys/sys/namei.h index 1fa20081a552..0950b0a8f583 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -210,7 +210,15 @@ void NDINIT_ALL(struct nameidata *ndp, u_long op, u_long flags, #define NDF_NO_FREE_PNBUF 0x00000020 #define NDF_ONLY_PNBUF (~NDF_NO_FREE_PNBUF) +void NDFREE_PNBUF(struct nameidata *); void NDFREE(struct nameidata *, const u_int); +#define NDFREE(ndp, flags) do { \ + struct nameidata *_ndp = (ndp); \ + if (__builtin_constant_p(flags) && flags == NDF_ONLY_PNBUF) \ + NDFREE_PNBUF(_ndp); \ + else \ + NDFREE(_ndp, flags); \ +} while (0) int namei(struct nameidata *ndp); int lookup(struct nameidata *ndp); diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 08fa64bed407..d0390ac42f4d 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -1096,10 +1096,10 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); #define CTL_P1003_1B_SIGQUEUE_MAX 24 /* int */ #define CTL_P1003_1B_TIMER_MAX 25 /* int */ -#define CTL_P1003_1B_MAXID 26 - #ifdef _KERNEL +#define CTL_P1003_1B_MAXID 26 + /* * Declare some common oids. */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 8273842a91f5..3a83ea5af6e1 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -869,23 +869,23 @@ void vop_symlink_post(void *a, int rc); int vop_sigdefer(struct vop_vector *vop, struct vop_generic_args *a); #ifdef DEBUG_VFS_LOCKS -void vop_fplookup_vexec_pre(void *a); -void vop_fplookup_vexec_post(void *a, int rc); -void vop_strategy_pre(void *a); -void vop_lock_pre(void *a); -void vop_lock_post(void *a, int rc); -void vop_unlock_pre(void *a); -void vop_need_inactive_pre(void *a); -void vop_need_inactive_post(void *a, int rc); +void vop_fplookup_vexec_debugpre(void *a); +void vop_fplookup_vexec_debugpost(void *a, int rc); +void vop_strategy_debugpre(void *a); +void vop_lock_debugpre(void *a); +void vop_lock_debugpost(void *a, int rc); +void vop_unlock_debugpre(void *a); +void vop_need_inactive_debugpre(void *a); +void vop_need_inactive_debugpost(void *a, int rc); #else -#define vop_fplookup_vexec_pre(x) do { } while (0) -#define vop_fplookup_vexec_post(x, y) do { } while (0) -#define vop_strategy_pre(x) do { } while (0) -#define vop_lock_pre(x) do { } while (0) -#define vop_lock_post(x, y) do { } while (0) -#define vop_unlock_pre(x) do { } while (0) -#define vop_need_inactive_pre(x) do { } while (0) -#define vop_need_inactive_post(x, y) do { } while (0) +#define vop_fplookup_vexec_debugpre(x) do { } while (0) +#define vop_fplookup_vexec_debugpost(x, y) do { } while (0) +#define vop_strategy_debugpre(x) do { } while (0) +#define vop_lock_debugpre(x) do { } while (0) +#define vop_lock_debugpost(x, y) do { } while (0) +#define vop_unlock_debugpre(x) do { } while (0) +#define vop_need_inactive_debugpre(x) do { } while (0) +#define vop_need_inactive_debugpost(x, y) do { } while (0) #endif void vop_rename_fail(struct vop_rename_args *ap); diff --git a/sys/tools/vnode_if.awk b/sys/tools/vnode_if.awk index cd138bef75da..486f0e6b2ce1 100644 --- a/sys/tools/vnode_if.awk +++ b/sys/tools/vnode_if.awk @@ -87,6 +87,24 @@ function add_debug_code(name, arg, pos, ind) } } +function add_debugpre(name) +{ + if (lockdata[name, "debugpre"]) { + printc("#ifdef DEBUG_VFS_LOCKS"); + printc("\t"lockdata[name, "debugpre"]"(a);"); + printc("#endif"); + } +} + +function add_debugpost(name) +{ + if (lockdata[name, "debugpost"]) { + printc("#ifdef DEBUG_VFS_LOCKS"); + printc("\t"lockdata[name, "debugpost"]"(a, rc);"); + printc("#endif"); + } +} + function add_pre(name) { if (lockdata[name, "pre"]) { @@ -101,6 +119,15 @@ function add_post(name) } } +function can_inline(name) +{ + if (lockdata[name, "pre"]) + return 0; + if (lockdata[name, "post"]) + return 0; + return 1; +} + function find_arg_with_type (type) { for (jj = 0; jj < numargs; jj++) { @@ -213,7 +240,8 @@ while ((getline < srcfile) > 0) { if ($1 ~ /^%!/) { if (NF != 4 || - ($3 != "pre" && $3 != "post")) { + ($3 != "pre" && $3 != "post" && + $3 != "debugpre" && $3 != "debugpost")) { die("Invalid %s construction", "%!"); continue; } @@ -316,7 +344,18 @@ while ((getline < srcfile) > 0) { printh("\ta.a_gen.a_desc = &" name "_desc;"); for (i = 0; i < numargs; ++i) printh("\ta.a_" args[i] " = " args[i] ";"); + if (can_inline(name)) { + printh("\n#if !defined(DEBUG_VFS_LOCKS) && !defined(INVARIANTS) && !defined(KTR)"); + printh("\tif (!SDT_PROBES_ENABLED())"); + printh("\t\treturn (" args[0]"->v_op->"name"(&a));"); + printh("\telse"); + printh("\t\treturn (" uname "_APV("args[0]"->v_op, &a));"); + printh("#else"); + } printh("\treturn (" uname "_APV("args[0]"->v_op, &a));"); + if (can_inline(name)) + printh("#endif"); + printh("}"); printh(""); @@ -364,6 +403,7 @@ while ((getline < srcfile) > 0) { printc("\t (\"Wrong a_desc in " name "(%p, %p)\", a->a_" args[0]", a));"); printc("\tVNASSERT(vop != NULL, a->a_" args[0]", (\"No "name"(%p, %p)\", a->a_" args[0]", a));") printc("\tKTR_START" ctrstr); + add_debugpre(name); add_pre(name); for (i = 0; i < numargs; ++i) add_debug_code(name, args[i], "Entry", "\t"); @@ -382,6 +422,7 @@ while ((getline < srcfile) > 0) { add_debug_code(name, args[i], "Error", "\t\t"); printc("\t}"); add_post(name); + add_debugpost(name); printc("\tKTR_STOP" ctrstr); printc("\treturn (rc);"); printc("}\n"); diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index a7d6f3dd9d64..ce107645d6a6 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -908,7 +908,7 @@ vm_page_busy_downgrade(vm_page_t m) vm_page_assert_xbusied(m); - x = m->busy_lock; + x = vm_page_busy_fetch(m); for (;;) { if (atomic_fcmpset_rel_int(&m->busy_lock, &x, VPB_SHARERS_WORD(1))) @@ -931,7 +931,7 @@ vm_page_busy_tryupgrade(vm_page_t m) vm_page_assert_sbusied(m); - x = m->busy_lock; + x = vm_page_busy_fetch(m); ce = VPB_CURTHREAD_EXCLUSIVE; for (;;) { if (VPB_SHARERS(x) > 1) @@ -955,7 +955,7 @@ vm_page_sbusied(vm_page_t m) { u_int x; - x = m->busy_lock; + x = vm_page_busy_fetch(m); return ((x & VPB_BIT_SHARED) != 0 && x != VPB_UNBUSIED); } @@ -971,7 +971,7 @@ vm_page_sunbusy(vm_page_t m) vm_page_assert_sbusied(m); - x = m->busy_lock; + x = vm_page_busy_fetch(m); for (;;) { KASSERT(x != VPB_FREED, ("vm_page_sunbusy: Unlocking freed page.")); @@ -1072,7 +1072,7 @@ _vm_page_busy_sleep(vm_object_t obj, vm_page_t m, vm_pindex_t pindex, xsleep = (allocflags & (VM_ALLOC_SBUSY | VM_ALLOC_IGN_SBUSY)) != 0; sleepq_lock(m); - x = atomic_load_int(&m->busy_lock); + x = vm_page_busy_fetch(m); do { /* * If the page changes objects or becomes unlocked we can @@ -1110,7 +1110,7 @@ vm_page_trysbusy(vm_page_t m) u_int x; obj = m->object; - x = m->busy_lock; + x = vm_page_busy_fetch(m); for (;;) { if ((x & VPB_BIT_SHARED) == 0) return (0); @@ -1146,7 +1146,7 @@ vm_page_tryxbusy(vm_page_t m) { vm_object_t obj; - if (atomic_cmpset_acq_int(&(m)->busy_lock, VPB_UNBUSIED, + if (atomic_cmpset_acq_int(&m->busy_lock, VPB_UNBUSIED, VPB_CURTHREAD_EXCLUSIVE) == 0) return (0); @@ -1354,7 +1354,7 @@ vm_page_readahead_finish(vm_page_t m) * have shown that deactivating the page is usually the best choice, * unless the page is wanted by another thread. */ - if ((m->busy_lock & VPB_BIT_WAITERS) != 0) + if ((vm_page_busy_fetch(m) & VPB_BIT_WAITERS) != 0) vm_page_activate(m); else vm_page_deactivate(m); @@ -1371,11 +1371,16 @@ vm_page_free_invalid(vm_page_t m) KASSERT(vm_page_none_valid(m), ("page %p is valid", m)); KASSERT(!pmap_page_is_mapped(m), ("page %p is mapped", m)); - vm_page_assert_xbusied(m); KASSERT(m->object != NULL, ("page %p has no object", m)); VM_OBJECT_ASSERT_WLOCKED(m->object); /* + * We may be attempting to free the page as part of the handling for an + * I/O error, in which case the page was xbusied by a different thread. + */ + vm_page_xbusy_claim(m); + + /* * If someone has wired this page while the object lock * was not held, then the thread that unwires is responsible * for freeing the page. Otherwise just free the page now. @@ -1714,7 +1719,7 @@ vm_page_busy_release(vm_page_t m) { u_int x; - x = atomic_load_int(&m->busy_lock); + x = vm_page_busy_fetch(m); for (;;) { if (x == VPB_FREED) break; diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h index 4a073cec8e51..93b3dc411925 100644 --- a/sys/vm/vm_page.h +++ b/sys/vm/vm_page.h @@ -100,7 +100,8 @@ * field and is described in detail below. * * The following annotations are possible: - * (A) the field is atomic and may require additional synchronization. + * (A) the field must be accessed using atomic(9) and may require + * additional synchronization. * (B) the page busy lock. * (C) the field is immutable. * (F) the per-domain lock for the free queues @@ -243,8 +244,8 @@ struct vm_page { vm_paddr_t phys_addr; /* physical address of page (C) */ struct md_page md; /* machine dependent stuff */ u_int ref_count; /* page references (A) */ - volatile u_int busy_lock; /* busy owners lock */ - union vm_page_astate a; /* state accessed atomically */ + u_int busy_lock; /* busy owners lock (A) */ + union vm_page_astate a; /* state accessed atomically (A) */ uint8_t order; /* index of the buddy queue (F) */ uint8_t pool; /* vm_phys freepool index (F) */ uint8_t flags; /* page PG_* flags (P) */ @@ -701,6 +702,8 @@ void vm_page_assert_locked_KBI(vm_page_t m, const char *file, int line); void vm_page_lock_assert_KBI(vm_page_t m, int a, const char *file, int line); #endif +#define vm_page_busy_fetch(m) atomic_load_int(&(m)->busy_lock) + #define vm_page_assert_busied(m) \ KASSERT(vm_page_busied(m), \ ("vm_page_assert_busied: page %p not busy @ %s:%d", \ @@ -712,7 +715,7 @@ void vm_page_lock_assert_KBI(vm_page_t m, int a, const char *file, int line); (m), __FILE__, __LINE__)) #define vm_page_assert_unbusied(m) \ - KASSERT((m->busy_lock & ~VPB_BIT_WAITERS) != \ + KASSERT((vm_page_busy_fetch(m) & ~VPB_BIT_WAITERS) != \ VPB_CURTHREAD_EXCLUSIVE, \ ("vm_page_assert_xbusied: page %p busy_lock %#x owned" \ " by me @ %s:%d", \ @@ -725,7 +728,7 @@ void vm_page_lock_assert_KBI(vm_page_t m, int a, const char *file, int line); } while (0) #define vm_page_assert_xbusied(m) do { \ vm_page_assert_xbusied_unchecked(m); \ - KASSERT((m->busy_lock & ~VPB_BIT_WAITERS) == \ + KASSERT((vm_page_busy_fetch(m) & ~VPB_BIT_WAITERS) == \ VPB_CURTHREAD_EXCLUSIVE, \ ("vm_page_assert_xbusied: page %p busy_lock %#x not owned" \ " by me @ %s:%d", \ @@ -733,7 +736,7 @@ void vm_page_lock_assert_KBI(vm_page_t m, int a, const char *file, int line); } while (0) #define vm_page_busied(m) \ - ((m)->busy_lock != VPB_UNBUSIED) + (vm_page_busy_fetch(m) != VPB_UNBUSIED) #define vm_page_sbusy(m) do { \ if (!vm_page_trysbusy(m)) \ @@ -742,10 +745,10 @@ void vm_page_lock_assert_KBI(vm_page_t m, int a, const char *file, int line); } while (0) #define vm_page_xbusied(m) \ - (((m)->busy_lock & VPB_SINGLE_EXCLUSIVE) != 0) + ((vm_page_busy_fetch(m) & VPB_SINGLE_EXCLUSIVE) != 0) #define vm_page_busy_freed(m) \ - ((m)->busy_lock == VPB_FREED) + (vm_page_busy_fetch(m) == VPB_FREED) #define vm_page_xbusy(m) do { \ if (!vm_page_tryxbusy(m)) \ @@ -771,9 +774,19 @@ void vm_page_object_busy_assert(vm_page_t m); void vm_page_assert_pga_writeable(vm_page_t m, uint16_t bits); #define VM_PAGE_ASSERT_PGA_WRITEABLE(m, bits) \ vm_page_assert_pga_writeable(m, bits) +/* + * Claim ownership of a page's xbusy state. In non-INVARIANTS kernels this + * operation is a no-op since ownership is not tracked. In particular + * this macro does not provide any synchronization with the previous owner. + */ #define vm_page_xbusy_claim(m) do { \ + u_int _busy_lock; \ + \ vm_page_assert_xbusied_unchecked((m)); \ - (m)->busy_lock = VPB_CURTHREAD_EXCLUSIVE; \ + do { \ + _busy_lock = vm_page_busy_fetch(m); \ + } while (!atomic_cmpset_int(&(m)->busy_lock, _busy_lock, \ + (_busy_lock & VPB_BIT_FLAGMASK) | VPB_CURTHREAD_EXCLUSIVE)); \ } while (0) #else #define VM_PAGE_OBJECT_BUSY_ASSERT(m) (void)0 diff --git a/sys/x86/include/acpica_machdep.h b/sys/x86/include/acpica_machdep.h index 89012b3f4bc4..05e8711c16fa 100644 --- a/sys/x86/include/acpica_machdep.h +++ b/sys/x86/include/acpica_machdep.h @@ -84,6 +84,7 @@ void madt_parse_interrupt_values(void *entry, enum intr_trigger *trig, enum intr_polarity *pol); extern int madt_found_sci_override; +extern int (*apei_nmi)(void); #endif /* _KERNEL */ diff --git a/sys/x86/include/bus_dma.h b/sys/x86/include/bus_dma.h index 5bb70419726a..b4da787e9cfc 100644 --- a/sys/x86/include/bus_dma.h +++ b/sys/x86/include/bus_dma.h @@ -191,11 +191,5 @@ _bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map, return (tc->impl->map_complete(dmat, map, segs, nsegs, error)); } -#ifdef _KERNEL -bool bus_dma_dmar_set_buswide(device_t dev); -int bus_dma_dmar_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map, - vm_paddr_t start, vm_size_t length, int flags); -#endif - #endif /* !_X86_BUS_DMA_H_ */ diff --git a/sys/x86/iommu/intel_ctx.c b/sys/x86/iommu/intel_ctx.c index 45151c8dd355..234a920d1ded 100644 --- a/sys/x86/iommu/intel_ctx.c +++ b/sys/x86/iommu/intel_ctx.c @@ -58,18 +58,18 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_page.h> #include <vm/vm_pager.h> #include <vm/vm_map.h> +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> #include <machine/atomic.h> #include <machine/bus.h> #include <machine/md_var.h> #include <machine/specialreg.h> -#include <contrib/dev/acpica/include/acpi.h> -#include <contrib/dev/acpica/include/accommon.h> #include <x86/include/busdma_impl.h> -#include <x86/iommu/intel_reg.h> #include <dev/iommu/busdma_iommu.h> -#include <dev/pci/pcireg.h> +#include <x86/iommu/intel_reg.h> #include <x86/iommu/intel_dmar.h> -#include <dev/pci/pcivar.h> static MALLOC_DEFINE(M_DMAR_CTX, "dmar_ctx", "Intel DMAR Context"); static MALLOC_DEFINE(M_DMAR_DOMAIN, "dmar_dom", "Intel DMAR Domain"); @@ -196,7 +196,7 @@ ctx_id_entry_init(struct dmar_ctx *ctx, dmar_ctx_entry_t *ctxp, bool move, IOMMU_PGF_NOALLOC); } - if (dmar_is_buswide_ctx(unit, busno)) { + if (iommu_is_buswide_ctx((struct iommu_unit *)unit, busno)) { MPASS(!move); for (i = 0; i <= PCI_BUSMAX; i++) { ctx_id_entry_init_one(&ctxp[i], domain, ctx_root); @@ -464,6 +464,7 @@ dmar_get_ctx_for_dev1(struct dmar_unit *dmar, device_t dev, uint16_t rid, { struct dmar_domain *domain, *domain1; struct dmar_ctx *ctx, *ctx1; + struct iommu_unit *unit; dmar_ctx_entry_t *ctxp; struct sf_buf *sf; int bus, slot, func, error; @@ -480,9 +481,10 @@ dmar_get_ctx_for_dev1(struct dmar_unit *dmar, device_t dev, uint16_t rid, } enable = false; TD_PREP_PINNED_ASSERT; + unit = (struct iommu_unit *)dmar; DMAR_LOCK(dmar); - KASSERT(!dmar_is_buswide_ctx(dmar, bus) || (slot == 0 && func == 0), - ("dmar%d pci%d:%d:%d get_ctx for buswide", dmar->iommu.unit, bus, + KASSERT(!iommu_is_buswide_ctx(unit, bus) || (slot == 0 && func == 0), + ("iommu%d pci%d:%d:%d get_ctx for buswide", dmar->iommu.unit, bus, slot, func)); ctx = dmar_find_ctx_locked(dmar, rid); error = 0; diff --git a/sys/x86/iommu/intel_dmar.h b/sys/x86/iommu/intel_dmar.h index fba5e36f95cd..eae01bcc134d 100644 --- a/sys/x86/iommu/intel_dmar.h +++ b/sys/x86/iommu/intel_dmar.h @@ -167,15 +167,6 @@ struct dmar_unit { struct iommu_map_entries_tailq tlb_flush_entries; struct task qi_task; struct taskqueue *qi_taskqueue; - - /* - * Bitmap of buses for which context must ignore slot:func, - * duplicating the page table pointer into all context table - * entries. This is a client-controlled quirk to support some - * NTBs. - */ - uint32_t buswide_ctxs[(PCI_BUSMAX + 1) / NBBY / sizeof(uint32_t)]; - }; #define DMAR_LOCK(dmar) mtx_lock(&(dmar)->iommu.lock) @@ -290,9 +281,6 @@ void dmar_quirks_pre_use(struct iommu_unit *dmar); int dmar_init_irt(struct dmar_unit *unit); void dmar_fini_irt(struct dmar_unit *unit); -void dmar_set_buswide_ctx(struct iommu_unit *unit, u_int busno); -bool dmar_is_buswide_ctx(struct dmar_unit *unit, u_int busno); - extern iommu_haddr_t dmar_high; extern int haw; extern int dmar_tbl_pagecnt; diff --git a/sys/x86/iommu/intel_drv.c b/sys/x86/iommu/intel_drv.c index a8a2bc7cf770..17fea13d1387 100644 --- a/sys/x86/iommu/intel_drv.c +++ b/sys/x86/iommu/intel_drv.c @@ -54,11 +54,6 @@ __FBSDID("$FreeBSD$"); #include <sys/taskqueue.h> #include <sys/tree.h> #include <sys/vmem.h> -#include <machine/bus.h> -#include <machine/pci_cfgreg.h> -#include <contrib/dev/acpica/include/acpi.h> -#include <contrib/dev/acpica/include/accommon.h> -#include <dev/acpica/acpivar.h> #include <vm/vm.h> #include <vm/vm_extern.h> #include <vm/vm_kern.h> @@ -66,11 +61,16 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_page.h> #include <vm/vm_pager.h> #include <vm/vm_map.h> -#include <x86/include/busdma_impl.h> -#include <x86/iommu/intel_reg.h> -#include <dev/iommu/busdma_iommu.h> +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> +#include <dev/acpica/acpivar.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> +#include <machine/bus.h> +#include <machine/pci_cfgreg.h> +#include <x86/include/busdma_impl.h> +#include <dev/iommu/busdma_iommu.h> +#include <x86/iommu/intel_reg.h> #include <x86/iommu/intel_dmar.h> #ifdef DEV_APIC @@ -592,29 +592,6 @@ static driver_t dmar_driver = { DRIVER_MODULE(dmar, acpi, dmar_driver, dmar_devclass, 0, 0); MODULE_DEPEND(dmar, acpi, 1, 1, 1); -void -dmar_set_buswide_ctx(struct iommu_unit *unit, u_int busno) -{ - struct dmar_unit *dmar; - - dmar = (struct dmar_unit *)unit; - - MPASS(busno <= PCI_BUSMAX); - DMAR_LOCK(dmar); - dmar->buswide_ctxs[busno / NBBY / sizeof(uint32_t)] |= - 1 << (busno % (NBBY * sizeof(uint32_t))); - DMAR_UNLOCK(dmar); -} - -bool -dmar_is_buswide_ctx(struct dmar_unit *unit, u_int busno) -{ - - MPASS(busno <= PCI_BUSMAX); - return ((unit->buswide_ctxs[busno / NBBY / sizeof(uint32_t)] & - (1U << (busno % (NBBY * sizeof(uint32_t))))) != 0); -} - static void dmar_print_path(int busno, int depth, const ACPI_DMAR_PCI_PATH *path) { diff --git a/sys/x86/iommu/intel_idpgtbl.c b/sys/x86/iommu/intel_idpgtbl.c index d85abefc54c4..4c151ffffef8 100644 --- a/sys/x86/iommu/intel_idpgtbl.c +++ b/sys/x86/iommu/intel_idpgtbl.c @@ -58,15 +58,15 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_page.h> #include <vm/vm_pager.h> #include <vm/vm_map.h> +#include <dev/pci/pcireg.h> #include <machine/atomic.h> #include <machine/bus.h> #include <machine/cpu.h> #include <machine/md_var.h> #include <machine/specialreg.h> #include <x86/include/busdma_impl.h> -#include <x86/iommu/intel_reg.h> #include <dev/iommu/busdma_iommu.h> -#include <dev/pci/pcireg.h> +#include <x86/iommu/intel_reg.h> #include <x86/iommu/intel_dmar.h> static int domain_unmap_buf_locked(struct dmar_domain *domain, diff --git a/sys/x86/iommu/intel_intrmap.c b/sys/x86/iommu/intel_intrmap.c index d2bce59c4c2e..e95d8a8090b3 100644 --- a/sys/x86/iommu/intel_intrmap.c +++ b/sys/x86/iommu/intel_intrmap.c @@ -40,24 +40,25 @@ __FBSDID("$FreeBSD$"); #include <sys/mutex.h> #include <sys/rman.h> #include <sys/rwlock.h> +#include <sys/sysctl.h> #include <sys/taskqueue.h> #include <sys/tree.h> #include <sys/vmem.h> -#include <machine/bus.h> -#include <machine/intr_machdep.h> #include <vm/vm.h> #include <vm/vm_extern.h> #include <vm/vm_kern.h> #include <vm/vm_object.h> #include <vm/vm_page.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <machine/bus.h> +#include <machine/intr_machdep.h> #include <x86/include/apicreg.h> #include <x86/include/apicvar.h> #include <x86/include/busdma_impl.h> -#include <x86/iommu/intel_reg.h> #include <dev/iommu/busdma_iommu.h> -#include <dev/pci/pcireg.h> +#include <x86/iommu/intel_reg.h> #include <x86/iommu/intel_dmar.h> -#include <dev/pci/pcivar.h> #include <x86/iommu/iommu_intrmap.h> static struct dmar_unit *dmar_ir_find(device_t src, uint16_t *rid, diff --git a/sys/x86/iommu/intel_qi.c b/sys/x86/iommu/intel_qi.c index 5377ac448df8..ab2c4d4e80fc 100644 --- a/sys/x86/iommu/intel_qi.c +++ b/sys/x86/iommu/intel_qi.c @@ -45,20 +45,20 @@ __FBSDID("$FreeBSD$"); #include <sys/time.h> #include <sys/tree.h> #include <sys/vmem.h> -#include <machine/bus.h> -#include <contrib/dev/acpica/include/acpi.h> -#include <contrib/dev/acpica/include/accommon.h> -#include <dev/acpica/acpivar.h> #include <vm/vm.h> #include <vm/vm_extern.h> #include <vm/vm_kern.h> #include <vm/vm_page.h> #include <vm/vm_map.h> +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> +#include <dev/acpica/acpivar.h> +#include <dev/pci/pcireg.h> +#include <machine/bus.h> #include <machine/cpu.h> #include <x86/include/busdma_impl.h> -#include <x86/iommu/intel_reg.h> #include <dev/iommu/busdma_iommu.h> -#include <dev/pci/pcireg.h> +#include <x86/iommu/intel_reg.h> #include <x86/iommu/intel_dmar.h> static bool diff --git a/sys/x86/iommu/intel_quirks.c b/sys/x86/iommu/intel_quirks.c index d0eac82e7298..1a025b3419eb 100644 --- a/sys/x86/iommu/intel_quirks.c +++ b/sys/x86/iommu/intel_quirks.c @@ -46,10 +46,6 @@ __FBSDID("$FreeBSD$"); #include <sys/taskqueue.h> #include <sys/tree.h> #include <sys/vmem.h> -#include <machine/bus.h> -#include <contrib/dev/acpica/include/acpi.h> -#include <contrib/dev/acpica/include/accommon.h> -#include <dev/acpica/acpivar.h> #include <vm/vm.h> #include <vm/vm_extern.h> #include <vm/vm_kern.h> @@ -57,12 +53,16 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_page.h> #include <vm/vm_pager.h> #include <vm/vm_map.h> +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> +#include <dev/acpica/acpivar.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <machine/bus.h> #include <x86/include/busdma_impl.h> -#include <x86/iommu/intel_reg.h> #include <dev/iommu/busdma_iommu.h> -#include <dev/pci/pcireg.h> +#include <x86/iommu/intel_reg.h> #include <x86/iommu/intel_dmar.h> -#include <dev/pci/pcivar.h> typedef void (*dmar_quirk_cpu_fun)(struct dmar_unit *); diff --git a/sys/x86/iommu/intel_utils.c b/sys/x86/iommu/intel_utils.c index 7e89465240af..43a00428c46c 100644 --- a/sys/x86/iommu/intel_utils.c +++ b/sys/x86/iommu/intel_utils.c @@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$"); #include <sys/time.h> #include <sys/tree.h> #include <sys/vmem.h> -#include <dev/pci/pcivar.h> #include <vm/vm.h> #include <vm/vm_extern.h> #include <vm/vm_kern.h> @@ -59,14 +58,15 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_page.h> #include <vm/vm_map.h> #include <vm/vm_pageout.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> #include <machine/bus.h> #include <machine/cpu.h> #include <machine/intr_machdep.h> #include <x86/include/apicvar.h> #include <x86/include/busdma_impl.h> -#include <x86/iommu/intel_reg.h> #include <dev/iommu/busdma_iommu.h> -#include <dev/pci/pcireg.h> +#include <x86/iommu/intel_reg.h> #include <x86/iommu/intel_dmar.h> u_int diff --git a/sys/x86/x86/busdma_machdep.c b/sys/x86/x86/busdma_machdep.c index 3442313f55c8..168645702bc5 100644 --- a/sys/x86/x86/busdma_machdep.c +++ b/sys/x86/x86/busdma_machdep.c @@ -300,14 +300,18 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat) } #ifndef ACPI_DMAR +bool bus_dma_iommu_set_buswide(device_t dev); +int bus_dma_iommu_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map, + vm_paddr_t start, vm_size_t length, int flags); + bool -bus_dma_dmar_set_buswide(device_t dev) +bus_dma_iommu_set_buswide(device_t dev) { return (false); } int -bus_dma_dmar_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map, +bus_dma_iommu_load_ident(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t start, vm_size_t length, int flags) { return (0); diff --git a/sys/x86/x86/cpu_machdep.c b/sys/x86/x86/cpu_machdep.c index 74a5261f9112..21efb6d6b122 100644 --- a/sys/x86/x86/cpu_machdep.c +++ b/sys/x86/x86/cpu_machdep.c @@ -831,6 +831,7 @@ int nmi_is_broadcast = 1; SYSCTL_INT(_machdep, OID_AUTO, nmi_is_broadcast, CTLFLAG_RWTUN, &nmi_is_broadcast, 0, "Chipset NMI is broadcast"); +int (*apei_nmi)(void); void nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame) @@ -846,6 +847,10 @@ nmi_call_kdb(u_int cpu, u_int type, struct trapframe *frame) } #endif /* DEV_ISA */ + /* ACPI Platform Error Interfaces callback. */ + if (apei_nmi != NULL && (*apei_nmi)()) + claimed = true; + /* * NMIs can be useful for debugging. They can be hooked up to a * pushbutton, usually on an ISA, PCI, or PCIe card. They can also be diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd index 7becc0dc2830..93b714ede7fb 100644 --- a/usr.bin/calendar/calendars/calendar.freebsd +++ b/usr.bin/calendar/calendars/calendar.freebsd @@ -404,6 +404,7 @@ 10/20 Joel Dahl <joel@FreeBSD.org> born in Bitterna, Skaraborg, Sweden, 1983 10/20 Dmitry Marakasov <amdmi3@FreeBSD.org> born in Moscow, Russian Federation, 1984 10/21 Ben Smithurst <ben@FreeBSD.org> born in Sheffield, South Yorkshire, United Kingdom, 1981 +10/21 Daniel Ebdrup Jensen <debdrup@FreeBSD.org> born in Aalborg, Denmark, 19XX 10/22 Jean-Sebastien Pedron <dumbbell@FreeBSD.org> born in Redon, Ille-et-Vilaine, France, 1980 10/23 Mario Sergio Fujikawa Ferreira <lioux@FreeBSD.org> born in Brasilia, Distrito Federal, Brazil, 1976 10/23 Romain Tartière <romain@FreeBSD.org> born in Clermont-Ferrand, France, 1984 diff --git a/usr.bin/comm/comm.1 b/usr.bin/comm/comm.1 index 6e258806287e..b70e08692bd6 100644 --- a/usr.bin/comm/comm.1 +++ b/usr.bin/comm/comm.1 @@ -31,7 +31,7 @@ .\" From: @(#)comm.1 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd December 12, 2009 +.Dd July 27, 2020 .Dt COMM 1 .Os .Sh NAME @@ -95,6 +95,35 @@ as described in .Xr environ 7 . .Sh EXIT STATUS .Ex -std +.Sh EXAMPLES +Assuming a file named +.Pa example.txt +with the following contents: +.Bd -literal -offset indent +a +b +c +d +.Ed +.Pp +Show lines only in +.Pa example.txt , +lines only in stdin and common lines: +.Bd -literal -offset indent +$ echo -e "B\enc" | comm example.txt - + B +a +b + c +d +.Ed +.Pp +Show only common lines doing case insensitive comparisons: +.Bd -literal -offset indent +$ echo -e "B\enc" | comm -1 -2 -i example.txt - +b +c +.Ed .Sh SEE ALSO .Xr cmp 1 , .Xr diff 1 , @@ -108,9 +137,7 @@ utility conforms to .Pp The .Fl i -option is an extension to the -.Tn POSIX -standard. +option is an extension to the POSIX standard. .Sh HISTORY A .Nm diff --git a/usr.bin/diff/tests/diff_test.sh b/usr.bin/diff/tests/diff_test.sh index 67a7300f8dd3..9f460231f480 100755 --- a/usr.bin/diff/tests/diff_test.sh +++ b/usr.bin/diff/tests/diff_test.sh @@ -108,8 +108,8 @@ side_by_side_body() atf_check -o save:A printf "A\nB\nC\n" atf_check -o save:B printf "D\nB\nE\n" - exp_output="A[[:space:]]+|[[:space:]]+D\nB[[:space:]]+B\nC[[:space:]]+|[[:space:]]+E" - exp_output_suppressed="A[[:space:]]+|[[:space:]]+D\nC[[:space:]]+|[[:space:]]+E" + exp_output=$(printf "A[[:space:]]+|[[:space:]]+D\nB[[:space:]]+B\nC[[:space:]]+|[[:space:]]+E") + exp_output_suppressed=$(printf "A[[:space:]]+|[[:space:]]+D\nC[[:space:]]+|[[:space:]]+E") atf_check -o match:"$exp_output" -s exit:1 \ diff --side-by-side A B diff --git a/usr.bin/sed/tests/sed2_test.sh b/usr.bin/sed/tests/sed2_test.sh index 9f831e0ed673..07f1ec844814 100755 --- a/usr.bin/sed/tests/sed2_test.sh +++ b/usr.bin/sed/tests/sed2_test.sh @@ -109,11 +109,9 @@ hex_subst_body() # Single digit \x should work as well. atf_check -o "inline:xn" sed 's/\xd/x/' c - # Invalid digit should cause us to ignore the sequence. This test - # invokes UB, escapes of an ordinary character. A future change will - # make regex(3) on longer tolerate this and we'll need to adjust what - # we're doing, but for now this will suffice. - atf_check -o "inline:" sed 's/\xx//' d + # This should get passed through to the underlying regex engine as + # \xx, which is an invalid escape of an ordinary character. + atf_check -s exit:1 -e not-empty sed 's/\xx//' d } atf_test_case commands_on_stdin diff --git a/usr.bin/truncate/truncate.1 b/usr.bin/truncate/truncate.1 index a6065b1de9f1..2058530162c5 100644 --- a/usr.bin/truncate/truncate.1 +++ b/usr.bin/truncate/truncate.1 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 19, 2006 +.Dd July 27, 2020 .Dt TRUNCATE 1 .Os .Sh NAME @@ -143,6 +143,43 @@ If the operation fails for an argument, .Nm will issue a diagnostic and continue processing the remaining arguments. +.Sh EXAMPLES +Adjust the size of the file +.Pa test_file +to 10 Megabytes but do not create it if it does not exist: +.Bd -literal -offset indent +truncate -c -s +10M test_file +.Ed +.Pp +Same as above but create the file if it does not exist: +.Bd -literal -offset indent +truncate -s +10M test_file +ls -l test_file +-rw-r--r-- 1 root wheel 10485760 Jul 22 18:48 test_file +.Ed +.Pp +Adjust the size of +.Pa test_file +to the size of the kernel and create another file +.Pa test_file2 +with the same size: +.Bd -literal -offset indent +truncate -r /boot/kernel/kernel test_file test_file2 +ls -l /boot/kernel/kernel test_file* +-r-xr-xr-x 1 root wheel 31352552 May 15 14:18 /boot/kernel/kernel* +-rw-r--r-- 1 root wheel 31352552 Jul 22 19:15 test_file +-rw-r--r-- 1 root wheel 31352552 Jul 22 19:15 test_file2 +.Ed +.Pp +Downsize +.Pa test_file +in 5 Megabytes: +.Bd -literal -offset indent +# truncate -s -5M test_file +ls -l test_file* +-rw-r--r-- 1 root wheel 26109672 Jul 22 19:17 test_file +-rw-r--r-- 1 root wheel 31352552 Jul 22 19:15 test_file2 +.Ed .Sh SEE ALSO .Xr dd 1 , .Xr touch 1 , diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8 index e92b39cc6825..2e91ed86d3a1 100644 --- a/usr.sbin/bhyve/bhyve.8 +++ b/usr.sbin/bhyve/bhyve.8 @@ -540,6 +540,18 @@ Sector size (defaults to blockif sector size). Serial number with maximum 20 characters. .El .Pp +AHCI devices: +.Bl -tag -width 10n +.It Li nmrr +Nominal Media Rotation Rate, known as RPM. value 1 will indicate device as Solid State Disk. default value is 0, not report. +.It Li ser +Serial Number with maximum 20 characters. +.It Li rev +Revision Number with maximum 8 characters. +.It Li model +Model Number with maximum 40 characters. +.El +.Pp HD Audio devices: .Bl -tag -width 10n .It Li play diff --git a/usr.sbin/bhyve/pci_ahci.c b/usr.sbin/bhyve/pci_ahci.c index 49e6452a355d..dfdf57f664e7 100644 --- a/usr.sbin/bhyve/pci_ahci.c +++ b/usr.sbin/bhyve/pci_ahci.c @@ -139,9 +139,9 @@ struct ahci_ioreq { struct ahci_port { struct blockif_ctxt *bctx; struct pci_ahci_softc *pr_sc; + struct ata_params ata_ident; uint8_t *cmd_lst; uint8_t *rfis; - char ident[AHCI_PORT_IDENT]; int port; int atapi; int reset; @@ -987,7 +987,50 @@ handle_identify(struct ahci_port *p, int slot, uint8_t *cfis) ahci_write_fis_d2h(p, slot, cfis, (ATA_E_ABORT << 8) | ATA_S_READY | ATA_S_ERROR); } else { - uint16_t buf[256]; + ahci_write_fis_piosetup(p); + write_prdt(p, slot, cfis, (void*)&p->ata_ident, sizeof(struct ata_params)); + ahci_write_fis_d2h(p, slot, cfis, ATA_S_DSC | ATA_S_READY); + } +} + +static void +ata_identify_init(struct ahci_port* p, int atapi) +{ + struct ata_params* ata_ident = &p->ata_ident; + + if (atapi) { + ata_ident->config = ATA_PROTO_ATAPI | ATA_ATAPI_TYPE_CDROM | + ATA_ATAPI_REMOVABLE | ATA_DRQ_FAST; + ata_ident->capabilities1 = ATA_SUPPORT_LBA | + ATA_SUPPORT_DMA; + ata_ident->capabilities2 = (1 << 14 | 1); + ata_ident->atavalid = ATA_FLAG_54_58 | ATA_FLAG_64_70; + ata_ident->obsolete62 = 0x3f; + ata_ident->mwdmamodes = 7; + if (p->xfermode & ATA_WDMA0) + ata_ident->mwdmamodes |= (1 << ((p->xfermode & 7) + 8)); + ata_ident->apiomodes = 3; + ata_ident->mwdmamin = 0x0078; + ata_ident->mwdmarec = 0x0078; + ata_ident->pioblind = 0x0078; + ata_ident->pioiordy = 0x0078; + ata_ident->satacapabilities = (ATA_SATA_GEN1 | ATA_SATA_GEN2 | ATA_SATA_GEN3); + ata_ident->satacapabilities2 = ((p->ssts & ATA_SS_SPD_MASK) >> 3); + ata_ident->satasupport = ATA_SUPPORT_NCQ_STREAM; + ata_ident->version_major = 0x3f0; + ata_ident->support.command1 = (ATA_SUPPORT_POWERMGT | ATA_SUPPORT_PACKET | + ATA_SUPPORT_RESET | ATA_SUPPORT_NOP); + ata_ident->support.command2 = (1 << 14); + ata_ident->support.extension = (1 << 14); + ata_ident->enabled.command1 = (ATA_SUPPORT_POWERMGT | ATA_SUPPORT_PACKET | + ATA_SUPPORT_RESET | ATA_SUPPORT_NOP); + ata_ident->enabled.extension = (1 << 14); + ata_ident->udmamodes = 0x7f; + if (p->xfermode & ATA_UDMA0) + ata_ident->udmamodes |= (1 << ((p->xfermode & 7) + 8)); + ata_ident->transport_major = 0x1020; + ata_ident->integrity = 0x00a5; + } else { uint64_t sectors; int sectsz, psectsz, psectoff, candelete, ro; uint16_t cyl; @@ -999,87 +1042,85 @@ handle_identify(struct ahci_port *p, int slot, uint8_t *cfis) sectors = blockif_size(p->bctx) / sectsz; blockif_chs(p->bctx, &cyl, &heads, &sech); blockif_psectsz(p->bctx, &psectsz, &psectoff); - memset(buf, 0, sizeof(buf)); - buf[0] = 0x0040; - buf[1] = cyl; - buf[3] = heads; - buf[6] = sech; - ata_string((uint8_t *)(buf+10), p->ident, 20); - ata_string((uint8_t *)(buf+23), "001", 8); - ata_string((uint8_t *)(buf+27), "BHYVE SATA DISK", 40); - buf[47] = (0x8000 | 128); - buf[48] = 0; - buf[49] = (1 << 8 | 1 << 9 | 1 << 11); - buf[50] = (1 << 14); - buf[53] = (1 << 1 | 1 << 2); + ata_ident->config = ATA_DRQ_FAST; + ata_ident->cylinders = cyl; + ata_ident->heads = heads; + ata_ident->sectors = sech; + + ata_ident->sectors_intr = (0x8000 | 128); + ata_ident->tcg = 0; + + ata_ident->capabilities1 = ATA_SUPPORT_DMA | + ATA_SUPPORT_LBA | ATA_SUPPORT_IORDY; + ata_ident->capabilities2 = (1 << 14); + ata_ident->atavalid = ATA_FLAG_54_58 | + ATA_FLAG_64_70; if (p->mult_sectors) - buf[59] = (0x100 | p->mult_sectors); + ata_ident->multi = (ATA_MULTI_VALID | p->mult_sectors); if (sectors <= 0x0fffffff) { - buf[60] = sectors; - buf[61] = (sectors >> 16); + ata_ident->lba_size_1 = sectors; + ata_ident->lba_size_2 = (sectors >> 16); } else { - buf[60] = 0xffff; - buf[61] = 0x0fff; + ata_ident->lba_size_1 = 0xffff; + ata_ident->lba_size_2 = 0x0fff; } - buf[63] = 0x7; + ata_ident->mwdmamodes = 0x7; if (p->xfermode & ATA_WDMA0) - buf[63] |= (1 << ((p->xfermode & 7) + 8)); - buf[64] = 0x3; - buf[65] = 120; - buf[66] = 120; - buf[67] = 120; - buf[68] = 120; - buf[69] = 0; - buf[75] = 31; - buf[76] = (ATA_SATA_GEN1 | ATA_SATA_GEN2 | ATA_SATA_GEN3 | - ATA_SUPPORT_NCQ); - buf[77] = (ATA_SUPPORT_RCVSND_FPDMA_QUEUED | - (p->ssts & ATA_SS_SPD_MASK) >> 3); - buf[80] = 0x3f0; - buf[81] = 0x28; - buf[82] = (ATA_SUPPORT_POWERMGT | ATA_SUPPORT_WRITECACHE| - ATA_SUPPORT_LOOKAHEAD | ATA_SUPPORT_NOP); - buf[83] = (ATA_SUPPORT_ADDRESS48 | ATA_SUPPORT_FLUSHCACHE | - ATA_SUPPORT_FLUSHCACHE48 | 1 << 14); - buf[84] = (1 << 14); - buf[85] = (ATA_SUPPORT_POWERMGT | ATA_SUPPORT_WRITECACHE| - ATA_SUPPORT_LOOKAHEAD | ATA_SUPPORT_NOP); - buf[86] = (ATA_SUPPORT_ADDRESS48 | ATA_SUPPORT_FLUSHCACHE | - ATA_SUPPORT_FLUSHCACHE48 | 1 << 15); - buf[87] = (1 << 14); - buf[88] = 0x7f; + ata_ident->mwdmamodes |= (1 << ((p->xfermode & 7) + 8)); + ata_ident->apiomodes = 0x3; + ata_ident->mwdmamin = 0x0078; + ata_ident->mwdmarec = 0x0078; + ata_ident->pioblind = 0x0078; + ata_ident->pioiordy = 0x0078; + ata_ident->support3 = 0; + ata_ident->queue = 31; + ata_ident->satacapabilities = (ATA_SATA_GEN1 | ATA_SATA_GEN2 | ATA_SATA_GEN3 | + ATA_SUPPORT_NCQ); + ata_ident->satacapabilities2 = (ATA_SUPPORT_RCVSND_FPDMA_QUEUED | + (p->ssts & ATA_SS_SPD_MASK) >> 3); + ata_ident->version_major = 0x3f0; + ata_ident->version_minor = 0x28; + ata_ident->support.command1 = (ATA_SUPPORT_POWERMGT | ATA_SUPPORT_WRITECACHE | + ATA_SUPPORT_LOOKAHEAD | ATA_SUPPORT_NOP); + ata_ident->support.command2 = (ATA_SUPPORT_ADDRESS48 | ATA_SUPPORT_FLUSHCACHE | + ATA_SUPPORT_FLUSHCACHE48 | 1 << 14); + ata_ident->support.extension = (1 << 14); + ata_ident->enabled.command1 = (ATA_SUPPORT_POWERMGT | ATA_SUPPORT_WRITECACHE | + ATA_SUPPORT_LOOKAHEAD | ATA_SUPPORT_NOP); + ata_ident->enabled.command2 = (ATA_SUPPORT_ADDRESS48 | ATA_SUPPORT_FLUSHCACHE | + ATA_SUPPORT_FLUSHCACHE48 | 1 << 15); + ata_ident->enabled.extension = (1 << 14); + ata_ident->udmamodes = 0x7f; if (p->xfermode & ATA_UDMA0) - buf[88] |= (1 << ((p->xfermode & 7) + 8)); - buf[100] = sectors; - buf[101] = (sectors >> 16); - buf[102] = (sectors >> 32); - buf[103] = (sectors >> 48); + ata_ident->udmamodes |= (1 << ((p->xfermode & 7) + 8)); + ata_ident->lba_size48_1 = sectors; + ata_ident->lba_size48_2 = (sectors >> 16); + ata_ident->lba_size48_3 = (sectors >> 32); + ata_ident->lba_size48_4 = (sectors >> 48); + if (candelete && !ro) { - buf[69] |= ATA_SUPPORT_RZAT | ATA_SUPPORT_DRAT; - buf[105] = 1; - buf[169] = ATA_SUPPORT_DSM_TRIM; + ata_ident->support3 |= ATA_SUPPORT_RZAT | ATA_SUPPORT_DRAT; + ata_ident->max_dsm_blocks = 1; + ata_ident->support_dsm = ATA_SUPPORT_DSM_TRIM; } - buf[106] = 0x4000; - buf[209] = 0x4000; + ata_ident->pss = ATA_PSS_VALID_VALUE; + ata_ident->lsalign = 0x4000; if (psectsz > sectsz) { - buf[106] |= 0x2000; - buf[106] |= ffsl(psectsz / sectsz) - 1; - buf[209] |= (psectoff / sectsz); + ata_ident->pss |= ATA_PSS_MULTLS; + ata_ident->pss |= ffsl(psectsz / sectsz) - 1; + ata_ident->lsalign |= (psectoff / sectsz); } if (sectsz > 512) { - buf[106] |= 0x1000; - buf[117] = sectsz / 2; - buf[118] = ((sectsz / 2) >> 16); + ata_ident->pss |= ATA_PSS_LSSABOVE512; + ata_ident->lss_1 = sectsz / 2; + ata_ident->lss_2 = ((sectsz / 2) >> 16); } - buf[119] = (ATA_SUPPORT_RWLOGDMAEXT | 1 << 14); - buf[120] = (ATA_SUPPORT_RWLOGDMAEXT | 1 << 14); - buf[222] = 0x1020; - buf[255] = 0x00a5; - ahci_checksum((uint8_t *)buf, sizeof(buf)); - ahci_write_fis_piosetup(p); - write_prdt(p, slot, cfis, (void *)buf, sizeof(buf)); - ahci_write_fis_d2h(p, slot, cfis, ATA_S_DSC | ATA_S_READY); + ata_ident->support2 = (ATA_SUPPORT_RWLOGDMAEXT | 1 << 14); + ata_ident->enabled2 = (ATA_SUPPORT_RWLOGDMAEXT | 1 << 14); + ata_ident->transport_major = 0x1020; + ata_ident->integrity = 0x00a5; } + ahci_checksum((uint8_t*)ata_ident, sizeof(struct ata_params)); } static void @@ -1089,44 +1130,8 @@ handle_atapi_identify(struct ahci_port *p, int slot, uint8_t *cfis) ahci_write_fis_d2h(p, slot, cfis, (ATA_E_ABORT << 8) | ATA_S_READY | ATA_S_ERROR); } else { - uint16_t buf[256]; - - memset(buf, 0, sizeof(buf)); - buf[0] = (2 << 14 | 5 << 8 | 1 << 7 | 2 << 5); - ata_string((uint8_t *)(buf+10), p->ident, 20); - ata_string((uint8_t *)(buf+23), "001", 8); - ata_string((uint8_t *)(buf+27), "BHYVE SATA DVD ROM", 40); - buf[49] = (1 << 9 | 1 << 8); - buf[50] = (1 << 14 | 1); - buf[53] = (1 << 2 | 1 << 1); - buf[62] = 0x3f; - buf[63] = 7; - if (p->xfermode & ATA_WDMA0) - buf[63] |= (1 << ((p->xfermode & 7) + 8)); - buf[64] = 3; - buf[65] = 120; - buf[66] = 120; - buf[67] = 120; - buf[68] = 120; - buf[76] = (ATA_SATA_GEN1 | ATA_SATA_GEN2 | ATA_SATA_GEN3); - buf[77] = ((p->ssts & ATA_SS_SPD_MASK) >> 3); - buf[78] = (1 << 5); - buf[80] = 0x3f0; - buf[82] = (ATA_SUPPORT_POWERMGT | ATA_SUPPORT_PACKET | - ATA_SUPPORT_RESET | ATA_SUPPORT_NOP); - buf[83] = (1 << 14); - buf[84] = (1 << 14); - buf[85] = (ATA_SUPPORT_POWERMGT | ATA_SUPPORT_PACKET | - ATA_SUPPORT_RESET | ATA_SUPPORT_NOP); - buf[87] = (1 << 14); - buf[88] = 0x7f; - if (p->xfermode & ATA_UDMA0) - buf[88] |= (1 << ((p->xfermode & 7) + 8)); - buf[222] = 0x1020; - buf[255] = 0x00a5; - ahci_checksum((uint8_t *)buf, sizeof(buf)); ahci_write_fis_piosetup(p); - write_prdt(p, slot, cfis, (void *)buf, sizeof(buf)); + write_prdt(p, slot, cfis, (void *)&p->ata_ident, sizeof(struct ata_params)); ahci_write_fis_d2h(p, slot, cfis, ATA_S_DSC | ATA_S_READY); } } @@ -2319,6 +2324,10 @@ pci_ahci_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts, int atapi) MD5_CTX mdctx; u_char digest[16]; char *next, *next2; + char *bopt, *uopt, *xopts, *config; + FILE* fp; + size_t block_len; + int comma, optpos; ret = 0; @@ -2335,6 +2344,9 @@ pci_ahci_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts, int atapi) slots = 32; for (p = 0; p < MAX_PORTS && opts != NULL; p++, opts = next) { + struct ata_params *ata_ident = &sc->port[p].ata_ident; + memset(ata_ident, 0, sizeof(struct ata_params)); + /* Identify and cut off type of present port. */ if (strncmp(opts, "hd:", 3) == 0) { atapi = 0; @@ -2357,13 +2369,82 @@ pci_ahci_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts, int atapi) if (opts[0] == 0) continue; + uopt = strdup(opts); + bopt = NULL; + fp = open_memstream(&bopt, &block_len); + comma = 0; + optpos = 0; + + for (xopts = strtok(uopt, ","); + xopts != NULL; + xopts = strtok(NULL, ",")) { + + /* First option assume as block filename. */ + if (optpos == 0) { + /* + * Create an identifier for the backing file. + * Use parts of the md5 sum of the filename + */ + char ident[AHCI_PORT_IDENT]; + MD5Init(&mdctx); + MD5Update(&mdctx, opts, strlen(opts)); + MD5Final(digest, &mdctx); + snprintf(ident, AHCI_PORT_IDENT, + "BHYVE-%02X%02X-%02X%02X-%02X%02X", + digest[0], digest[1], digest[2], digest[3], digest[4], + digest[5]); + ata_string((uint8_t*)&ata_ident->serial, ident, 20); + ata_string((uint8_t*)&ata_ident->revision, "001", 8); + if (atapi) { + ata_string((uint8_t*)&ata_ident->model, "BHYVE SATA DVD ROM", 40); + } + else { + ata_string((uint8_t*)&ata_ident->model, "BHYVE SATA DISK", 40); + } + } + + if ((config = strchr(xopts, '=')) != NULL) { + *config++ = '\0'; + if (!strcmp("nmrr", xopts)) { + ata_ident->media_rotation_rate = atoi(config); + } + else if (!strcmp("ser", xopts)) { + ata_string((uint8_t*)(&ata_ident->serial), config, 20); + } + else if (!strcmp("rev", xopts)) { + ata_string((uint8_t*)(&ata_ident->revision), config, 8); + } + else if (!strcmp("model", xopts)) { + ata_string((uint8_t*)(&ata_ident->model), config, 40); + } + else { + /* Pass all other options to blockif_open. */ + *--config = '='; + fprintf(fp, "%s%s", comma ? "," : "", xopts); + comma = 1; + } + } + else { + /* Pass all other options to blockif_open. */ + fprintf(fp, "%s%s", comma ? "," : "", xopts); + comma = 1; + } + optpos++; + } + free(uopt); + fclose(fp); + + DPRINTF("%s\n", bopt); + /* * Attempt to open the backing image. Use the PCI slot/func * and the port number for the identifier string. */ snprintf(bident, sizeof(bident), "%d:%d:%d", pi->pi_slot, pi->pi_func, p); - bctxt = blockif_open(opts, bident); + bctxt = blockif_open(bopt, bident); + free(bopt); + if (bctxt == NULL) { sc->ports = p; ret = 1; @@ -2374,17 +2455,7 @@ pci_ahci_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts, int atapi) sc->port[p].port = p; sc->port[p].atapi = atapi; - /* - * Create an identifier for the backing file. - * Use parts of the md5 sum of the filename - */ - MD5Init(&mdctx); - MD5Update(&mdctx, opts, strlen(opts)); - MD5Final(digest, &mdctx); - snprintf(sc->port[p].ident, AHCI_PORT_IDENT, - "BHYVE-%02X%02X-%02X%02X-%02X%02X", - digest[0], digest[1], digest[2], digest[3], digest[4], - digest[5]); + ata_identify_init(&sc->port[p], atapi); /* * Allocate blockif request structures and add them diff --git a/usr.sbin/bsdinstall/partedit/partedit_sparc64.c b/usr.sbin/bsdinstall/partedit/partedit_sparc64.c deleted file mode 100644 index 514c0e9ffd1d..000000000000 --- a/usr.sbin/bsdinstall/partedit/partedit_sparc64.c +++ /dev/null @@ -1,84 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2011 Nathan Whitehorn - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include <string.h> - -#include "partedit.h" - -const char * -default_scheme(void) { - return ("VTOC8"); -} - -int -is_scheme_bootable(const char *part_type) { - if (strcmp(part_type, "VTOC8") == 0) - return (1); - return (0); -} - -int -is_fs_bootable(const char *part_type, const char *fs) -{ - if (strcmp(fs, "freebsd-ufs") == 0 || strcmp(fs, "freebsd-zfs") == 0) - return (1); - return (0); -} - - -size_t -bootpart_size(const char *part_type) { - /* No standalone boot partition */ - - return (0); -} - -const char * -bootpart_type(const char *scheme, const char **mountpoint) { - return ("freebsd-boot"); -} - -const char * -bootcode_path(const char *part_type) { - return (NULL); -} - -const char * -partcode_path(const char *part_type, const char *fs_type) { - if (strcmp(part_type, "VTOC8") == 0) { - if (strcmp(fs_type, "ufs") == 0) { - return ("/boot/boot1"); - } else if (strcmp(fs_type, "zfs") == 0) { - return ("/boot/zfsboot"); - } - } - return (NULL); -} - diff --git a/usr.sbin/ctld/kernel.c b/usr.sbin/ctld/kernel.c index 4da7c05f1e66..ed8d46d27a0e 100644 --- a/usr.sbin/ctld/kernel.c +++ b/usr.sbin/ctld/kernel.c @@ -777,6 +777,30 @@ kernel_lun_modify(struct lun *lun) req.reqdata.modify.lun_id = lun->l_ctl_lun; req.reqdata.modify.lun_size_bytes = lun->l_size; + if (lun->l_path != NULL) { + o = option_find(&lun->l_options, "file"); + if (o != NULL) { + option_set(o, lun->l_path); + } else { + o = option_new(&lun->l_options, "file", lun->l_path); + assert(o != NULL); + } + } + + o = option_find(&lun->l_options, "ctld_name"); + if (o != NULL) { + option_set(o, lun->l_name); + } else { + o = option_new(&lun->l_options, "ctld_name", lun->l_name); + assert(o != NULL); + } + + o = option_find(&lun->l_options, "scsiname"); + if (o == NULL && lun->l_scsiname != NULL) { + o = option_new(&lun->l_options, "scsiname", lun->l_scsiname); + assert(o != NULL); + } + if (!TAILQ_EMPTY(&lun->l_options)) { req.args_nvl = nvlist_create(0); if (req.args_nvl == NULL) { diff --git a/usr.sbin/kldxref/ef_sparc64.c b/usr.sbin/kldxref/ef_sparc64.c deleted file mode 100644 index 27abfc7b31ec..000000000000 --- a/usr.sbin/kldxref/ef_sparc64.c +++ /dev/null @@ -1,71 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2003 Jake Burkholder. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <machine/elf.h> - -#include <err.h> -#include <string.h> - -#include "ef.h" - -/* - * Apply relocations to the values we got from the file. `relbase' is the - * target relocation address of the section, and `dataoff' is the target - * relocation address of the data in `dest'. - */ -int -ef_reloc(struct elf_file *ef, const void *reldata, int reltype, Elf_Off relbase, - Elf_Off dataoff, size_t len, void *dest) -{ - const Elf_Rela *a; - Elf_Size w; - - switch (reltype) { - case EF_RELOC_RELA: - a = reldata; - if (relbase + a->r_offset >= dataoff && relbase + a->r_offset < - dataoff + len) { - switch (ELF_R_TYPE(a->r_info)) { - case R_SPARC_RELATIVE: - w = a->r_addend + relbase; - memcpy((u_char *)dest + (relbase + a->r_offset - - dataoff), &w, sizeof(w)); - break; - default: - warnx("unhandled relocation type %u", - (unsigned int)ELF_R_TYPE(a->r_info)); - break; - } - } - break; - } - return (0); -} diff --git a/usr.sbin/nologin/nologin.8 b/usr.sbin/nologin/nologin.8 index a6be6ac249fd..90b1d10f28f0 100644 --- a/usr.sbin/nologin/nologin.8 +++ b/usr.sbin/nologin/nologin.8 @@ -44,7 +44,7 @@ have been disabled. .Pp When executed, .Nm -first writes about the login attempt to +first logs about the login attempt using .Xr syslog 3 and then displays a message that an account is not available. .Pp |